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 +28 -0
- data/lib/dockly.rb +8 -11
- data/lib/dockly/deb.rb +15 -1
- data/lib/dockly/docker.rb +56 -14
- data/lib/dockly/docker/registry.rb +42 -0
- data/lib/dockly/version.rb +1 -1
- data/spec/dockly/build_cache/docker_spec.rb +3 -4
- data/spec/dockly/docker/registry_spec.rb +64 -0
- data/spec/dockly/docker_spec.rb +30 -8
- metadata +5 -2
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] =
|
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
|
-
|
32
|
+
images = {}
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
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(
|
39
|
+
export_image(images[:four])
|
36
40
|
|
37
41
|
true
|
38
42
|
ensure
|
39
|
-
cleanup.
|
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 =>
|
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
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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
|
-
|
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
|
data/lib/dockly/version.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
data/spec/dockly/docker_spec.rb
CHANGED
@@ -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('
|
177
|
-
paths.should include('
|
178
|
-
paths.should include('
|
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('
|
206
|
-
paths.should include('
|
207
|
-
paths.should include('
|
208
|
-
}.
|
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.
|
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-
|
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
|