Skip to content

Instantly share code, notes, and snippets.

@jjttjj
Created August 15, 2020 20:25
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save jjttjj/0125979c18b683c94043b0c9cdf0b9d0 to your computer and use it in GitHub Desktop.
(ns x.user.deploy
(:require [digitalocean.v2.core :as dg]
[org.httpkit.client :as http]
[clojure.repl :refer :all]
[clojure.pprint :refer :all]
[hf.depstar.uberjar :as uj]
[clojure.java.shell :refer [sh]]
[hf.depstar.uberjar :as uj]
[shadow.cljs.devtools.api :as shadow]
[clojure.string :as str]
[clojure.java.io :as io]
[cheshire.core :as json]
[clojure.tools.logging :as log])
(:import
net.schmizz.sshj.SSHClient
net.schmizz.sshj.common.IOUtils
net.schmizz.sshj.connection.channel.direct.Session
net.schmizz.sshj.connection.channel.direct.Session$Command
net.schmizz.sshj.transport.verification.PromiscuousVerifier
net.schmizz.sshj.common.LoggerFactory
net.schmizz.sshj.common.StreamCopier
java.util.concurrent.TimeUnit
net.schmizz.sshj.common.IOUtils
net.schmizz.sshj.xfer.LocalSourceFile
(java.io InputStreamReader BufferedReader)))
(def TKN (System/getenv "DIGITAL_OCEAN_DEV_DEPLOY_KEY"))
(def PASSPHRASE (System/getenv "PPK_PASS"))
(defn get-server [name]
(->> (dg/droplets TKN)
:droplets
(filter (comp #{name} :name))
first))
(defn get-ip [name]
(-> (get-server name)
:networks
:v4
first
:ip_address))
(defn create-server [name img tags ssh-keys]
(let [ip (assert (not (get-ip name)) (str "Server: " name " already exists."))
imgs {:ubuntu19 53871280
:debian 60461760 ;;["10.3 x64" "Debian" 60461760]
:caddy-ubuntu18 63123613}
img-id (get imgs img)]
(assert img-id (str "invalid image: " img))
(log/info "Creating server with image-id" img-id)
(dg/create-droplet TKN nil
{:name name
:region "nyc1"
:size "s-1vcpu-1gb"
:image img-id
:tags (or tags [])
:ssh_keys (or ssh-keys [])})))
#_
(binding [*print-length* 500]
(->> (dg/images TKN nil {:per_page "999"})
:images
(filter (comp #(str/includes? % "Caddy") :name))
pprint))
(def keypath "C:/Users/me/.ssh/key.ppk")
(defn mkssh [ip]
(let [ssh (SSHClient.)
kp (.loadKeys ssh keypath PASSPHRASE)]
(doto ssh
(.addHostKeyVerifier (PromiscuousVerifier.))
(.connect ip 22)
.loadKnownHosts
(.authPublickey "root" (into-array [kp])))))
(defn exec [ssh cmd-str & [{:keys [timeout] :as opt}]]
(assert (.isAuthenticated ssh) "ssh isn't authenticated")
(let [sesh (.startSession ssh)
cmd (.exec sesh cmd-str)
rdr (BufferedReader. (InputStreamReader. (.getInputStream cmd)))
err (BufferedReader. (InputStreamReader. (.getErrorStream cmd)))
]
;;https://gist.github.com/h4ck4life/96fb6fa214e9be135087d45c91d56300
;;wip
#_(-> (StreamCopier. (.getInputStream cmd)
System/out LoggerFactory/DEFAULT )
(.bufSize (spy (.getLocalMaxPacketSize cmd)))
(.spawn "stdout" ))
#_(str (IOUtils/readFully (.getInputStream cmd)))
(.join cmd (or timeout 20) TimeUnit/SECONDS) ;;i belive this just adds a timeout
;;(.join cmd)
(loop []
(when-let [line (.readLine rdr)]
(println line)
(recur)))
(loop []
(when-let [line (.readLine err)]
(println line)
(recur)))
(log/info "exec loop done")
(or (.getExitErrorMessage cmd) (.getExitStatus cmd))))
(defn upload [ssh from to]
(.upload (.newSCPFileTransfer ssh)
from to))
(defn apt-install [package-string]
(str "apt-get -y install " package-string ))
(defn apt-update []
"apt-get -y update")
(def DEV-SERVER "my-dev-server-name")
(def DEV-DOMAIN "mydomain.com")
(def DEV-IP (get-ip DEV-SERVER))
(def endpoint "https://api.digitalocean.com/v2/")
;;must only have one a record
(defn delete-domain-a-record [domain]
(let [[a-record :as a-records] (->> (dg/records TKN domain)
:domain_records
(filter (comp #{"A"} :type)))
_ (assert (= (count a-records) 1))
result (http/delete (str endpoint "domains/"
domain "/records/" (:id a-record))
{:headers {"Content-Type" "application/json"
"Authorization" (str "Bearer " TKN)}})]
(pprint @result)))
(defn delete-domain-a-records [domain]
(doseq [a-record (->> (dg/records TKN domain)
:domain_records
(filter (comp #{"A"} :type)))]
(let [result (http/delete (str endpoint "domains/"
domain "/records/" (:id a-record))
{:headers {"Content-Type" "application/json"
"Authorization" (str "Bearer " TKN)}})]
(pprint @result))))
(defn create-domain-a-records [domain server-name]
(let [ip (get-ip server-name)]
(assert ip (str "IP DOESN'T EXIST FOR SERVER " domain))
(-> @(http/post (str endpoint "domains/" domain "/records")
{:headers {"Content-Type" "application/json"
"Authorization" (str "Bearer " TKN)}
:body (json/generate-string
{
:type "A"
:name "@"
:data ip
:priority nil
:port nil
:ttl 1800
:weight nil
:flags nil
:tag nil
})})
pprint)
(-> @(http/post (str endpoint "domains/" domain "/records")
{:headers {"Content-Type" "application/json"
"Authorization" (str "Bearer " TKN)}
:body (json/generate-string
{
:type "A"
:name "www"
:data ip
:priority nil
:port nil
:ttl 1800
:weight nil
:flags nil
:tag nil
})})
pprint)))
#_(->> (dg/records TKN "jt.dev")
:domain_records
(filter (comp #{"A"} :type))
pprint)
#_
(do (assert false "careful")
(delete-domain-a-records "mydomain.com")
(create-domain-a-records "mydomain.com" PROD-SERVER))
(defn init-server [ssh]
(exec ssh (str (apt-update) ";" (apt-install "openjdk-11-jdk")
";java -version")
{:timeout 260}))
(def builds [:app])
(defn release-cljs []
(doseq [build builds] (shadow/release build)))
(defn send-jar [ssh]
(release-cljs)
(uj/uber-main {:dest "srv.jar" :jar :uber} {})
(upload ssh "srv.jar" "/root"))
;;todo: use caddy json
(defn mkcaddyfile [domain]
(spit "Caddyfile" (str
;; "www." domain " {\n"
;; "redir " "https://" domain "{uri}\n"
;; "}\n\n"
;;domain " { \n" "reverse_proxy localhost:8080 \n}"
domain" \n" "reverse_proxy localhost:8080 \n"
)))
(defn upload-caddyfile [ssh domain]
(mkcaddyfile domain)
(upload ssh "Caddyfile" "/root"))
;;(mkcaddyfile "mydomain.com")
;;(upload ssh "Caddyfile" "") ;;where to upload?
(defn start-server [ssh]
(exec ssh "ENV=prod java -cp srv.jar clojure.main -m com.mydomain.site.main &" {:timeout 160}))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;start to finish
(def new "mydomain.com-PROD1")
;;(create-server new :caddy-ubuntu18)
(def new-ip (get-ip new))
(def new-ssh (mkssh new-ip))
;; (send-jar new-ssh)
;; (exec new-ssh "killall java")
;; (exec new-ssh "ufw allow 8080")
;; (start-server new-ssh)
;;(exec new-ssh "ls -al log")
;;(exec new-ssh "tail log/all.log")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment