docker-api 1.27.0 → 2.0.0

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.
@@ -1,89 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Docker::Event do
4
- describe "#to_s" do
5
- subject { described_class.new(status, id, from, time) }
6
-
7
- let(:status) { "start" }
8
- let(:id) { "398c9f77b5d2" }
9
- let(:from) { "debian:wheezy" }
10
- let(:time) { 1381956164 }
11
-
12
- let(:expected_string) {
13
- "Docker::Event { :status => #{status}, :id => #{id}, "\
14
- ":from => #{from}, :time => #{time.to_s} }"
15
- }
16
-
17
- it "equals the expected string" do
18
- expect(subject.to_s).to eq(expected_string)
19
- end
20
- end
21
-
22
- describe ".stream" do
23
- let(:container) { Docker::Image.create('fromImage' => 'debian:wheezy').run('bash') }
24
- it 'receives at least 4 events' do
25
- expect(Docker::Event)
26
- .to receive(:new_event)
27
- .at_least(4).times
28
- .and_call_original
29
-
30
- stream_thread = Thread.new do
31
- Docker::Event.stream do |event|
32
- puts "#{event}"
33
- end
34
- end
35
-
36
- stream_thread.join(0.1)
37
- container.wait
38
- stream_thread.join(10)
39
- stream_thread.kill
40
-
41
- container.remove
42
- end
43
- end
44
-
45
- describe ".since" do
46
- let(:time) { Time.now.to_i + 1 }
47
- let(:container) { Docker::Image.create('fromImage' => 'debian:wheezy').run('bash') }
48
-
49
- it 'receives at least 4 events' do
50
- expect(Docker::Event)
51
- .to receive(:new_event)
52
- .at_least(4).times
53
- .and_call_original
54
-
55
- stream_thread = Thread.new do
56
- Docker::Event.since(time) do |event|
57
- puts "#{event}"
58
- end
59
- end
60
-
61
- stream_thread.join(0.1)
62
- container.wait
63
- stream_thread.join(10)
64
- stream_thread.kill
65
-
66
- container.remove
67
- end
68
- end
69
-
70
- describe ".new_event" do
71
- subject { Docker::Event.new_event(response_body, nil, nil) }
72
- let(:status) { "start" }
73
- let(:id) { "398c9f77b5d2" }
74
- let(:from) { "debian:wheezy" }
75
- let(:time) { 1381956164 }
76
- let(:response_body) {
77
- "{\"status\":\"#{status}\",\"id\":\"#{id}\""\
78
- ",\"from\":\"#{from}\",\"time\":#{time}}"
79
- }
80
-
81
- it "returns a Docker::Event" do
82
- expect(subject).to be_kind_of(Docker::Event)
83
- expect(subject.status).to eq(status)
84
- expect(subject.id).to eq(id)
85
- expect(subject.from).to eq(from)
86
- expect(subject.time).to eq(time)
87
- end
88
- end
89
- end
@@ -1,181 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Docker::Exec do
4
- let(:container) {
5
- Docker::Container.create(
6
- 'Cmd' => %w(sleep 300),
7
- 'Image' => 'debian:wheezy'
8
- ).start!
9
- }
10
-
11
- describe '#to_s' do
12
- subject {
13
- described_class.send(:new, Docker.connection, 'id' => rand(10000).to_s)
14
- }
15
-
16
- let(:id) { 'bf119e2' }
17
- let(:connection) { Docker.connection }
18
- let(:expected_string) {
19
- "Docker::Exec { :id => #{id}, :connection => #{connection} }"
20
- }
21
- before do
22
- {
23
- :@id => id,
24
- :@connection => connection
25
- }.each { |k, v| subject.instance_variable_set(k, v) }
26
- end
27
-
28
- its(:to_s) { should == expected_string }
29
- end
30
-
31
- describe '.create' do
32
- subject { described_class }
33
-
34
- context 'when the HTTP request returns a 201' do
35
- let(:options) do
36
- {
37
- 'AttachStdin' => false,
38
- 'AttachStdout' => false,
39
- 'AttachStderr' => false,
40
- 'Tty' => false,
41
- 'Cmd' => [
42
- 'date'
43
- ],
44
- 'Container' => container.id
45
- }
46
- end
47
- let(:process) { subject.create(options) }
48
- after { container.kill!.remove }
49
-
50
- it 'sets the id' do
51
- expect(process).to be_a Docker::Exec
52
- expect(process.id).to_not be_nil
53
- expect(process.connection).to_not be_nil
54
- end
55
- end
56
-
57
- context 'when the parent container does not exist' do
58
- before do
59
- Docker.options = { :mock => true }
60
- Excon.stub({ :method => :post }, { :status => 404 })
61
- end
62
- after do
63
- Excon.stubs.shift
64
- Docker.options = {}
65
- end
66
-
67
- it 'raises an error' do
68
- expect { subject.create }.to raise_error(Docker::Error::NotFoundError)
69
- end
70
- end
71
- end
72
-
73
- describe '#json' do
74
- subject {
75
- described_class.create(
76
- 'Container' => container.id,
77
- 'Detach' => true,
78
- 'Cmd' => %w[true]
79
- )
80
- }
81
-
82
- let(:description) { subject.json }
83
- before { subject.start! }
84
- after { container.kill!.remove }
85
-
86
- it 'returns the description as a Hash' do
87
- expect(description).to be_a Hash
88
- expect(description['ID']).to start_with(subject.id)
89
- end
90
- end
91
-
92
- describe '#start!' do
93
- context 'when the exec instance does not exist' do
94
- subject do
95
- described_class.send(:new, Docker.connection, 'id' => rand(10000).to_s)
96
- end
97
-
98
- it 'raises an error' do
99
- expect { subject.start! }.to raise_error(Docker::Error::NotFoundError)
100
- end
101
- end
102
-
103
- context 'when :detach is set to false' do
104
- subject {
105
- described_class.create(
106
- 'Container' => container.id,
107
- 'AttachStdout' => true,
108
- 'Cmd' => ['bash','-c','sleep 2; echo hello']
109
- )
110
- }
111
- after { container.kill!.remove }
112
-
113
- it 'returns the stdout and stderr messages' do
114
- expect(subject.start!).to eq([["hello\n"],[],0])
115
- end
116
-
117
- context 'block is passed' do
118
- it 'attaches to the stream' do
119
- chunk = nil
120
- result = subject.start! do |stream, c|
121
- chunk ||= c
122
- end
123
- expect(chunk).to eq("hello\n")
124
- expect(result).to eq([["hello\n"], [], 0])
125
- end
126
- end
127
- end
128
-
129
- context 'when :detach is set to true' do
130
- subject {
131
- described_class.create('Container' => container.id, 'Cmd' => %w[date])
132
- }
133
- after { container.kill!.remove }
134
-
135
- it 'returns empty stdout/stderr messages with exitcode' do
136
- expect(subject.start!(:detach => true).length).to eq(3)
137
- end
138
- end
139
-
140
- context 'when :wait set long time value' do
141
- subject {
142
- described_class.create(
143
- 'Container' => container.id,
144
- 'AttachStdout' => true,
145
- 'Cmd' => %w[true]
146
- )
147
- }
148
- after { container.kill!.remove }
149
-
150
- it 'returns empty stdout and stderr messages with exitcode' do
151
- expect(subject.start!(:wait => 100)).to eq([[], [], 0])
152
- end
153
- end
154
-
155
- context 'when :wait set short time value' do
156
- subject {
157
- described_class.create(
158
- 'Container' => container.id,
159
- 'AttachStdout' => true,
160
- 'Cmd' => ['bash', '-c', 'sleep 2; echo hello']
161
- )
162
- }
163
- after { container.kill!.remove }
164
-
165
- it 'raises an error' do
166
- expect { subject.start!(:wait => 1) }.to raise_error(Docker::Error::TimeoutError)
167
- end
168
- end
169
-
170
- context 'when the HTTP request returns a 201' do
171
- subject {
172
- described_class.create('Container' => container.id, 'Cmd' => ['date'])
173
- }
174
- after { container.kill!.remove }
175
-
176
- it 'starts the exec instance' do
177
- expect { subject.start! }.not_to raise_error
178
- end
179
- end
180
- end
181
- end
@@ -1,683 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Docker::Image do
4
- describe '#to_s' do
5
- subject { described_class.new(Docker.connection, info) }
6
-
7
- let(:id) { 'bf119e2' }
8
- let(:connection) { Docker.connection }
9
-
10
- let(:info) do
11
- {"id" => "bf119e2", "Repository" => "debian", "Tag" => "wheezy",
12
- "Created" => 1364102658, "Size" => 24653, "VirtualSize" => 180116135}
13
- end
14
-
15
- let(:expected_string) do
16
- "Docker::Image { :id => #{id}, :info => #{info.inspect}, "\
17
- ":connection => #{connection} }"
18
- end
19
-
20
- its(:to_s) { should == expected_string }
21
- end
22
-
23
- describe '#remove' do
24
-
25
- context 'when no name is given' do
26
- let(:id) { subject.id }
27
- subject { described_class.create('fromImage' => 'busybox:latest') }
28
- after { described_class.create('fromImage' => 'busybox:latest') }
29
-
30
- it 'removes the Image' do
31
- subject.remove(:force => true)
32
- expect(Docker::Image.all.map(&:id)).to_not include(id)
33
- end
34
- end
35
-
36
- context 'when a valid tag is given' do
37
- it 'untags the Image'
38
- end
39
-
40
- context 'when an invalid tag is given' do
41
- it 'raises an error'
42
- end
43
- end
44
-
45
- describe '#insert_local' do
46
- include_context "local paths"
47
-
48
- subject { described_class.create('fromImage' => 'debian:wheezy') }
49
-
50
- let(:rm) { false }
51
- let(:new_image) {
52
- opts = {'localPath' => file, 'outputPath' => '/'}
53
- opts[:rm] = true if rm
54
- subject.insert_local(opts)
55
- }
56
-
57
- context 'when the local file does not exist' do
58
- let(:file) { '/lol/not/a/file' }
59
-
60
- it 'raises an error' do
61
- expect { new_image }.to raise_error(Docker::Error::ArgumentError)
62
- end
63
- end
64
-
65
- context 'when the local file does exist' do
66
- let(:file) { File.join(project_dir, 'Gemfile') }
67
- let(:gemfile) { File.read('Gemfile') }
68
- let(:container) { new_image.run('cat /Gemfile').tap(&:wait) }
69
- after do
70
- container.remove
71
- new_image.remove
72
- end
73
-
74
- it 'creates a new Image that has that file' do
75
- output = container.streaming_logs(stdout: true)
76
- expect(output).to eq(gemfile)
77
- end
78
- end
79
-
80
- context 'when a direcory is passed' do
81
- let(:new_image) {
82
- subject.insert_local(
83
- 'localPath' => File.join(project_dir, 'lib'),
84
- 'outputPath' => '/lib'
85
- )
86
- }
87
- let(:container) { new_image.run('ls -a /lib/docker') }
88
- let(:response) { container.tap(&:wait).streaming_logs(stdout: true) }
89
- after do
90
- container.tap(&:wait).remove
91
- new_image.remove
92
- end
93
-
94
- it 'inserts the directory' do
95
- expect(response.split("\n").sort).to eq(Dir.entries('lib/docker').sort)
96
- end
97
- end
98
-
99
- context 'when there are multiple files passed' do
100
- let(:file) {
101
- [File.join(project_dir, 'Gemfile'), File.join(project_dir, 'LICENSE')]
102
- }
103
- let(:gemfile) { File.read('Gemfile') }
104
- let(:license) { File.read('LICENSE') }
105
- let(:container) { new_image.run('cat /Gemfile /LICENSE') }
106
- let(:response) {
107
- container.tap(&:wait).streaming_logs(stdout: true)
108
- }
109
- after do
110
- container.remove
111
- new_image.remove
112
- end
113
-
114
- it 'creates a new Image that has each file' do
115
- expect(response).to eq("#{gemfile}#{license}")
116
- end
117
- end
118
-
119
- context 'when removing intermediate containers' do
120
- let(:rm) { true }
121
- let(:file) { File.join(project_dir, 'Gemfile') }
122
- after(:each) { new_image.remove }
123
-
124
- it 'leave no intermediate containers' do
125
- expect { new_image }.to change {
126
- Docker::Container.all(:all => true).count
127
- }.by 0
128
- end
129
-
130
- it 'creates a new image' do
131
- expect{new_image}.to change{Docker::Image.all.count}.by 1
132
- end
133
- end
134
- end
135
-
136
- describe '#push' do
137
- let(:credentials) {
138
- {
139
- 'username' => ENV['DOCKER_API_USER'],
140
- 'password' => ENV['DOCKER_API_PASS'],
141
- 'serveraddress' => 'https://index.docker.io/v1',
142
- 'email' => ENV['DOCKER_API_EMAIL']
143
- }
144
- }
145
- let(:repo_tag) { "#{ENV['DOCKER_API_USER']}/true" }
146
- let(:image) {
147
- described_class.build("FROM tianon/true\n", "t" => repo_tag).refresh!
148
- }
149
- after { image.remove(:name => repo_tag, :noprune => true) }
150
-
151
- it 'pushes the Image' do
152
- image.push(credentials)
153
- end
154
-
155
- it 'streams output from push' do
156
- expect { |b| image.push(credentials, &b) }
157
- .to yield_control.at_least(1)
158
- end
159
-
160
- context 'when a tag is specified' do
161
- it 'pushes that specific tag'
162
- end
163
-
164
- context 'when the image was retrived by get' do
165
- let(:image) {
166
- described_class.build("FROM tianon/true\n", "t" => repo_tag).refresh!
167
- described_class.get(repo_tag)
168
- }
169
-
170
- context 'when no tag is specified' do
171
- it 'looks up the first repo tag' do
172
- expect { image.push }.to_not raise_error
173
- end
174
- end
175
- end
176
-
177
- context 'when there are no credentials' do
178
- let(:credentials) { nil }
179
- let(:repo_tag) { "localhost:5000/true" }
180
-
181
- it 'still pushes' do
182
- expect { image.push }.to_not raise_error
183
- end
184
- end
185
- end
186
-
187
- describe '#tag' do
188
- subject { described_class.create('fromImage' => 'debian:wheezy') }
189
- after { subject.remove(:name => 'teh:latest', :noprune => true) }
190
-
191
- it 'tags the image with the repo name' do
192
- subject.tag(:repo => :teh, :force => true)
193
- expect(subject.info['RepoTags']).to include 'teh:latest'
194
- end
195
- end
196
-
197
- describe '#json' do
198
- subject { described_class.create('fromImage' => 'debian:wheezy') }
199
- let(:json) { subject.json }
200
-
201
- it 'returns additional information about image image' do
202
- expect(json).to be_a Hash
203
- expect(json.length).to_not be_zero
204
- end
205
- end
206
-
207
- describe '#history' do
208
- subject { described_class.create('fromImage' => 'debian:wheezy') }
209
- let(:history) { subject.history }
210
-
211
- it 'returns the history of the Image' do
212
- expect(history).to be_a Array
213
- expect(history.length).to_not be_zero
214
- expect(history).to be_all { |elem| elem.is_a? Hash }
215
- end
216
- end
217
-
218
- describe '#run' do
219
- subject { described_class.create('fromImage' => 'debian:wheezy') }
220
- let(:container) { subject.run(cmd).tap(&:wait) }
221
- let(:output) { container.streaming_logs(stdout: true) }
222
-
223
- context 'when the argument is a String' do
224
- let(:cmd) { 'ls /lib64/' }
225
- after { container.remove }
226
-
227
- it 'splits the String by spaces and creates a new Container' do
228
- expect(output).to eq("ld-linux-x86-64.so.2\n")
229
- end
230
- end
231
-
232
- context 'when the argument is an Array' do
233
- let(:cmd) { %w[which pwd] }
234
- after { container.remove }
235
-
236
- it 'creates a new Container' do
237
- expect(output).to eq("/bin/pwd\n")
238
- end
239
- end
240
-
241
- context 'when the argument is nil' do
242
- let(:cmd) { nil }
243
- context 'no command configured in image' do
244
- subject { described_class.create('fromImage' => 'swipely/base') }
245
- it 'should raise an error if no command is specified' do
246
- expect {container}.to raise_error(Docker::Error::ServerError,
247
- "No command specified.")
248
- end
249
- end
250
-
251
- context "command configured in image" do
252
- let(:cmd) { 'pwd' }
253
- after { container.remove }
254
-
255
- it 'should normally show result if image has Cmd configured' do
256
- expect(output).to eql "/\n"
257
- end
258
- end
259
- end
260
- end
261
-
262
- describe '#save' do
263
- let(:image) { Docker::Image.get('busybox') }
264
-
265
- it 'calls the class method' do
266
- expect(Docker::Image).to receive(:save)
267
- .with(image.id, 'busybox.tar', anything)
268
- image.save('busybox.tar')
269
- end
270
- end
271
-
272
- describe '#save_stream' do
273
- let(:image) { Docker::Image.get('busybox') }
274
- let(:block) { proc { |chunk| puts chunk } }
275
-
276
- it 'calls the class method' do
277
- expect(Docker::Image).to receive(:save_stream)
278
- .with(image.id, instance_of(Hash), instance_of(Docker::Connection))
279
- image.save_stream(:chunk_size => 1024 * 1024, &block)
280
- end
281
- end
282
-
283
- describe '#load' do
284
- include_context "local paths"
285
- let(:file) { File.join(project_dir, 'spec', 'fixtures', 'load.tar') }
286
- context 'test image upload' do
287
- it 'load tianon/true image' do
288
- result = Docker::Image.load(file)
289
- expect(result).to eq("")
290
- end
291
- end
292
- end
293
-
294
- describe '#refresh!' do
295
- let(:image) { Docker::Image.create('fromImage' => 'debian:wheezy') }
296
-
297
- it 'updates the @info hash' do
298
- size = image.info.size
299
- image.refresh!
300
- expect(image.info.size).to be > size
301
- end
302
-
303
- context 'with an explicit connection' do
304
- let(:connection) { Docker::Connection.new(Docker.url, Docker.options) }
305
- let(:image) {
306
- Docker::Image.create({'fromImage' => 'debian:wheezy'}, nil, connection)
307
- }
308
-
309
- it 'updates using the provided connection' do
310
- image.refresh!
311
- end
312
- end
313
- end
314
-
315
- describe '.create' do
316
- subject { described_class }
317
-
318
- context 'when the Image does not yet exist and the body is a Hash' do
319
- let(:image) { subject.create('fromImage' => 'swipely/base') }
320
- let(:creds) {
321
- {
322
- :username => ENV['DOCKER_API_USER'],
323
- :password => ENV['DOCKER_API_PASS'],
324
- :email => ENV['DOCKER_API_EMAIL']
325
- }
326
- }
327
-
328
- before do
329
- Docker::Image.create('fromImage' => 'swipely/base').remove
330
- end
331
- after { Docker::Image.create('fromImage' => 'swipely/base') }
332
-
333
- it 'sets the id and sends Docker.creds' do
334
- allow(Docker).to receive(:creds).and_return(creds)
335
- expect(image).to be_a Docker::Image
336
- expect(image.id).to match(/\A(sha256:)?[a-fA-F0-9]+\Z/)
337
- expect(image.id).to_not include('base')
338
- expect(image.id).to_not be_nil
339
- expect(image.id).to_not be_empty
340
- end
341
- end
342
-
343
- context 'with a block capturing create output' do
344
- let(:create_output) { "" }
345
- let(:block) { Proc.new { |chunk| create_output << chunk } }
346
-
347
- before do
348
- Docker.creds = nil
349
- subject.create('fromImage' => 'tianon/true').remove
350
- end
351
-
352
- it 'calls the block and passes build output' do
353
- subject.create('fromImage' => 'tianon/true', &block)
354
- expect(create_output).to match(/Pulling.*tianon\/true/)
355
- end
356
- end
357
- end
358
-
359
- describe '.get' do
360
- subject { described_class }
361
- let(:image) { subject.get(image_name) }
362
-
363
- context 'when the image does exist' do
364
- let(:image_name) { 'debian:wheezy' }
365
-
366
- it 'returns the new image' do
367
- expect(image).to be_a Docker::Image
368
- end
369
- end
370
-
371
- context 'when the image does not exist' do
372
- let(:image_name) { 'abcdefghijkl' }
373
-
374
- before do
375
- Docker.options = { :mock => true }
376
- Excon.stub({ :method => :get }, { :status => 404 })
377
- end
378
-
379
- after do
380
- Docker.options = {}
381
- Excon.stubs.shift
382
- end
383
-
384
- it 'raises a not found error' do
385
- expect { image }.to raise_error(Docker::Error::NotFoundError)
386
- end
387
- end
388
- end
389
-
390
- describe '.save' do
391
- include_context "local paths"
392
-
393
- context 'when a filename is specified' do
394
- let(:file) { "#{project_dir}/scratch.tar" }
395
- after { FileUtils.remove(file) }
396
-
397
- it 'exports tarball of image to specified file' do
398
- Docker::Image.save('swipely/base', file)
399
- expect(File.exist?(file)).to eq true
400
- expect(File.read(file)).to_not be_nil
401
- end
402
- end
403
-
404
- context 'when no filename is specified' do
405
- it 'returns raw binary data as string' do
406
- raw = Docker::Image.save('swipely/base')
407
- expect(raw).to_not be_nil
408
- end
409
- end
410
- end
411
-
412
- describe '.save_stream' do
413
- let(:image) { 'busybox:latest' }
414
- let(:non_streamed) do
415
- Docker.connection.get(
416
- '/images/get',
417
- 'names' => URI.encode(image)
418
- )
419
- end
420
- let(:streamed) { '' }
421
- let(:tar_files) do
422
- proc do |string|
423
- Gem::Package::TarReader
424
- .new(StringIO.new(string, 'rb'))
425
- .map(&:full_name)
426
- .sort
427
- end
428
- end
429
-
430
- it 'yields each chunk of the image' do
431
- Docker::Image.save_stream(image) { |chunk| streamed << chunk }
432
- expect(tar_files.call(streamed)).to eq(tar_files.call(non_streamed))
433
- end
434
- end
435
-
436
- describe '.exist?' do
437
- subject { described_class }
438
- let(:exists) { subject.exist?(image_name) }
439
-
440
- context 'when the image does exist' do
441
- let(:image_name) { 'debian:wheezy' }
442
-
443
- it 'returns true' do
444
- expect(exists).to eq(true)
445
- end
446
- end
447
-
448
- context 'when the image does not exist' do
449
- let(:image_name) { 'abcdefghijkl' }
450
-
451
- before do
452
- Docker.options = { :mock => true }
453
- Excon.stub({ :method => :get }, { :status => 404 })
454
- end
455
-
456
- after do
457
- Docker.options = {}
458
- Excon.stubs.shift
459
- end
460
-
461
- it 'return false' do
462
- expect(exists).to eq(false)
463
- end
464
- end
465
- end
466
-
467
- describe '.import' do
468
- include_context "local paths"
469
-
470
- subject { described_class }
471
-
472
- context 'when the file does not exist' do
473
- let(:file) { '/lol/not/a/file' }
474
-
475
- it 'raises an error' do
476
- expect { subject.import(file) }
477
- .to raise_error(Docker::Error::IOError)
478
- end
479
- end
480
-
481
- context 'when the file does exist' do
482
- let(:file) { File.join(project_dir, 'spec', 'fixtures', 'export.tar') }
483
- let(:import) { subject.import(file) }
484
- after { import.remove(:noprune => true) }
485
-
486
- it 'creates the Image' do
487
- expect(import).to be_a Docker::Image
488
- expect(import.id).to_not be_nil
489
- end
490
- end
491
-
492
- context 'when the argument is a URI' do
493
- context 'when the URI is invalid' do
494
- it 'raises an error' do
495
- expect { subject.import('http://google.com') }
496
- .to raise_error(Docker::Error::IOError)
497
- end
498
- end
499
-
500
- context 'when the URI is valid' do
501
- let(:uri) { 'http://swipely-pub.s3.amazonaws.com/tianon_true.tar' }
502
- let(:import) { subject.import(uri) }
503
- after { import.remove(:noprune => true) }
504
-
505
- it 'returns an Image' do
506
- expect(import).to be_a Docker::Image
507
- expect(import.id).to_not be_nil
508
- end
509
- end
510
- end
511
- end
512
-
513
- describe '.all' do
514
- subject { described_class }
515
-
516
- let(:images) { subject.all(:all => true) }
517
- before { subject.create('fromImage' => 'debian:wheezy') }
518
-
519
- it 'materializes each Image into a Docker::Image' do
520
- images.each do |image|
521
- expect(image).to_not be_nil
522
-
523
- expect(image).to be_a(described_class)
524
-
525
- expect(image.id).to_not be_nil
526
-
527
- %w(Created Size VirtualSize).each do |key|
528
- expect(image.info).to have_key(key)
529
- end
530
- end
531
-
532
- expect(images.length).to_not be_zero
533
- end
534
- end
535
-
536
- describe '.search' do
537
- subject { described_class }
538
-
539
- it 'materializes each Image into a Docker::Image' do
540
- expect(subject.search('term' => 'sshd')).to be_all { |image|
541
- !image.id.nil? && image.is_a?(described_class)
542
- }
543
- end
544
- end
545
-
546
- describe '.build' do
547
- subject { described_class }
548
- context 'with an invalid Dockerfile' do
549
- it 'throws a UnexpectedResponseError' do
550
- expect { subject.build('lololol') }
551
- .to raise_error(Docker::Error::UnexpectedResponseError)
552
- end
553
- end
554
-
555
- context 'with a valid Dockerfile' do
556
- context 'without query parameters' do
557
- let(:image) { subject.build("FROM debian:wheezy\n") }
558
-
559
- it 'builds an image' do
560
- expect(image).to be_a Docker::Image
561
- expect(image.id).to_not be_nil
562
- expect(image.connection).to be_a Docker::Connection
563
- end
564
- end
565
-
566
- context 'with specifying a repo in the query parameters' do
567
- let(:image) {
568
- subject.build(
569
- "FROM debian:wheezy\nRUN true\n",
570
- "t" => "#{ENV['DOCKER_API_USER']}/debian:true"
571
- )
572
- }
573
- after { image.remove(:noprune => true) }
574
-
575
- it 'builds an image and tags it' do
576
- expect(image).to be_a Docker::Image
577
- expect(image.id).to_not be_nil
578
- expect(image.connection).to be_a Docker::Connection
579
- image.refresh!
580
- expect(image.info["RepoTags"]).to eq(
581
- ["#{ENV['DOCKER_API_USER']}/debian:true"]
582
- )
583
- end
584
- end
585
-
586
- context 'with a block capturing build output' do
587
- let(:build_output) { "" }
588
- let(:block) { Proc.new { |chunk| build_output << chunk } }
589
- let!(:image) { subject.build("FROM debian:wheezy\n", &block) }
590
-
591
- it 'calls the block and passes build output' do
592
- expect(build_output).to match(/Step \d : FROM debian:wheezy/)
593
- end
594
- end
595
- end
596
- end
597
-
598
- describe '.build_from_dir' do
599
- subject { described_class }
600
-
601
- context 'with a valid Dockerfile' do
602
- let(:dir) {
603
- File.join(File.dirname(__FILE__), '..', 'fixtures', 'build_from_dir')
604
- }
605
- let(:docker_file) { File.new("#{dir}/Dockerfile") }
606
- let(:image) { subject.build_from_dir(dir, opts, &block) }
607
- let(:opts) { {} }
608
- let(:block) { Proc.new {} }
609
- let(:container) do
610
- Docker::Container.create(
611
- 'Image' => image.id,
612
- 'Cmd' => %w[cat /Dockerfile]
613
- ).tap(&:start).tap(&:wait)
614
- end
615
- let(:output) { container.streaming_logs(stdout: true) }
616
-
617
- after(:each) do
618
- container.remove
619
- image.remove(:noprune => true)
620
- end
621
-
622
- context 'with no query parameters' do
623
- it 'builds the image' do
624
- expect(output).to eq(docker_file.read)
625
- end
626
- end
627
-
628
- context 'with specifying a repo in the query parameters' do
629
- let(:opts) { { "t" => "#{ENV['DOCKER_API_USER']}/debian:from_dir" } }
630
- it 'builds the image and tags it' do
631
- expect(output).to eq(docker_file.read)
632
- image.refresh!
633
- expect(image.info["RepoTags"]).to eq(
634
- ["#{ENV['DOCKER_API_USER']}/debian:from_dir"]
635
- )
636
- end
637
- end
638
-
639
- context 'with a block capturing build output' do
640
- let(:build_output) { "" }
641
- let(:block) { Proc.new { |chunk| build_output << chunk } }
642
-
643
- it 'calls the block and passes build output' do
644
- image # Create the image variable, which is lazy-loaded by Rspec
645
- expect(build_output).to match(/Step \d : FROM debian:wheezy/)
646
- end
647
-
648
- context 'uses a cached version the second time' do
649
- let(:build_output_two) { "" }
650
- let(:block_two) { Proc.new { |chunk| build_output_two << chunk } }
651
- let(:image_two) { subject.build_from_dir(dir, opts, &block_two) }
652
-
653
- it 'calls the block and passes build output' do
654
- image # Create the image variable, which is lazy-loaded by Rspec
655
- expect(build_output).to match(/Step \d : FROM debian:wheezy/)
656
- expect(build_output).to_not match(/Using cache/)
657
-
658
- image_two # Create the image_two variable, which is lazy-loaded by Rspec
659
- expect(build_output_two).to match(/Using cache/)
660
- end
661
- end
662
- end
663
-
664
- context 'with credentials passed' do
665
- let(:creds) {
666
- {
667
- :username => ENV['DOCKER_API_USER'],
668
- :password => ENV['DOCKER_API_PASS'],
669
- :email => ENV['DOCKER_API_EMAIL'],
670
- :serveraddress => 'https://index.docker.io/v1'
671
- }
672
- }
673
-
674
- before { Docker.creds = creds }
675
- after { Docker.creds = nil }
676
-
677
- it 'sends X-Registry-Config header' do
678
- expect(image.info[:headers].keys).to include('X-Registry-Config')
679
- end
680
- end
681
- end
682
- end
683
- end