dockly 3.3.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ODI3Y2E3MmU4NzIzNGM3Y2Q5MzA5MzQ0MTU0MmM5OTA5N2VjZTc3Mg==
5
- data.tar.gz: !binary |-
6
- M2RkM2IzMjJlNzhiMGMwZTdjNGI2NDIzYTliMDEyOGRhNThkOTQ3ZQ==
2
+ SHA1:
3
+ metadata.gz: 817b3a75ce89c73e9ad40e97913c7e694f6d5d39
4
+ data.tar.gz: 7a0a50ba3a0c833f77deefda46eace5917b0b1d2
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- OTBmZjQ3OWUwOTU2N2RkYjk4ODYyY2M2ZmQ2ZDM5YmUzNjhkNGUwNWUzNmQ1
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.9.3-p547
1
+ 2.3.1
data/.travis.yml CHANGED
@@ -1,14 +1,13 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9
4
- - 2.0
5
- - 2.1
6
- - 2.2
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', '~> 2.0'
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
@@ -4,7 +4,9 @@ require 'dockly/util/git'
4
4
  require 'foreman/cli_fix'
5
5
  require 'foreman/export/base_fix'
6
6
  require 'minigit'
7
- require 'aws-sdk'
7
+ require 'aws-sdk-core'
8
+ require 'aws-sdk-s3'
9
+ require 'aws-sdk-ecr'
8
10
  require 'open3'
9
11
 
10
12
  module Dockly
@@ -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.copy(output_directory) { |chunk| file.write(chunk.to_s) }
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
- add_startup_script(@dir_package) if package_startup_script
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.authentication_required?
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
- return unless docker.registry.nil?
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
- if get_registry
211
- scripts << bb.registry_import(docker.repo, docker.tag)
212
- elsif docker
213
- if docker.s3_bucket.nil?
214
- docker_output = File.join(docker.package_dir, docker.export_filename)
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
- if docker.tar_diff
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 add_startup_script(package)
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, "dockly-startup.sh")
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("dockly-startup.sh")
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 :registry, Dockly::Docker::Registry
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 { |img| img.info['RepoTags'].include?("#{repo}:#{tag}") }
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
- ensure_present! :registry
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
- image = Docker::Image.all(:all => true).find { |img|
323
- img.id.start_with?(image.id) || image.id.start_with?(img.id)
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
- image.push(registry.to_h, :registry => registry.server_address)
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
@@ -1,6 +1,6 @@
1
1
  module Dockly
2
- MAJOR = 3
3
- MINOR = 3
2
+ MAJOR = 4
3
+ MINOR = 2
4
4
  PATCH = 0
5
5
  RELEASE = nil
6
6
 
@@ -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"
@@ -1,3 +1,3 @@
1
1
  <% if data[:tag] %>
2
- docker tag <%= data[:repo] %>:<%= data[:tag] %> <%= data[:repo] %>:latest
2
+ docker tag <%= data[:repo] %>:<%= data[:tag] %> <%= data[:new_name] %>:latest
3
3
  <% end %>
@@ -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(subject.connection)
18
- .to receive(:head_object)
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(subject.connection)
27
- .to receive(:head_object)
28
- .and_raise(Aws::S3::Errors::NoSuchKey.new('Some Error', 500))
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(subject.connection)
41
- .to receive(:get_object)
42
- .and_return(object)
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))