docker-api 1.27.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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