From 47397c18abe6825eec3b228f71d56177a2ce9adf Mon Sep 17 00:00:00 2001 From: Jaromil Date: Fri, 5 Oct 2018 17:12:55 +0200 Subject: [PATCH] first working prototype to upload jobs to jenkins and list them --- clojure_frontend/project.clj | 1 + .../public/static/img/whale_toast.jpg | Bin 0 -> 3607 bytes clojure_frontend/src/toaster/handler.clj | 15 +++- clojure_frontend/src/toaster/jobs.clj | 36 ++++++++++ clojure_frontend/src/toaster/views.clj | 64 ++++++++++++++++++ clojure_frontend/src/toaster/webpage.clj | 9 ++- 6 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 clojure_frontend/resources/public/static/img/whale_toast.jpg create mode 100644 clojure_frontend/src/toaster/jobs.clj create mode 100644 clojure_frontend/src/toaster/views.clj diff --git a/clojure_frontend/project.clj b/clojure_frontend/project.clj index 650af4e..6a4da44 100644 --- a/clojure_frontend/project.clj +++ b/clojure_frontend/project.clj @@ -23,6 +23,7 @@ [prismatic/schema "1.1.9"] ;; filesystem utilities [me.raynes/fs "1.4.6"] + [me.raynes/conch "0.8.0"] ;; time from joda-time [clj-time "0.14.4"]] :aliases {"test" "midje"} diff --git a/clojure_frontend/resources/public/static/img/whale_toast.jpg b/clojure_frontend/resources/public/static/img/whale_toast.jpg new file mode 100644 index 0000000000000000000000000000000000000000..149ffd3d65136d8902dd066e622bbc442d3c2cee GIT binary patch literal 3607 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 eB&R`Z~p> views/dockerfile-get + ;; (s/check request))) + (POST "/dockerfile" request + (views/dockerfile-upload-post request nil nil)) - + (GET "/list" request + (web/render [:div {:class "container-fluid"} + [:h1 "List all created jobs"] + (job/listall config)])) ;; JUST-AUTH ROUTES (GET "/login" request diff --git a/clojure_frontend/src/toaster/jobs.clj b/clojure_frontend/src/toaster/jobs.clj new file mode 100644 index 0000000..4d08c19 --- /dev/null +++ b/clojure_frontend/src/toaster/jobs.clj @@ -0,0 +1,36 @@ +(ns toaster.jobs + (:require + [clojure.string :as str] + [clojure.java.io :as io] + [failjure.core :as f] + [taoensso.timbre :as log :refer [debug]] + [me.raynes.conch :as sh :refer [with-programs]] + [toaster.webpage :as web] + [hiccup.form :as hf])) + +(defn add [path config account] + (with-programs [ssh scp] + (let [jobname "test@dyne.org-vm_amd64-12345678" ;; TODO: + jobdir (str "/srv/toaster/" jobname)] + (f/attempt-all + [r_mkdir (ssh "-i" "../id_ed25519" "jenkins@sdk.bridge" "mkdir" "-p" jobdir ) + r_scp (scp "-i" "../id_ed25519" path (str "jenkins@sdk.bridge:" jobdir)) + r_ssh (ssh "-i" "../id_ed25519" "jenkins@sdk.bridge" "sync_jobs.py" "-a" jobname {:verbose true})] + (f/when-failed [e] + (web/render-error-page + (str "Job add failure: " (f/message e)))))))) + + +(defn listall [config] + (with-programs [ssh] + (f/attempt-all + [r_ssh (ssh "-i" "../id_ed25519" "jenkins@sdk.bridge" "sync_jobs.py" "-l" "all" {:verbose true})] + ;; (let [jobs (str/split (:stdout r_ssh) #" ")] + ;; jobs) + (:stdout r_ssh) + (f/when-failed [e] + (web/render-error-page + (str "Job list failure: " (f/message e))))))) + + + diff --git a/clojure_frontend/src/toaster/views.clj b/clojure_frontend/src/toaster/views.clj new file mode 100644 index 0000000..356ed4b --- /dev/null +++ b/clojure_frontend/src/toaster/views.clj @@ -0,0 +1,64 @@ +(ns toaster.views + (:require + [clojure.java.io :as io] + ;; [clojure.data.json :as json :refer [read-str]] + [toaster.webpage :as web] + [toaster.session :as s] + [toaster.ring :as ring] + [toaster.jobs :as job] + [failjure.core :as f] + [auxiliary.string :refer [strcasecmp]] + [toaster.config :as conf] + [taoensso.timbre :as log :refer [debug]] + [me.raynes.conch :as sh :refer [with-programs]] + [hiccup.form :as hf])) + +(def dockerfile-upload-form + [:div {:class "container-fluid"} + [:h1 "Upload a Dockerfile to toast"] + [:p " Choose the file in your computer and click 'Submit' to +proceed to validation."] + [:div {:class "form-group"} + [:form {:action "dockerfile" :method "post" + :class "form-shell" + :enctype "multipart/form-data"} + [:fieldset {:class "fieldset btn btn-default btn-file btn-lg"} + [:input {:name "file" :type "file"}]] + ;; [:fieldset {:class "fieldset-submit"} + [:input {:class "btn btn-primary btn-lg" + :id "field-submit" :type "submit" + :name "submit" :value "submit"}]]]]) + +(defn dockerfile-upload-post + [request config account] + (web/render + (let + [tempfile (get-in request [:params :file :tempfile]) + filename (get-in request [:params :file :filename]) + params (:params request)] + (cond + (> (get-in params [:file :size]) 64000) + ;; max upload size in bytes + ;; TODO: put in config + (web/render-error-page params "File too big in upload (64KB limit).") + :else + (let [file (io/copy tempfile (io/file "/tmp" filename)) + path (str "/tmp/" filename)] + (io/delete-file tempfile) + (if (not (.exists (io/file path))) + (web/render-error-page + (log/spy :error + [:h1 (str "Uploaded file not found: " filename)])) + ;; file is now in 'tmp' var + (with-programs [ssh scp] + ;; (require '[clj-time.core :as time] + ;; '[clj-time.coerce :as tc]) + ;; timestamp: (tc/to-long (time/now)) + (let [jobname "test@dyne.org-vm_amd64-12345678" ;; TODO: + jobdir (str "/srv/toaster/" jobname)] + (log/spy (ssh "-i" "../id_ed25519" "jenkins@sdk.bridge" "mkdir" "-p" jobdir {:throw false})) + (log/spy (scp "-i" "../id_ed25519" path (str "jenkins@sdk.bridge:" jobdir) {:throw false})) + (log/spy (ssh "-i" "../id_ed25519" "jenkins@sdk.bridge" "sync_jobs.py" "-a" jobname {:verbose true :throw false})))) + + ;; TODO: launch scripts + )))))) diff --git a/clojure_frontend/src/toaster/webpage.clj b/clojure_frontend/src/toaster/webpage.clj index 469cca8..6597763 100644 --- a/clojure_frontend/src/toaster/webpage.clj +++ b/clojure_frontend/src/toaster/webpage.clj @@ -164,9 +164,12 @@ [:span {:class "icon-bar"}] [:span {:class "icon-bar"}] [:span {:class "icon-bar"}]] - [:a {:class "navbar-brand far fa-handshake" :href "/"} "toaster"]] + [:a {:class "navbar-item " :href "/"} + [:img {:src "/static/img/whale_toast.jpg"}] + ]] + [:div {:class "collapse navbar-collapse" :id "navbarResponsive"} - [:ul {:class "nav navbar-nav hidden-sm hidden-md ml-auto"} + [:ul {:class "nav navbar-nav hidden-sm md-auto ml-auto"} ;; -- [:li {:class "divider" :role "separator"}] [:li {:class "nav-item"} @@ -189,7 +192,7 @@ [:a {:class "navbar-brand far fa-handshake" :href "/"} "toaster"]] [:div {:class "collapse navbar-collapse" :id "navbarResponsive"} - [:ul {:class "nav navbar-nav hidden-sm hidden-md ml-auto"} + [:ul {:class "nav navbar-nav hidden-sm ml-auto"} ;; -- [:li {:class "divider" :role "separator"}] ;; LIST OF RELEVANT LINKS AFTER LOGIN