Skip to content

Commit

Permalink
refactored execution internals
Browse files Browse the repository at this point in the history
  • Loading branch information
TimoKramer committed Feb 23, 2020
1 parent 5b3b25b commit 2036b96
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 47 deletions.
97 changes: 57 additions & 40 deletions src/bob/execution/internals.clj
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,6 @@
(do (log/debugf "Found image locally: %s" name)
name))))

(defn kill-container
"Kills a running container using SIGKILL.
Returns the name or the error if any."
[name]
(let [result (docker/invoke states/containers {:op :ContainerKill :params {:id name}})]
(if (cs/blank? result)
name
(u/log-and-fail "Could not kill" name))))

;; TODO default to latest?
(defn pull-image
"Pulls in an image if it's not present locally.
Expand All @@ -67,6 +58,36 @@
(do (log/debugf "Successfully pulled image: %s" name)
name))))

(defn commit-image
"Create a new image from a container
Defaults to repo containing of container-id a timestamp
and tag latest
Returns image identifier"
[container-id cmd]
(let [repo (format "%s/%d" container-id (System/currentTimeMillis))
result (docker/invoke states/commit {:op :ImageCommit
:params {:container container-id
:repo repo
:tag "latest"
:containerConfig {:Cmd [cmd]}}})]
(if (contains? result :message)
(u/log-and-fail "Could not commit image:" (:message result))
result)))

(defn delete-image
"Remove an image, along with any untagged parent images that were referenced by that image.
Takes image id or repo-tag-combination, latest is appended if no tag is provided.
Returns id of deleted image."
[image]
(let [_ (log/debugf "Deleting image with id %s" image)
result (docker/invoke states/images {:op :ImageDelete
:params {:name image}})]
(if (contains? result :message)
(u/log-and-fail "Could not delete image:" (:message result))
result)))

; TODO should be create-container
(defn build
"Builds a container.
Expand All @@ -78,7 +99,7 @@
:params {:body {:Image image}}})]
(if (contains? result :message)
(u/log-and-fail "Could not build image:" (:message result))
result)))
(:Id result))))
([image step evars] (let [resource (:needs_resource step)
working-dir (when resource (str "/root/" resource))
cmd (:cmd step)
Expand All @@ -99,7 +120,7 @@
:WorkingDir working-dir}}})]
(if (contains? result :message)
(u/log-and-fail "Could not build image:" (:message result))
result))))
(:Id result)))))

(defn status-of
"Returns the status of a container by id."
Expand Down Expand Up @@ -127,53 +148,44 @@
status (-> (docker/invoke states/containers {:op :ContainerInspect :params {:id id}})
:State
:ExitCode)]
(do (log/debugf (str status))
(f/when-failed [err]
(do (f/when-failed [err]
(u/log-and-fail "Error in running container"
(str id ":")
(f/message err)))
(if (zero? status)
(u/format-id id)
(u/log-and-fail "Container"
"with id"
(u/log-and-fail "Container with id"
id
"exited with non-zero status:"
status)))))

; TODO should this default to force?
(defn kill-container
"Kills a running container using SIGKILL.
Returns the name or the error if any."
[name]
(let [result (docker/invoke states/containers {:op :ContainerKill :params {:id name}})]
(if (cs/blank? result)
name
(u/log-and-fail "Could not kill" name))))

(defn delete-container
"Removes container by id. Takes optional keyword argument :force to force-remove container.
Defaults to force-remove.
Returns a Failure object if failed."
([run-id force-flag]
(let [run-id (str run-id)
([id force-flag]
(let [id (str id)
force-flag (= force-flag :force)
_ (log/debugf "Deleting container with id %s" run-id)
_ (log/debugf "Deleting container with id %s" id)
result (docker/invoke states/containers
{:op :ContainerDelete
:params {:id run-id
:force force-flag}})]
:params {:id id
:force force-flag}})
_ (log/debugf (str result))]
(if-let [message (get result :message)]
(u/log-and-fail "Could not delete container:" message)
result)))
([run-id] (delete-container run-id "")))

(defn commit-image
"Create a new image from a container
Defaults to repo containing of container-id a timestamp
and tag latest
Returns image identifier"
[container-id cmd]
(let [repo (format "%s/%d" container-id (System/currentTimeMillis))
result (docker/invoke states/commit {:op :ImageCommit
:params {:container container-id
:repo repo
:tag "latest"
:containerConfig {:Cmd [cmd]}}})]
(if (contains? result :message)
(u/log-and-fail "Could not commit image:" (:message result))
result)))
([id] (delete-container id :force)))

(comment
(docker/ops states/images)
Expand Down Expand Up @@ -250,4 +262,9 @@
"/root")

(docker/invoke states/containers {:op :ContainerDelete :params {:id "16a4b4e860b4" :force true}})
(delete-container "3c12417d5a7e" true))
(delete-container "3c12417d5a7e" true)

(docker/invoke states/images {:op :ImageDelete
:params {:name "clojure:latest"}})

(delete-image "clojure"))
30 changes: 23 additions & 7 deletions test/bob/execution/internals_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
(with-redefs-fn {#'docker/invoke (constantly [{:RepoTags ["clojure:latest"]}])}
#(let [result (has-image "clojure")]
(is (and (f/failed? result)
(= "Failed to find clojure"
(= "Failed to find clojure locally"
(f/message result)))))))

(testing "image absent"
(with-redefs-fn {#'docker/invoke (constantly [{:RepoTags ["clojure:foo"]}])}
#(let [result (has-image "clojure:latest")]
(is (and (f/failed? result)
(= "Failed to find clojure:latest"
(= "Failed to find clojure:latest locally"
(f/message result))))))))

(deftest container-kill
Expand Down Expand Up @@ -81,14 +81,14 @@
(deftest container-build
(testing "successful build"
(with-redefs-fn {#'docker/invoke (constantly {:Id "83996a1d", :Warnings []})}
#(is (= {:Id "83996a1d", :Warnings []} (build "foo:bar"
{:needs_resource "source"
:cmd ["ls"]}
["FOO=bar"])))))
#(is (= "83996a1d" (build "foo:bar"
{:needs_resource "source"
:cmd ["ls"]}
["FOO=bar"])))))

(testing "successful build single param"
(with-redefs-fn {#'docker/invoke (constantly {:Id "83996a1d", :Warnings []})}
#(is (= {:Id "83996a1d", :Warnings []} (build "foo:bar")))))
#(is (= "83996a1d" (build "foo:bar")))))

(testing "failing build"
(with-redefs-fn {#'docker/invoke (constantly {:message "failed"})}
Expand Down Expand Up @@ -157,3 +157,19 @@
(testing "Failed creation of new image from container"
(with-redefs-fn {#'docker/invoke (constantly {:message "foobar"})}
#(is (f/failed? (commit-image "12121212" "foo"))))))

(deftest test-delete-image
(testing "Successful deletion of image"
(let [image "foobar:1.1.0"]
(with-redefs-fn {#'docker/invoke (fn [_ opmap]
(tu/check-and-fail
#(= image (-> opmap
:params
:name)))
[{:Untagged image} {:Deleted image}])}
#(is (= (delete-image image) [{:Untagged image} {:Deleted image}])))))

(testing "Failed deletion of image"
(let [image "foobar:1.1.0"]
(with-redefs-fn {#'docker/invoke (constantly (f/fail "No such image: foobar:1.1.0"))}
#(is (= (delete-image image) (f/fail "Could not delete image: No such image: foobar:1.1.0")))))))

0 comments on commit 2036b96

Please sign in to comment.