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
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
M2RkM2IzMjJlNzhiMGMwZTdjNGI2NDIzYTliMDEyOGRhNThkOTQ3ZQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 817b3a75ce89c73e9ad40e97913c7e694f6d5d39
|
4
|
+
data.tar.gz: 7a0a50ba3a0c833f77deefda46eace5917b0b1d2
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MWNlYmE4ZjlmZmYyMTczZDQ1MTRmODhhNjBhNjc3YzA2Nzg4NDdkODMwOWYw
|
11
|
-
ZjgyOTMxZWRjZDc4YmU2YzdiZmIxZTc3Nzg1Zjg1YWI4NDVmYjc=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YTZjYjU2OTYzZDc2ZmViM2IyNmUwZTE4NzQ3ZmYyNmM4OGQwMWM1NDc4NGE3
|
14
|
-
N2FjZjIzZjNiYWI4ZGNiNTJlODg3MmRjMjRjZTcxMDcyMTQwODg1OGQ4MjYz
|
15
|
-
ZWI4NWQ4NDNhMmJlYTFjNDA3ODdjNGIyOTFmMjI5ZGM1ZWUwNzg=
|
6
|
+
metadata.gz: d3e29e2b40e5dede34e76d19a7635b2e8d051fc799b41961871a5fee4e2011c1616954518aef46cae0f591561452180816e786aa0a919a9b0713c9c94b6c61a3
|
7
|
+
data.tar.gz: d4f4dc7bd97cbca3071ef9099ae8150b77b826daa4ba62c999d88ddb15dd62f175523f0c802d0e949d361c933179c987cb887fe1066917a8ad10f9387ed5bbef
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.3.1
|
data/.travis.yml
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
- 2.0
|
4
|
+
- 2.1
|
5
|
+
- 2.2
|
6
|
+
- 2.3
|
7
7
|
script:
|
8
8
|
- git fetch --tags
|
9
9
|
- CI=true bundle exec rake
|
10
10
|
before_install:
|
11
11
|
- sudo apt-get update -qq
|
12
12
|
- sudo apt-get install -qq rpm
|
13
|
-
- gem install bundler
|
14
|
-
|
13
|
+
- gem install bundler -v 1.17.3
|
data/README.md
CHANGED
@@ -174,6 +174,11 @@ In addition to the above attributes, `docker` has the following references:
|
|
174
174
|
- allows one
|
175
175
|
- class: `Dockly::Docker::Registry`
|
176
176
|
- description: a registry to push to in lieu of exporting as a tar -- the registry will be automatically pulled upon installing the package
|
177
|
+
- `ecr`
|
178
|
+
- required: `false`
|
179
|
+
- allows one
|
180
|
+
- class: `Dockly::Docker::ECR`
|
181
|
+
- description: an AWS ECR Docker registry to push to in lieu of exporting as a tar -- the registry will be automatically pulled upon installing the package
|
177
182
|
|
178
183
|
Need finer control of Docker packages? We also wrote [docker-api](https://github.com/swipely/docker-api).
|
179
184
|
|
@@ -200,6 +205,23 @@ The `registry` DSL is used to define Docker Registries. It has the following att
|
|
200
205
|
- default: `https://index.docker.io/v1`
|
201
206
|
- description: the server where the registry lives
|
202
207
|
|
208
|
+
`ecr`
|
209
|
+
--------
|
210
|
+
|
211
|
+
The `ecr` DSL is used to define AWS ECR Docker registries. It has the following attributes:
|
212
|
+
|
213
|
+
- `server_address`
|
214
|
+
- required: `true`
|
215
|
+
- description: the server where the registry lives without the repo name, eg `accountid.dkr.ecr.region.amazonaws.com`
|
216
|
+
- `username`
|
217
|
+
- required: `false`
|
218
|
+
- default: pulled from auth data obtained using assumed role's credentials
|
219
|
+
- description: the username to authenticate
|
220
|
+
- `password`
|
221
|
+
- required: `false`
|
222
|
+
- default: pulled from auth data obtained using assumed role's credentials
|
223
|
+
- description: the password to authenticate
|
224
|
+
|
203
225
|
`foreman`
|
204
226
|
---------
|
205
227
|
|
data/dockly.gemspec
CHANGED
@@ -18,14 +18,17 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.add_dependency 'docker-api', '>= 1.14.0'
|
19
19
|
gem.add_dependency 'dockly-util', '>= 0.0.9', '< 1.0'
|
20
20
|
gem.add_dependency 'excon'
|
21
|
-
gem.add_dependency 'aws-sdk', '~>
|
21
|
+
gem.add_dependency 'aws-sdk-core', '~> 3'
|
22
|
+
gem.add_dependency 'aws-sdk-s3', '~> 1'
|
23
|
+
gem.add_dependency 'aws-sdk-ecr', '~> 1'
|
22
24
|
gem.add_dependency 'foreman'
|
23
25
|
gem.add_dependency 'fpm', '~> 1.2.0'
|
24
26
|
gem.add_dependency 'minigit', '~> 0.0.4'
|
25
27
|
gem.add_development_dependency 'cane'
|
26
28
|
gem.add_development_dependency 'pry'
|
27
|
-
gem.add_development_dependency 'rake'
|
29
|
+
gem.add_development_dependency 'rake', '< 11.0'
|
28
30
|
gem.add_development_dependency 'rspec', '~> 2.14.1'
|
29
31
|
gem.add_development_dependency 'vcr'
|
30
|
-
gem.add_development_dependency 'webmock'
|
32
|
+
gem.add_development_dependency 'webmock', '<= 1.18.0'
|
33
|
+
gem.add_development_dependency 'addressable', '<= 2.3.6'
|
31
34
|
end
|
data/lib/dockly.rb
CHANGED
data/lib/dockly/bash_builder.rb
CHANGED
@@ -24,7 +24,8 @@ module Dockly
|
|
24
24
|
generate_snippet_for :s3_docker_import, [:s3_url, :repo, :tag]
|
25
25
|
generate_snippet_for :s3_diff_docker_import, [:base_image, :diff_image, :repo, :tag]
|
26
26
|
generate_snippet_for :registry_import, [:repo, :tag], { :tag => "latest" }
|
27
|
+
generate_snippet_for :auth_ecr, [:server_address]
|
27
28
|
|
28
|
-
generate_snippet_for :docker_tag_latest, [:repo, :tag]
|
29
|
+
generate_snippet_for :docker_tag_latest, [:repo, :tag, :new_name]
|
29
30
|
end
|
30
31
|
end
|
@@ -77,7 +77,7 @@ class Dockly::BuildCache::Docker < Dockly::BuildCache::Base
|
|
77
77
|
debug 'Restarting the container to copy the cache\'s output'
|
78
78
|
# Restart the container so we can copy its output
|
79
79
|
container = container.commit.run('sleep 3600')
|
80
|
-
container.
|
80
|
+
container.archive_out(output_directory) { |chunk| file.write(chunk.to_s) }
|
81
81
|
container.kill
|
82
82
|
file.tap(&:rewind)
|
83
83
|
end
|
data/lib/dockly/deb.rb
CHANGED
@@ -77,7 +77,6 @@ class Dockly::Deb
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def upload_to_s3
|
80
|
-
info "uploading to s3"
|
81
80
|
return if s3_bucket.nil?
|
82
81
|
raise "Package wasn't created!" unless File.exist?(build_path)
|
83
82
|
info "uploading package to s3"
|
@@ -126,7 +125,14 @@ private
|
|
126
125
|
add_files(@dir_package)
|
127
126
|
add_docker_auth_config(@dir_package)
|
128
127
|
add_docker(@dir_package)
|
129
|
-
|
128
|
+
|
129
|
+
if package_startup_script.is_a?(String)
|
130
|
+
raise ArgumentError,
|
131
|
+
'package_startup_script filename must not be empty if specified' if package_startup_script.empty?
|
132
|
+
add_startup_script(@dir_package, package_startup_script)
|
133
|
+
elsif package_startup_script
|
134
|
+
add_startup_script(@dir_package)
|
135
|
+
end
|
130
136
|
|
131
137
|
convert_package
|
132
138
|
|
@@ -174,7 +180,7 @@ private
|
|
174
180
|
end
|
175
181
|
|
176
182
|
def add_docker_auth_config(package)
|
177
|
-
return if (registry = get_registry).nil? || !registry
|
183
|
+
return if (registry = get_registry).nil? || !should_auth?(registry)
|
178
184
|
info "adding docker config file"
|
179
185
|
registry.generate_config_file!
|
180
186
|
|
@@ -185,11 +191,18 @@ private
|
|
185
191
|
package.attributes[:prefix] = nil
|
186
192
|
end
|
187
193
|
|
194
|
+
def should_auth?(registry)
|
195
|
+
registry.is_a?(Dockly::Docker::Registry) &&
|
196
|
+
registry.authentication_required?
|
197
|
+
end
|
198
|
+
|
188
199
|
def add_docker(package)
|
189
200
|
return if docker.nil? || docker.s3_bucket
|
190
201
|
info "adding docker image"
|
191
202
|
docker.generate!
|
192
|
-
|
203
|
+
|
204
|
+
return if get_registry
|
205
|
+
|
193
206
|
package.attributes[:prefix] = docker.package_dir
|
194
207
|
Dir.chdir(File.dirname(docker.tar_path)) do
|
195
208
|
package.input(File.basename(docker.tar_path))
|
@@ -198,7 +211,7 @@ private
|
|
198
211
|
end
|
199
212
|
|
200
213
|
def get_registry
|
201
|
-
if docker && registry = docker.registry
|
214
|
+
if docker && (registry = docker.registry)
|
202
215
|
registry
|
203
216
|
end
|
204
217
|
end
|
@@ -207,38 +220,53 @@ private
|
|
207
220
|
scripts = ["#!/bin/bash"]
|
208
221
|
bb = Dockly::BashBuilder.new
|
209
222
|
scripts << bb.normalize_for_dockly
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
if docker.tar_diff
|
216
|
-
scripts << bb.file_diff_docker_import(docker.import, docker_output, docker.name, docker.tag)
|
217
|
-
else
|
218
|
-
scripts << bb.file_docker_import(docker_output, docker.name, docker.tag)
|
223
|
+
|
224
|
+
if docker
|
225
|
+
if (registry = docker.registry)
|
226
|
+
if registry.is_a?(Dockly::Docker::ECR)
|
227
|
+
scripts << bb.auth_ecr(registry.server_address)
|
219
228
|
end
|
229
|
+
|
230
|
+
scripts << bb.registry_import(docker.repo, docker.tag)
|
231
|
+
scripts << bb.docker_tag_latest(docker.repo, docker.tag, docker.name)
|
220
232
|
else
|
221
|
-
|
222
|
-
scripts << bb.s3_diff_docker_import(docker.import, docker.s3_url, docker.name, docker.tag)
|
223
|
-
else
|
224
|
-
scripts << bb.s3_docker_import(docker.s3_url, docker.name, docker.tag)
|
225
|
-
end
|
233
|
+
scripts += collect_non_registry_scripts(bb)
|
226
234
|
end
|
227
|
-
scripts << bb.docker_tag_latest(docker.repo, docker.tag)
|
228
235
|
end
|
229
236
|
scripts.join("\n")
|
230
237
|
end
|
231
238
|
|
232
|
-
def
|
239
|
+
def collect_non_registry_scripts(bb)
|
240
|
+
scripts = []
|
241
|
+
|
242
|
+
if docker.s3_bucket.nil?
|
243
|
+
docker_output = File.join(docker.package_dir, docker.export_filename)
|
244
|
+
if docker.tar_diff
|
245
|
+
scripts << bb.file_diff_docker_import(docker.import, docker_output, docker.name, docker.tag)
|
246
|
+
else
|
247
|
+
scripts << bb.file_docker_import(docker_output, docker.name, docker.tag)
|
248
|
+
end
|
249
|
+
else
|
250
|
+
if docker.tar_diff
|
251
|
+
scripts << bb.s3_diff_docker_import(docker.import, docker.s3_url, docker.name, docker.tag)
|
252
|
+
else
|
253
|
+
scripts << bb.s3_docker_import(docker.s3_url, docker.name, docker.tag)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
scripts << bb.docker_tag_latest(docker.repo, docker.tag, docker.repo)
|
258
|
+
end
|
259
|
+
|
260
|
+
def add_startup_script(package, startup_script = "dockly-startup.sh")
|
233
261
|
ensure_present! :build_dir
|
234
|
-
startup_script_path = File.join(build_dir,
|
262
|
+
startup_script_path = File.join(build_dir, startup_script)
|
235
263
|
File.open(startup_script_path, 'w+') do |f|
|
236
264
|
f.write(post_startup_script)
|
237
265
|
f.chmod(0755)
|
238
266
|
end
|
239
267
|
package.attributes[:prefix] = "/opt/dockly"
|
240
268
|
Dir.chdir(build_dir) do
|
241
|
-
package.input(
|
269
|
+
package.input(startup_script)
|
242
270
|
end
|
243
271
|
package.attributes[:prefix] = nil
|
244
272
|
end
|
data/lib/dockly/docker.rb
CHANGED
@@ -10,11 +10,13 @@ class Dockly::Docker
|
|
10
10
|
include Dockly::Util::Logger::Mixin
|
11
11
|
|
12
12
|
autoload :Registry, 'dockly/docker/registry'
|
13
|
+
autoload :ECR, 'dockly/docker/ecr'
|
13
14
|
|
14
15
|
logger_prefix '[dockly docker]'
|
15
16
|
|
16
17
|
dsl_class_attribute :build_cache, Dockly::BuildCache.model, type: Array
|
17
|
-
dsl_class_attribute :
|
18
|
+
dsl_class_attribute :docker_registry, Dockly::Docker::Registry
|
19
|
+
dsl_class_attribute :ecr, Dockly::Docker::ECR
|
18
20
|
|
19
21
|
dsl_attribute :name, :import, :git_archive, :build, :tag, :build_dir, :package_dir,
|
20
22
|
:timeout, :cleanup_images, :tar_diff, :s3_bucket, :s3_object_prefix
|
@@ -32,6 +34,10 @@ class Dockly::Docker
|
|
32
34
|
(@build_env ||= {}).tap { |env| env.merge!(hash) if hash.is_a?(Hash) }
|
33
35
|
end
|
34
36
|
|
37
|
+
def registry
|
38
|
+
ecr || docker_registry
|
39
|
+
end
|
40
|
+
|
35
41
|
def copy_from_s3(sha)
|
36
42
|
return if s3_bucket.nil?
|
37
43
|
object = s3_object_for(sha)
|
@@ -177,7 +183,9 @@ class Dockly::Docker
|
|
177
183
|
repo = "#{name}-base"
|
178
184
|
tag = "dockly-#{Dockly::VERSION}-#{File.basename(import).split('.').first}"
|
179
185
|
info "looking for imported base image with tag: #{tag}"
|
180
|
-
image = Docker::Image.all.find
|
186
|
+
image = Docker::Image.all.find do |img|
|
187
|
+
img.info['RepoTags'] && img.info['RepoTags'].include?("#{repo}:#{tag}")
|
188
|
+
end
|
181
189
|
if image
|
182
190
|
info "found imported base image: #{image.id}"
|
183
191
|
image
|
@@ -316,14 +324,26 @@ class Dockly::Docker
|
|
316
324
|
end
|
317
325
|
|
318
326
|
def push_to_registry(image)
|
319
|
-
|
327
|
+
raise "No registry to push to" if registry.nil?
|
328
|
+
|
320
329
|
info "Exporting #{image.id} to Docker registry at #{registry.server_address}"
|
330
|
+
|
321
331
|
registry.authenticate!
|
322
|
-
|
323
|
-
|
324
|
-
|
332
|
+
|
333
|
+
image =
|
334
|
+
Docker::Image
|
335
|
+
.all(:all => true)
|
336
|
+
.find do |img|
|
337
|
+
img.id.include?(image.id) || image.id.include?(img.id)
|
338
|
+
end
|
339
|
+
|
325
340
|
raise "Could not find image after authentication" if image.nil?
|
326
|
-
|
341
|
+
|
342
|
+
image.push(registry.to_h, :registry => registry.server_address) do |resp|
|
343
|
+
if resp.include?('errorDetail')
|
344
|
+
raise "Error pushing to registry: #{resp}"
|
345
|
+
end
|
346
|
+
end
|
327
347
|
end
|
328
348
|
|
329
349
|
def fetch_import
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class Dockly::Docker::ECR
|
2
|
+
include Dockly::Util::DSL
|
3
|
+
include Dockly::Util::Logger::Mixin
|
4
|
+
|
5
|
+
logger_prefix '[dockly docker ecr]'
|
6
|
+
|
7
|
+
dsl_attribute :name, :server_address, :password, :username
|
8
|
+
|
9
|
+
def authenticate!
|
10
|
+
@username ||= login_from_aws[0]
|
11
|
+
@password ||= login_from_aws[1]
|
12
|
+
|
13
|
+
ensure_present! :password, :server_address, :username
|
14
|
+
|
15
|
+
debug "Attempting to authenticate at #{server_address}"
|
16
|
+
|
17
|
+
::Docker.authenticate!(self.to_h)
|
18
|
+
|
19
|
+
info "Successfully authenticated at #{server_address}"
|
20
|
+
rescue ::Docker::Error::AuthenticationError
|
21
|
+
raise "Could not authenticate at #{server_address}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def authentication_required?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_server_address?
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def login_from_aws
|
33
|
+
@login_from_aws ||=
|
34
|
+
Base64
|
35
|
+
.decode64(auth_data.authorization_token)
|
36
|
+
.split(':')
|
37
|
+
end
|
38
|
+
|
39
|
+
def auth_data
|
40
|
+
@auth_data ||=
|
41
|
+
client
|
42
|
+
.get_authorization_token
|
43
|
+
.authorization_data
|
44
|
+
.first
|
45
|
+
end
|
46
|
+
|
47
|
+
def client
|
48
|
+
@client ||= Aws::ECR::Client.new(region: 'us-east-1')
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_h
|
52
|
+
ensure_present! :username, :password, :server_address
|
53
|
+
|
54
|
+
{
|
55
|
+
'serveraddress' => "https://#{server_address}",
|
56
|
+
'username' => username,
|
57
|
+
'password' => password
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
data/lib/dockly/version.rb
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
auth_ecr() {
|
2
|
+
$(aws ecr get-login --region us-east-1 --no-include-email)
|
3
|
+
}
|
4
|
+
|
5
|
+
worked=1
|
6
|
+
for attempt in {1..10}; do
|
7
|
+
[[ $worked != 0 ]] || break
|
8
|
+
auth_ecr && worked=0 || (log "ecr auth: attempt $attempt failed, sleeping 30"; sleep 30)
|
9
|
+
done
|
10
|
+
[[ $worked != 0 ]] && fatal "failed to auth to ecr"
|
11
|
+
log "ecr auth: successfully authenticated"
|
@@ -32,8 +32,8 @@ describe Dockly::BashBuilder do
|
|
32
32
|
|
33
33
|
context "when there is a tag" do
|
34
34
|
it "tags the repo:tag as repo:latest" do
|
35
|
-
output = subject.docker_tag_latest("test_repo", "a_tag")
|
36
|
-
expect(output).to include("docker tag test_repo:a_tag test_repo:latest")
|
35
|
+
output = subject.docker_tag_latest("registry/test_repo", "a_tag", "test_repo")
|
36
|
+
expect(output).to include("docker tag registry/test_repo:a_tag test_repo:latest")
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -14,8 +14,11 @@ describe Dockly::BuildCache::Base do
|
|
14
14
|
describe '#up_to_date?' do
|
15
15
|
context 'when the object exists in s3' do
|
16
16
|
before do
|
17
|
-
allow(
|
18
|
-
.to receive(:
|
17
|
+
allow(Dockly)
|
18
|
+
.to receive(:s3)
|
19
|
+
.and_return(
|
20
|
+
Aws::S3::Client.new(stub_responses: true)
|
21
|
+
)
|
19
22
|
end
|
20
23
|
|
21
24
|
its(:up_to_date?) { should be_true }
|
@@ -23,9 +26,13 @@ describe Dockly::BuildCache::Base do
|
|
23
26
|
|
24
27
|
context 'when the object does not exist in s3' do
|
25
28
|
before do
|
26
|
-
allow(
|
27
|
-
.to receive(:
|
28
|
-
.
|
29
|
+
allow(Dockly)
|
30
|
+
.to receive(:s3)
|
31
|
+
.and_return(
|
32
|
+
Aws::S3::Client.new(
|
33
|
+
stub_responses: { :head_object => 'NoSuchKey' }
|
34
|
+
)
|
35
|
+
)
|
29
36
|
end
|
30
37
|
|
31
38
|
its(:up_to_date?) { should be_false }
|
@@ -37,9 +44,12 @@ describe Dockly::BuildCache::Base do
|
|
37
44
|
let(:object) { double(:object) }
|
38
45
|
|
39
46
|
before do
|
40
|
-
allow(
|
41
|
-
.to receive(:
|
42
|
-
.and_return(
|
47
|
+
allow(Dockly)
|
48
|
+
.to receive(:s3)
|
49
|
+
.and_return(Aws::S3::Client.new(
|
50
|
+
stub_responses: { :get_object => object }
|
51
|
+
))
|
52
|
+
|
43
53
|
allow(object)
|
44
54
|
.to receive(:body)
|
45
55
|
.and_return(StringIO.new('hey dad').tap(&:rewind))
|