docker-api 1.28.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,61 +0,0 @@
1
- description "Docker daemon"
2
-
3
- start on (local-filesystems and net-device-up IFACE!=lo)
4
- stop on runlevel [!2345]
5
- limit nofile 524288 1048576
6
- limit nproc 524288 1048576
7
-
8
- respawn
9
-
10
- kill timeout 20
11
-
12
- pre-start script
13
- # see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount
14
- if grep -v '^#' /etc/fstab | grep -q cgroup \
15
- || [ ! -e /proc/cgroups ] \
16
- || [ ! -d /sys/fs/cgroup ]; then
17
- exit 0
18
- fi
19
- if ! mountpoint -q /sys/fs/cgroup; then
20
- mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
21
- fi
22
- (
23
- cd /sys/fs/cgroup
24
- for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do
25
- mkdir -p $sys
26
- if ! mountpoint -q $sys; then
27
- if ! mount -n -t cgroup -o $sys cgroup $sys; then
28
- rmdir $sys || true
29
- fi
30
- fi
31
- done
32
- )
33
- end script
34
-
35
- script
36
- # modify these in /etc/default/$UPSTART_JOB (/etc/default/docker)
37
- DOCKER=/usr/bin/$UPSTART_JOB
38
- DOCKER_OPTS=
39
- if [ -f /etc/default/$UPSTART_JOB ]; then
40
- . /etc/default/$UPSTART_JOB
41
- fi
42
- exec "$DOCKER" -d $DOCKER_OPTS
43
- end script
44
-
45
- # Don't emit "started" event until docker.sock is ready.
46
- # See https://github.com/docker/docker/issues/6647
47
- post-start script
48
- DOCKER_OPTS=
49
- if [ -f /etc/default/$UPSTART_JOB ]; then
50
- . /etc/default/$UPSTART_JOB
51
- fi
52
- if ! printf "%s" "$DOCKER_OPTS" | grep -qE -e '-H|--host'; then
53
- while ! [ -e /var/run/docker.sock ]; do
54
- initctl status $UPSTART_JOB | grep -qE "(stop|respawn)/" && exit 1
55
- echo "Waiting for /var/run/docker.sock"
56
- sleep 0.1
57
- done
58
- echo "/var/run/docker.sock is up"
59
- fi
60
- end script
61
-
@@ -1,35 +0,0 @@
1
- #!/bin/bash
2
- set -x
3
- set -e
4
-
5
- # argv[0]
6
- DOCKER_VERSION=$1
7
-
8
- # disable travis default installation
9
- service docker stop
10
- apt-get -y --purge remove docker-engine
11
-
12
- # install gpg key for docker rpo
13
- apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D
14
-
15
- # enable docker repo
16
- echo 'deb "https://apt.dockerproject.org/repo" ubuntu-trusty main' >> /etc/apt/sources.list.d/docker-main.list
17
- apt-get update -o Dir::Etc::sourcelist='sources.list.d/docker-main.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0'
18
- apt-cache gencaches
19
-
20
- # install package
21
- apt-get -y --force-yes install docker-engine=${DOCKER_VERSION}-0~trusty
22
- echo 'DOCKER_OPTS="-H unix:///var/run/docker.sock --pidfile=/var/run/docker.pid"' > /etc/default/docker
23
- cat /etc/default/docker
24
-
25
- # docker 1.6 packages did not come with init files
26
- if [[ $DOCKER_VERSION == 1.6.* ]]
27
- then
28
- cp script/docker.conf /etc/init/docker.conf
29
- cp script/docker /etc/init.d/docker
30
- chmod +x /etc/init.d/docker
31
- else
32
- service docker stop
33
- fi
34
-
35
- service docker start
@@ -1,123 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Docker::Connection do
4
- subject { described_class.new('http://localhost:4243', {}) }
5
-
6
- describe '#initialize' do
7
- let(:url) { 'http://localhost:4243' }
8
- let(:options) { {} }
9
- subject { described_class.new(url, options) }
10
-
11
- context 'when the first argument is not a String' do
12
- let(:url) { :lol_not_a_string }
13
-
14
- it 'raises an error' do
15
- expect { subject }.to raise_error(Docker::Error::ArgumentError)
16
- end
17
- end
18
-
19
- context 'when the first argument is a String' do
20
- context 'and the url is a unix socket' do
21
- let(:url) { 'unix:///var/run/docker.sock' }
22
-
23
- it 'sets the socket path in the options' do
24
- expect(subject.url).to eq('unix:///')
25
- expect(subject.options).to include(:socket => '/var/run/docker.sock')
26
- end
27
- end
28
-
29
- context 'but the second argument is not a Hash' do
30
- let(:options) { :lol_not_a_hash }
31
-
32
- it 'raises an error' do
33
- expect { subject }.to raise_error(Docker::Error::ArgumentError)
34
- end
35
- end
36
-
37
- context 'and the second argument is a Hash' do
38
- it 'sets the url and options' do
39
- expect(subject.url).to eq url
40
- expect(subject.options).to eq options
41
- end
42
- end
43
- end
44
-
45
- context 'url conversion to uri' do
46
- context 'when the url does not contain a scheme' do
47
- let(:url) { 'localhost:4243' }
48
-
49
- it 'adds the scheme to the url' do
50
- expect(subject.url).to eq "http://#{url}"
51
- end
52
- end
53
-
54
- context 'when the url is a complete uri' do
55
- let(:url) { 'http://localhost:4243' }
56
-
57
- it 'leaves the url intact' do
58
- expect(subject.url).to eq url
59
- end
60
- end
61
- end
62
- end
63
-
64
- describe '#resource' do
65
- its(:resource) { should be_a Excon::Connection }
66
- end
67
-
68
- describe '#request' do
69
- let(:method) { :get }
70
- let(:path) { '/test' }
71
- let(:query) { { :all => true } }
72
- let(:options) { { :expects => 201, :lol => true } }
73
- let(:body) { rand(10000000) }
74
- let(:resource) { double(:resource) }
75
- let(:response) { double(:response, :body => body) }
76
- let(:expected_hash) {
77
- {
78
- :method => method,
79
- :path => "/v#{Docker::API_VERSION}#{path}",
80
- :query => query,
81
- :headers => { 'Content-Type' => 'text/plain',
82
- 'User-Agent' => "Swipely/Docker-API #{Docker::VERSION}",
83
- },
84
- :expects => 201,
85
- :idempotent => true,
86
- :lol => true
87
- }
88
- }
89
-
90
- before do
91
- allow(subject).to receive(:resource).and_return(resource)
92
- expect(resource).to receive(:request).
93
- with(expected_hash).
94
- and_return(response)
95
- end
96
-
97
- it 'sends #request to #resource with the compiled params' do
98
- expect(subject.request(method, path, query, options)).to eq body
99
- end
100
- end
101
-
102
- [:get, :put, :post, :delete].each do |method|
103
- describe "##{method}" do
104
- it 'is delegated to #request' do
105
- expect(subject).to receive(:request).with(method)
106
- subject.public_send(method)
107
- end
108
- end
109
- end
110
-
111
- describe '#to_s' do
112
- let(:url) { 'http://google.com:4000' }
113
- let(:options) { {} }
114
- let(:expected_string) {
115
- "Docker::Connection { :url => #{url}, :options => #{options} }"
116
- }
117
- subject { described_class.new(url, options) }
118
-
119
- it 'returns a pretty version with the url and port' do
120
- expect(subject.to_s).to eq expected_string
121
- end
122
- end
123
- end
@@ -1,801 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Docker::Container do
4
- describe '#to_s' do
5
- subject {
6
- described_class.send(:new, Docker.connection, 'id' => rand(10000).to_s)
7
- }
8
-
9
- let(:id) { 'bf119e2' }
10
- let(:connection) { Docker.connection }
11
- let(:expected_string) {
12
- "Docker::Container { :id => #{id}, :connection => #{connection} }"
13
- }
14
- before do
15
- {
16
- :@id => id,
17
- :@connection => connection
18
- }.each { |k, v| subject.instance_variable_set(k, v) }
19
- end
20
-
21
- its(:to_s) { should == expected_string }
22
- end
23
-
24
- describe '#json' do
25
- subject {
26
- described_class.create('Cmd' => %w[true], 'Image' => 'debian:wheezy')
27
- }
28
- let(:description) { subject.json }
29
- after(:each) { subject.remove }
30
-
31
- it 'returns the description as a Hash' do
32
- expect(description).to be_a Hash
33
- expect(description['Id']).to start_with(subject.id)
34
- end
35
- end
36
-
37
- describe '#streaming_logs' do
38
- let(:options) { {} }
39
- subject do
40
- described_class.create(
41
- {'Cmd' => ['/bin/bash', '-lc', 'echo hello'], 'Image' => 'debian:wheezy'}.merge(options)
42
- )
43
- end
44
-
45
- before(:each) { subject.tap(&:start).wait }
46
- after(:each) { subject.remove }
47
-
48
- context 'when not selecting any stream' do
49
- let(:non_destination) { subject.streaming_logs }
50
- it 'raises a client error' do
51
- expect { non_destination }.to raise_error(Docker::Error::ClientError)
52
- end
53
- end
54
-
55
- context 'when selecting stdout' do
56
- let(:stdout) { subject.streaming_logs(stdout: 1) }
57
- it 'returns blank logs' do
58
- expect(stdout).to be_a String
59
- expect(stdout).to match("hello")
60
- end
61
- end
62
-
63
- context 'when using a tty' do
64
- let(:options) { { 'Tty' => true } }
65
-
66
- let(:output) { subject.streaming_logs(stdout: 1, tty: 1) }
67
- it 'returns `hello`' do
68
- expect(output).to be_a(String)
69
- expect(output).to match("hello")
70
- end
71
- end
72
-
73
- context 'when passing a block' do
74
- let(:lines) { [] }
75
- let(:output) { subject.streaming_logs(stdout: 1, follow: 1) { |s,c| lines << c } }
76
- it 'returns `hello`' do
77
- expect(output).to be_a(String)
78
- expect(output).to match("hello")
79
- expect(lines.join).to match("hello")
80
- end
81
- end
82
- end
83
-
84
- describe '#logs' do
85
- subject {
86
- described_class.create('Cmd' => "echo hello", 'Image' => 'debian:wheezy')
87
- }
88
- after(:each) { subject.remove }
89
-
90
- context "when not selecting any stream" do
91
- let(:non_destination) { subject.logs }
92
- it 'raises a client error' do
93
- expect { non_destination }.to raise_error(Docker::Error::ClientError)
94
- end
95
- end
96
-
97
- context "when selecting stdout" do
98
- let(:stdout) { subject.logs(stdout: 1) }
99
- it 'returns blank logs' do
100
- expect(stdout).to be_a String
101
- expect(stdout).to eq ""
102
- end
103
- end
104
- end
105
-
106
- describe '#create' do
107
- subject {
108
- described_class.create({
109
- 'Cmd' => %w[true],
110
- 'Image' => 'debian:wheezy'
111
- }.merge(opts))
112
- }
113
-
114
- context 'when creating a container named bob' do
115
- let(:opts) { {"name" => "bob"} }
116
- after(:each) { subject.remove }
117
-
118
- it 'should have name set to bob' do
119
- expect(subject.json["Name"]).to eq("/bob")
120
- end
121
- end
122
- end
123
-
124
- describe '#rename' do
125
- subject {
126
- described_class.create({
127
- 'name' => 'foo',
128
- 'Cmd' => %w[true],
129
- 'Image' => 'debian:wheezy'
130
- })
131
- }
132
-
133
- before { subject.start }
134
- after(:each) { subject.tap(&:wait).remove }
135
-
136
- it 'renames the container' do
137
- subject.rename('bar')
138
- expect(subject.json["Name"]).to match(%r{bar})
139
- end
140
- end
141
-
142
- describe '#changes' do
143
- subject {
144
- described_class.create(
145
- 'Cmd' => %w[rm -rf /root],
146
- 'Image' => 'debian:wheezy'
147
- )
148
- }
149
- let(:changes) { subject.changes }
150
-
151
- before { subject.tap(&:start).tap(&:wait) }
152
- after(:each) { subject.tap(&:wait).remove }
153
-
154
- it 'returns the changes as an array' do
155
- expect(changes).to eq [
156
- {
157
- "Path" => "/root",
158
- "Kind" => 2
159
- },
160
- ]
161
- end
162
- end
163
-
164
- describe '#top' do
165
- let(:dir) {
166
- File.join(File.dirname(__FILE__), '..', 'fixtures', 'top')
167
- }
168
- let(:image) { Docker::Image.build_from_dir(dir) }
169
- let(:top) { sleep 1; container.top }
170
- let!(:container) { image.run('/while') }
171
- after do
172
- container.kill!.remove
173
- image.remove
174
- end
175
-
176
- it 'returns the top commands as an Array' do
177
- expect(top).to be_a Array
178
- expect(top).to_not be_empty
179
- expect(top.first.keys).to include('PID')
180
- end
181
- end
182
-
183
- describe '#copy' do
184
- let(:image) { Docker::Image.create('fromImage' => 'debian:wheezy') }
185
- subject { image.run('touch /test').tap { |c| c.wait } }
186
-
187
- after(:each) { subject.remove }
188
-
189
- context 'when the file does not exist' do
190
- it 'raises an error' do
191
- expect { subject.copy('/lol/not/a/real/file') { |chunk| puts chunk } }
192
- .to raise_error
193
- end
194
- end
195
-
196
- context 'when the input is a file' do
197
- it 'yields each chunk of the tarred file' do
198
- chunks = []
199
- subject.copy('/test') { |chunk| chunks << chunk }
200
- chunks = chunks.join("\n")
201
- expect(chunks).to be_include('test')
202
- end
203
- end
204
-
205
- context 'when the input is a directory' do
206
- it 'yields each chunk of the tarred directory' do
207
- chunks = []
208
- subject.copy('/etc/logrotate.d') { |chunk| chunks << chunk }
209
- chunks = chunks.join("\n")
210
- expect(%w[apt dpkg]).to be_all { |file| chunks.include?(file) }
211
- end
212
- end
213
- end
214
-
215
- describe '#archive_in', :docker_1_8 do
216
- let(:license_path) { File.absolute_path(File.join(__FILE__, '..', '..', '..', 'LICENSE')) }
217
- subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ['/bin/sh']) }
218
- let(:committed_image) { subject.commit }
219
- let(:ls_container) { committed_image.run('ls /').tap(&:wait) }
220
- let(:output) { ls_container.streaming_logs(stdout: true, stderr: true) }
221
-
222
- after do
223
- subject.remove
224
- end
225
-
226
- context 'when the input is a tar' do
227
- after do
228
- ls_container.remove
229
- committed_image.remove
230
- end
231
-
232
- it 'file exists in the container' do
233
- subject.archive_in(license_path, '/', overwrite: false)
234
- expect(output).to include('LICENSE')
235
- end
236
- end
237
- end
238
-
239
- describe '#archive_in_stream', :docker_1_8 do
240
- let(:tar) { StringIO.new(Docker::Util.create_tar('/lol' => 'TEST')) }
241
- subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ['/bin/sh']) }
242
- let(:committed_image) { subject.commit }
243
- let(:ls_container) { committed_image.run('ls /').tap(&:wait) }
244
- let(:output) { ls_container.streaming_logs(stdout: true, stderr: true) }
245
-
246
- after do
247
- subject.remove
248
- end
249
-
250
- context 'when the input is a tar' do
251
- after do
252
- ls_container.remove
253
- committed_image.remove
254
- end
255
-
256
- it 'file exists in the container' do
257
- subject.archive_in_stream('/', overwrite: false) { tar.read }
258
- expect(output).to include('lol')
259
- end
260
- end
261
-
262
- context 'when the input would overwrite a directory with a file' do
263
- let(:tar) { StringIO.new(Docker::Util.create_tar('/etc' => 'TEST')) }
264
-
265
- it 'raises an error' do
266
- # Docs say this should return a client error: clearly wrong
267
- # https://docs.docker.com/engine/reference/api/docker_remote_api_v1.21/
268
- # #extract-an-archive-of-files-or-folders-to-a-directory-in-a-container
269
- expect {
270
- subject.archive_in_stream('/', overwrite: false) { tar.read }
271
- }.to raise_error(Docker::Error::ServerError)
272
- end
273
- end
274
- end
275
-
276
- describe '#archive_out', :docker_1_8 do
277
- subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ['touch','/test']) }
278
-
279
- after { subject.remove }
280
-
281
- context 'when the file does not exist' do
282
- it 'raises an error' do
283
- subject.start
284
- subject.wait
285
-
286
- expect { subject.archive_out('/lol') { |chunk| puts chunk } }
287
- .to raise_error(Docker::Error::NotFoundError)
288
- end
289
- end
290
-
291
- context 'when the input is a file' do
292
- it 'yields each chunk of the tarred file' do
293
- subject.start; subject.wait
294
-
295
- chunks = []
296
- subject.archive_out('/test') { |chunk| chunks << chunk }
297
- chunks = chunks.join("\n")
298
- expect(chunks).to be_include('test')
299
- end
300
- end
301
-
302
- context 'when the input is a directory' do
303
- it 'yields each chunk of the tarred directory' do
304
- subject.start; subject.wait
305
-
306
- chunks = []
307
- subject.archive_out('/etc/logrotate.d') { |chunk| chunks << chunk }
308
- chunks = chunks.join("\n")
309
- expect(%w[apt dpkg]).to be_all { |file| chunks.include?(file) }
310
- end
311
- end
312
- end
313
-
314
- describe '#export' do
315
- subject { described_class.create('Cmd' => %w[/true],
316
- 'Image' => 'tianon/true') }
317
- before { subject.start }
318
- after { subject.tap(&:wait).remove }
319
-
320
- it 'yields each chunk' do
321
- first = nil
322
- subject.export do |chunk|
323
- first ||= chunk
324
- end
325
- expect(first[257..261]).to eq "ustar" # Make sure the export is a tar.
326
- end
327
- end
328
-
329
- describe '#attach' do
330
- subject {
331
- described_class.create(
332
- 'Cmd' => ['bash','-c','sleep 2; echo hello'],
333
- 'Image' => 'debian:wheezy'
334
- )
335
- }
336
-
337
- before { subject.start }
338
- after(:each) { subject.stop.remove }
339
-
340
- context 'with normal sized chunks' do
341
- it 'yields each chunk' do
342
- chunk = nil
343
- subject.attach do |stream, c|
344
- chunk ||= c
345
- end
346
- expect(chunk).to eq("hello\n")
347
- end
348
- end
349
-
350
- context 'with very small chunks' do
351
- before do
352
- Docker.options = { :chunk_size => 1 }
353
- end
354
-
355
- after do
356
- Docker.options = {}
357
- end
358
-
359
- it 'yields each chunk' do
360
- chunk = nil
361
- subject.attach do |stream, c|
362
- chunk ||= c
363
- end
364
- expect(chunk).to eq("hello\n")
365
- end
366
- end
367
- end
368
-
369
- describe '#attach with stdin' do
370
- it 'yields the output' do
371
- container = described_class.create(
372
- 'Cmd' => %w[cat],
373
- 'Image' => 'debian:wheezy',
374
- 'OpenStdin' => true,
375
- 'StdinOnce' => true
376
- )
377
- chunk = nil
378
- container
379
- .tap(&:start)
380
- .attach(stdin: StringIO.new("foo\nbar\n")) do |stream, c|
381
- chunk ||= c
382
- end
383
- container.tap(&:wait).remove
384
-
385
- expect(chunk).to eq("foo\nbar\n")
386
- end
387
- end
388
-
389
- describe '#start' do
390
- subject {
391
- described_class.create(
392
- 'Cmd' => %w[test -d /foo],
393
- 'Image' => 'debian:wheezy',
394
- 'Volumes' => {'/foo' => {}}
395
- )
396
- }
397
- let(:all) { Docker::Container.all(all: true) }
398
-
399
- before { subject.start('Binds' => ["/tmp:/foo"]) }
400
- after(:each) { subject.remove }
401
-
402
- it 'starts the container' do
403
- expect(all.map(&:id)).to be_any { |id| id.start_with?(subject.id) }
404
- expect(subject.wait(10)['StatusCode']).to be_zero
405
- end
406
- end
407
-
408
- describe '#stop' do
409
- subject {
410
- described_class.create('Cmd' => %w[true], 'Image' => 'debian:wheezy')
411
- }
412
-
413
- before { subject.tap(&:start).stop('timeout' => '10') }
414
- after { subject.remove }
415
-
416
- it 'stops the container' do
417
- expect(described_class.all(:all => true).map(&:id)).to be_any { |id|
418
- id.start_with?(subject.id)
419
- }
420
- expect(described_class.all.map(&:id)).to be_none { |id|
421
- id.start_with?(subject.id)
422
- }
423
- end
424
- end
425
-
426
- describe '#exec' do
427
- subject {
428
- described_class.create(
429
- 'Cmd' => %w[sleep 20],
430
- 'Image' => 'debian:wheezy'
431
- ).start
432
- }
433
- after { subject.kill!.remove }
434
-
435
- context 'when passed only a command' do
436
- let(:output) { subject.exec(['bash','-c','sleep 2; echo hello']) }
437
-
438
- it 'returns the stdout/stderr messages and exit code' do
439
- expect(output).to eq([["hello\n"], [], 0])
440
- end
441
- end
442
-
443
- context 'when detach is true' do
444
- let(:output) { subject.exec(['date'], detach: true) }
445
-
446
- it 'returns the Docker::Exec object' do
447
- expect(output).to be_a Docker::Exec
448
- expect(output.id).to_not be_nil
449
- end
450
- end
451
-
452
- context 'when passed a block' do
453
- it 'streams the stdout/stderr messages' do
454
- chunk = nil
455
- subject.exec(['bash','-c','sleep 2; echo hello']) do |stream, c|
456
- chunk ||= c
457
- end
458
- expect(chunk).to eq("hello\n")
459
- end
460
- end
461
-
462
- context 'when stdin object is passed' do
463
- let(:output) { subject.exec(['cat'], stdin: StringIO.new("hello")) }
464
-
465
- it 'returns the stdout/stderr messages' do
466
- expect(output).to eq([["hello"],[],0])
467
- end
468
- end
469
-
470
- context 'when tty is true' do
471
- let(:command) { [
472
- "bash", "-c",
473
- "if [ -t 1 ]; then echo -n \"I'm a TTY!\"; fi"
474
- ] }
475
- let(:output) { subject.exec(command, tty: true) }
476
-
477
- it 'returns the raw stdout/stderr output' do
478
- expect(output).to eq([["I'm a TTY!"], [], 0])
479
- end
480
- end
481
- end
482
-
483
- describe '#kill' do
484
- let(:command) { ['/bin/bash', '-c', 'while [ 1 ]; do echo hello; done'] }
485
- subject {
486
- described_class.create('Cmd' => command, 'Image' => 'debian:wheezy')
487
- }
488
-
489
- before { subject.start }
490
- after(:each) {subject.remove }
491
-
492
- it 'kills the container' do
493
- subject.kill
494
- expect(described_class.all.map(&:id)).to be_none { |id|
495
- id.start_with?(subject.id)
496
- }
497
- expect(described_class.all(:all => true).map(&:id)).to be_any { |id|
498
- id.start_with?(subject.id)
499
- }
500
- end
501
-
502
- context 'with a kill signal' do
503
- let(:command) {
504
- [
505
- '/bin/bash',
506
- '-c',
507
- 'trap echo SIGTERM; while [ 1 ]; do echo hello; done'
508
- ]
509
- }
510
- it 'kills the container' do
511
- subject.kill(:signal => "SIGTERM")
512
- expect(described_class.all.map(&:id)).to be_any { |id|
513
- id.start_with?(subject.id)
514
- }
515
- expect(described_class.all(:all => true).map(&:id)).to be_any { |id|
516
- id.start_with?(subject.id)
517
- }
518
-
519
- subject.kill(:signal => "SIGKILL")
520
- expect(described_class.all.map(&:id)).to be_none { |id|
521
- id.start_with?(subject.id)
522
- }
523
- expect(described_class.all(:all => true).map(&:id)).to be_any { |id|
524
- id.start_with?(subject.id)
525
- }
526
- end
527
- end
528
- end
529
-
530
- describe '#delete' do
531
- subject {
532
- described_class.create('Cmd' => ['ls'], 'Image' => 'debian:wheezy')
533
- }
534
-
535
- it 'deletes the container' do
536
- subject.delete(:force => true)
537
- expect(described_class.all.map(&:id)).to be_none { |id|
538
- id.start_with?(subject.id)
539
- }
540
- end
541
- end
542
-
543
- describe '#restart' do
544
- subject {
545
- described_class.create('Cmd' => %w[sleep 10], 'Image' => 'debian:wheezy')
546
- }
547
-
548
- before { subject.start }
549
- after { subject.kill!.remove }
550
-
551
- it 'restarts the container' do
552
- expect(described_class.all.map(&:id)).to be_any { |id|
553
- id.start_with?(subject.id)
554
- }
555
- subject.stop
556
- expect(described_class.all.map(&:id)).to be_none { |id|
557
- id.start_with?(subject.id)
558
- }
559
- subject.restart('timeout' => '10')
560
- expect(described_class.all.map(&:id)).to be_any { |id|
561
- id.start_with?(subject.id)
562
- }
563
- end
564
- end
565
-
566
- describe '#pause' do
567
- subject {
568
- described_class.create(
569
- 'Cmd' => %w[sleep 50],
570
- 'Image' => 'debian:wheezy'
571
- ).start
572
- }
573
- after { subject.unpause.kill!.remove }
574
-
575
- it 'pauses the container' do
576
- subject.pause
577
- expect(described_class.get(subject.id).info['State']['Paused']).to be true
578
- end
579
- end
580
-
581
- describe '#unpause' do
582
- subject {
583
- described_class.create(
584
- 'Cmd' => %w[sleep 50],
585
- 'Image' => 'debian:wheezy'
586
- ).start
587
- }
588
- before { subject.pause }
589
- after { subject.kill!.remove }
590
-
591
- it 'unpauses the container' do
592
- subject.unpause
593
- expect(
594
- described_class.get(subject.id).info['State']['Paused']
595
- ).to be false
596
- end
597
- end
598
-
599
- describe '#wait' do
600
- subject {
601
- described_class.create(
602
- 'Cmd' => %w[tar nonsense],
603
- 'Image' => 'debian:wheezy'
604
- )
605
- }
606
-
607
- before { subject.start }
608
- after(:each) { subject.remove }
609
-
610
- it 'waits for the command to finish' do
611
- expect(subject.wait['StatusCode']).to_not be_zero
612
- end
613
-
614
- context 'when an argument is given' do
615
- subject { described_class.create('Cmd' => %w[sleep 5],
616
- 'Image' => 'debian:wheezy') }
617
-
618
- it 'sets the :read_timeout to that amount of time' do
619
- expect(subject.wait(6)['StatusCode']).to be_zero
620
- end
621
-
622
- context 'and a command runs for too long' do
623
- it 'raises a ServerError' do
624
- expect{subject.wait(4)}.to raise_error(Docker::Error::TimeoutError)
625
- subject.tap(&:wait)
626
- end
627
- end
628
- end
629
- end
630
-
631
- describe '#run' do
632
- let(:run_command) { subject.run('ls') }
633
-
634
- context 'when the Container\'s command does not return status code of 0' do
635
- subject { described_class.create('Cmd' => %w[false],
636
- 'Image' => 'debian:wheezy') }
637
-
638
- after do
639
- subject.remove
640
- end
641
-
642
- it 'raises an error' do
643
- expect { run_command }
644
- .to raise_error(Docker::Error::UnexpectedResponseError)
645
- end
646
- end
647
-
648
- context 'when the Container\'s command returns a status code of 0' do
649
- subject { described_class.create('Cmd' => %w[pwd],
650
- 'Image' => 'debian:wheezy') }
651
- after do
652
- subject.remove
653
- image = run_command.json['Image']
654
- run_command.remove
655
- Docker::Image.get(image).history.each do |layer|
656
- next unless layer['CreatedBy'] == 'pwd'
657
- Docker::Image.get(layer['Id']).remove(:noprune => true)
658
- end
659
- end
660
-
661
- it 'creates a new container to run the specified command' do
662
- expect(run_command.wait['StatusCode']).to be_zero
663
- end
664
- end
665
- end
666
-
667
- describe '#commit' do
668
- subject {
669
- described_class.create('Cmd' => %w[true], 'Image' => 'debian:wheezy')
670
- }
671
- let(:image) { subject.commit }
672
-
673
- after(:each) do
674
- subject.remove
675
- image.remove
676
- end
677
-
678
- it 'creates a new Image from the Container\'s changes' do
679
- subject.tap(&:start).wait
680
-
681
- expect(image).to be_a Docker::Image
682
- expect(image.id).to_not be_nil
683
- end
684
-
685
- context 'if run is passed, it saves the command in the image' do
686
- let(:image) { subject.commit }
687
- let(:container) { image.run('pwd') }
688
-
689
- it 'saves the command' do
690
- container.wait
691
- expect(container.attach(logs: true, stream: false)).to eql [["/\n"],[]]
692
- container.remove
693
- end
694
- end
695
- end
696
-
697
- describe '.create' do
698
- subject { described_class }
699
-
700
- context 'when the Container does not yet exist' do
701
- context 'when the HTTP request does not return a 200' do
702
- before do
703
- Docker.options = { :mock => true }
704
- Excon.stub({ :method => :post }, { :status => 400 })
705
- end
706
- after do
707
- Excon.stubs.shift
708
- Docker.options = {}
709
- end
710
-
711
- it 'raises an error' do
712
- expect { subject.create }.to raise_error(Docker::Error::ClientError)
713
- end
714
- end
715
-
716
- context 'when the HTTP request returns a 200' do
717
- let(:options) do
718
- {
719
- "Cmd" => ["date"],
720
- "Image" => "debian:wheezy",
721
- }
722
- end
723
- let(:container) { subject.create(options) }
724
- after { container.remove }
725
-
726
- it 'sets the id' do
727
- expect(container).to be_a Docker::Container
728
- expect(container.id).to_not be_nil
729
- expect(container.connection).to_not be_nil
730
- end
731
- end
732
- end
733
- end
734
-
735
- describe '.get' do
736
- subject { described_class }
737
-
738
- context 'when the HTTP response is not a 200' do
739
- before do
740
- Docker.options = { :mock => true }
741
- Excon.stub({ :method => :get }, { :status => 500 })
742
- end
743
- after do
744
- Excon.stubs.shift
745
- Docker.options = {}
746
- end
747
-
748
- it 'raises an error' do
749
- expect { subject.get('randomID') }
750
- .to raise_error(Docker::Error::ServerError)
751
- end
752
- end
753
-
754
- context 'when the HTTP response is a 200' do
755
- let(:container) {
756
- subject.create('Cmd' => ['ls'], 'Image' => 'debian:wheezy')
757
- }
758
- after { container.remove }
759
-
760
- it 'materializes the Container into a Docker::Container' do
761
- expect(subject.get(container.id)).to be_a Docker::Container
762
- end
763
- end
764
-
765
- end
766
-
767
- describe '.all' do
768
- subject { described_class }
769
-
770
- context 'when the HTTP response is not a 200' do
771
- before do
772
- Docker.options = { :mock => true }
773
- Excon.stub({ :method => :get }, { :status => 500 })
774
- end
775
- after do
776
- Excon.stubs.shift
777
- Docker.options = {}
778
- end
779
-
780
- it 'raises an error' do
781
- expect { subject.all }
782
- .to raise_error(Docker::Error::ServerError)
783
- end
784
- end
785
-
786
- context 'when the HTTP response is a 200' do
787
- let(:container) {
788
- subject.create('Cmd' => ['ls'], 'Image' => 'debian:wheezy')
789
- }
790
- before { container }
791
- after { container.remove }
792
-
793
- it 'materializes each Container into a Docker::Container' do
794
- expect(subject.all(:all => true)).to be_all { |container|
795
- container.is_a?(Docker::Container)
796
- }
797
- expect(subject.all(:all => true).length).to_not be_zero
798
- end
799
- end
800
- end
801
- end