dockly 3.3.0 → 4.2.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.
- checksums.yaml +5 -13
- data/.ruby-version +1 -1
- data/.travis.yml +5 -6
- data/README.md +22 -0
- data/dockly.gemspec +6 -3
- data/lib/dockly.rb +3 -1
- data/lib/dockly/bash_builder.rb +2 -1
- data/lib/dockly/build_cache/docker.rb +1 -1
- data/lib/dockly/deb.rb +51 -23
- data/lib/dockly/docker.rb +27 -7
- data/lib/dockly/docker/ecr.rb +60 -0
- data/lib/dockly/version.rb +2 -2
- data/snippets/auth_ecr.erb +11 -0
- data/snippets/docker_tag_latest.erb +1 -1
- data/spec/dockly/bash_builder_spec.rb +2 -2
- data/spec/dockly/build_cache/base_spec.rb +18 -8
- data/spec/dockly/build_cache/docker_spec.rb +1 -1
- data/spec/dockly/deb_spec.rb +52 -12
- data/spec/dockly/docker/ecr_spec.rb +80 -0
- data/spec/dockly/docker_spec.rb +179 -4
- data/spec/dockly/foreman_spec.rb +3 -3
- data/spec/dockly/rpm_spec.rb +31 -11
- metadata +98 -51
@@ -156,7 +156,7 @@ describe Dockly::BuildCache::Docker, :docker do
|
|
156
156
|
context "when parameter command returns successfully" do
|
157
157
|
let(:command) { "uname -r" }
|
158
158
|
it 'returns the output of the parameter_command' do
|
159
|
-
expect(build_cache.parameter_output(command)).to match(/\
|
159
|
+
expect(build_cache.parameter_output(command)).to match(/\A\d.\d.\d+-\w+-\w+\z/)
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
data/spec/dockly/deb_spec.rb
CHANGED
@@ -175,6 +175,25 @@ describe Dockly::Deb do
|
|
175
175
|
expect(`dpkg --contents #{filename}`).to_not include("dockly-startup.sh")
|
176
176
|
end
|
177
177
|
end
|
178
|
+
|
179
|
+
context 'when package_startup_script is a string' do
|
180
|
+
context 'when the string is empty' do
|
181
|
+
before { subject.package_startup_script('') }
|
182
|
+
|
183
|
+
it 'does not place a startup script with the provided name in the package' do
|
184
|
+
expect{subject.create_package!}.to raise_error(ArgumentError)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'when the string is not empty' do
|
189
|
+
before { subject.package_startup_script('special-startup.sh') }
|
190
|
+
|
191
|
+
it 'places a startup script with the provided name in the package' do
|
192
|
+
subject.create_package!
|
193
|
+
expect(`dpkg --contents #{filename}`).to include("special-startup.sh")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
178
197
|
end
|
179
198
|
|
180
199
|
describe '#exists?' do
|
@@ -186,14 +205,19 @@ describe Dockly::Deb do
|
|
186
205
|
pre_install "ls"
|
187
206
|
post_install "rd /s /q C:\*"
|
188
207
|
build_dir 'build/deb/s3'
|
208
|
+
s3_bucket 'bucket'
|
189
209
|
end
|
190
210
|
end
|
191
211
|
|
192
212
|
context 'when the object does exist' do
|
193
213
|
before do
|
194
|
-
allow(Dockly
|
195
|
-
.to receive(:
|
196
|
-
.and_return(
|
214
|
+
allow(Dockly)
|
215
|
+
.to receive(:s3)
|
216
|
+
.and_return(
|
217
|
+
Aws::S3::Client.new(
|
218
|
+
stub_responses: { :head_object => {} }
|
219
|
+
)
|
220
|
+
)
|
197
221
|
end
|
198
222
|
|
199
223
|
it 'is true' do
|
@@ -203,12 +227,16 @@ describe Dockly::Deb do
|
|
203
227
|
|
204
228
|
context 'when the object does not exist' do
|
205
229
|
before do
|
206
|
-
allow(Dockly
|
207
|
-
.to receive(:
|
208
|
-
.
|
230
|
+
allow(Dockly)
|
231
|
+
.to receive(:s3)
|
232
|
+
.and_return(
|
233
|
+
Aws::S3::Client.new(
|
234
|
+
stub_responses: { :head_object => 'ObjectDoesNotExist' }
|
235
|
+
)
|
236
|
+
)
|
209
237
|
end
|
210
238
|
|
211
|
-
it 'is
|
239
|
+
it 'is false' do
|
212
240
|
expect(subject.exists?).to be_false
|
213
241
|
end
|
214
242
|
end
|
@@ -248,12 +276,24 @@ describe Dockly::Deb do
|
|
248
276
|
context 'when the package has been created' do
|
249
277
|
before { subject.create_package! }
|
250
278
|
|
279
|
+
let(:client) do
|
280
|
+
client = Aws::S3::Client.new(stub_responses: true)
|
281
|
+
client.stub_responses(
|
282
|
+
:put_object, ->(context) do
|
283
|
+
expect(context.params[:bucket]).to eq(bucket_name)
|
284
|
+
expect(context.params[:key]).to eq(subject.s3_object_name)
|
285
|
+
expect(context.params).to have_key(:body)
|
286
|
+
|
287
|
+
{}
|
288
|
+
end
|
289
|
+
)
|
290
|
+
client
|
291
|
+
end
|
292
|
+
|
251
293
|
it 'inserts the deb package into that bucket' do
|
252
|
-
expect(Dockly
|
253
|
-
|
254
|
-
|
255
|
-
expect(hash).to have_key(:body)
|
256
|
-
end
|
294
|
+
expect(Dockly)
|
295
|
+
.to receive(:s3)
|
296
|
+
.and_return(client)
|
257
297
|
|
258
298
|
subject.upload_to_s3
|
259
299
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dockly::Docker::ECR do
|
4
|
+
subject do
|
5
|
+
described_class.new(name: 'ecr', server_address: registry)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:username) { 'AWS' }
|
9
|
+
let(:password) { 'password' }
|
10
|
+
let(:registry) { 'accountid.dkr.ecr.region.amazonaws.com' }
|
11
|
+
let(:endpoint) { "https://#{registry}" }
|
12
|
+
let(:ecr_client) { Aws::ECR::Client.new(stub_responses: true) }
|
13
|
+
|
14
|
+
after do
|
15
|
+
Aws.config[:ecr] = { stub_responses: {} }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#authenticate!' do
|
19
|
+
context 'when AWS provides a username and password for ECR' do
|
20
|
+
before do
|
21
|
+
Aws.config[:ecr] = {
|
22
|
+
stub_responses: {
|
23
|
+
get_authorization_token: {
|
24
|
+
authorization_data: [
|
25
|
+
{
|
26
|
+
authorization_token: Base64.encode64("#{username}:#{password}"),
|
27
|
+
proxy_endpoint: endpoint
|
28
|
+
}
|
29
|
+
]
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'and docker auth succeeds' do
|
36
|
+
before do
|
37
|
+
allow(::Docker)
|
38
|
+
.to receive(:authenticate!)
|
39
|
+
.with({
|
40
|
+
'serveraddress' => endpoint,
|
41
|
+
'username' => username,
|
42
|
+
'password' => password
|
43
|
+
})
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'does not error' do
|
47
|
+
expect { subject.authenticate! }.to_not raise_error
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'and docker auth raises and error' do
|
52
|
+
before do
|
53
|
+
allow(::Docker)
|
54
|
+
.to receive(:authenticate!)
|
55
|
+
.and_raise(::Docker::Error::AuthenticationError)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'raises' do
|
59
|
+
expect { subject.authenticate! }
|
60
|
+
.to raise_error(/Could not authenticate/)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when it is unable to get auth from AWS' do
|
67
|
+
before do
|
68
|
+
Aws.config[:ecr] = {
|
69
|
+
stub_responses: {
|
70
|
+
get_authorization_token: ->(_context) { raise 'Unable to get token' }
|
71
|
+
}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'raises' do
|
76
|
+
expect(::Docker).not_to receive(:authenticate!)
|
77
|
+
expect { subject.authenticate! }.to raise_error
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/spec/dockly/docker_spec.rb
CHANGED
@@ -3,6 +3,76 @@ require 'spec_helper'
|
|
3
3
|
describe Dockly::Docker do
|
4
4
|
subject { described_class.new(:name => :test_docker) }
|
5
5
|
|
6
|
+
describe '#registry' do
|
7
|
+
context 'when there is no registry' do
|
8
|
+
it 'returns nil' do
|
9
|
+
expect(subject.registry).to eq(nil)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when there is only an ecr registry' do
|
14
|
+
subject do
|
15
|
+
Dockly::Docker.new do
|
16
|
+
ecr { server_address 'accountid.dkr.ecr.region.amazonaws.com' }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns an ecr registry' do
|
21
|
+
registry = subject.registry
|
22
|
+
|
23
|
+
expect(registry).not_to eq(nil)
|
24
|
+
expect(registry).to be_a(Dockly::Docker::ECR)
|
25
|
+
expect(registry.server_address)
|
26
|
+
.to eq('accountid.dkr.ecr.region.amazonaws.com')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when there is a docker registry' do
|
31
|
+
context 'and an ecr registry' do
|
32
|
+
subject do
|
33
|
+
Dockly::Docker.new do
|
34
|
+
registry do
|
35
|
+
username ENV['DOCKER_USER']
|
36
|
+
email ENV['DOCKER_EMAIL']
|
37
|
+
password ENV['DOCKER_PASS']
|
38
|
+
end
|
39
|
+
|
40
|
+
ecr { server_address 'accountid.dkr.ecr.region.amazonaws.com' }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'prefers the ecr registry' do
|
45
|
+
registry = subject.registry
|
46
|
+
|
47
|
+
expect(registry).not_to eq(nil)
|
48
|
+
expect(registry).to be_a(Dockly::Docker::ECR)
|
49
|
+
expect(registry.server_address)
|
50
|
+
.to eq('accountid.dkr.ecr.region.amazonaws.com')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'and only a docker registry' do
|
55
|
+
subject do
|
56
|
+
Dockly::Docker.new do
|
57
|
+
registry do
|
58
|
+
username ENV['DOCKER_USER']
|
59
|
+
email ENV['DOCKER_EMAIL']
|
60
|
+
password ENV['DOCKER_PASS']
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns the docker registry' do
|
65
|
+
registry = subject.registry
|
66
|
+
|
67
|
+
expect(registry).not_to eq(nil)
|
68
|
+
expect(registry).to be_a(Dockly::Docker::Registry)
|
69
|
+
expect(registry.username).to eq(ENV['DOCKER_USER'])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
6
76
|
describe '#ensure_tar' do
|
7
77
|
let(:action) { subject.ensure_tar(file) }
|
8
78
|
|
@@ -134,11 +204,15 @@ describe Dockly::Docker do
|
|
134
204
|
let(:url) { 's3://bucket/object' }
|
135
205
|
let(:data) { 'sweet, sweet data' }
|
136
206
|
|
207
|
+
let(:client) { double() }
|
208
|
+
|
137
209
|
before do
|
138
|
-
allow(
|
210
|
+
allow(client)
|
139
211
|
.to receive(:get_object)
|
140
|
-
.with(bucket: 'bucket', key: 'object')
|
212
|
+
.with(hash_including({ bucket: 'bucket', key: 'object' }))
|
141
213
|
.and_yield(data)
|
214
|
+
|
215
|
+
allow(Dockly).to receive(:s3).and_return(client)
|
142
216
|
end
|
143
217
|
|
144
218
|
it 'pulls the file from S3' do
|
@@ -147,7 +221,7 @@ describe Dockly::Docker do
|
|
147
221
|
end
|
148
222
|
|
149
223
|
context 'and it points to a non-S3 url' do
|
150
|
-
let(:url) { 'http://
|
224
|
+
let(:url) { 'http://html5zombo.com' }
|
151
225
|
|
152
226
|
before { subject.tag 'yolo' }
|
153
227
|
|
@@ -172,7 +246,7 @@ describe Dockly::Docker do
|
|
172
246
|
context "with a registry export" do
|
173
247
|
let(:registry) { double(:registry) }
|
174
248
|
before do
|
175
|
-
subject.instance_variable_set(:"@
|
249
|
+
subject.instance_variable_set(:"@docker_registry", registry)
|
176
250
|
expect(subject).to receive(:push_to_registry)
|
177
251
|
end
|
178
252
|
|
@@ -243,6 +317,107 @@ describe Dockly::Docker do
|
|
243
317
|
end
|
244
318
|
end
|
245
319
|
|
320
|
+
describe '#push_to_registry', :docker do
|
321
|
+
let(:image) { Docker::Image.create('fromImage' => 'ubuntu:14.04') }
|
322
|
+
let(:ecr) { double(:ecr) }
|
323
|
+
|
324
|
+
context 'when there is no registry' do
|
325
|
+
it 'raises' do
|
326
|
+
expect(subject.registry).to eq(nil)
|
327
|
+
|
328
|
+
expect { subject.push_to_registry(image) }.to raise_error(/No registry/)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
context 'when there is a registry' do
|
333
|
+
before do
|
334
|
+
subject.instance_variable_set(:"@ecr", ecr)
|
335
|
+
|
336
|
+
allow(ecr)
|
337
|
+
.to receive(:server_address)
|
338
|
+
.and_return('server_address')
|
339
|
+
|
340
|
+
expect(subject.registry).to eq(ecr)
|
341
|
+
end
|
342
|
+
|
343
|
+
context "that can't be authenticated to" do
|
344
|
+
before do
|
345
|
+
allow(ecr)
|
346
|
+
.to receive(:authenticate!)
|
347
|
+
.and_raise
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'raises' do
|
351
|
+
expect { subject.push_to_registry(image) }
|
352
|
+
.to raise_error(StandardError)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
context 'that can be authenticated to' do
|
357
|
+
before do
|
358
|
+
allow(ecr).to receive(:authenticate!)
|
359
|
+
|
360
|
+
allow(Docker::Image)
|
361
|
+
.to receive(:all)
|
362
|
+
.with(all: true)
|
363
|
+
.and_return(available_images)
|
364
|
+
end
|
365
|
+
|
366
|
+
context "but the image isn't found" do
|
367
|
+
let(:available_images) { [] }
|
368
|
+
|
369
|
+
it 'raises' do
|
370
|
+
expect { subject.push_to_registry(image) }
|
371
|
+
.to raise_error(/Could not find image after authentication/)
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
context 'and the image is found' do
|
376
|
+
let(:available_images) { [image] }
|
377
|
+
|
378
|
+
before do
|
379
|
+
allow(ecr)
|
380
|
+
.to receive(:to_h)
|
381
|
+
.and_return({})
|
382
|
+
allow(image)
|
383
|
+
.to receive(:push)
|
384
|
+
.and_yield(push_message)
|
385
|
+
end
|
386
|
+
|
387
|
+
context 'but the push to the registry fails' do
|
388
|
+
let(:push_message) do
|
389
|
+
<<-EOF
|
390
|
+
{"errorDetail":{"message":"name unknown: The repository with name 'repository'
|
391
|
+
does not exist in the registry with id 'accoundid'"},"error":"name unknown:
|
392
|
+
The repository with name 'repository' does not exist in the registry with id 'accountid'"}
|
393
|
+
EOF
|
394
|
+
end
|
395
|
+
|
396
|
+
it 'raises' do
|
397
|
+
expect { subject.push_to_registry(image) }
|
398
|
+
.to raise_error(/Error pushing to registry/)
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
context 'and the push to the registry succeeds' do
|
403
|
+
let(:push_message) do
|
404
|
+
<<-EOF
|
405
|
+
{"status":"Pushed","progressDetail":{},"id":"id"}
|
406
|
+
{"status":"sha: digest: digest size: 2048"}
|
407
|
+
{"progressDetail":{},"aux":{"Tag":"sha","Digest":"digest","Size":2048}}
|
408
|
+
EOF
|
409
|
+
end
|
410
|
+
|
411
|
+
it 'passes' do
|
412
|
+
expect(subject.push_to_registry(image))
|
413
|
+
.not_to raise_error
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
246
421
|
describe '#export_image_diff', :docker do
|
247
422
|
let(:images) { [] }
|
248
423
|
let(:output) { StringIO.new }
|
data/spec/dockly/foreman_spec.rb
CHANGED
@@ -29,9 +29,9 @@ describe Dockly::Foreman do
|
|
29
29
|
subject.create!
|
30
30
|
File.exist?('build/foreman/foreman.target').should be_true
|
31
31
|
File.exist?('build/foreman/foreman-web.target').should be_true
|
32
|
-
File.exist?('build/foreman/foreman-web
|
33
|
-
File.
|
34
|
-
.
|
32
|
+
File.exist?('build/foreman/foreman-web@.service').should be_true
|
33
|
+
File.open('build/foreman/foreman-web@.service')
|
34
|
+
.grep(/^ExecStart=\/bin\/bash -lc 'exec \/bin\/sh start_my_server'$/)
|
35
35
|
.length.should == 1
|
36
36
|
end
|
37
37
|
end
|
data/spec/dockly/rpm_spec.rb
CHANGED
@@ -11,6 +11,7 @@ describe Dockly::Rpm do
|
|
11
11
|
pre_install "ls"
|
12
12
|
post_install "rd /s /q C:\*"
|
13
13
|
build_dir 'build'
|
14
|
+
s3_bucket 'bucket'
|
14
15
|
end
|
15
16
|
end
|
16
17
|
let(:filename) { "build/rpm/my-sweet-rpm_77.0.8_x86_64.rpm" }
|
@@ -173,14 +174,17 @@ describe Dockly::Rpm do
|
|
173
174
|
pre_install "ls"
|
174
175
|
post_install "rd /s /q C:\*"
|
175
176
|
build_dir 'build/rpm/s3'
|
177
|
+
s3_bucket 'bucket'
|
176
178
|
end
|
177
179
|
end
|
178
180
|
|
179
181
|
context 'when the object does exist' do
|
180
182
|
before do
|
181
|
-
allow(Dockly
|
182
|
-
.to receive(:
|
183
|
-
.and_return(
|
183
|
+
allow(Dockly)
|
184
|
+
.to receive(:s3)
|
185
|
+
.and_return(
|
186
|
+
Aws::S3::Client.new(stub_responses: true)
|
187
|
+
)
|
184
188
|
end
|
185
189
|
|
186
190
|
it 'is true' do
|
@@ -190,9 +194,13 @@ describe Dockly::Rpm do
|
|
190
194
|
|
191
195
|
context 'when the object does not exist' do
|
192
196
|
before do
|
193
|
-
allow(Dockly
|
194
|
-
.to receive(:
|
195
|
-
.
|
197
|
+
allow(Dockly)
|
198
|
+
.to receive(:s3)
|
199
|
+
.and_return(
|
200
|
+
Aws::S3::Client.new(
|
201
|
+
stub_responses: { :head_object => 'NoSuchKey' }
|
202
|
+
)
|
203
|
+
)
|
196
204
|
end
|
197
205
|
|
198
206
|
it 'is true' do
|
@@ -235,12 +243,24 @@ describe Dockly::Rpm do
|
|
235
243
|
context 'when the package has been created' do
|
236
244
|
before { subject.create_package! }
|
237
245
|
|
246
|
+
let(:client) do
|
247
|
+
client = Aws::S3::Client.new(stub_responses: true)
|
248
|
+
client.stub_responses(
|
249
|
+
:put_object, ->(context) do
|
250
|
+
expect(context.params[:bucket]).to eq(bucket_name)
|
251
|
+
expect(context.params[:key]).to eq(subject.s3_object_name)
|
252
|
+
expect(context.params).to have_key(:body)
|
253
|
+
|
254
|
+
{}
|
255
|
+
end
|
256
|
+
)
|
257
|
+
client
|
258
|
+
end
|
259
|
+
|
238
260
|
it 'inserts the rpm package into that bucket' do
|
239
|
-
expect(Dockly
|
240
|
-
|
241
|
-
|
242
|
-
expect(hash).to have_key(:body)
|
243
|
-
end
|
261
|
+
expect(Dockly)
|
262
|
+
.to receive(:s3)
|
263
|
+
.and_return(client)
|
244
264
|
|
245
265
|
subject.upload_to_s3
|
246
266
|
end
|