Skip to content

Instantly share code, notes, and snippets.

@jeroenvandijk
Created May 19, 2020 11:52
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jeroenvandijk/e4fca617cf3eea82d58bc87e37e35465 to your computer and use it in GitHub Desktop.
Save jeroenvandijk/e4fca617cf3eea82d58bc87e37e35465 to your computer and use it in GitHub Desktop.
Packer with Spire
(require '[clojure.java.shell :as sh]
'[clojure.string :as str])
(defn format-arg [arg]
(cond
(symbol? arg) (str arg)
(seq? arg) (let [f (first arg)]
(if (and (symbol? f) (= "unquote" (name f)))
(second arg)
arg))
(nil? arg) nil
:else (pr-str arg)))
(defn generate-command [args]
(str/join " " (mapv format-arg args)))
(defn exec-command [args]
(sh/sh "bash" "-c" (generate-command args)))
(defn kw->str [x]
(if (keyword? x)
(name x)
(str x)))
(require '[clojure.data.json :as json])
(defn parse-json [s]
#_(cheshire.core/parse-string (:out res) true)
(clojure.data.json/read-str s :key-fn keyword))
(defn aws [service action {:keys [output] :as args :or {output :json}}]
(let [args (assoc args :output output)
cmd (into ['aws (name service) (name action)] (mapcat (fn [[k v]]
[(symbol (str "--" (name k)))
(kw->str v)])
args))
_ (println (generate-command cmd))
res (exec-command cmd)]
(if (zero? (:exit res))
(if (= output :json)
(parse-json (:out res))
(:out res))
(throw (ex-info "Failure" res)))))
(def PROFILE "dev1")
(def REGION "eu-central-1")
(def AWS_LINUX_AMI "ami-076431be05aaf8080")
(def SSH_FILE (str (System/getenv "HOME") "/.ssh/id_rsa")))
(aws :ec2 :describe-instances {:output :json
:region REGION
:profile PROFILE })
(def running-instance (aws :ec2 :run-instances
{:image-id AWS_LINUX_AMI
:region REGION
:profile PROFILE}))
(def ec2-instance (get-in running-instance [:Instances 0]))
(def ec2-instance-id (:InstanceId ec2-instance))
(def availability-zone (get-in ec2-instance [:Placement :AvailabilityZone]))
(clojure.pprint/pprint ec2-instance)
(defn describe-instance [ec2-instance-id]
(let [res (aws :ec2 :describe-instances {:output :json
:region REGION
:instance-ids ec2-instance-id
:profile PROFILE })]
(get-in res [:Reservations 0 :Instances 0])))
(def ec2-instance (describe-instance ec2-instance-id))
;;; WAIT for instance to have a :PublicDnsName value
(aws :ec2-instance-connect :send-ssh-public-key
{:ssh-public-key (str "file://" SSH_FILE ".pub")
:instance-id ec2-instance-id
:availability-zone availability-zone
:instance-os-user "ec2-user"
:region REGION
:profile PROFILE})
;; Run ssh commands
(require '[spire.transport :refer [ssh]]
'[spire.module.shell :refer [shell]])
;; Fails with Caused by: java.lang.IllegalArgumentException: Vector arg to map conj must be a pair
(ssh {:host-string (str "ec2-user@" (:PublicDnsName ec2-instance))
:identity SSH_FILE
:passphrase "***"
:accept-host-key true}
;; commands here?
(shell {:cmd "pwd"} )
(spire.facts/get-fact))
;; TODO build image
(defn create-image [ec2-instance-id]
(let [res (aws :ec2 :create-image {:output :json
:region REGION
:block-device-mapping []
:name "..."
:description "..."
:reboot nil
:instance-ids ec2-instance-id
:profile PROFILE })]
(get-in res [:Reservations 0 :Instances 0])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment