Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Herding cattle with Clojure at MixRadio

Avatar for Neil Prosser Neil Prosser
December 04, 2014

Herding cattle with Clojure at MixRadio

A talk given at Clojure eXchange 2014.

Video available here: https://skillsmatter.com/skillscasts/6057-herding-cattle-with-clojure-at-mixradio

Avatar for Neil Prosser

Neil Prosser

December 04, 2014

Other Decks in Technology

Transcript

  1. PHP

  2. { "name": "search", "metadata": { "bakeType": "hvm", "contact": "Fusion", "jobsPath":

    "http://jenkins/view/Search/", "releasePath": "http://jenkins/job/search-‐release/", "srcRepo": "git@github:helios/search.git", "statusPath": "/search-‐query-‐rest/2.x/ping" } }
  3. (ns applications (:require [taoensso.faraday :as far])) (def table :applications) (defn

    create-‐application [name] (far/put-‐item table {:name name :some "info"})) (defn get-‐application [name] (far/get-‐item table {:name name}))
  4. (ns application (:require [me.raynes.conch :as conch])) (defn packer-‐build [template-‐path] (conch/let-‐programs

    [packer "/opt/packer/packer"] (let [out-‐stream (PipedOutputStream.) in-‐stream (PipedInputStream. out-‐stream)] (future (packer "build" template-‐path {:out out-‐stream :timeout (* 1000 60 30)})) in-‐stream)))
  5. { "desiredCapacity": 2, "max": 2, "min": 2, "selectedLoadBalancers": [ "application"

    ], "selectedSecurityGroups": [ "internal-‐8080", "internal-‐ssh" ] } Deployment parameters
  6. [ "/usr/bin/yes | mdadm -‐C /dev/md0 -‐v -‐n 2 -‐l

    0 /dev/sdb /dev/sdc", "mkfs.ext4 /dev/md0", "mkdir -‐p /var/lib/solr", "mount /var/lib/solr", "chown -‐R solr:solr /var/lib/solr" ] Launch data
  7. #!/bin/bash cat > /etc/profile.d/asgard.sh <<EOF export CLOUD_APP=application export CLOUD_CLUSTER=application-‐environment export

    CLOUD_STACK=environment EOF cat > /etc/application.properties <<EOF anotherService.baseUrl=https://somewhere:8080/api database.connectionString=mysql://db:3306/database service.port=8080 EOF "/usr/bin/yes | mdadm -‐C /dev/md0 -‐v -‐n 2 -‐l 0 /dev/sdb /dev/sdc" "mkfs.ext4 /dev/md0" "mkdir -‐p /var/lib/solr" "mount /var/lib/solr" "chown -‐R solr:solr /var/lib/solr"
  8. (def $sg-‐http-‐80 "internal-‐http") (def $sg-‐egress-‐all [{:IpRanges "0.0.0.0/0" :IpProtocol -‐1}]) (def

    $app-‐subnets ["subnet-‐a123321a" "subnet-‐b456654b" "subnet-‐c789987c"]) (def $private-‐ips ["192.168.0.0/16"]) (def $vpc-‐id "vpc-‐d123321d") {:SecurityGroups [{:GroupName $sg-‐http-‐80 :GroupDescription "internal-‐http" :VpcId $vpc-‐id :Ingress [{:IpRanges $private-‐ips :IpProtocol "tcp" :FromPort 80 :ToPort 80}] :Egress $sg-‐egress-‐all}]}
  9. (def $sg-‐http-‐80 "internal-‐http") (def $sg-‐egress-‐all [{:IpRanges "0.0.0.0/0" :IpProtocol -‐1}]) (def

    $app-‐subnets ["subnet-‐a123321a" "subnet-‐b456654b" "subnet-‐c789987c"]) (def $private-‐ips ["192.168.0.0/16"]) (def $vpc-‐id "vpc-‐d123321d") {:SecurityGroups [{:GroupName "internal-‐http" :GroupDescription "internal-‐http" :VpcId "vpc-‐d123321d" :Ingress [{:IpRanges ["192.168.0.0/16"] :IpProtocol "tcp" :FromPort 80 :ToPort 80}] :Egress [{:IpRanges "0.0.0.0/0" :IpProtocol -‐1}]}]}
  10. (def bucket (if (= $env "prod") "prod-‐bucket" "dev-‐bucket")) {:LoadBalancer {:LoadBalancerName

    $app-‐name :Listeners [{:LoadBalancerPort 80 :InstancePort 8080 :Protocol "http" :InstanceProtocol "http"}] :SecurityGroups [$sg-‐http-‐80] :Subnets $app-‐subnets :Scheme "internal" :HealthCheck {:Target "HTTP:8080/healthcheck" :HealthyThreshold 2 :UnhealthyThreshold 4 :Interval 12 :Timeout 5}} :Role {:RoleName $app-‐name} :S3 [{:BucketName bucket}]}
  11. (def $sg-‐http-‐80 "internal-‐http") (def $sg-‐egress-‐all [{:IpRanges "0.0.0.0/0" :IpProtocol -‐1}]) (def

    $app-‐subnets ["subnet-‐a123321a" "subnet-‐b456654b" "subnet-‐c789987c"]) (def $private-‐ips ["192.168.0.0/16"]) (def $vpc-‐id "vpc-‐d123321d") (def bucket (if (= $env "prod") "prod-‐bucket" "dev-‐bucket")) {:LoadBalancer {:LoadBalancerName $app-‐name :Listeners [{:LoadBalancerPort 80 :InstancePort 8080 :Protocol "http" :InstanceProtocol "http"}] :SecurityGroups [$sg-‐http-‐80] :Subnets $app-‐subnets :Scheme "internal" :HealthCheck {:Target "HTTP:8080/healthcheck" :HealthyThreshold 2 :UnhealthyThreshold 4 :Interval 12 :Timeout 5}} :Role {:RoleName $app-‐name} :S3 [{:BucketName bucket}]} (def $app-‐name "something") (def $env "prod")
  12. (defn some-‐task [message] ...) {:id "abc" :attempt 1 :parameters {:value

    "one"}} {:parameters {:value "one" :something "else"} :status :success}
  13. (defn populate-‐vpc-‐zone-‐identifier [{:keys [parameters]}] (let [{:keys [environment region]} parameters state

    (:new-‐state parameters) {:keys [selected-‐subnets]} state] (log/write "Populating VPC zone identifier.") {:status :success :parameters (assoc-‐in parameters [:new-‐state :vpc-‐zone-‐identifier] (str/join "," selected-‐subnets))}))
  14. (defn wait-‐for-‐old-‐auto-‐scaling-‐group-‐deletion [{:keys [attempt parameters]}] (let [old-‐asg-‐name (old-‐asg-‐name parameters)] (try

    (if (asg old-‐asg-‐name environment region) (do (when (= 1 attempt) (log/write "Waiting for auto scaling group deletion.")) (capped-‐retry-‐after 10000 attempt max-‐attempts)) (do (log/write "Auto scaling group deleted.") (success parameters))) (catch Exception e (error-‐with e)))))
  15. (ns maestro.actions (:require [linked.set :refer [linked-‐set]] [maestro.messages [asg :as asg]

    [data :as data] [health :as health] [notification :as notification]])) (def ^:private action-‐ordering (linked-‐set ... :maestro.messages.data/generate-‐user-‐data :maestro.messages.data/complete-‐deployment-‐preparation :maestro.messages.data/start-‐deployment :maestro.messages.asg/create-‐launch-‐configuration :maestro.messages.asg/create-‐auto-‐scaling-‐group :maestro.messages.asg/disable-‐adding-‐instances :maestro.messages.asg/add-‐scaling-‐notifications ...))
  16. (defn to-‐function [action-‐kw] (when action-‐kw (let [ns (namespace action-‐kw) name

    (name action-‐kw)] (resolve (symbol (format "%s/%s" ns name))))))
  17. { "application": "app", "environment": "env", "id": "dccffd4c-‐af6a-‐4bed-‐b49a-‐92935e85479c", "message": "Make things

    better", "new-‐state": { "auto-‐scaling-‐group-‐name": "app-‐env-‐v030", "auto-‐scaling-‐group-‐tags": [...], "availability-‐zones": [...], "block-‐device-‐mappings": [...], "created": true, "hash": "de41a5d44f2248e13c591e717fd26e916dc3c577", "image-‐details": { "application": "app", "bake-‐date": "2014-‐11-‐25T17:54:36.000Z", "id": "ami-‐0c5dedeb", "image-‐name": "ent-‐app-‐1.2-‐1-‐hvm-‐2014-‐11-‐25_17-‐54-‐36", "iteration": "1", "version": "1.2", "virt-‐type": "hvm" },
  18. "launch-‐configuration-‐name": "app-‐env-‐v030-‐20141125182609", "lister": {...}, "selected-‐security-‐group-‐ids": [...], "selected-‐subnets": [...], "termination-‐policies": [...],

    "tyrant": { "application-‐properties": {...}, "deployment-‐params": {...}, "launch-‐data": [...] }, "user-‐data": ..., "vpc-‐zone-‐identifier": ... }, "phase": "deployment", "previous-‐state": {...}, "region": "eu-‐west-‐1", "silent": false, "start": "2014-‐11-‐25T18:25:52.548Z", "status": "running", "user": "nprosser" }