presidium 0.15.35 → 0.15.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/Docker.js +29 -0
  2. package/Docker.test.js +380 -351
  3. package/package.json +1 -1
package/Docker.js CHANGED
@@ -1136,6 +1136,18 @@ Docker.prototype.updateService = function dockerUpdateService(service, options)
1136
1136
  })
1137
1137
  }
1138
1138
 
1139
+ /**
1140
+ * @name Docker.prototype.deleteService
1141
+ *
1142
+ * @synopsis
1143
+ * ```coffeescript [specscript]
1144
+ * new Docker().deleteService(id string) -> Promise<HttpResponse>
1145
+ * ```
1146
+ */
1147
+ Docker.prototype.deleteService = function deleteService(id) {
1148
+ return this.http.delete(`/services/${id}`)
1149
+ }
1150
+
1139
1151
  /**
1140
1152
  * @name Docker.prototype.listServices
1141
1153
  *
@@ -1189,6 +1201,23 @@ Docker.prototype.getServiceLogs = async function getServiceLogs(serviceId, optio
1189
1201
  }`)
1190
1202
  }
1191
1203
 
1204
+ /**
1205
+ * @name Docker.prototype.listTasks
1206
+ *
1207
+ * @synopsis
1208
+ * ```coffeescript [specscript]
1209
+ * new Docker().listTasks(options {
1210
+ * service?: string,
1211
+ * node?: string,
1212
+ * }) -> Promise<HttpResponse>
1213
+ * ```
1214
+ */
1215
+ Docker.prototype.listTasks = async function listTasks(options) {
1216
+ return this.http.get(`/tasks?${
1217
+ querystring.stringify(pick(['service', 'node'])(options))
1218
+ }`)
1219
+ }
1220
+
1192
1221
  /**
1193
1222
  * @name Docker.prototype.pruneImages
1194
1223
  *
package/Docker.test.js CHANGED
@@ -15,372 +15,401 @@ const {
15
15
  curry, __,
16
16
  } = rubico
17
17
 
18
- module.exports = [
18
+ const test = Test.all([
19
19
  Test('Docker - prune', Docker)
20
- .case(async docker => {
21
- {
22
- const response = await docker.pruneContainers()
23
- assert.equal(response.status, 200)
24
- }
25
- {
26
- const response = await docker.pruneVolumes()
27
- assert.equal(response.status, 200)
28
- }
29
- {
30
- const response = await docker.pruneImages()
31
- assert.equal(response.status, 200)
32
- }
33
- {
34
- const response = await docker.pruneNetworks()
35
- assert.equal(response.status, 200)
36
- }
37
- }),
20
+ .case(async docker => {
21
+ {
22
+ const response = await docker.pruneContainers()
23
+ assert.equal(response.status, 200)
24
+ }
25
+ {
26
+ const response = await docker.pruneVolumes()
27
+ assert.equal(response.status, 200)
28
+ }
29
+ {
30
+ const response = await docker.pruneImages()
31
+ assert.equal(response.status, 200)
32
+ }
33
+ {
34
+ const response = await docker.pruneNetworks()
35
+ assert.equal(response.status, 200)
36
+ }
37
+ }),
38
38
 
39
39
  Test('Docker - auth', Docker)
40
- .case(async docker => {
41
- const response = await docker.auth({
42
- username: 'admin',
43
- password: 'password',
44
- email: 'hey@example.com',
45
- serveraddress: 'localhost:5000',
46
- })
47
- assert.equal(response.status, 200)
48
- const body = await pipe([
49
- reduce((a, b) => a + b, ''),
50
- JSON.parse,
51
- ])(response.body)
52
- this.identitytoken = get('IdentityToken')(body)
53
- assert.equal(this.identitytoken, '')
54
- }),
40
+ .case(async docker => {
41
+ const response = await docker.auth({
42
+ username: 'admin',
43
+ password: 'password',
44
+ email: 'hey@example.com',
45
+ serveraddress: 'localhost:5000',
46
+ })
47
+ assert.equal(response.status, 200)
48
+ const body = await pipe([
49
+ reduce((a, b) => a + b, ''),
50
+ JSON.parse,
51
+ ])(response.body)
52
+ this.identitytoken = get('IdentityToken')(body)
53
+ assert.equal(this.identitytoken, '')
54
+ }),
55
55
 
56
56
  Test('Docker - image', Docker)
57
- .case(async function (docker) {
58
- {
59
- const response = await docker.buildImage('presidium-test:ayo', pathResolve(__dirname), {
60
- archive: {
61
- Dockerfile: `
62
- FROM node:15-alpine
63
- WORKDIR /opt
64
- COPY . .
65
- EXPOSE 8888`,
66
- },
67
- platform: 'linux/x86_64',
68
- })
69
- assert.equal(response.status, 200)
70
- response.body.pipe(process.stdout)
71
- await new Promise(resolve => {
72
- response.body.on('end', resolve)
73
- })
74
- }
75
- {
76
- const response = await docker.listImages()
77
- assert.equal(response.status, 200)
78
- const body = await response.json()
79
- assert(body.length > 1)
80
- this.initialBodyLength = body.length
81
- }
82
- {
83
- const response = await docker.tagImage('presidium-test:ayo', {
84
- tag: 'ayo',
85
- repo: 'localhost:5000/presidium-test',
86
- })
87
- response.body.pipe(process.stdout)
88
- await new Promise(resolve => {
89
- response.body.on('end', resolve)
90
- })
91
- }
92
- {
93
- const response = await docker.pushImage('presidium-test:ayo', 'localhost:5000', {
94
- identitytoken: this.identitytoken,
95
- })
96
- response.body.pipe(process.stdout)
97
- await new Promise(resolve => {
98
- response.body.on('end', resolve)
99
- })
100
- }
101
- {
102
- const response = await docker.inspectImage('localhost:5000/presidium-test:ayo')
103
- assert.equal(response.status, 200)
104
- }
105
- {
106
- const responses = await Promise.all([
107
- docker.removeImage('presidium-test:ayo'),
108
- docker.removeImage('localhost:5000/presidium-test:ayo'),
109
- ])
110
- for (const response of responses) {
111
- const response = await docker.removeImage('presidium-test:ayo')
112
- assert(response.status == 200 || response.status == 404)
113
- }
57
+ .case(async function (docker) {
58
+ {
59
+ const response = await docker.buildImage('presidium-test:ayo', pathResolve(__dirname), {
60
+ archive: {
61
+ Dockerfile: `
62
+ FROM node:15-alpine
63
+ WORKDIR /opt
64
+ COPY . .
65
+ EXPOSE 8888`,
66
+ },
67
+ platform: 'linux/x86_64',
68
+ })
69
+ assert.equal(response.status, 200)
70
+ response.body.pipe(process.stdout)
71
+ await new Promise(resolve => {
72
+ response.body.on('end', resolve)
73
+ })
74
+ }
75
+ {
76
+ const response = await docker.listImages()
77
+ assert.equal(response.status, 200)
78
+ const body = await response.json()
79
+ assert(body.length > 1)
80
+ this.initialBodyLength = body.length
81
+ }
82
+ {
83
+ const response = await docker.tagImage('presidium-test:ayo', {
84
+ tag: 'ayo',
85
+ repo: 'localhost:5000/presidium-test',
86
+ })
87
+ response.body.pipe(process.stdout)
88
+ await new Promise(resolve => {
89
+ response.body.on('end', resolve)
90
+ })
91
+ }
92
+ {
93
+ const response = await docker.pushImage('presidium-test:ayo', 'localhost:5000', {
94
+ identitytoken: this.identitytoken,
95
+ })
96
+ response.body.pipe(process.stdout)
97
+ await new Promise(resolve => {
98
+ response.body.on('end', resolve)
99
+ })
100
+ }
101
+ {
102
+ const response = await docker.inspectImage('localhost:5000/presidium-test:ayo')
103
+ assert.equal(response.status, 200)
104
+ }
105
+ {
106
+ const responses = await Promise.all([
107
+ docker.removeImage('presidium-test:ayo'),
108
+ docker.removeImage('localhost:5000/presidium-test:ayo'),
109
+ ])
110
+ for (const response of responses) {
111
+ const response = await docker.removeImage('presidium-test:ayo')
112
+ assert(response.status == 200 || response.status == 404)
114
113
  }
115
- }),
114
+ }
115
+ }),
116
116
 
117
117
  Test('Docker - container', Docker)
118
- .case(async function (docker) {
119
- {
120
- const createResponse = await docker.createContainer({
121
- name: 'test-alpine-3',
122
- image: 'node:15-alpine',
123
- cmd: ['node', '-e', 'console.log(\'heyy\')'],
124
- rm: true,
125
- })
126
- assert(createResponse.ok)
127
- const containerId = (await createResponse.json()).Id
128
- const attachResponse = await docker.attachContainer(containerId),
129
- startResponse = await docker.startContainer(containerId)
130
- assert(startResponse.ok)
131
- assert(attachResponse.ok)
132
-
133
- const body = await attachResponse.buffer()
134
- assert.equal(body.constructor, Buffer)
135
- assert.strictEqual(body[0], 1) // stdout
136
- assert.strictEqual(body[1], 0) // empty
137
- assert.strictEqual(body[2], 0) // empty
138
- assert.strictEqual(body[3], 0) // empty
139
- assert.strictEqual(body[4], 0) // SIZE1
140
- assert.strictEqual(body[5], 0) // SIZE2
141
- assert.strictEqual(body[6], 0) // SIZE3
142
- assert.strictEqual(body[7], 5) // SIZE4
143
- assert.strictEqual(body.slice(8).toString(), 'heyy\n')
144
-
145
- this.removedContainerId = containerId
146
- }
118
+ .case(async function (docker) {
119
+ {
120
+ const createResponse = await docker.createContainer({
121
+ name: 'test-alpine-3',
122
+ image: 'node:15-alpine',
123
+ cmd: ['node', '-e', 'console.log(\'heyy\')'],
124
+ rm: true,
125
+ })
126
+ assert(createResponse.ok)
127
+ const containerId = (await createResponse.json()).Id
128
+ const attachResponse = await docker.attachContainer(containerId),
129
+ startResponse = await docker.startContainer(containerId)
130
+ assert(startResponse.ok)
131
+ assert(attachResponse.ok)
147
132
 
148
- {
149
- const createResponse = await docker.createContainer({
150
- name: 'test-alpine-1',
151
- image: 'node:15-alpine',
152
- cmd: ['node', '-e', 'console.log(\'hey\')'],
153
- workdir: '/opt/heyo',
154
- expose: [22, 8888, '8889/udp'],
155
- env: { HEY: 'hey' },
156
- volume: ['/opt/my-volume'],
157
- mounts: [{
158
- source: 'other-volume',
159
- target: '/opt/other-volume',
160
- readonly: true,
161
- }],
162
- memory: 512e6, // bytes
163
- restart: 'on-failure:5',
164
-
165
- healthCmd: ['echo', 'ok'],
166
- healthInterval: 1e9,
167
- healthTimeout: 30e9,
168
- healthRetries: 10,
169
- healthStartPeriod: 5e9,
170
-
171
- publish: {
172
- 23: 22, // hostPort -> containerPort[/protocol]
173
- 8888: '8000/tcp',
174
- },
175
- logDriver: 'json-file',
176
- logDriverOptions: {
177
- 'max-file': '10',
178
- 'max-size': '100m',
179
- },
180
- })
181
- assert(createResponse.ok)
182
- const containerId = (await createResponse.json()).Id
183
- this.containerId = containerId
184
- const attachResponse = await docker.attachContainer(containerId),
185
- startResponse = await docker.startContainer(containerId)
186
- assert(startResponse.ok)
187
- assert(attachResponse.ok)
188
-
189
- const body = await attachResponse.buffer()
190
- assert.equal(body.constructor, Buffer)
191
- assert.strictEqual(body[0], 1) // stdout
192
- assert.strictEqual(body[1], 0) // empty
193
- assert.strictEqual(body[2], 0) // empty
194
- assert.strictEqual(body[3], 0) // empty
195
- assert.strictEqual(body[4], 0) // SIZE1
196
- assert.strictEqual(body[5], 0) // SIZE2
197
- assert.strictEqual(body[6], 0) // SIZE3
198
- assert.strictEqual(body[7], 4) // SIZE4
199
- assert.strictEqual(body.slice(8).toString(), 'hey\n')
200
- }
133
+ const body = await attachResponse.buffer()
134
+ assert.equal(body.constructor, Buffer)
135
+ assert.strictEqual(body[0], 1) // stdout
136
+ assert.strictEqual(body[1], 0) // empty
137
+ assert.strictEqual(body[2], 0) // empty
138
+ assert.strictEqual(body[3], 0) // empty
139
+ assert.strictEqual(body[4], 0) // SIZE1
140
+ assert.strictEqual(body[5], 0) // SIZE2
141
+ assert.strictEqual(body[6], 0) // SIZE3
142
+ assert.strictEqual(body[7], 5) // SIZE4
143
+ assert.strictEqual(body.slice(8).toString(), 'heyy\n')
201
144
 
202
- {
203
- const createResponse = await docker.createContainer({
204
- name: 'test-alpine-2',
205
- image: 'node:15-alpine',
206
- cmd: ['node', '-e', 'http.createServer((request, response) => response.end(\'hey0\')).listen(2999)'],
207
- rm: true,
208
- })
209
- assert(createResponse.ok)
210
- const containerId = (await createResponse.json()).Id
211
- assert((await docker.startContainer(containerId)).ok)
212
- const execResponse = await docker.execContainer(containerId, ['node', '-e', 'console.log(\'heyyy\')'])
213
- const body = await execResponse.buffer()
214
- assert.equal(body.constructor, Buffer)
215
- assert.strictEqual(body[0], 1) // stdout
216
- assert.strictEqual(body[1], 0) // empty
217
- assert.strictEqual(body[2], 0) // empty
218
- assert.strictEqual(body[3], 0) // empty
219
- assert.strictEqual(body[4], 0) // SIZE1
220
- assert.strictEqual(body[5], 0) // SIZE2
221
- assert.strictEqual(body[6], 0) // SIZE3
222
- assert.strictEqual(body[7], 6) // SIZE4
223
- assert.strictEqual(body.slice(8).toString(), 'heyyy\n')
224
- await docker.stopContainer(containerId, { time: 1 })
225
- }
145
+ this.removedContainerId = containerId
146
+ }
226
147
 
227
- {
228
- const response = await docker.inspectContainer(this.containerId)
229
- assert.equal(response.status, 200)
230
- const body = await response.json()
231
- assert.equal(body.Config.Image, 'node:15-alpine')
232
- assert.deepEqual(body.Config.Volumes, { '/opt/my-volume': {} })
233
- assert.equal(body.Config.WorkingDir, '/opt/heyo')
234
- assert.deepEqual(body.Config.ExposedPorts, { '22/tcp': {}, '8888/tcp': {}, '8889/udp': {} })
235
- assert.equal(body.HostConfig.Memory, 512e6)
236
- assert.deepEqual(body.HostConfig.PortBindings, {
237
- '22/tcp': [{ HostIp: '', HostPort: '23' }],
238
- '8000/tcp': [{ HostIp: '', HostPort: '8888' }]
239
- })
240
- assert.deepEqual(body.HostConfig.LogConfig, {
241
- Type: 'json-file',
242
- Config: {
243
- 'max-file': '10',
244
- 'max-size': '100m',
245
- },
246
- })
247
- assert.deepEqual(body.Config.Healthcheck, {
248
- Test: ['CMD', 'echo', 'ok'],
249
- Interval: 1000000000,
250
- Timeout: 30000000000,
251
- StartPeriod: 5000000000,
252
- Retries: 10,
253
- })
254
- assert.deepEqual(body.HostConfig.Mounts, [{
255
- Type: 'volume',
256
- Source: 'other-volume',
257
- Target: '/opt/other-volume',
258
- ReadOnly: true
259
- }])
260
- }
148
+ {
149
+ const createResponse = await docker.createContainer({
150
+ name: 'test-alpine-1',
151
+ image: 'node:15-alpine',
152
+ cmd: ['node', '-e', 'console.log(\'hey\')'],
153
+ workdir: '/opt/heyo',
154
+ expose: [22, 8888, '8889/udp'],
155
+ env: { HEY: 'hey' },
156
+ volume: ['/opt/my-volume'],
157
+ mounts: [{
158
+ source: 'other-volume',
159
+ target: '/opt/other-volume',
160
+ readonly: true,
161
+ }],
162
+ memory: 512e6, // bytes
163
+ restart: 'on-failure:5',
261
164
 
262
- {
263
- const containersResponse = await docker.listContainers()
264
- assert.equal(containersResponse.status, 200)
265
- const body = await containersResponse.json()
266
- assert(!body.map(get('Id')).includes(this.removedContainerId))
267
- }
268
- }),
165
+ healthCmd: ['echo', 'ok'],
166
+ healthInterval: 1e9,
167
+ healthTimeout: 30e9,
168
+ healthRetries: 10,
169
+ healthStartPeriod: 5e9,
170
+
171
+ publish: {
172
+ 23: 22, // hostPort -> containerPort[/protocol]
173
+ 8888: '8000/tcp',
174
+ },
175
+ logDriver: 'json-file',
176
+ logDriverOptions: {
177
+ 'max-file': '10',
178
+ 'max-size': '100m',
179
+ },
180
+ })
181
+ assert(createResponse.ok)
182
+ const containerId = (await createResponse.json()).Id
183
+ this.containerId = containerId
184
+ const attachResponse = await docker.attachContainer(containerId),
185
+ startResponse = await docker.startContainer(containerId)
186
+ assert(startResponse.ok)
187
+ assert(attachResponse.ok)
188
+
189
+ const body = await attachResponse.buffer()
190
+ assert.equal(body.constructor, Buffer)
191
+ assert.strictEqual(body[0], 1) // stdout
192
+ assert.strictEqual(body[1], 0) // empty
193
+ assert.strictEqual(body[2], 0) // empty
194
+ assert.strictEqual(body[3], 0) // empty
195
+ assert.strictEqual(body[4], 0) // SIZE1
196
+ assert.strictEqual(body[5], 0) // SIZE2
197
+ assert.strictEqual(body[6], 0) // SIZE3
198
+ assert.strictEqual(body[7], 4) // SIZE4
199
+ assert.strictEqual(body.slice(8).toString(), 'hey\n')
200
+ }
201
+
202
+ {
203
+ const createResponse = await docker.createContainer({
204
+ name: 'test-alpine-2',
205
+ image: 'node:15-alpine',
206
+ cmd: ['node', '-e', 'http.createServer((request, response) => response.end(\'hey0\')).listen(2999)'],
207
+ rm: true,
208
+ })
209
+ assert(createResponse.ok)
210
+ const containerId = (await createResponse.json()).Id
211
+ assert((await docker.startContainer(containerId)).ok)
212
+ const execResponse = await docker.execContainer(containerId, ['node', '-e', 'console.log(\'heyyy\')'])
213
+ const body = await execResponse.buffer()
214
+ assert.equal(body.constructor, Buffer)
215
+ assert.strictEqual(body[0], 1) // stdout
216
+ assert.strictEqual(body[1], 0) // empty
217
+ assert.strictEqual(body[2], 0) // empty
218
+ assert.strictEqual(body[3], 0) // empty
219
+ assert.strictEqual(body[4], 0) // SIZE1
220
+ assert.strictEqual(body[5], 0) // SIZE2
221
+ assert.strictEqual(body[6], 0) // SIZE3
222
+ assert.strictEqual(body[7], 6) // SIZE4
223
+ assert.strictEqual(body.slice(8).toString(), 'heyyy\n')
224
+ await docker.stopContainer(containerId, { time: 1 })
225
+ }
226
+
227
+ {
228
+ const response = await docker.inspectContainer(this.containerId)
229
+ assert.equal(response.status, 200)
230
+ const body = await response.json()
231
+ assert.equal(body.Config.Image, 'node:15-alpine')
232
+ assert.deepEqual(body.Config.Volumes, { '/opt/my-volume': {} })
233
+ assert.equal(body.Config.WorkingDir, '/opt/heyo')
234
+ assert.deepEqual(body.Config.ExposedPorts, { '22/tcp': {}, '8888/tcp': {}, '8889/udp': {} })
235
+ assert.equal(body.HostConfig.Memory, 512e6)
236
+ assert.deepEqual(body.HostConfig.PortBindings, {
237
+ '22/tcp': [{ HostIp: '', HostPort: '23' }],
238
+ '8000/tcp': [{ HostIp: '', HostPort: '8888' }]
239
+ })
240
+ assert.deepEqual(body.HostConfig.LogConfig, {
241
+ Type: 'json-file',
242
+ Config: {
243
+ 'max-file': '10',
244
+ 'max-size': '100m',
245
+ },
246
+ })
247
+ assert.deepEqual(body.Config.Healthcheck, {
248
+ Test: ['CMD', 'echo', 'ok'],
249
+ Interval: 1000000000,
250
+ Timeout: 30000000000,
251
+ StartPeriod: 5000000000,
252
+ Retries: 10,
253
+ })
254
+ assert.deepEqual(body.HostConfig.Mounts, [{
255
+ Type: 'volume',
256
+ Source: 'other-volume',
257
+ Target: '/opt/other-volume',
258
+ ReadOnly: true
259
+ }])
260
+ }
261
+
262
+ {
263
+ const containersResponse = await docker.listContainers()
264
+ assert.equal(containersResponse.status, 200)
265
+ const body = await containersResponse.json()
266
+ assert(!body.map(get('Id')).includes(this.removedContainerId))
267
+ }
268
+ }),
269
269
 
270
270
  Test('Docker - swarm and service', Docker)
271
- .case(async function (docker) {
272
- {
273
- const response = await docker.leaveSwarm({ force: true })
274
- assert([200, 503].includes(response.status))
275
- }
276
- {
277
- const response = await docker.initSwarm('[::1]:2377')
278
- assert.equal(response.status, 200)
279
- }
280
- {
281
- const response = await docker.inspectSwarm()
282
- assert.equal(response.status, 200)
283
- const body = await response.json()
284
- assert.equal(typeof body.JoinTokens.Worker, 'string')
285
- assert.equal(typeof body.JoinTokens.Manager, 'string')
286
- this.workerJoinToken = body.JoinTokens.Worker
287
- }
271
+ .case(async function (docker) {
272
+ { // initial leaveSwarm
273
+ const response = await docker.leaveSwarm({ force: true })
274
+ assert([200, 503].includes(response.status))
275
+ }
288
276
 
289
- {
290
- const response = await docker.createService('hey1', {
291
- image: 'node:15-alpine',
292
- replicas: 2,
293
- cmd: ['node', '-e', 'http.createServer((request, response) => response.end(\'hey1\')).listen(3000)'],
294
- workdir: '/opt/heyo',
295
- env: { HEY: 'hey' },
296
- mounts: [{
297
- source: 'other-volume',
298
- target: '/opt/other-volume',
299
- readonly: true,
300
- }],
301
- memory: 512e6, // bytes
302
- restart: 'on-failure:5',
303
-
304
- healthCmd: ['wget', '--no-verbose', '--tries=1', '--spider', 'localhost:3000'],
305
- healthInterval: 1e9,
306
- healthTimeout: 30e9,
307
- healthRetries: 10,
308
- healthStartPeriod: 5e9,
309
-
310
- publish: {
311
- 23: 22, // hostPort -> containerPort[/protocol]
312
- 8080: 3000,
313
- },
314
-
315
- logDriver: 'json-file',
316
- logDriverOptions: {
317
- 'max-file': '10',
318
- 'max-size': '100m',
319
- },
320
- })
321
- assert.equal(response.status, 201)
322
- const body = await response.json()
323
- this.serviceId = body.ID
324
- }
277
+ { // initSwarm
278
+ const response = await docker.initSwarm('[::1]:2377')
279
+ assert.equal(response.status, 200)
280
+ }
325
281
 
326
- {
327
- const response = await docker.createService('hey2', {
328
- image: 'node:15-alpine',
329
- replicas: 2,
330
- cmd: ['node', '-e', 'http.createServer((request, response) => response.end(\'hey2\')).listen(3001)'],
331
- workdir: '/opt/heyo',
332
- env: { HEY: 'hey' },
333
- mounts: [{
334
- source: 'other-volume',
335
- target: '/opt/other-volume',
336
- readonly: true,
337
- }],
338
- memory: 512e6, // bytes
339
- restart: 'on-failure',
340
- publish: { 8081: 3001 },
341
-
342
- healthCmd: ['wget', '--no-verbose', '--tries=1', '--spider', 'localhost:3001'],
343
- })
344
- assert.equal(response.status, 201)
345
- }
346
- {
347
- const response = await docker.listServices()
348
- assert.equal(response.status, 200)
349
- const body = await response.json()
350
- assert.equal(body.length, 2)
351
- }
352
- {
353
- const response = await docker.inspectService(this.serviceId)
354
- assert.equal(response.status, 200)
355
- }
282
+ { // inspectSwarm
283
+ const response = await docker.inspectSwarm()
284
+ assert.equal(response.status, 200)
285
+ const body = await response.json()
286
+ assert.equal(typeof body.JoinTokens.Worker, 'string')
287
+ assert.equal(typeof body.JoinTokens.Manager, 'string')
288
+ this.workerJoinToken = body.JoinTokens.Worker
289
+ }
356
290
 
357
- {
358
- const response = await docker.leaveSwarm()
359
- assert.equal(response.status, 503)
360
- assert((await response.json()).message.startsWith('You are attempting to leave'))
361
- }
362
- {
363
- const response = await docker.leaveSwarm({ force: true })
364
- assert.equal(response.status, 200)
365
- }
291
+ { // create a service
292
+ const response = await docker.createService('hey1', {
293
+ image: 'node:15-alpine',
294
+ replicas: 2,
295
+ cmd: ['node', '-e', 'http.createServer((request, response) => response.end(\'hey1\')).listen(3000)'],
296
+ workdir: '/opt/heyo',
297
+ env: { HEY: 'hey' },
298
+ mounts: [{
299
+ source: 'other-volume',
300
+ target: '/opt/other-volume',
301
+ readonly: true,
302
+ }],
303
+ memory: 512e6, // bytes
304
+ restart: 'on-failure:5',
366
305
 
367
- await Promise.all([ // TODO figure out a real test for join. Checking for the 503 is ok but is both slow and not a 200
368
- docker.joinSwarm('[::1]:2377', this.workerJoinToken, {
369
- listenAddr: 'hey',
370
- }).then(async response => {
371
- console.log('hey1', await response.text())
372
- // assert.equal(response.status, 503)
373
- assert.equal(response.status, 400)
374
- }),
375
- docker.joinSwarm('[::1]:2377', this.workerJoinToken, {
376
- advertiseAddr: '[::1]:2377',
377
- listenAddr: 'hey',
378
- dataPathAddr: '127.0.0.1',
379
- }).then(async response => {
380
- console.log('hey2', await response.text())
381
- // assert.equal(response.status, 503)
382
- assert.equal(response.status, 400)
383
- }),
384
- ])
385
- }),
386
- ]
306
+ healthCmd: ['wget', '--no-verbose', '--tries=1', '--spider', 'localhost:3000'],
307
+ healthInterval: 1e9,
308
+ healthTimeout: 30e9,
309
+ healthRetries: 10,
310
+ healthStartPeriod: 5e9,
311
+
312
+ publish: {
313
+ // 23: 22, // hostPort -> containerPort[/protocol]
314
+ 8080: 3000,
315
+ },
316
+
317
+ logDriver: 'json-file',
318
+ logDriverOptions: {
319
+ 'max-file': '10',
320
+ 'max-size': '100m',
321
+ },
322
+ })
323
+ assert.equal(response.status, 201)
324
+ const body = await response.json()
325
+ this.serviceId = body.ID
326
+ }
327
+
328
+ { // create another service
329
+ const response = await docker.createService('hey2', {
330
+ image: 'node:15-alpine',
331
+ replicas: 2,
332
+ cmd: ['node', '-e', 'http.createServer((request, response) => response.end(\'hey2\')).listen(3001)'],
333
+ workdir: '/opt/heyo',
334
+ env: { HEY: 'hey' },
335
+ mounts: [{
336
+ source: 'other-volume',
337
+ target: '/opt/other-volume',
338
+ readonly: true,
339
+ }],
340
+ memory: 512e6, // bytes
341
+ restart: 'on-failure',
342
+ publish: { 8081: 3001 },
343
+
344
+ healthCmd: ['wget', '--no-verbose', '--tries=1', '--spider', 'localhost:3001'],
345
+ })
346
+ assert.equal(response.status, 201)
347
+ }
348
+
349
+ { // listServices
350
+ const response = await docker.listServices()
351
+ assert.equal(response.status, 200)
352
+ const body = await response.json()
353
+ assert.equal(body.length, 2)
354
+ }
355
+
356
+ { // listTasks
357
+ const response = await docker.listTasks()
358
+ const body = await response.json()
359
+ assert.equal(body.length, 4) // 2 for hey1, 2 for hey2
360
+ }
361
+
362
+ { // inspectService
363
+ const response = await docker.inspectService(this.serviceId)
364
+ assert.equal(response.status, 200)
365
+ }
366
+
367
+ { // deleteService
368
+ const response = await docker.deleteService(this.serviceId)
369
+ assert.equal(response.status, 200)
370
+ }
371
+
372
+ { // listServices again
373
+ const response = await docker.listServices()
374
+ assert.equal(response.status, 200)
375
+ const body = await response.json()
376
+ assert.equal(body.length, 1)
377
+ }
378
+
379
+ { // leaveSwarm without forcing
380
+ const response = await docker.leaveSwarm()
381
+ assert.equal(response.status, 503)
382
+ assert((await response.json()).message.startsWith('You are attempting to leave'))
383
+ }
384
+
385
+ { // force leaveSwarm
386
+ const response = await docker.leaveSwarm({ force: true })
387
+ assert.equal(response.status, 200)
388
+ }
389
+
390
+ await Promise.all([ // TODO figure out a real test for join. Checking for the 503 is ok but is both slow and not a 200
391
+ docker.joinSwarm('[::1]:2377', this.workerJoinToken, {
392
+ listenAddr: 'hey',
393
+ }).then(async response => {
394
+ console.log('hey1', await response.text())
395
+ // assert.equal(response.status, 503)
396
+ assert.equal(response.status, 400)
397
+ }),
398
+ docker.joinSwarm('[::1]:2377', this.workerJoinToken, {
399
+ advertiseAddr: '[::1]:2377',
400
+ listenAddr: 'hey',
401
+ dataPathAddr: '127.0.0.1',
402
+ }).then(async response => {
403
+ console.log('hey2', await response.text())
404
+ // assert.equal(response.status, 503)
405
+ assert.equal(response.status, 400)
406
+ }),
407
+ ])
408
+ }),
409
+ ])
410
+
411
+ if (process.argv[1] == __filename) {
412
+ test()
413
+ }
414
+
415
+ module.exports = test
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "presidium",
3
- "version": "0.15.35",
3
+ "version": "0.15.36",
4
4
  "description": "A library for creating web services",
5
5
  "author": "Richard Tong",
6
6
  "license": "MIT",