dockly 3.2.0.pre.1 → 4.1.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
- N2MzMTNlNjU1OGM5MDJmY2M5MDYxNzk2YjA0OGIyMTVhZmNlNTBkYQ==
5
- data.tar.gz: !binary |-
6
- MzRhMzcwZTNjYTRmYjFjODk3NTNjNWZjZDJiMGE3YmE2OGE4NjU2Mw==
2
+ SHA1:
3
+ metadata.gz: 0eb949e588205c02f1c15dbc3b609b7d14e3fd24
4
+ data.tar.gz: 52ab9c8916b071f0035400ced4c4fd73cf407885
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NzNmMjE0ZWE2NmI1OTcxOTNhZTY1MzU0NzhlNGRmYTQwMzc2NWNhOGYwZWRm
10
- ZDljZGI3ODZiYjdkZjI3MzM2NzAwODM1ZDEwYjU1MjIzOGQ5YzQ2OWRlMjg0
11
- MWNjNjBlMGI0M2NkYTBjNmI4ZmI1ZjZlYTcxZjBlY2I0MmViMDU=
12
- data.tar.gz: !binary |-
13
- NDQwYWNkOWViYWFmZDg3NzljNGMyM2VmNjc0NGZhOTUyMDQ0Yjc4MTlmMDRj
14
- NDQzNzVjMjEyMjBjODllMmJkOWY4ZDE4NGQ1NjIxZWMyZjQzZTUzZjg3NDU1
15
- NWVhMTRlYjg1NWVjMmQ1MDMzNDNhOTA2NDQ5MjNiZGQzYTlmNGQ=
6
+ metadata.gz: e5ec4ce34a0bc5b270451dbd717988038a4ad3344e1a2f1d497a089cf287f3da1d8d3b940291575b8d69f75a9d00df685e36a1ec2cd9134e3d651d190f32dd75
7
+ data.tar.gz: 3400f1bf912778501d3b360d75a17d22e959ad68d1a5dee63bbfe9785d73bbb9a42fac4465486f8445469dbd6fd9f99b67c38be066edfd2f2dbd860d808d4ca9
@@ -1 +1 @@
1
- 1.9.3-p547
1
+ 2.3.1
@@ -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
 
@@ -24,8 +24,9 @@ Gem::Specification.new do |gem|
24
24
  gem.add_dependency 'minigit', '~> 0.0.4'
25
25
  gem.add_development_dependency 'cane'
26
26
  gem.add_development_dependency 'pry'
27
- gem.add_development_dependency 'rake'
27
+ gem.add_development_dependency 'rake', '< 11.0'
28
28
  gem.add_development_dependency 'rspec', '~> 2.14.1'
29
29
  gem.add_development_dependency 'vcr'
30
- gem.add_development_dependency 'webmock'
30
+ gem.add_development_dependency 'webmock', '<= 1.18.0'
31
+ gem.add_development_dependency 'addressable', '<= 2.3.6'
31
32
  end
@@ -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
@@ -89,11 +89,17 @@ class Dockly::BuildCache::Base
89
89
 
90
90
  def push_to_s3(file)
91
91
  ensure_present! :s3_bucket, :s3_object_prefix
92
- connection.put_object(bucket: s3_bucket, key: s3_object(hash_output), body: file)
92
+ connection.put_object(
93
+ bucket: s3_bucket,
94
+ key: s3_object(hash_output),
95
+ body: file,
96
+ acl: 'bucket-owner-full-control',
97
+ )
93
98
  connection.copy_object(
94
99
  copy_source: [s3_bucket, s3_object(hash_output)].join('/'),
95
100
  bucket: s3_bucket,
96
- key: s3_object('latest')
101
+ key: s3_object('latest'),
102
+ acl: 'bucket-owner-full-control',
97
103
  )
98
104
  end
99
105
 
@@ -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
@@ -55,7 +55,8 @@ class Dockly::Deb
55
55
  Dockly.s3.copy_object(
56
56
  copy_source: File.join(s3_bucket, object),
57
57
  bucket: s3_bucket,
58
- key: s3_object_name
58
+ key: s3_object_name,
59
+ acl: 'bucket-owner-full-control',
59
60
  )
