dockly 1.3.5 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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