dockly 1.3.5 → 1.4.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.
data/README.md CHANGED
@@ -142,9 +142,37 @@ In addition to the above attributes, `docker` has the following references:
142
142
  - allows multiple
143
143
  - class: `Dockly::BuildCache`
144
144
  - description: a caching system to stop rebuilding/compiling the same files every time
145
+ - `build_cache`
146
+ - required: `false`
147
+ - allows one
148
+ - class: `Dockly::Docker::Registry`
149
+ - description: a registry to push to in lieu of exporting as a tar -- the registry will be automatically pulled upon installing the debian package
145
150
 
146
151
  Need finer control of Docker packages? We also wrote [docker-api](https://github.com/swipely/docker-api).
147
152
 
153
+ `registry`
154
+ --------
155
+
156
+ The `registry` DSL is used to define Docker Registries. It has the following attributes:
157
+
158
+ - `authentication_required`
159
+ - required: `false`
160
+ - default: `true`
161
+ - description: a boolean that determines whether or not authentication is required on the registry.
162
+ - `username`
163
+ - required: `true` unless `authentication_required` is `false`
164
+ - description: the username to authenticate
165
+ - `email`:
166
+ - required: `true` unless `authentication_required` is `false`
167
+ - description: the email to authenticate
168
+ - `password`:
169
+ - required: `false`
170
+ - description: the user's password; unless supplied, `ENV['DOCKER_REGISTRY_PASSWORD']` will be checked. not that `ENV['DOCKER_REGISTRY_PASSWORD']` is required to be set on the host on to which the package will be deployed
171
+ - `server_address`:
172
+ - required: `true`
173
+ - default: `https://index.docker.io/v1`
174
+ - description: the server where the registry lives
175
+
148
176
  `foreman`
149
177
  ---------
150
178
 
data/lib/dockly.rb CHANGED
@@ -1,23 +1,20 @@
1
1
  require 'dockly/util'
2
+ require 'dockly/util/tar'
3
+ require 'dockly/util/git'
2
4
  require 'fog'
3
5
  require 'foreman/cli_fix'
4
6
  require 'foreman/export/base_fix'
5
7
 
6
- module Dockly
7
- end
8
-
9
- require 'dockly/aws'
10
- require 'dockly/foreman'
11
- require 'dockly/build_cache'
12
- require 'dockly/docker'
13
- require 'dockly/deb'
14
- require 'dockly/util/tar'
15
- require 'dockly/util/git'
16
-
17
8
  module Dockly
18
9
  attr_reader :instance, :git_sha
19
10
  attr_writer :load_file
20
11
 
12
+ autoload :AWS, 'dockly/aws'
13
+ autoload :Foreman, 'dockly/foreman'
14
+ autoload :BuildCache, 'dockly/build_cache'
15
+ autoload :Docker, 'dockly/docker'
16
+ autoload :Deb, 'dockly/deb'
17
+
21
18
  LOAD_FILE = 'dockly.rb'
22
19
 
23
20
  def load_file
data/lib/dockly/deb.rb CHANGED
@@ -92,7 +92,7 @@ private
92
92
  debug "converting to deb"
93
93
  @deb_package = @dir_package.convert(FPM::Package::Deb)
94
94
 
95
- @deb_package.scripts[:before_install] = pre_install
95
+ @deb_package.scripts[:before_install] = compile_pre_install
96
96
  @deb_package.scripts[:after_install] = post_install
97
97
  @deb_package.scripts[:before_remove] = pre_uninstall
98
98
  @deb_package.scripts[:after_remove] = post_uninstall
@@ -120,6 +120,7 @@ private
120
120
  return if docker.nil?
121
121
  info "adding docker image"
122
122
  docker.generate!
123
+ return unless docker.registry.nil?
123
124
  package.attributes[:prefix] = docker.package_dir
124
125
  Dir.chdir(File.dirname(docker.tar_path)) do
125
126
  package.input(File.basename(docker.tar_path))
@@ -138,4 +139,17 @@ private
138
139
  package.attributes[:prefix] = nil
139
140
  end
140
141
  end
142
+
143
+ def compile_pre_install
144
+ registry = !docker.nil? && docker.registry
145
+ if registry
146
+ [
147
+ pre_install,
148
+ "docker login -e '#{registry.email}' -p '$DOCKER_REGISTRY_PASSWORD' -u '#{registry.username}'",
149
+ "docker pull #{docker.repo}"
150
+ ].join("\n")
151
+ else
152
+ pre_install
153
+ end
154
+ end
141
155
  end
data/lib/dockly/docker.rb CHANGED
@@ -9,9 +9,12 @@ class Dockly::Docker
9
9
  include Dockly::Util::DSL
10
10
  include Dockly::Util::Logger::Mixin
11
11
 
12
+ autoload :Registry, 'dockly/docker/registry'
13
+
12
14
  logger_prefix '[dockly docker]'
13
15
 
14
16
  dsl_class_attribute :build_cache, Dockly::BuildCache.model, type: Array
17
+ dsl_class_attribute :registry, Dockly::Docker::Registry
15
18
 
16
19
  dsl_attribute :name, :import, :git_archive, :build, :tag, :build_dir, :package_dir,
17
20
  :timeout, :cleanup_images
@@ -26,17 +29,29 @@ class Dockly::Docker
26
29
  Docker.options = { :read_timeout => timeout, :write_timeout => timeout }
27
30
  docker_tar = File.absolute_path(ensure_tar(fetch_import))
28
31
 
29
- import = import_base(docker_tar)
32
+ images = {}
30
33
 
31
- cleanup = add_git_archive(import)
32
- cleanup = run_build_caches(cleanup)
33
- cleanup = build_image(cleanup)
34
+ images[:one] = import_base(docker_tar)
35
+ images[:two] = add_git_archive(images[:one])
36
+ images[:three] = run_build_caches(images[:two])
37
+ images[:four] = build_image(images[:three])
34
38
 
35
- export_image(cleanup)
39
+ export_image(images[:four])
36
40
 
37
41
  true
38
42
  ensure
39
- cleanup.remove if cleanup_images && !cleanup.nil?
43
+ cleanup(images.values.compact) if cleanup_images
44
+ end
45
+
46
+ def cleanup(images)
47
+ ::Docker::Container.all(:all => true).each do |container|
48
+ image_id = container.json['Image']
49
+ if images.any? { |image| image.id.start_with?(image_id) || image_id.start_with?(image.id) }
50
+ container.kill
51
+ container.delete
52
+ end
53
+ end
54
+ images.each { |image| image.remove rescue nil }
40
55
  end
41
56
 
42
57
  def export_filename
@@ -116,20 +131,47 @@ class Dockly::Docker
116
131
  info "starting build from #{image.id}"
117
132
  out_image = ::Docker::Image.build("from #{image.id}\n#{build}")
118
133
  info "built the image: #{out_image.id}"
119
- out_image.tag(:repo => name, :tag => tag)
134
+ out_image.tag(:repo => repo, :tag => tag)
120
135
  out_image
121
136
  end
122
137
 
138
+ def repo
139
+ @repo ||= case
140
+ when registry.nil?
141
+ name
142
+ when registry.default_server_address?
143
+ "#{registry.username}/#{name}"
144
+ else
145
+ "#{registry.server_address}/#{name}"
146
+ end
147
+ end
148
+
123
149
  def export_image(image)
124
- ensure_present! :name, :build_dir
125
- container = ::Docker::Container.create('Image' => image.id, 'Cmd' => %w[true])
126
- info "created the container: #{container.id}"
127
- Zlib::GzipWriter.open(tar_path) do |file|
128
- container.export do |chunk, remaining, total|
129
- file.write(chunk)
150
+ ensure_present! :name
151
+ if registry.nil?
152
+ ensure_present! :build_dir
153
+ container = ::Docker::Container.create('Image' => image.id, 'Cmd' => %w[true])
154
+ info "created the container: #{container.id}"
155
+ Zlib::GzipWriter.open(tar_path) do |file|
156
+ container.export do |chunk, remaining, total|
157
+ file.write(chunk)
158
+ end
130
159
  end
160
+ info "done writing the docker tar: #{export_filename}"
161
+ else
162
+ push_to_registry(image)
131
163
  end
132
- info "done writing the docker tar: #{export_filename}"
164
+ end
165
+
166
+ def push_to_registry(image)
167
+ ensure_present! :registry
168
+ info "Exporting #{image.id} to Docker registry at #{registry.server_address}"
169
+ registry.authenticate!
170
+ image = Docker::Image.all(:all => true).find { |img|
171
+ img.id.start_with?(image.id) || image.id.start_with?(img.id)
172
+ }
173
+ raise "Could not find image after authentication" if image.nil?
174
+ image.push(registry.to_h, :registry => registry.server_address)
133
175
  end
134
176
 
135
177
  def fetch_import
@@ -0,0 +1,42 @@
1
+ class Dockly::Docker::Registry
2
+ include Dockly::Util::DSL
3
+ include Dockly::Util::Logger::Mixin
4
+
5
+ DEFAULT_SERVER_ADDRESS = 'https://index.docker.io/v1/'
6
+
7
+ logger_prefix '[dockly docker registry]'
8
+
9
+ dsl_attribute :name, :server_address, :email, :username, :password,
10
+ :authentication_required
11
+
12
+ default_value :server_address, DEFAULT_SERVER_ADDRESS
13
+ default_value :authentication_required, true
14
+
15
+ alias_method :authentication_required?, :authentication_required
16
+
17
+ def authenticate!
18
+ return unless authentication_required?
19
+
20
+ @password ||= ENV['DOCKER_REGISTRY_PASSWORD']
21
+ ensure_present! :email, :password, :server_address, :username
22
+
23
+ debug "Attempting to authenticate at #{server_address}"
24
+ ::Docker.authenticate!(self.to_h)
25
+ info "Successfully authenticated at #{server_address} with username #{username}"
26
+ rescue ::Docker::Error::AuthenticationError
27
+ raise "Could not authenticate at #{server_address} with username #{username}"
28
+ end
29
+
30
+ def default_server_address?
31
+ server_address == DEFAULT_SERVER_ADDRESS
32
+ end
33
+
34
+ def to_h
35
+ {
36
+ 'serveraddress' => server_address,
37
+ 'email' => email,
38
+ 'username' => username,
39
+ 'password' => password
40
+ }
41
+ end
42
+ end
@@ -1,3 +1,3 @@
1
1
  module Dockly
2
- VERSION = '1.3.5'
2
+ VERSION = '1.4.0'
3
3
  end
@@ -59,9 +59,8 @@ describe Dockly::BuildCache::Docker, :docker do
59
59
 
60
60
  it "does have the file lol" do
61
61
  i = build_cache.execute!
62
- output = ""
63
- i.run('ls /').attach { |source,chunk| output += chunk }
64
- output.should include('lol')
62
+ output = i.run('ls /').attach(:stdout => true)
63
+ output.first.first.lines.map(&:chomp).should include('lol')
65
64
  end
66
65
  end
67
66
  end
@@ -152,7 +151,7 @@ describe Dockly::BuildCache::Docker, :docker do
152
151
  before do
153
152
  build_cache.parameter_command command
154
153
  end
155
- let(:output) { "3.8.0-27-generic" }
154
+ let(:output) { "3.12.9-2-ARCH" }
156
155
 
157
156
  context "when parameter command returns successfully" do
158
157
  let(:command) { "uname -r" }
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dockly::Docker::Registry, :current do
4
+ subject { described_class.new(:name => :dockly_registry) }
5
+
6
+ describe '#authenticate!' do
7
+ context 'when authentication is not required' do
8
+ before { subject.authentication_required false }
9
+
10
+ it 'does nothing' do
11
+ ::Docker.should_not_receive(:authenticate!)
12
+ subject.authenticate!
13
+ end
14
+ end
15
+
16
+ context 'when the password has not been supplied via the DSL' do
17
+ subject {
18
+ described_class.new(
19
+ :name => 'no-password',
20
+ :email => 'fake@email.com',
21
+ :username => 'fakeuser'
22
+ )
23
+ }
24
+
25
+ before { ::Docker.stub(:authenticate!) }
26
+
27
+ it 'prompts the user for the password' do
28
+ ENV.should_receive(:[]).and_return('password')
29
+ expect { subject.authenticate! }.to_not raise_error
30
+ end
31
+ end
32
+
33
+ context 'when the password has been supplied via the DSL' do
34
+ subject {
35
+ described_class.new(
36
+ :name => 'no-password',
37
+ :email => 'fake@email.com',
38
+ :password => 'fakepassword',
39
+ :username => 'fakeuser'
40
+ )
41
+ }
42
+
43
+ context 'when authentication succeeds' do
44
+ before { ::Docker.stub(:authenticate!) }
45
+
46
+ it 'does nothing' do
47
+ ENV.should_not_receive(:[])
48
+ expect { subject.authenticate! }.to_not raise_error
49
+ end
50
+ end
51
+
52
+ context 'when authentication fails' do
53
+ before do
54
+ ::Docker.stub(:authenticate!).and_raise(::Docker::Error::AuthenticationError)
55
+ end
56
+
57
+ it 'raieses an error' do
58
+ ENV.should_not_receive(:[])
59
+ expect { subject.authenticate! }.to raise_error
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -173,9 +173,9 @@ describe Dockly::Docker do
173
173
  paths << entry.header.name
174
174
  end
175
175
  paths.size.should be > 1000
176
- paths.should include('./sbin/init')
177
- paths.should include('./lib/dockly.rb')
178
- paths.should include('./it_worked')
176
+ paths.should include('sbin/init')
177
+ paths.should include('lib/dockly.rb')
178
+ paths.should include('it_worked')
179
179
  }.to change { ::Docker::Image.all(:all => true).length }.by(3)
180
180
  end
181
181
  end
@@ -191,6 +191,7 @@ describe Dockly::Docker do
191
191
  cleanup_images true
192
192
  end
193
193
  end
194
+
194
195
  it 'builds a docker image' do
195
196
  expect {
196
197
  subject.generate!
@@ -202,12 +203,33 @@ describe Dockly::Docker do
202
203
  paths << entry.header.name
203
204
  end
204
205
  paths.size.should be > 1000
205
- paths.should include('./sbin/init')
206
- paths.should include('./lib/dockly.rb')
207
- paths.should include('./it_worked')
208
- }.to change { ::Docker::Image.all(:all => true).length }.by(0)
206
+ paths.should include('sbin/init')
207
+ paths.should include('lib/dockly.rb')
208
+ paths.should include('it_worked')
209
+ }.to_not change { ::Docker::Image.all(:all => true).length }
210
+ end
211
+ end
212
+
213
+ context 'when there is a registry' do
214
+ subject {
215
+ Dockly::Docker.new do
216
+ import 'https://s3.amazonaws.com/swipely-pub/docker-export-ubuntu-latest.tgz'
217
+ git_archive '.'
218
+ build "run touch /it_worked"
219
+ repository 'dockly_test'
220
+ build_dir 'build/docker'
221
+
222
+ registry do
223
+ username 'nahiluhmot'
224
+ email 'tomhulihan@swipely.com'
225
+ end
226
+ end
227
+ }
228
+
229
+ it 'pushes the image to the registry instead of exporting it' do
230
+ subject.generate!
231
+ expect { ::Docker::Image.build('from nahiluhmot/dockly_test') }.to_not raise_error
209
232
  end
210
233
  end
211
234
  end
212
235
  end
213
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dockly
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.5
4
+ version: 1.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-13 00:00:00.000000000 Z
12
+ date: 2014-02-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: clamp
@@ -266,6 +266,7 @@ files:
266
266
  - lib/dockly/cli.rb
267
267
  - lib/dockly/deb.rb
268
268
  - lib/dockly/docker.rb
269
+ - lib/dockly/docker/registry.rb
269
270
  - lib/dockly/foreman.rb
270
271
  - lib/dockly/rake_task.rb
271
272
  - lib/dockly/util/git.rb
@@ -279,6 +280,7 @@ files:
279
280
  - spec/dockly/build_cache/local_spec.rb
280
281
  - spec/dockly/cli_spec.rb
281
282
  - spec/dockly/deb_spec.rb
283
+ - spec/dockly/docker/registry_spec.rb
282
284
  - spec/dockly/docker_spec.rb
283
285
  - spec/dockly/foreman_spec.rb
284
286
  - spec/dockly_spec.rb
@@ -323,6 +325,7 @@ test_files:
323
325
  - spec/dockly/build_cache/local_spec.rb
324
326
  - spec/dockly/cli_spec.rb
325
327
  - spec/dockly/deb_spec.rb
328
+ - spec/dockly/docker/registry_spec.rb
326
329
  - spec/dockly/docker_spec.rb
327
330
  - spec/dockly/foreman_spec.rb
328
331
  - spec/dockly_spec.rb