Last active
August 13, 2021 02:06
-
-
Save olivergeorge/691230277059c644a259109aa5d11d3a to your computer and use it in GitHub Desktop.
Devops tools for simple Datomic Ions app
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{:paths ["resources" "dev"] | |
:deps {com.datomic/ion {:mvn/version "0.9.28"}} | |
:mvn/repos {"datomic-cloud" {:url "s3://datomic-releases-1fc2183a/maven/releases"}} | |
:aliases {:dev {:extra-paths ["dev"] | |
:extra-deps {com.datomic/client-cloud {:mvn/version "0.8.71"} | |
com.datomic/ion-dev {:mvn/version "0.9.186"} | |
com.cognitect.aws/api {:mvn/version "0.8.171"} | |
com.cognitect.aws/endpoints {:mvn/version "1.1.11.479"} | |
com.cognitect.aws/cloudformation {:mvn/version "684.2.377.0"} | |
com.cognitect.aws/autoscaling {:mvn/version "668.2.364.0"} | |
com.cognitect.aws/ec2 {:mvn/version "693.2.386.0"}}}}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns devops | |
(:require [datomic.ion.dev :as ion-dev] | |
[cognitect.aws.client.api :as aws] | |
[clojure.edn :as edn] | |
[clojure.java.io :as io] | |
[clojure.main :as cljmain] | |
[clojure.data.json :as json])) | |
(def ion-config (edn/read-string (slurp (io/resource "datomic/ion-config.edn")))) | |
(defn find-where | |
[ms kvs] | |
(first (filter #(= kvs (select-keys % (keys kvs))) ms))) | |
(defn push | |
[args] | |
(let [push-args (select-keys args [:creds-profile :region :uname])] | |
(ion-dev/push push-args))) | |
(defn deploy | |
[args] | |
(let [deploy-args (select-keys args [:creds-profile :region :uname :group])] | |
(ion-dev/deploy deploy-args))) | |
(defn deploy-status [args] | |
(let [deploy-status-args (select-keys args [:execution-arn])] | |
(ion-dev/deploy-status deploy-status-args))) | |
(defn release | |
"Do push and deploy of app. Supports stable and unstable releases. Returns when deploy finishes running." | |
[req args] | |
(let [push-data (push args) | |
primary-group (-> (aws/client {:api :cloudformation}) | |
(aws/invoke {:op :DescribeStacks :request req}) | |
(get-in [:Stacks 0 :Outputs]) | |
(find-where {:OutputKey "CodeDeployDeploymentGroup"}) | |
:OutputValue) | |
deploy-args (merge {:group primary-group} args (select-keys push-data [:rev])) | |
deploy-data (deploy deploy-args)] | |
(loop [] | |
(let [status-data (deploy-status deploy-data)] | |
(case (:code-deploy-status status-data) | |
"RUNNING" (do (Thread/sleep 5000) (recur)) | |
"SUCCEEDED" status-data | |
(throw (ex-info "ion-release did not succeed" status-data))))))) | |
(defn autoscaling-groups [req] | |
(let [ComputeStackName (-> (aws/client {:api :cloudformation}) | |
(aws/invoke {:op :DescribeStacks :request req}) | |
(get-in [:Stacks 0 :Outputs]) | |
(find-where {:OutputKey "CodeDeployDeploymentGroup"}) | |
:OutputValue) | |
ComputeStackResources (-> (aws/client {:api :cloudformation}) | |
(aws/invoke {:op :DescribeStackResources :request {:StackName ComputeStackName}}) | |
:StackResources) | |
TxAutoScalingGroup (:PhysicalResourceId (find-where ComputeStackResources {:LogicalResourceId "TxAutoScalingGroup"})) | |
BastionAutoScalingGroup (:PhysicalResourceId (find-where ComputeStackResources {:LogicalResourceId "BastionAutoScalingGroup"}))] | |
{:TxAutoScalingGroup TxAutoScalingGroup | |
:BastionAutoScalingGroup BastionAutoScalingGroup})) | |
(defn cloud-off [req] | |
(let [{:keys [TxAutoScalingGroup BastionAutoScalingGroup]} (autoscaling-groups req) | |
autoscaling (aws/client {:api :autoscaling})] | |
(aws/invoke autoscaling {:op :UpdateAutoScalingGroup :request {:AutoScalingGroupName TxAutoScalingGroup :MinSize 0}}) | |
(aws/invoke autoscaling {:op :SetDesiredCapacity :request {:AutoScalingGroupName TxAutoScalingGroup :DesiredCapacity 0}}) | |
(aws/invoke autoscaling {:op :SetDesiredCapacity :request {:AutoScalingGroupName BastionAutoScalingGroup :DesiredCapacity 0}}))) | |
(defn cloud-on [req] | |
(let [{:keys [TxAutoScalingGroup BastionAutoScalingGroup]} (autoscaling-groups req) | |
autoscaling (aws/client {:api :autoscaling})] | |
(aws/invoke autoscaling {:op :UpdateAutoScalingGroup :request {:AutoScalingGroupName TxAutoScalingGroup :MinSize 1}}) | |
(aws/invoke autoscaling {:op :SetDesiredCapacity :request {:AutoScalingGroupName TxAutoScalingGroup :DesiredCapacity 1}}) | |
(aws/invoke autoscaling {:op :SetDesiredCapacity :request {:AutoScalingGroupName BastionAutoScalingGroup :DesiredCapacity 1}}))) | |
(def datomic-solo-template "https://awsmp-fulfillment-cf-templates-prod.s3-external-1.amazonaws.com/5e99c028-1707-4840-8e41-f70361e29600/decd6065-c6d8-4250-8fab-a8f26f87afa2/d16575983c03499488729bcd677300ec.template") | |
(defn provision | |
[{:keys [KeyPair Stack]}] | |
(aws/invoke (aws/client {:api :ec2}) {:op :CreateKeyPair :request {:KeyName (:KeyName KeyPair)}}) | |
(aws/invoke (aws/client {:api :cloudformation}) | |
{:op :CreateStack | |
:request {:StackName (:StackName Stack) | |
:TemplateBody (:TemplateBody Stack) | |
:Parameters (conj (:Parameters Stack) {:ParameterKey "KeyName" :ParameterValue (:KeyName KeyPair)}) | |
:Capabilities ["CAPABILITY_NAMED_IAM"]}})) | |
(defn teardown | |
[{:keys [StackName]}] | |
(aws/invoke (aws/client {:api :cloudformation}) {:op :DeleteStack :request {:StackName StackName}})) | |
(defn -main [& args] | |
(let [cmd (first args) | |
edn (edn/read-string (second args))] | |
(try | |
(println | |
(case cmd | |
"provision" (provision {:KeyPair {:KeyName (:app-name ion-config)} | |
:Stack {:StackName (:app-name ion-config) | |
:TemplateBody datomic-solo-template | |
:Parameters [{:ParameterKey "EnvironmentMap" :ParameterValue "{:env :dev}"}]}}) | |
"teardown" (teardown {:StackName (:app-name ion-config)}) | |
"release" (release {:StackName (:app-name ion-config)} edn) | |
"cloud-on" (cloud-on {:StackName (:app-name ion-config)}) | |
"cloud-off" (cloud-off {:StackName (:app-name ion-config)}))) | |
(flush) | |
(System/exit 0) | |
(catch Exception e | |
(println (-> e Throwable->map cljmain/ex-triage cljmain/ex-str)) | |
(System/exit 1)) | |
(finally | |
(shutdown-agents))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{:allow [] | |
:lambdas {} | |
:app-name "XXX"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
provision: | |
clojure -A:dev -m devops provision | |
teardown: | |
clojure -A:dev -m devops teardown | |
cloud-on: | |
clojure -A:dev -m devops cloud-on | |
cloud-off: | |
clojure -A:dev -m devops cloud-off | |
release-rev: | |
clojure -A:dev -m devops release '{}' | |
release-dev: | |
clojure -A:dev -m devops release '{:uname "dev"}' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment