Skip to content

Instantly share code, notes, and snippets.

@armed
Last active April 6, 2021 04:25
Show Gist options
  • Save armed/9dbd9bed4b304cba93d366d4c08d17c0 to your computer and use it in GitHub Desktop.
Save armed/9dbd9bed4b304cba93d366d4c08d17c0 to your computer and use it in GitHub Desktop.
#!/bin/env/bb
;; script for creating DigitalOcean's droplet snapshot
(require '[babashka.curl :as curl])
(require '[cheshire.core :as json])
(def token (System/getenv "DO_TOKEN"))
(def droplet-id (System/getenv "DO_DROPLET_ID"))
(when (not token)
(println "DO_TOKEN not defined.")
(System/exit 1))
(when (not droplet-id)
(println "DO_DROPLET_ID not defined.")
(System/exit 1))
(def base-url "https://api.digitalocean.com/v2")
(def base-headers {"Authorization" (str "Bearer " token)
"Content-Type" "application/json"})
(defn list-snapshots
[]
(->
(curl/get (str base-url "/droplets/" droplet-id "/snapshots")
{:headers base-headers
:query-params {"page" "1"
"per_page" "100"}})
:body
(json/parse-string true)
:snapshots))
(defn delete-snapshot!
[snapshot-id]
(curl/delete (str base-url "/snapshots/" snapshot-id)
{:headers base-headers}))
(defn get-action
[action-id]
(->
(curl/get (str base-url "/actions/" action-id)
{:headers base-headers})
:body
(json/parse-string true)
:action))
(defn droplet-action!
[type]
(->
(curl/post (str base-url "/droplets/" droplet-id "/actions")
{:headers base-headers
:body (json/generate-string {:type type})})
:body
(json/parse-string true)
:action))
(defn try-droplet-action!
"Invokes action, returns boolean"
([action-type]
(try-droplet-action! action-type 3000 false))
([action-type wait-time-ms]
(try-droplet-action! action-type wait-time-ms false))
([action-type wait-time-ms exit-on-err?]
(loop [action (droplet-action! action-type)]
(case (:status action)
"in-progress" (do
(println (str "Waiting for " action-type "..."))
(Thread/sleep wait-time-ms)
(recur (get-action (:id action))))
"errored" (do
(println "Droplet " action-type " error, exiting.")
(if exit-on-err?
(System/exit 1)
false))
"completed" (do
(println "Droplet " action-type " complete.")
true)))))
(defn run []
(let [existing-snapshots (list-snapshots)]
;; shutdown a droplet (check every 3 secs)
(try-droplet-action! "shutdown" 3000 true)
;; snapshot a droplet (check every 10 mins for completion)
(when (try-droplet-action! "snapshot" 600000)
;; delete all existing snapshots
(doseq [snapshot existing-snapshots]
(delete-snapshot! (:id snapshot))))
;; power on a droplet
(try-droplet-action! "power_on" 3000)
(println "Operation complete.")))
(run)
@armed
Copy link
Author

armed commented Apr 5, 2021

$ DO_TOKEN=<token> DO_DROPLET_ID=<droplet_id> bb -f bb_droplet_snapshot.clj

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment