diff --git a/src/clj/swarmpit/api.clj b/src/clj/swarmpit/api.clj index 1d7e3fb7..03a048b5 100644 --- a/src/clj/swarmpit/api.clj +++ b/src/clj/swarmpit/api.clj @@ -8,6 +8,7 @@ [swarmpit.registry.client :as rc] [swarmpit.registry.mapper.inbound :as rci] [swarmpit.couchdb.client :as cc] + [swarmpit.couchdb.mapper.inbound :as cmi] [swarmpit.couchdb.mapper.outbound :as cmo])) (defn create-database @@ -55,8 +56,9 @@ (defn update-service [service-id service] - (->> (dmo/->service service) - (dc/update-service service-id))) + (let [service-version (:version service)] + (->> (dmo/->service service) + (dc/update-service service-id service-version)))) ;;; Network API @@ -109,7 +111,8 @@ (defn registries [] - (cc/registries)) + (->> (cc/registries) + (cmi/->registries))) (defn registries-sum [] diff --git a/src/clj/swarmpit/couchdb/mapper/inbound.clj b/src/clj/swarmpit/couchdb/mapper/inbound.clj new file mode 100644 index 00000000..20d8fda7 --- /dev/null +++ b/src/clj/swarmpit/couchdb/mapper/inbound.clj @@ -0,0 +1,7 @@ +(ns swarmpit.couchdb.mapper.inbound) + +(defn ->registries + [registries] + (->> registries + (map #(assoc % :id (hash (:name %)))) + (into []))) \ No newline at end of file diff --git a/src/clj/swarmpit/docker/mapper/inbound.clj b/src/clj/swarmpit/docker/mapper/inbound.clj index 715444cf..2f7619c5 100644 --- a/src/clj/swarmpit/docker/mapper/inbound.clj +++ b/src/clj/swarmpit/docker/mapper/inbound.clj @@ -125,7 +125,8 @@ image (get-in service [:Spec :TaskTemplate :ContainerSpec :Image]) image-info (str/split image #"@") image-name (first image-info) - image-digest (second image-info)] + image-digest (second image-info) + image-segments (str/split image-name #":")] (array-map :id service-id :version (get-in service [:Version :Index]) @@ -133,6 +134,8 @@ :updatedAt (date (get service :UpdatedAt)) :image image-name :imageDigest image-digest + :imageName (first image-segments) + :imageTag (second image-segments) :serviceName service-name :mode service-mode :replicas replicas diff --git a/src/clj/swarmpit/docker/mapper/outbound.clj b/src/clj/swarmpit/docker/mapper/outbound.clj index d624b925..12486908 100644 --- a/src/clj/swarmpit/docker/mapper/outbound.clj +++ b/src/clj/swarmpit/docker/mapper/outbound.clj @@ -38,12 +38,16 @@ {:DriverConfig {}}})) (into []))) +(defn ->service-image + [service] + (str (:imageName service) ":" (:imageTag service))) + (defn ->service [service] {:Name (:serviceName service) :TaskTemplate {:ContainerSpec - {:Image (:image service) + {:Image (->service-image service) :Mounts (->service-volumes service) :Env (->service-variables service)}} :Mode (->service-mode service) diff --git a/src/clj/swarmpit/server.clj b/src/clj/swarmpit/server.clj index d6f3975b..2b5c5700 100644 --- a/src/clj/swarmpit/server.clj +++ b/src/clj/swarmpit/server.clj @@ -27,10 +27,10 @@ "v1/registries/" {:get {[:registryName "/repo"] {"" handler/v1-repositories "/tags" handler/v1-repository-tags}}} "v2/registries/" {:get {[:registryName "/repo"] {"" handler/v2-repositories - "/tags" handler/v2-repository-tags}}}} - "/admin/" {"users" {:get handler/users} - "registries" {:get handler/registries - :post handler/registry-create}}]) + "/tags" handler/v2-repository-tags}}} + "admin/" {:get {"users" {"" handler/users} + "registries" {"" handler/registries}} + :post {"registries" {"" handler/registry-create}}}}]) (def unsecure-api #{{:request-method :post :uri "/login"}}) diff --git a/src/cljs/swarmpit/component/page_401.cljs b/src/cljs/swarmpit/component/page_401.cljs index 66d3ce4e..49aed713 100644 --- a/src/cljs/swarmpit/component/page_401.cljs +++ b/src/cljs/swarmpit/component/page_401.cljs @@ -6,7 +6,8 @@ [:div.page [:span [:h1 "401"] - [:p "You are not authotized for selected action"]]]]) + [:p "You are not authotized for selected action"] + [:p "Go to login " [:a {:href "/#/login"} "page"]]]]]) (defn mount! [] diff --git a/src/cljs/swarmpit/component/service/create.cljs b/src/cljs/swarmpit/component/service/create.cljs index 4fab9eb0..6e56ee5d 100644 --- a/src/cljs/swarmpit/component/service/create.cljs +++ b/src/cljs/swarmpit/component/service/create.cljs @@ -57,6 +57,7 @@ (defn- form-previous-button [index] (comp/raised-button {:label "Previous" + :key "fpb" :style form-previous-button-style :disabled (= 0 index) :onTouchTap (fn [] (step-previous index))})) @@ -64,6 +65,7 @@ (defn- form-next-button [index] (comp/raised-button {:label "Next" + :key "fnb" :style form-next-button-style :disabled (= (- (count steps) 1) index) :onTouchTap (fn [] (step-next index))})) @@ -80,7 +82,7 @@ :onClick (fn [] (reset! step-index index))} item) (comp/step-content - {} + {:key "step-context"} (form-item index) (form-previous-button index) (form-next-button index)))) @@ -94,7 +96,8 @@ variables (state/get-value variables/cursor) deployment (state/get-value deployment/cursor)] (ajax/POST "/services" - {:headers {"Authorization" (storage/get "token")} + {:format :json + :headers {"Authorization" (storage/get "token")} :params (-> settings (assoc :ports ports) (assoc :volumes volumes) @@ -137,8 +140,8 @@ (defn- init-state [registry registry-version repository] (settings/image-tags-handler registry registry-version repository) - (state/set-value {:image repository - :imageTag nil + (state/set-value {:imageName repository + :imageTag "" :tags [] :serviceName "" :mode "replicated" diff --git a/src/cljs/swarmpit/component/service/edit.cljs b/src/cljs/swarmpit/component/service/edit.cljs index ab49a868..de7db7b2 100644 --- a/src/cljs/swarmpit/component/service/edit.cljs +++ b/src/cljs/swarmpit/component/service/edit.cljs @@ -38,7 +38,7 @@ (dispatch! (str "/#/services/" service-id)) (message/mount! message))) :error-handler (fn [{:keys [status response]}] - (let [error (get response "error") + (let [error (get-in response ["error" "message"]) message (str "Service update failed. Status: " status " Reason: " error)] (progress/unmount!) (message/mount! message)))}))) @@ -80,7 +80,7 @@ (defn- init-state [item] - (state/set-value (select-keys item [:image :version :serviceName :mode :replicas]) settings/cursor) + (state/set-value (select-keys item [:imageName :imageTag :version :serviceName :mode :replicas]) settings/cursor) (state/set-value (:ports item) ports/cursor) (state/set-value (:volumes item) volumes/cursor) (state/set-value (:variables item) variables/cursor) diff --git a/src/cljs/swarmpit/component/service/form_settings.cljs b/src/cljs/swarmpit/component/service/form_settings.cljs index 55eeccca..40bb5e22 100644 --- a/src/cljs/swarmpit/component/service/form_settings.cljs +++ b/src/cljs/swarmpit/component/service/form_settings.cljs @@ -32,13 +32,23 @@ :inputStyle form-image-style :value value}))) -(defn- form-image-tags [tags] +(defn- form-image-tag-ac [tags] (comp/form-comp "IMAGE TAG" (comp/autocomplete {:id "imageTag" :onUpdateInput (fn [v] (state/update-value :imageTag v cursor)) :dataSource tags}))) +(defn- form-image-tag [value] + "Temporary solution. Will be fixed with persistence. There is no way to get tags without context during update" + (comp/form-comp + "IMAGE TAG" + (comp/text-field + {:id "imageTag" + :value value + :onChange (fn [_ v] + (state/update-value :imageTag v cursor))}))) + (defn- form-name [value update-form?] (comp/form-comp "SERVICE NAME" @@ -92,14 +102,17 @@ (state/update-value :tags response cursor))})) (rum/defc form < rum/reactive [update-form?] - (let [{:keys [image + (let [{:keys [imageName + imageTag serviceName mode replicas tags]} (state/react cursor)] [:div.form-edit - (form-image image) - (form-image-tags tags) + (form-image imageName) + (if update-form? + (form-image-tag imageTag) + (form-image-tag-ac tags)) (form-name serviceName update-form?) (form-mode mode update-form?) (if (= "replicated" mode) diff --git a/src/cljs/swarmpit/component/service/info.cljs b/src/cljs/swarmpit/component/service/info.cljs index 288c452a..206f25b6 100644 --- a/src/cljs/swarmpit/component/service/info.cljs +++ b/src/cljs/swarmpit/component/service/info.cljs @@ -2,6 +2,7 @@ (:require [material.component :as comp] [material.icon :as icon] [swarmpit.url :refer [dispatch!]] + [swarmpit.storage :as storage] [swarmpit.component.service.form-ports :as ports] [swarmpit.component.service.form-volumes :as volumes] [swarmpit.component.service.form-variables :as variables] @@ -15,7 +16,8 @@ (defn- delete-service-handler [service-id] (ajax/DELETE (str "/services/" service-id) - {:handler (fn [_] + {:headers {"Authorization" (storage/get "token")} + :handler (fn [_] (let [message (str "Service " service-id " has been removed.")] (dispatch! "/#/services") (message/mount! message))) diff --git a/src/cljs/swarmpit/component/task/list.cljs b/src/cljs/swarmpit/component/task/list.cljs index 613407ff..7eb50d77 100644 --- a/src/cljs/swarmpit/component/task/list.cljs +++ b/src/cljs/swarmpit/component/task/list.cljs @@ -14,6 +14,8 @@ (case value "preparing" (comp/label-yellow value) "starting" (comp/label-yellow value) + "pending" (comp/label-yellow value) + "new" (comp/label-blue value) "ready" (comp/label-blue value) "assigned" (comp/label-blue value) diff --git a/src/cljs/swarmpit/controller.cljs b/src/cljs/swarmpit/controller.cljs index 1d07cbc6..1a3eed72 100644 --- a/src/cljs/swarmpit/controller.cljs +++ b/src/cljs/swarmpit/controller.cljs @@ -5,6 +5,7 @@ [cemerick.url :refer [query->map]] [swarmpit.storage :as storage] [swarmpit.component.page-login :as page-login] + [swarmpit.component.page-401 :as page-401] [swarmpit.component.page-404 :as page-404] [swarmpit.component.page-error :as page-error] [swarmpit.component.service.create :as screate] @@ -33,18 +34,14 @@ (-> resp api-resp-fx))) :error-handler (fn [{:keys [status]}] (if (= status 401) - (dispatch! "/#/login") - (dispatch! "/#/error")))})) + (page-401/mount!) + (page-error/mount!)))})) (defmulti dispatch (fn [location] (:handler location))) (defmethod dispatch :index [_] - (print "index")) - -(defmethod dispatch :error - [_] - (page-error/mount!)) + (print "TO-DO")) (defmethod dispatch nil [_] @@ -141,7 +138,7 @@ (defmethod dispatch :user-list [_] - (fetch "/users" + (fetch "/admin/users" (fn [response] (tlist/mount! response)))) @@ -149,7 +146,7 @@ (defmethod dispatch :registry-list [_] - (fetch "/registries" + (fetch "/admin/registries" (fn [response] (reglist/mount! response)))) diff --git a/src/cljs/swarmpit/router.cljs b/src/cljs/swarmpit/router.cljs index 01dd1ce7..924e3314 100644 --- a/src/cljs/swarmpit/router.cljs +++ b/src/cljs/swarmpit/router.cljs @@ -7,7 +7,7 @@ (defonce location (atom nil)) -(def resource +(def location-domains {:index "Home" :service-list "Services" :service-create "Services / Wizard" @@ -26,6 +26,9 @@ :repository-v1-list "Services / Wizard" :repository-v2-list "Services / Wizard"}) +(def location-page + #{:login nil}) + (def routes ["" {"/" :index "/login" :login "/error" :error @@ -48,6 +51,11 @@ ;;; Router config +(defn- is-layout? + "Check whether `loc` belong to layout. Not single page!" + [loc] + (not (contains? location-page loc))) + (defn- route "Route to given `loc`" [loc] @@ -57,9 +65,9 @@ (defn- route-to-loc "Route to given `loc` and update state domain" [loc] - (let [domain (get resource (:handler loc))] + (let [domain (get location-domains (:handler loc))] (state/update-value :domain domain [:menu]) - (if (some? domain) + (if (is-layout? loc) (layout/mount!)) (route loc)))