60
61
  info "Successfully copied s3://#{s3_bucket}/#{object} to s3://#{s3_bucket}/#{s3_object_name}"
61
62
  end
@@ -76,12 +77,16 @@ class Dockly::Deb
76
77
  end
77
78
 
78
79
  def upload_to_s3
79
- info "uploading to s3"
80
80
  return if s3_bucket.nil?
81
81
  raise "Package wasn't created!" unless File.exist?(build_path)
82
82
  info "uploading package to s3"
83
83
  File.open(build_path, 'rb') do |file|
84
- Dockly.s3.put_object(bucket: s3_bucket, key: s3_object_name, body: file)
84
+ Dockly.s3.put_object(
85
+ bucket: s3_bucket,
86
+ key: s3_object_name,
87
+ body: file,
88
+ acl: 'bucket-owner-full-control',
89
+ )
85
90
  end
86
91
  end
87
92
 
@@ -120,7 +125,14 @@ private
120
125
  add_files(@dir_package)
121
126
  add_docker_auth_config(@dir_package)
122
127
  add_docker(@dir_package)
123
- 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
124
136
 
125
137
  convert_package
126
138
 
@@ -168,7 +180,7 @@ private
168
180
  end
169
181
 
170
182
  def add_docker_auth_config(package)
171
- return if (registry = get_registry).nil? || !registry.authentication_required?
183
+ return if (registry = get_registry).nil? || !should_auth?(registry)
172
184
  info "adding docker config file"
173
185
  registry.generate_config_file!
174
186
 
@@ -179,11 +191,18 @@ private
179
191
  package.attributes[:prefix] = nil
180
192
  end
181
193
 
194
+ def should_auth?(registry)
195
+ registry.is_a?(Dockly::Docker::Registry) &&
196
+ registry.authentication_required?
197
+ end
198
+
182
199
  def add_docker(package)
183
200
  return if docker.nil? || docker.s3_bucket
184
201
  info "adding docker image"
185
202
  docker.generate!
186
- return unless docker.registry.nil?
203
+
204
+ return if get_registry
205
+
187
206
  package.attributes[:prefix] = docker.package_dir
188
207
  Dir.chdir(File.dirname(docker.tar_path)) do
189
208
  package.input(File.basename(docker.tar_path))
@@ -192,7 +211,7 @@ private
192
211
  end
193
212
 
194
213
  def get_registry
195
- if docker && registry = docker.registry
214
+ if docker && (registry = docker.registry)
196
215
  registry
197
216
  end
198
217
  end
@@ -201,38 +220,53 @@ private
201
220
  scripts = ["#!/bin/bash"]
202
221
  bb = Dockly::BashBuilder.new
203
222
  scripts << bb.normalize_for_dockly
204
- if get_registry
205
- scripts << bb.registry_import(docker.repo, docker.tag)
206
- elsif docker
207
- if docker.s3_bucket.nil?
208
- docker_output = File.join(docker.package_dir, docker.export_filename)
209
- if docker.tar_diff
210
- scripts << bb.file_diff_docker_import(docker.import, docker_output, docker.name, docker.tag)
211
- else
212
- 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)
213
228
  end
229
+
230
+ scripts << bb.registry_import(docker.repo, docker.tag)
231
+ scripts << bb.docker_tag_latest(docker.repo, docker.tag, docker.name)
214
232
  else
215
- if docker.tar_diff
216
- scripts << bb.s3_diff_docker_import(docker.import, docker.s3_url, docker.name, docker.tag)
217
- else
218
- scripts << bb.s3_docker_import(docker.s3_url, docker.name, docker.tag)
219
- end
233
+ scripts += collect_non_registry_scripts(bb)
220
234
  end
221
- scripts << bb.docker_tag_latest(docker.repo, docker.tag)
222
235
  end
223
236
  scripts.join("\n")
224
237
  end
225
238
 
226
- 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")
227
261
  ensure_present! :build_dir
228
- startup_script_path = File.join(build_dir, "dockly-startup.sh")
262
+ startup_script_path = File.join(build_dir, startup_script)
229
263
  File.open(startup_script_path, 'w+') do |f|
