-
Notifications
You must be signed in to change notification settings - Fork 13
/
core.clj
274 lines (228 loc) · 8.5 KB
/
core.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
; This file is part of clj-docker-client.
;
; clj-docker-client is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; clj-docker-client is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with clj-docker-client. If not, see <http://www.gnu.org/licenses/>.
(ns clj-docker-client.core
(:require [clj-docker-client.utils :as u]
[clj-docker-client.formatters :as f])
(:import (java.nio.file Paths)
(com.spotify.docker.client DefaultDockerClient
DockerClient
DockerClient$ListImagesParam
DockerClient$BuildParam
DockerClient$ListContainersParam
DockerClient$LogsParam)
(com.spotify.docker.client.messages ContainerConfig
HostConfig
ContainerCreation
RegistryAuth)
(java.util List)))
(defn connect
"Connects to the local Docker daemon with default settings.
Returns the connection."
[]
(.build (DefaultDockerClient/fromEnv)))
(defn disconnect
"Closes the connection to the Docker server."
[^DockerClient connection]
(.close connection))
(defn ping
"Healthiness check for the connection to the Docker server.
Returns OK if everything is fine."
[^DockerClient connection]
(.ping connection))
(defn register
"Builds login info for a Docker registry."
[^String username ^String password]
(-> (RegistryAuth/builder)
(.username username)
(.password password)
(.build)))
(defn info
"Fetches system wide info about the connected Docker server."
[^DockerClient connection]
(f/format-info (.info connection)))
(defn- config-of
[^String image ^List cmd ^List env-vars]
(-> (ContainerConfig/builder)
(.hostConfig (.build (HostConfig/builder)))
(.env env-vars)
(.image image)
(.cmd cmd)
(.build)))
;; Images
(defn pull
"Pulls an image by *name*.
The *name* is represented by <repo>:<tag>."
[^DockerClient connection ^String name]
(do (.pull connection name)
name))
(defn build
"Builds an image from a provided directory, repo and optional tag.
Assumes a Dockerfile to be present in that directory."
([^DockerClient connection ^String path ^String repo]
(build connection path repo "latest"))
([^DockerClient connection ^String path ^String repo ^String tag]
(let [build-path (Paths/get path (into-array String []))]
(.build
connection
build-path
(format "%s:%s" repo tag)
(into-array DockerClient$BuildParam [])))))
(defn push
"Pushes an image by *name*.
The *name* is represented by <repo>:<tag>."
[^DockerClient connection ^String name ^RegistryAuth auth]
(do (.push connection name auth)
name))
(defn image-rm
"Deletes an image by *name* or id.
The *name* is represented by <repo>:<tag>."
([^DockerClient connection ^String name]
(.removeImage connection name))
([^DockerClient connection ^String name force? no-prune?]
(.removeImage connection name force? no-prune?)))
(defn image-ls
"Lists all available images."
[^DockerClient connection]
(->> (.listImages
connection
(into-array DockerClient$ListImagesParam
[(DockerClient$ListImagesParam/allImages)]))
(mapv f/format-image)))
(defn commit-container
"Creates an image from the changes of a container by name or id.
Takes the repo, tag of the image and the new entry point command.
Returns the id of the new image."
[^DockerClient connection ^String id ^String repo ^String tag ^String command]
(-> connection
(.commitContainer id
repo
tag
(config-of (-> connection
(.inspectContainer id)
(.config)
(.image))
(u/sh-tokenize! command)
[])
nil
nil)
(.id)
(u/format-id)))
;; Containers
(defn create
"Creates a container.
Takes the image, entry point command and environment vars as a map
and returns the id of the created container."
[^DockerClient connection image cmd env-vars]
(let [config (config-of image
(u/sh-tokenize! cmd)
(f/format-env-vars env-vars))
creation ^ContainerCreation (.createContainer connection config)]
(u/format-id (.id creation))))
(defn ps
"Lists all containers.
Lists all running containers by default, all can be listed by passing a true param to *all?*"
([^DockerClient connection] (ps connection false))
([^DockerClient connection all?]
(->> (.listContainers
connection
(into-array DockerClient$ListContainersParam
[(DockerClient$ListContainersParam/allContainers all?)]))
(mapv f/format-container-ps))))
(defn start
"Starts a created container asynchronously by name or id.
Returns the name or id."
[^DockerClient connection name]
(do (.startContainer connection name)
name))
(defn stop
"Stops a container with SIGTERM by name or id.
Waits for timeout secs or value of timeout before killing.
Returns the name or id."
([^DockerClient connection name] (stop connection name 30))
([^DockerClient connection name timeout]
(do (.stopContainer connection name timeout)
name)))
(defn kill
"Kills container with SIGKILL by name or id.
Assumes the container to be running.
Returns the name or id."
[^DockerClient connection name]
(do (.killContainer connection name)
name))
(defn restart
"Restarts a container with by name or id.
Waits for timeout secs or value of timeout before killing.
Returns the name or id."
([^DockerClient connection name] (restart connection name 30))
([^DockerClient connection name timeout]
(do (.restartContainer connection name timeout)
name)))
(defn pause
"Pauses a container by name or id.
Returns the name or id."
[^DockerClient connection name]
(do (.pauseContainer connection name)
name))
(defn un-pause
"Un-pauses a container by name or id.
Returns the name or id."
[^DockerClient connection name]
(do (.unpauseContainer connection name)
name))
(defn logs
"Returns a line-seq of logs from a container by name or id."
[^DockerClient connection name]
(-> (.logs connection
name
(into-array DockerClient$LogsParam
[(DockerClient$LogsParam/stdout)
(DockerClient$LogsParam/stderr)]))
(.readFully)
(clojure.string/split-lines)))
(defn container-state
"Returns the current state of a created container by name or id."
[^DockerClient connection name]
(-> connection
(.inspectContainer name)
(.state)
(f/format-state)))
(defn wait-container
"Waits for the exit of a container by id or name."
[^DockerClient connection name]
(.statusCode (.waitContainer connection name)))
(defn run
"Runs a container with a specified image, command and env vars.
Returns the container id.
Runs synchronously by default, i.e. waits for the container exit.
If detached? flag is true, executes asynchronously."
([^DockerClient connection image command env-vars]
(run connection image command env-vars false))
([^DockerClient connection image command env-vars detached?]
(let [id (->> (create connection image command env-vars)
(start connection))]
(if (not detached?)
(do (wait-container connection id)
id)
id))))
(defn rm
"Removes a container by name or id.
Pass true to force kill a running container and remove it.
Returns the name or id."
([^DockerClient connection name] (rm connection name false))
([^DockerClient connection name force?]
(do (when force?
(kill connection name))
(.removeContainer connection name)
name)))