-
Notifications
You must be signed in to change notification settings - Fork 1
/
fixture.clj
64 lines (58 loc) · 2.36 KB
/
fixture.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
(ns docker.fixture
"Docker-based clojure.test fixture"
(:require [com.stuartsierra.component :as component]
[clojure.string :refer [trim-newline split]]
[clojure.java.shell :refer [sh]]
[taoensso.timbre :as log]))
(defn rand-port
"Get a string representation of a random TCP port in the ephemeral range"
[]
(str (+ 0x400 (rand-int (- 0x10000 0x400)))))
(def host
"Get the container host; try docker-machine, default to localhost"
(memoize #(try
(trim-newline (sh "docker-machine" "ip"))
(catch Exception e "localhost"))))
(defrecord Container [cmd sleep]
component/Lifecycle
(start [component]
(log/debug "starting container" cmd)
(log/debug "note, pulling the container if needed may take some time")
(let [shell-result (apply sh cmd)
container-id (if (not= 0 (:exit shell-result))
(throw (ex-info "Unable to start docker container" shell-result))
(trim-newline (:out shell-result)))
container-host (host)]
(log/debug "waiting for container" container-id)
(Thread/sleep sleep)
(log/debug "sleep complete")
(merge component {:container-id container-id
:host container-host})))
(stop [component]
(log/debug "killing container" (:container-id component))
(sh "docker" "kill" (:container-id component))
(sh "docker" "rm" (:container-id component))
(log/debug "Stopped and removed container" (:container-id component))))
(defn new-container
"Create a new docker container using cmd, waiting for sleep for the container to become ready"
[{:keys [cmd sleep]}]
(map->Container {:cmd cmd :sleep sleep}))
(defn new-fixture
"A new test fixture using the docker cmd, sleeping for sleep ms
before allowing test to continue, then running init-fn for side
effects, a fn taking an argument of component."
[{:keys [cmd sleep init-fn]
:or {init-fn identity
sleep 1000}}]
(let [component (atom nil)]
(fn [f]
(reset! component
(try (component/start (new-container {:cmd cmd :sleep sleep}))
(catch Exception e
(log/error "Unable to start container" (ex-data e))
(throw e))))
(init-fn component)
(try
(f)
(finally
(component/stop @component))))))