google-cloud

mozinator2 2020-12-08T20:02:20.048900Z

I wrote a hacky babashka script that extracts all the http requests to the google cloud api from terraform. This way I can see how terraform sets up a google cloud project and learn how I can do it myself using babashka and direct google cloud http requests

# first collect all output in the shell to file
TF_LOG=debug terraform apply -auto-approve -no-color &> apply.txt

then in babashka extract all requests

  (def requests  
    (->> (slurp "apply.txt") 
         (re-seq #"(?s)---\[ REQUEST \]-{39}(.*?)-{53}" )
         (map #(second %))
         (map (fn [lines] 
                (->> lines
                     (clojure.string/split-lines)
                     (map (fn [line] (second (clojure.string/split line #"0_x5: " )))) ; you might need to modify 0_x5
                     (remove nil?)
                     (map (fn [line] 
                            (let [[_ method url] (re-find #"^(POST|GET|PUT) (.*?) HTTP" line)
                                  [_ hk hv] (re-find #"^([a-zA-Z-]*?): (.*?)$" line)
                                  ]
                              (cond (some? method) [:method-and-url method url]
                                    (some? hk) [:header [hk hv]] 
                                   :else [:body line] 
                                    ) )
                            ))
                     (reduce (fn [acc [k v1 v2]]
                               (condp = k
                                 :method-and-url (merge acc {:method v1 :url v2})
                                 :header (merge acc {:headers (conj (:headers acc) v1 v2)})
                                 :body (merge acc {:body (str (:body acc) v1 "\n")})
                                 acc)
                               ) {:headers {} :body "" :method "" :url ""})
                     )))))

; write to edn file for reference
(clojure.pprint/pprint requests ( "apply2.edn")

domparry 2020-12-08T20:03:10.049200Z

neat!!!

mozinator2 2020-12-08T20:04:03.050Z

Also working on some functions to easily interact with google cloud from babashka

mozinator2 2020-12-08T20:05:02.050400Z

It's a work in progress. But this is how it looks like

(def headers
  {"Accept" "application/json"
   "Content-Type" "application/json"
    "Authorization"
  (str "Bearer "
       (clojure.string/trim (:out (sh "gcloud" "beta" "auth" "application-default" "print-access-token"))))})

(defn to-kebab [inp]
  (-> inp 
      (s/replace #"([A-Z0-9])([A-Z])" "$1-$2")
      (s/replace #"([a-z0-9])([A-Z])" "$1-$2")
      (s/replace #"[\s_]+", "-")
      (s/lower-case)
      keyword))

(defn to-camel-case-name [inp]
  (-> inp
      name
      (s/replace #"-(\w)" #(s/upper-case (second %1)))))

(def hosts 
  {:crm  "" 
   :iam  "" 
   :sql  ""
   :run  "" 
   :use  ""
   :bill "" 
   :sec  "" })

(defn url [api & paths]
  (str "https://" 
       (get hosts api) "/" 
       (clojure.string/join "/" paths)))

(defn purl [api & paths] 
  (apply url (concat [api "v1" "projects"] paths)))

(def knative-apis 
  {:serving "serving.knative.dev"
   :domains ""})

(defn kurl [api & paths]
  (apply url (concat [:run "apis" (get knative-apis api) "v1" ] paths)))

(defn api [opts method url & [params]]
  (let [body (-> params :body)
        conv (or (:convert-keys opts) false)
        _ (clojure.pprint/pprint [method params] (io/writer (str "req.edn")))
        res (apply 
              (condp method = :get curl/get :post curl/post :put curl/put) 
              [url
               (merge 
                 {:headers headers
                  :throw false}  
                 params
                 (when 
                   (map? body) 
                   {:body 
                    (-> body 
                        (json/generate-string 
                          (if conv {:key-fn to-camel-case-name} {})))}))])
        _ (clojure.pprint/pprint res (io/writer (str "res.edn")))
        body (-> res :body (json/parse-string (if conv to-kebab true)))]
    (clojure.pprint/pprint body (io/writer (str "body.edn"))) 
    body))

(def gc (partial api {:convert-keys true}))
(def kn (partial api {:convert-keys false}))

(def project-id "shed-suite-classic-auth")

; services activated on the project
(gc :get 
        (purl :use project-id "services") 
        {:query-params {"fields" "services/name,nextPageToken"
                        "filter" "state:ENABLED"}})

mozinator2 2020-12-08T20:06:07.050900Z

get all service accounts for instance

(gc :get (purl :crm project-id "serviceAccounts"))

mozinator2 2020-12-08T20:08:05.052500Z

Input and output keys get converted from and to kebab case. so it's more idiomatic clojure. request / response and body get written to edn files for testing purposes

mozinator2 2020-12-08T20:08:42.053100Z

Can't do the kebab conversion for knative / cloud run because that would mess up the manifest files