230
264
  f.write(post_startup_script)
231
265
  f.chmod(0755)
232
266
  end
233
267
  package.attributes[:prefix] = "/opt/dockly"
234
268
  Dir.chdir(build_dir) do
235
- package.input("dockly-startup.sh")
269
+ package.input(startup_script)
236
270
  end
237
271
  package.attributes[:prefix] = nil
238
272
  end
@@ -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)
@@ -39,7 +45,8 @@ class Dockly::Docker
39
45
  Dockly.s3.copy_object(
40
46
  copy_source: File.join(s3_bucket, object),
41
47
  bucket: s3_bucket,
42
- key: s3_object
48
+ key: s3_object,
49
+ acl: 'bucket-owner-full-control',
43
50
  )
44
51
  info "Successfully copied s3://#{s3_bucket}/#{object} to s3://#{s3_bucket}/#{s3_object}"
45
52
  end
@@ -176,7 +183,9 @@ class Dockly::Docker
176
183
  repo = "#{name}-base"
177
184
  tag = "dockly-#{Dockly::VERSION}-#{File.basename(import).split('.').first}"
178
185
  info "looking for imported base image with tag: #{tag}"
179
- 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
180
189
  if image
181
190
  info "found imported base image: #{image.id}"
182
191
  image
@@ -315,14 +324,26 @@ class Dockly::Docker
315
324
  end
316
325
 
317
326
  def push_to_registry(image)
318
- ensure_present! :registry
327
+ raise "No registry to push to" if registry.nil?
328
+
319
329
  info "Exporting #{image.id} to Docker registry at #{registry.server_address}"
330
+
320
331
  registry.authenticate!
321
- image = Docker::Image.all(:all => true).find { |img|
322
- img.id.start_with?(image.id) || image.id.start_with?(img.id)
323
- }
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
+
324
340
  raise "Could not find image after authentication" if image.nil?
325
- 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
326
347
  end
327
348
 
328
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
@@ -72,8 +72,11 @@ module Dockly
72
72
  end
73
73
 
74
74
  def multipart_upload
75
- @multipart_upload ||=
76
- connection.create_multipart_upload(bucket: s3_bucket, key: s3_object)
75
+ @multipart_upload ||= connection.create_multipart_upload(
76
+ bucket: s3_bucket,
77
+ key: s3_object,
78
+ acl: 'bucket-owner-full-control',
79
+ )
77
80
  end
78
81
  end
79
82
  end
@@ -1,8 +1,8 @@
1
1
  module Dockly
2
- MAJOR = 3
3
- MINOR = 2
2
+ MAJOR = 4
3
+ MINOR = 1
4
4
  PATCH = 0
5
- RELEASE = 'pre.1'
5
+ RELEASE = nil
6
6
 
7
7
  VERSION = [MAJOR, MINOR, PATCH, RELEASE].compact.join('.')
8
8
  end
@@ -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
@@ -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(/\A3\.\d{2}\.\d-\d{1,2}-\w+\Z/)
159
+ expect(build_cache.parameter_output(command)).to match(/\A\d.\d.\d+-\w+-\w+\z/)
160
160
  end
161
161
  end
162
162
 
@@ -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
@@ -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
@@ -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
 
@@ -147,7 +217,7 @@ describe Dockly::Docker do
147
217
  end
148
218
 
149
219
  context 'and it points to a non-S3 url' do
150
- let(:url) { 'http://www.html5zombo.com' }
220
+ let(:url) { 'http://html5zombo.com' }
151
221
 
152
222
  before { subject.tag 'yolo' }
153
223
 
@@ -172,7 +242,7 @@ describe Dockly::Docker do
172
242
  context "with a registry export" do
173
243
  let(:registry) { double(:registry) }
174
244
  before do
175
- subject.instance_variable_set(:"@registry", registry)
245
+ subject.instance_variable_set(:"@docker_registry", registry)
176
246
  expect(subject).to receive(:push_to_registry)
177
247
  end
178
248
 
@@ -243,6 +313,107 @@ describe Dockly::Docker do
243
313
  end
244
314
  end
245
315
 
