dockly 3.1.1 → 4.0.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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ODQyMjgwNGJkYWE2YThjOTI1OTAxZWRlZmY5ZmIyNThhOThjNWFkMQ==
5
- data.tar.gz: !binary |-
6
- MjgxMDZlMTFmN2QxODZlYTJmZjRlZTJlMzlmNmJmNDA2ODZmNmRmNw==
2
+ SHA256:
3
+ metadata.gz: cdd9e8a044854b4149effa288483edb90a66ee8f58d35108696f0abc3a21ed95
4
+ data.tar.gz: 8ee450caf29059b5c7a389683676953c02f3c497809eef2287648504d59c9023
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NDk1ZjAzYmU3MGI3Njk0NDM5MDBkNWNhM2UyMWFiOGZmNDI5OGQ4MDA2Y2Zm
10
- MjE2MzYzOThkYzg1MzZkNTZjZTM0MjEwY2I1ZGMwZTM1OTY4MTQ5ZTk0MTZi
11
- ZGQyYzM4ODg2YjgyMmE4ZDYxMDIwZDY3ZDM3MGQyYmFkNDIyMTE=
12
- data.tar.gz: !binary |-
13
- MmM2YTFhODIzZWE3MTFlOWY4YTgyMGNlNzZkMWJiZmYxNDIzOTkxMTk1ZjMw
14
- MTQxOTE2ODA2NjM4OGFiNjhlNGQyOTk2YWM1OTQ0ZDRhNzZkYjNhNmRhNDIz
15
- NTg2ZjI1NTc5MWM3MzU3ZWFkNGJjZWUwZTVkYTA2MjQzMTg4ZTA=
6
+ metadata.gz: 2cf097573867f7c8ddafa597b0e0249780789fe098f6b4ffec3d48ae0b3dfc7cb6e48686214d846ab021c7cee5dec3bdd2c29f3423c1b82341d8173c2570fc05
7
+ data.tar.gz: 5bb556418f6b975bc1cd2dfffcb0117ee61379b6426be681a80961f4831976319f91fd78e0e81c94bcd4a5ce3a7a1bb093f39d77379b2bb1708d2da7e7cfbaae
@@ -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
@@ -10,8 +10,9 @@ require 'open3'
10
10
  module Dockly
11
11
  LOAD_FILE = 'dockly.rb'
12
12
 
13
- attr_reader :instance, :git_sha
14
- attr_writer :load_file
13
+ class << self
14
+ attr_writer :load_file
15
+ end
15
16
 
16
17
  autoload :Foreman, 'dockly/foreman'
17
18
  autoload :BashBuilder, 'dockly/bash_builder'
@@ -30,7 +31,7 @@ module Dockly
30
31
  @load_file || LOAD_FILE
31
32
  end
32
33
 
33
- def inst
34
+ def instance
34
35
  @instance ||= load_inst
35
36
  end
36
37
 
@@ -82,7 +83,7 @@ module Dockly
82
83
 
83
84
  [:debs, :rpms, :dockers, :foremans].each do |method|
84
85
  define_method(method) do
85
- inst[method]
86
+ instance[method]
86
87
  end
87
88
 
88
89
  module_function method
@@ -96,7 +97,7 @@ module Dockly
96
97
  }.each do |method, klass|
97
98
  define_method(method) do |sym, &block|
98
99
  if block.nil?
99
- inst[:"#{method}s"][sym]
100
+ instance[:"#{method}s"][sym]
100
101
  else
101
102
  klass.new!(:name => sym, &block)
102
103
  end
@@ -24,6 +24,7 @@ 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
29
  generate_snippet_for :docker_tag_latest, [:repo, :tag]
29
30
  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
@@ -14,17 +14,40 @@ class Dockly::AbstractCommand < Clamp::Command
14
14
  end
15
15
  end
16
16
 
17
- class Dockly::BuildCommand < Dockly::AbstractCommand
17
+ class Dockly::BuildOrCopyAllCommand < Dockly::AbstractCommand
18
+ def execute
19
+ super
20
+ Rake::Task["dockly:build_or_copy_all"].invoke
21
+ end
22
+ end
23
+
24
+ class Dockly::BuildDebCommand < Dockly::AbstractCommand
25
+ parameter 'PACKAGE', 'the name to build the package for', :attribute_name => :package_name
26
+ option ['-n', '--no-export'], :flag, 'do not export', :default => false, :attribute_name => :noexport
27
+
28
+ def execute
29
+ super
30
+ if Dockly.debs[package_name.to_sym]
31
+ if noexport?
32
+ Rake::Task["dockly:deb:prepare"].invoke(package_name)
33
+ else
34
+ Rake::Task["dockly:deb:build"].invoke(package_name)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ class Dockly::BuildRpmCommand < Dockly::AbstractCommand
18
41
  parameter 'PACKAGE', 'the name to build the package for', :attribute_name => :package_name
19
- option ['-f', '--force'], :flag, 'force the package build', :default => false, :attribute_name => :force
42
+ option ['-n', '--no-export'], :flag, 'do not export', :default => false, :attribute_name => :noexport
20
43
 
21
44
  def execute
22
45
  super
23
- if package = Dockly.debs[package_name.to_sym]
24
- if force? || !package.exists?
25
- package.build
46
+ if Dockly.rpms[package_name.to_sym]
47
+ if noexport?
48
+ Rake::Task["dockly:rpm:prepare"].invoke(package_name)
26
49
  else
27
- puts "Package already exists!"
50
+ Rake::Task["dockly:rpm:build"].invoke(package_name)
28
51
  end
29
52
  end
30
53
  end
@@ -32,20 +55,15 @@ end
32
55
 
33
56
  class Dockly::DockerCommand < Dockly::AbstractCommand
34
57
  parameter 'DOCKER', 'the name to generate the docker image for', :attribute_name => :docker_name
35
- option ['-f', '--force'], :flag, 'force the package build', :default => false, :attribute_name => :force
36
58
  option ['-n', '--no-export'], :flag, 'do not export', :default => false, :attribute_name => :noexport
37
59
 
38
60
  def execute
39
61
  super
40
- if docker = Dockly.dockers[docker_name.to_sym]
41
- if force? || !docker.exists?
42
- if noexport?
43
- docker.generate_build
44
- else
45
- docker.generate!
46
- end
62
+ if Dockly.dockers[docker_name.to_sym]
63
+ if noexport?
64
+ Rake::Task["dockly:docker:prepare"].invoke(docker_name)
47
65
  else
48
- puts "Package already exists!"
66
+ Rake::Task["dockly:docker:build"].invoke(docker_name)
49
67
  end
50
68
  end
51
69
  end
@@ -56,6 +74,7 @@ class Dockly::ListCommand < Dockly::AbstractCommand
56
74
  super
57
75
  dockers = Dockly.dockers.dup
58
76
  debs = Dockly.debs
77
+ rpms = Dockly.rpms
59
78
 
60
79
  puts "Debs" unless debs.empty?
61
80
  debs.each_with_index do |(name, package), index|
@@ -66,6 +85,15 @@ class Dockly::ListCommand < Dockly::AbstractCommand
66
85
  end
67
86
  end
68
87
 
88
+ puts "RPMs" unless rpms.empty?
89
+ rpms.each_with_index do |(name, package), index|
90
+ puts "#{index + 1}. #{name}"
91
+ if package.docker
92
+ dockers.delete(package.docker.name)
93
+ puts " - Docker: #{package.docker.name}"
94
+ end
95
+ end
96
+
69
97
  puts "Dockers" unless dockers.empty?
70
98
  dockers.each_with_index do |(name, docker), index|
71
99
  puts "#{index + 1}. #{name}"
@@ -104,7 +132,10 @@ class Dockly::BuildCacheCommand < Dockly::AbstractCommand
104
132
  end
105
133
 
106
134
  class Dockly::Cli < Dockly::AbstractCommand
107
- subcommand ['build', 'b'], 'Create package', Dockly::BuildCommand
135
+ subcommand ['build-or-copy-all'], 'Run build or copy all Rake task', Dockly::BuildOrCopyAllCommand
136
+ subcommand ['build', 'b'], 'Create deb package', Dockly::BuildDebCommand
137
+ subcommand ['build-deb', 'bd'], 'Create deb package', Dockly::BuildDebCommand
138
+ subcommand ['build-rpm', 'br'], 'Create RPM package', Dockly::BuildRpmCommand
108
139
  subcommand ['docker', 'd'], 'Generate docker image', Dockly::DockerCommand
109
140
  subcommand ['list', 'l'], 'List packages', Dockly::ListCommand
110
141
  subcommand ['build_cache', 'bc'], 'Build Cache commands', Dockly::BuildCacheCommand
@@ -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,51 @@ 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
+ scripts << bb.registry_import(docker.repo, docker.tag)
214
230
  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
231
+ scripts += collect_non_registry_scripts(bb)
220
232
  end
221
- scripts << bb.docker_tag_latest(docker.repo, docker.tag)
222
233
  end
234
+
223
235
  scripts.join("\n")
224
236
  end
225
237
 
226
- def add_startup_script(package)
238
+ def collect_non_registry_scripts(bb)
239
+ scripts = []
240
+
241
+ if docker.s3_bucket.nil?
242
+ docker_output = File.join(docker.package_dir, docker.export_filename)
243
+ if docker.tar_diff
244
+ scripts << bb.file_diff_docker_import(docker.import, docker_output, docker.name, docker.tag)
245
+ else
246
+ scripts << bb.file_docker_import(docker_output, docker.name, docker.tag)
247
+ end
248
+ else
249
+ if docker.tar_diff
250
+ scripts << bb.s3_diff_docker_import(docker.import, docker.s3_url, docker.name, docker.tag)
251
+ else
252
+ scripts << bb.s3_docker_import(docker.s3_url, docker.name, docker.tag)
253
+ end
254
+ end
255
+ scripts << bb.docker_tag_latest(docker.repo, docker.tag)
256
+ end
257
+
258
+ def add_startup_script(package, startup_script = "dockly-startup.sh")
227
259
  ensure_present! :build_dir
228
- startup_script_path = File.join(build_dir, "dockly-startup.sh")
260
+ startup_script_path = File.join(build_dir, startup_script)
229
261
  File.open(startup_script_path, 'w+') do |f|
230
262
  f.write(post_startup_script)
231
263
  f.chmod(0755)
232
264
  end
233
265
  package.attributes[:prefix] = "/opt/dockly"
234
266
  Dir.chdir(build_dir) do
235
- package.input("dockly-startup.sh")
267
+ package.input(startup_script)
236
268
  end
237
269
  package.attributes[:prefix] = nil
238
270
  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,13 +324,21 @@ 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?
341
+
325
342
  image.push(registry.to_h, :registry => registry.server_address)
326
343
  end
327
344
 
@@ -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
@@ -34,7 +34,7 @@ namespace :dockly do
34
34
 
35
35
  task :load do
36
36
  raise "No #{Dockly.load_file} found!" unless File.exist?(Dockly.load_file)
37
- Dockly.inst
37
+ Dockly.instance
38
38
  end
39
39
 
40
40
  task :assume_role => 'dockly:load' do
@@ -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,7 +1,7 @@
1
1
  module Dockly
2
- MAJOR = 3
3
- MINOR = 1
4
- PATCH = 1
2
+ MAJOR = 4
3
+ MINOR = 0
4
+ PATCH = 0
5
5
  RELEASE = nil
6
6
 
7
7
  VERSION = [MAJOR, MINOR, PATCH, RELEASE].compact.join('.')
@@ -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"
@@ -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
 
@@ -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.1.1
4
+ version: 4.0.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-03-26 00:00:00.000000000 Z
11
+ date: 2021-01-14 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,23 @@ 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
327
  version: '0'
311
328
  requirements: []
312
- rubyforge_project:
313
- rubygems_version: 2.6.2
314
- signing_key:
329
+ rubygems_version: 3.0.6
330
+ signing_key:
315
331
  specification_version: 4
316
332
  summary: Packaging made easy
317
333
  test_files:
@@ -321,6 +337,7 @@ test_files:
321
337
  - spec/dockly/build_cache/local_spec.rb
322
338
  - spec/dockly/cli_spec.rb
323
339
  - spec/dockly/deb_spec.rb
340
+ - spec/dockly/docker/ecr_spec.rb
324
341
  - spec/dockly/docker/registry_spec.rb
325
342
  - spec/dockly/docker_spec.rb
326
343
  - spec/dockly/foreman_spec.rb