Skip to content

Commit

Permalink
refactor by defining a protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
minhtuannguyen committed Jul 17, 2016
1 parent 7a7cf32 commit 60700d1
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 47 deletions.
43 changes: 28 additions & 15 deletions src/cljocker/hh/dsl/docker.clj
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
:healthcheck
:shell})

(defn- instruction-concat [instruction v]
(defn- instruction-concat [instruction value]
(str
(s/upper-case (name instruction))
" "
(s/join " " v)))
(s/join " " value)))

(defn- resolve [args]
(cond
Expand All @@ -44,7 +44,7 @@
(conj m))
m))

(defn validate [[first & rest :as spec]]
(defn- validate-spec [[first & rest :as spec]]
(cond
(nil? spec)
[:invalid "spec is empty"]
Expand All @@ -66,23 +66,36 @@

:else [:valid]))

(defn valid? [spec]
(= :valid (first (validate spec))))

(defn docker
(defn- parse-docker-spec
([spec]
(let [[status reason] (validate spec)]
(let [[status reason] (validate-spec spec)]
(if (= :valid status)
(docker spec [])
(parse-docker-spec spec [])
(throw (new IllegalArgumentException reason)))))
([[instruction args & rest] m]
(let [m (build-instruction instruction args m)]
(if (seq rest)
(docker rest m) m))))
(recur rest m) m))))

(defprotocol Dockerfile
(as-str [self])
(write! [self path])
(valid? [self])
(validate [self]))

(defrecord DockerfileWithSpec [spec]
Dockerfile
(as-str [_]
(s/join "\n" (parse-docker-spec spec)))

(write! [self path]
(spit (str path "/Dockerfile") (as-str self)))

(validate [_]
(validate-spec spec))

(defn dockerfile-str [spec]
(s/join "\n" (docker spec)))
(valid? [self]
(= :valid (first (validate self)))))

(defn write-dockerfile! [spec path]
(spit (str path "/Dockerfile")
(dockerfile-str spec)))
(defn new-dockerfile [spec]
(DockerfileWithSpec. spec))
102 changes: 70 additions & 32 deletions test/cljocker/hh/dsl/docker_test.clj
Original file line number Diff line number Diff line change
@@ -1,42 +1,72 @@
(ns cljocker.hh.dsl.docker-test
(:require [clojure.test :refer :all]
[cljocker.hh.dsl.docker :as d]))
[cljocker.hh.dsl.docker :as d]
[clojure.string :as str]))

(deftest ^:unit validate
(is (= [:valid]
(d/validate [:from "image" :cmd "echo"])))
(-> [:from "image" :cmd "echo"]
(d/new-dockerfile)
(d/validate))))

(is (= [:invalid "spec is empty"]
(d/validate nil)))
(-> nil
(d/new-dockerfile)
(d/validate))))

(is (= [:invalid "some instruction has empty argument"]
(d/validate [:from ""])
(d/validate [:from "image" :cmd ""])))
(-> [:from ""]
(d/new-dockerfile)
(d/validate))
(-> [:from "image" :cmd ""]
(d/new-dockerfile)
(d/validate))))

(is (= [:invalid "spec is not well-formed"]
(d/validate [:from "image" :cmd])))
(-> [:from "image" :cmd]
(d/new-dockerfile)
(d/validate))))

(is (= [:invalid "spec has some unknown instruction"]
(d/validate [:from "image" :bla "blub" :cmd "echo"])))
(-> [:from "image" :bla "blub" :cmd "echo"]
(d/new-dockerfile)
(d/validate))))

(is (= [:invalid "There can only be one CMD instruction"]
(d/validate [:from "image"])
(d/validate [:from "image" :cmd "echo 1" :cmd "echo 2"])))
(-> [:from "image"]
(d/new-dockerfile)
(d/validate))
(-> [:from "image" :cmd "echo 1" :cmd "echo 2"]
(d/new-dockerfile)
(d/validate))))

(is (= [:invalid "first instruction must be FROM"]
(d/validate [:cmd "echo"])
(d/validate []))))
(-> [:cmd "echo"]
(d/new-dockerfile)
(d/validate))
(-> []
(d/new-dockerfile)
(d/validate)))))

(deftest ^:unit valid?
(is (true? (d/valid? [:from "image" :cmd "echo"])))
(is (false? (d/valid? nil))))
(is (-> [:from "image" :cmd "echo"]
(d/new-dockerfile)
(d/valid?)
(true?)))

(is (-> nil
(d/new-dockerfile)
(d/valid?)
(false?))))

(defn- heap [heap] (str "-Xmx=" heap "m "))
(defn- port [port] (str "-Dport=" port))

(deftest ^:unit test-docker-dsl
(testing "throw exception if spec is invalid"
(is (thrown? IllegalArgumentException (d/docker [:from]))))
(is (thrown? IllegalArgumentException (-> [:from]
(d/new-dockerfile)
(d/as-str)))))

(testing "happy case"
(is (= ["FROM java:8"
Expand All @@ -45,24 +75,32 @@
"ADD from to"
"WORKDIR /var/opt/folder"
"CMD java -Xmx=512m -Dport=512 -jar artifact.jar"]
(d/docker [:from "java:8"
:run (lazy-seq ["mkdir" "-p" "/var/opt/folder"])
:user "nobody"
:add ["from" "to"]
:workdir "/var/opt/folder"
:cmd ["java" (heap 512) (port 512) ["-jar" "artifact.jar"]]])
(d/docker [:from "java:8"
:run ["mkdir" "-p" "/var/opt/folder"]
:user "nobody"
:add ["from" "to"]
:workdir "/var/opt/folder"
:cmd ["java" (heap 512) (port 512) "-jar" "artifact.jar"]])))))

(-> [:from "java:8"
:run (lazy-seq ["mkdir" "-p" "/var/opt/folder"])
:user "nobody"
:add ["from" "to"]
:workdir "/var/opt/folder"
:cmd ["java" (heap 512) (port 512) ["-jar" "artifact.jar"]]]
(d/new-dockerfile)
(d/as-str)
(str/split-lines))

(-> [:from "java:8"
:run ["mkdir" "-p" "/var/opt/folder"]
:user "nobody"
:add ["from" "to"]
:workdir "/var/opt/folder"
:cmd ["java" (heap 512) (port 512) "-jar" "artifact.jar"]]
(d/new-dockerfile)
(d/as-str)
(str/split-lines))))))

(deftest ^:unit write-docker-file-to-disk
(let [spec [:from "java:8"
:cmd ["java " "-jar artifact.jar"]]
path "target"
_ (d/write-dockerfile! spec path)]
(let [dockerfile (-> [:from "java:8"
:cmd ["java " "-jar artifact.jar"]]
(d/new-dockerfile))

_ (d/write! dockerfile "target")]
(is (= "FROM java:8\nCMD java -jar artifact.jar"
(slurp "target/Dockerfile")
(d/dockerfile-str spec)))))
(slurp "target/Dockerfile")))))

0 comments on commit 60700d1

Please sign in to comment.