316
+ describe '#push_to_registry', :docker do
317
+ let(:image) { Docker::Image.create('fromImage' => 'ubuntu:14.04') }
318
+ let(:ecr) { double(:ecr) }
319
+
320
+ context 'when there is no registry' do
321
+ it 'raises' do
322
+ expect(subject.registry).to eq(nil)
323
+
324
+ expect { subject.push_to_registry(image) }.to raise_error(/No registry/)
325
+ end
326
+ end
327
+
328
+ context 'when there is a registry' do
329
+ before do
330
+ subject.instance_variable_set(:"@ecr", ecr)
331
+
332
+ allow(ecr)
333
+ .to receive(:server_address)
334
+ .and_return('server_address')
335
+
336
+ expect(subject.registry).to eq(ecr)
337
+ end
338
+
339
+ context "that can't be authenticated to" do
340
+ before do
341
+ allow(ecr)
342
+ .to receive(:authenticate!)
343
+ .and_raise
344
+ end
345
+
346
+ it 'raises' do
347
+ expect { subject.push_to_registry(image) }
348
+ .to raise_error(StandardError)
349
+ end
350
+ end
351
+
352
+ context 'that can be authenticated to' do
353
+ before do
354
+ allow(ecr).to receive(:authenticate!)
355
+
356
+ allow(Docker::Image)
357
+ .to receive(:all)
358
+ .with(all: true)
359
+ .and_return(available_images)
360
+ end
361
+
362
+ context "but the image isn't found" do
363
+ let(:available_images) { [] }
364
+
365
+ it 'raises' do
366
+ expect { subject.push_to_registry(image) }
367
+ .to raise_error(/Could not find image after authentication/)
368
+ end
369
+ end
370
+
371
+ context 'and the image is found' do
372
+ let(:available_images) { [image] }
373
+
374
+ before do
375
+ allow(ecr)
376
+ .to receive(:to_h)
377
+ .and_return({})
378
+ allow(image)
379
+ .to receive(:push)
380
+ .and_yield(push_message)
381
+ end
382
+
383
+ context 'but the push to the registry fails' do
384
+ let(:push_message) do
385
+ <<-EOF
386
+ {"errorDetail":{"message":"name unknown: The repository with name 'repository'
387
+ does not exist in the registry with id 'accoundid'"},"error":"name unknown:
388
+ The repository with name 'repository' does not exist in the registry with id 'accountid'"}
389
+ EOF
390
+ end
391
+
392
+ it 'raises' do
393
+ expect { subject.push_to_registry(image) }
394
+ .to raise_error(/Error pushing to registry/)
395
+ end
396
+ end
397
+
398
+ context 'and the push to the registry succeeds' do
399
+ let(:push_message) do
400
+ <<-EOF
401
+ {"status":"Pushed","progressDetail":{},"id":"id"}
402
+ {"status":"sha: digest: digest size: 2048"}
403
+ {"progressDetail":{},"aux":{"Tag":"sha","Digest":"digest","Size":2048}}
404
+ EOF
405
+ end
406
+
407
+ it 'passes' do
408
+ expect(subject.push_to_registry(image))
409
+ .not_to raise_error
410
+ end
411
+ end
412
+ end
413
+ end
414
+ end
415
+ end
416
+
246
417
  describe '#export_image_diff', :docker do
247
418
  let(:images) { [] }
248
419
  let(:output) { StringIO.new }
@@ -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-1.service').should be_true
33
- File.read('build/foreman/foreman-web-1.service')
34
- .lines.grep(/^ExecStart=\/bin\/bash -lc '\/bin\/sh start_my_server'$/)
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
metadata CHANGED
@@ -1,217 +1,231 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dockly
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0.pre.1
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Swipely, Inc.
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-29 00:00:00.000000000 Z
11
+ date: 2021-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clamp
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.6'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.6'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: docker-api
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.14.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.14.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: dockly-util
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: 0.0.9
48
- - - <
48
+ - - "<"
49
49
  - !ruby/object:Gem::Version
50
50
  version: '1.0'
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - ! '>='
55
+ - - ">="
56
56
  - !ruby/object:Gem::Version
57
57
  version: 0.0.9
58
- - - <
58
+ - - "<"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '1.0'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: excon
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - ! '>='
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - ! '>='
72
+ - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: aws-sdk
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - ~>
79
+ - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '2.0'
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
- - - ~>
86
+ - - "~>"
87
87
  - !ruby/object:Gem::Version
88
88
  version: '2.0'
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: foreman
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
- - - ! '>='
93
+ - - ">="
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
- - - ! '>='
100
+ - - ">="
101
101
  - !ruby/object:Gem::Version
102
102
  version: '0'
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: fpm
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - ~>
107
+ - - "~>"
108
108
  - !ruby/object:Gem::Version
109
109
  version: 1.2.0
110
110
  type: :runtime
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
- - - ~>
114
+ - - "~>"
115
115
  - !ruby/object:Gem::Version
116
116
  version: 1.2.0
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: minigit
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
- - - ~>
121
+ - - "~>"
122
122
  - !ruby/object:Gem::Version
123
123
  version: 0.0.4
124
124
  type: :runtime
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
- - - ~>
128
+ - - "~>"
129
129
  - !ruby/object:Gem::Version
130
130
  version: 0.0.4
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: cane
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
- - - ! '>='
135
+ - - ">="
136
136
  - !ruby/object:Gem::Version
137
137
  version: '0'
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
- - - ! '>='
142
+ - - ">="
143
143
  - !ruby/object:Gem::Version
144
144
  version: '0'
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: pry
147
147
  requirement: !ruby/object:Gem::Requirement
148
148
  requirements:
149
- - - ! '>='
149
+ - - ">="
150
150
  - !ruby/object:Gem::Version
151
151
  version: '0'
152
152
  type: :development
153
153
  prerelease: false
154
154
  version_requirements: !ruby/object:Gem::Requirement
155
155
  requirements:
156
- - - ! '>='
156
+ - - ">="
157
157
  - !ruby/object:Gem::Version
158
158
  version: '0'
159
159
  - !ruby/object:Gem::Dependency
160
160
  name: rake
161
161
  requirement: !ruby/object:Gem::Requirement
162
162
  requirements:
163
- - - ! '>='
163
+ - - "<"
164
164
  - !ruby/object:Gem::Version
165
- version: '0'
165
+ version: '11.0'
166
166
  type: :development
167
167
  prerelease: false
168
168
  version_requirements: !ruby/object:Gem::Requirement
169
169
  requirements:
170
- - - ! '>='
170
+ - - "<"
171
171
  - !ruby/object:Gem::Version
172
- version: '0'
172
+ version: '11.0'
173
173
  - !ruby/object:Gem::Dependency
174
174
  name: rspec
175
175
  requirement: !ruby/object:Gem::Requirement
176
176
  requirements:
177
- - - ~>
177
+ - - "~>"
178
178
  - !ruby/object:Gem::Version
179
179
  version: 2.14.1
180
180
  type: :development
181
181
  prerelease: false
182
182
  version_requirements: !ruby/object:Gem::Requirement
183
183
  requirements:
184
- - - ~>
184
+ - - "~>"
185
185
  - !ruby/object:Gem::Version
186
186
  version: 2.14.1
187
187
  - !ruby/object:Gem::Dependency
188
188
  name: vcr
189
189
  requirement: !ruby/object:Gem::Requirement
190
190
  requirements:
191
- - - ! '>='
191
+ - - ">="
192
192
  - !ruby/object:Gem::Version
193
193
  version: '0'
194
194
  type: :development
195
195
  prerelease: false
196
196
  version_requirements: !ruby/object:Gem::Requirement
197
197
  requirements:
198
- - - ! '>='
198
+ - - ">="
199
199
  - !ruby/object:Gem::Version
200
200
  version: '0'
201
201
  - !ruby/object:Gem::Dependency
202
202
  name: webmock
203
203
  requirement: !ruby/object:Gem::Requirement
204
204
  requirements:
205
- - - ! '>='
205
+ - - "<="
206
206
  - !ruby/object:Gem::Version
207
- version: '0'
207
+ version: 1.18.0
208
208
  type: :development
209
209
  prerelease: false
210
210
  version_requirements: !ruby/object:Gem::Requirement
211
211
  requirements:
212
- - - ! '>='
212
+ - - "<="
213
213
  - !ruby/object:Gem::Version
214
- version: '0'
214
+ version: 1.18.0
215
+ - !ruby/object:Gem::Dependency
216
+ name: addressable
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - "<="
220
+ - !ruby/object:Gem::Version
221
+ version: 2.3.6
222
+ type: :development
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "<="
227
+ - !ruby/object:Gem::Version
228
+ version: 2.3.6
215
229
  description: Packaging made easy
216
230
  email:
217
231
  - tomhulihan@swipely.com
@@ -222,11 +236,11 @@ executables:
222
236
  extensions: []
223
237
  extra_rdoc_files: []
224
238
  files:
225
- - .cane
226
- - .gitignore
227
- - .rspec
228
- - .ruby-version
229
- - .travis.yml
239
+ - ".cane"
240
+ - ".gitignore"
241
+ - ".rspec"
242
+ - ".ruby-version"
243
+ - ".travis.yml"
230
244
  - Gemfile
231
245
  - LICENSE.txt
232
246
  - README.md
@@ -243,6 +257,7 @@ files:
243
257
  - lib/dockly/cli.rb
244
258
  - lib/dockly/deb.rb
245
259
  - lib/dockly/docker.rb
260
+ - lib/dockly/docker/ecr.rb
246
261
  - lib/dockly/docker/registry.rb
247
262
  - lib/dockly/foreman.rb
248
263
  - lib/dockly/history.rb
@@ -255,6 +270,7 @@ files:
255
270
  - lib/dockly/version.rb
256
271
  - lib/foreman/cli_fix.rb
257
272
  - lib/foreman/export/base_fix.rb
273
+ - snippets/auth_ecr.erb
258
274
  - snippets/docker_tag_latest.erb
259
275
  - snippets/file_diff_docker_import.erb
260
276
  - snippets/file_docker_import.erb
@@ -272,6 +288,7 @@ files:
272
288
  - spec/dockly/build_cache/local_spec.rb
273
289
  - spec/dockly/cli_spec.rb
274
290
  - spec/dockly/deb_spec.rb
291
+ - spec/dockly/docker/ecr_spec.rb
275
292
  - spec/dockly/docker/registry_spec.rb
276
293
  - spec/dockly/docker_spec.rb
277
294
  - spec/dockly/foreman_spec.rb
@@ -294,24 +311,24 @@ homepage: https://github.com/swipely/dockly
294
311
  licenses:
295
312
  - MIT
296
313
  metadata: {}
297
- post_install_message:
314
+ post_install_message:
298
315
  rdoc_options: []
299
316
  require_paths:
300
317
  - lib
301
318
  required_ruby_version: !ruby/object:Gem::Requirement
302
319
  requirements:
303
- - - ! '>='
320
+ - - ">="
304
321
  - !ruby/object:Gem::Version
305
322
  version: '0'
306
323
  required_rubygems_version: !ruby/object:Gem::Requirement
307
324
  requirements:
308
- - - ! '>'
325
+ - - ">="
309
326
  - !ruby/object:Gem::Version
310
- version: 1.3.1
327
+ version: '0'
311
328
  requirements: []
312
- rubyforge_project:
313
- rubygems_version: 2.6.2
314
- signing_key:
329
+ rubyforge_project:
330
+ rubygems_version: 2.5.1
331
+ signing_key:
315
332
  specification_version: 4
316
333
  summary: Packaging made easy
317
334
  test_files:
@@ -321,6 +338,7 @@ test_files:
321
338
  - spec/dockly/build_cache/local_spec.rb
322
339
  - spec/dockly/cli_spec.rb
323
340
  - spec/dockly/deb_spec.rb
341
+ - spec/dockly/docker/ecr_spec.rb
324
342
  - spec/dockly/docker/registry_spec.rb
325
343
  - spec/dockly/docker_spec.rb
326
344
  - spec/dockly/foreman_spec.rb
@@ -339,3 +357,4 @@ test_files:
339
357
  - spec/fixtures/test-2.tar.gz
340
358
  - spec/fixtures/test-3.tar
341
359
  - spec/spec_helper.rb
360
+ has_rdoc: