dockly 3.1.1 → 4.0.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
- 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