dockly 1.5.8 → 1.5.9
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/Gemfile +3 -0
- data/README.md +14 -0
- data/Rakefile +1 -0
- data/dockly.gemspec +1 -1
- data/lib/dockly.rb +2 -0
- data/lib/dockly/aws.rb +2 -0
- data/lib/dockly/aws/s3_writer.rb +59 -0
- data/lib/dockly/bash_builder.rb +29 -0
- data/lib/dockly/build_cache.rb +4 -4
- data/lib/dockly/build_cache/docker.rb +2 -2
- data/lib/dockly/cli.rb +36 -1
- data/lib/dockly/deb.rb +79 -23
- data/lib/dockly/docker.rb +83 -12
- data/lib/dockly/docker/registry.rb +1 -1
- data/lib/dockly/rake_task.rb +31 -2
- data/lib/dockly/tar_diff.rb +150 -0
- data/lib/dockly/version.rb +1 -1
- data/snippets/docker_import.erb +1 -0
- data/snippets/file_diff_docker_import.erb +4 -0
- data/snippets/file_docker_import.erb +1 -0
- data/snippets/get_and_install_deb.erb +2 -0
- data/snippets/get_from_s3.erb +11 -0
- data/snippets/install_package.erb +1 -0
- data/snippets/normalize_for_dockly.erb +12 -0
- data/snippets/registry_import.erb +1 -0
- data/snippets/s3_diff_docker_import.erb +14 -0
- data/snippets/s3_docker_import.erb +4 -0
- data/spec/dockly/aws/s3_writer_spec.rb +154 -0
- data/spec/dockly/bash_builder_spec.rb +138 -0
- data/spec/dockly/build_cache/local_spec.rb +1 -1
- data/spec/dockly/deb_spec.rb +16 -8
- data/spec/dockly/docker_spec.rb +104 -3
- data/spec/dockly/tar_diff_spec.rb +85 -0
- data/spec/fixtures/test-1.tar +0 -0
- data/spec/fixtures/test-3.tar +0 -0
- metadata +25 -4
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -16,6 +16,8 @@ Usage
|
|
16
16
|
-----
|
17
17
|
|
18
18
|
Once a `deb` block has been defined by the DSL below, dockly is invoked by either `bundle exec dockly build #{deb block name}` or `bundle exec rake dockly:deb:#{deb block name}`.
|
19
|
+
If looking to just build a `docker` block, run either `bundle exec dockly docker #{docker block name}` or `bundle exec rake dockly:docker:#{docker block name}`.
|
20
|
+
To build without exporting, run add either `--no-export` or `:noexport` to the CLI program or Rake task
|
19
21
|
|
20
22
|
The DSL
|
21
23
|
-------
|
@@ -142,6 +144,18 @@ The `docker` DSL is used to define Docker containers. It has the following attri
|
|
142
144
|
- required: `false`
|
143
145
|
- default: `[]`
|
144
146
|
- description: a listing of references to build caches to run
|
147
|
+
- `s3_bucket`
|
148
|
+
- required: `false`
|
149
|
+
- default: `nil`
|
150
|
+
- description: S3 bucket for where the docker image is exported
|
151
|
+
- `s3_object_prefix`
|
152
|
+
- required: `false`
|
153
|
+
- default: `nil`
|
154
|
+
- description: prefix to be added to S3 exported docker images
|
155
|
+
- `tar_diff`
|
156
|
+
- required: `false`
|
157
|
+
- default: `false`
|
158
|
+
- description: after docker export, performs a diff between the base image and the new image
|
145
159
|
|
146
160
|
In addition to the above attributes, `docker` has the following references:
|
147
161
|
|
data/Rakefile
CHANGED
data/dockly.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.require_paths = %w{lib}
|
16
16
|
gem.version = Dockly::VERSION
|
17
17
|
gem.add_dependency 'clamp', '~> 0.6'
|
18
|
-
gem.add_dependency 'docker-api', '>= 1.
|
18
|
+
gem.add_dependency 'docker-api', '>= 1.13.1'
|
19
19
|
gem.add_dependency 'dockly-util', '~> 0.0.8'
|
20
20
|
gem.add_dependency 'excon'
|
21
21
|
gem.add_dependency 'fog', '~> 1.21.0'
|
data/lib/dockly.rb
CHANGED
@@ -11,9 +11,11 @@ module Dockly
|
|
11
11
|
|
12
12
|
autoload :AWS, 'dockly/aws'
|
13
13
|
autoload :Foreman, 'dockly/foreman'
|
14
|
+
autoload :BashBuilder, 'dockly/bash_builder'
|
14
15
|
autoload :BuildCache, 'dockly/build_cache'
|
15
16
|
autoload :Docker, 'dockly/docker'
|
16
17
|
autoload :Deb, 'dockly/deb'
|
18
|
+
autoload :TarDiff, 'dockly/tar_diff'
|
17
19
|
|
18
20
|
LOAD_FILE = 'dockly.rb'
|
19
21
|
|
data/lib/dockly/aws.rb
CHANGED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Dockly
|
2
|
+
module AWS
|
3
|
+
class S3Writer
|
4
|
+
include Dockly::Util::Logger::Mixin
|
5
|
+
|
6
|
+
logger_prefix '[dockly s3writer]'
|
7
|
+
|
8
|
+
attr_accessor :buffer
|
9
|
+
attr_reader :connection, :s3_bucket, :s3_object, :upload_id
|
10
|
+
|
11
|
+
def initialize(connection, s3_bucket, s3_object)
|
12
|
+
@connection = connection
|
13
|
+
@s3_bucket = s3_bucket
|
14
|
+
@s3_object = s3_object
|
15
|
+
@parts = []
|
16
|
+
@closed = false
|
17
|
+
@buffer = ""
|
18
|
+
|
19
|
+
init_upload_res = connection.initiate_multipart_upload(s3_bucket, s3_object)
|
20
|
+
@upload_id = init_upload_res.body['UploadId']
|
21
|
+
end
|
22
|
+
|
23
|
+
def upload_buffer
|
24
|
+
res = connection.upload_part(s3_bucket, s3_object, upload_id, @parts.size + 1, buffer)
|
25
|
+
@parts << res.headers["ETag"]
|
26
|
+
debug "Writing a chunk"
|
27
|
+
@buffer = ""
|
28
|
+
end
|
29
|
+
|
30
|
+
def write(chunk)
|
31
|
+
self.buffer << chunk
|
32
|
+
|
33
|
+
upload_buffer if buffer.bytesize > 5242880
|
34
|
+
|
35
|
+
chunk.length
|
36
|
+
end
|
37
|
+
|
38
|
+
def close
|
39
|
+
return if @closed
|
40
|
+
upload_buffer unless buffer.empty?
|
41
|
+
|
42
|
+
res = connection.complete_multipart_upload(s3_bucket, s3_object, upload_id, @parts)
|
43
|
+
if res.body['Code'] || res.body['Message']
|
44
|
+
raise "Failed to upload to S3: #{res.body['Code']}: #{res.body['Message']}"
|
45
|
+
end
|
46
|
+
@closed = true
|
47
|
+
end
|
48
|
+
|
49
|
+
def abort
|
50
|
+
connection.abort_multipart_upload(s3_bucket, s3_object, upload_id)
|
51
|
+
end
|
52
|
+
|
53
|
+
def abort_unless_closed
|
54
|
+
abort unless @closed
|
55
|
+
@closed = true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Dockly
|
5
|
+
class BashBuilder
|
6
|
+
SNIPPET_PATH = File.expand_path("../../../snippets", __FILE__)
|
7
|
+
|
8
|
+
def self.generate_snippet_for(name, opts, defaults={})
|
9
|
+
define_method(name) do |*args|
|
10
|
+
zipped_array = opts.zip(args).flatten
|
11
|
+
snippet = File.read(File.join(SNIPPET_PATH, "#{name}.erb"))
|
12
|
+
hash = Hash[*zipped_array].delete_if { |_,v| v.nil? }
|
13
|
+
data = defaults.merge(hash)
|
14
|
+
ERB.new(snippet).result(binding)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
generate_snippet_for :normalize_for_dockly, []
|
19
|
+
generate_snippet_for :get_from_s3, [:s3_url, :output_path], { :output_path => "-" }
|
20
|
+
generate_snippet_for :install_package, [:path]
|
21
|
+
generate_snippet_for :get_and_install_deb, [:s3_url, :deb_path]
|
22
|
+
generate_snippet_for :docker_import, [:repo, :tag], { :tag => "latest" }
|
23
|
+
generate_snippet_for :file_docker_import, [:path, :repo, :tag]
|
24
|
+
generate_snippet_for :file_diff_docker_import, [:base_image, :diff_image, :repo, :tag]
|
25
|
+
generate_snippet_for :s3_docker_import, [:s3_url, :repo, :tag]
|
26
|
+
generate_snippet_for :s3_diff_docker_import, [:base_image, :diff_image, :repo, :tag]
|
27
|
+
generate_snippet_for :registry_import, [:repo, :tag], { :tag => "latest" }
|
28
|
+
end
|
29
|
+
end
|
data/lib/dockly/build_cache.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module Dockly::BuildCache
|
2
2
|
end
|
3
3
|
|
4
|
-
require 'dockly/build_cache/base'
|
5
|
-
require 'dockly/build_cache/docker'
|
6
|
-
require 'dockly/build_cache/local'
|
7
|
-
|
8
4
|
module Dockly::BuildCache
|
5
|
+
autoload :Base, 'dockly/build_cache/base'
|
6
|
+
autoload :Docker, 'dockly/build_cache/docker'
|
7
|
+
autoload :Local, 'dockly/build_cache/local'
|
8
|
+
|
9
9
|
class << self
|
10
10
|
attr_writer :model
|
11
11
|
|
@@ -59,7 +59,7 @@ class Dockly::BuildCache::Docker < Dockly::BuildCache::Base
|
|
59
59
|
container.wait(3600) # 1 hour max timeout
|
60
60
|
debug 'Restarting the container to copy the cache\'s output'
|
61
61
|
# Restart the container so we can copy its output
|
62
|
-
container = container.commit.run('sleep 3600')
|
62
|
+
container = container.commit.run('sleep 3600')
|
63
63
|
container.copy(output_directory) { |chunk| file.write(chunk.to_s) }
|
64
64
|
container.kill
|
65
65
|
file.tap(&:rewind)
|
@@ -88,7 +88,7 @@ class Dockly::BuildCache::Docker < Dockly::BuildCache::Base
|
|
88
88
|
resp = ""
|
89
89
|
debug "running command `#{command}` on image #{image.id}"
|
90
90
|
container = image.run(["/bin/bash", "-lc", "cd #{command_directory} && #{command}"])
|
91
|
-
container.attach { |source,chunk| resp += chunk }
|
91
|
+
container.attach(logs: true) { |source,chunk| resp += chunk }
|
92
92
|
status = container.wait['StatusCode']
|
93
93
|
debug "`#{command}` returned the following output:"
|
94
94
|
debug resp.strip
|
data/lib/dockly/cli.rb
CHANGED
@@ -30,10 +30,44 @@ class Dockly::BuildCommand < Dockly::AbstractCommand
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
class Dockly::DockerCommand < Dockly::AbstractCommand
|
34
|
+
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
|
+
option ['-n', '--no-export'], :flag, 'do not export', :default => false, :attribute_name => :noexport
|
37
|
+
|
38
|
+
def execute
|
39
|
+
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
|
47
|
+
else
|
48
|
+
puts "Package already exists!"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
33
54
|
class Dockly::ListCommand < Dockly::AbstractCommand
|
34
55
|
def execute
|
35
56
|
super
|
36
|
-
Dockly.
|
57
|
+
dockers = Dockly.dockers.dup
|
58
|
+
debs = Dockly.debs
|
59
|
+
|
60
|
+
puts "Debs" unless debs.empty?
|
61
|
+
debs.each_with_index do |(name, package), index|
|
62
|
+
puts "#{index + 1}. #{name}"
|
63
|
+
if package.docker
|
64
|
+
dockers.delete(package.docker.name)
|
65
|
+
puts " - Docker: #{package.docker.name}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
puts "Dockers" unless dockers.empty?
|
70
|
+
dockers.each_with_index do |(name, docker), index|
|
37
71
|
puts "#{index + 1}. #{name}"
|
38
72
|
end
|
39
73
|
end
|
@@ -68,6 +102,7 @@ end
|
|
68
102
|
|
69
103
|
class Dockly::Cli < Dockly::AbstractCommand
|
70
104
|
subcommand ['build', 'b'], 'Create package', Dockly::BuildCommand
|
105
|
+
subcommand ['docker', 'd'], 'Generate docker image', Dockly::DockerCommand
|
71
106
|
subcommand ['list', 'l'], 'List packages', Dockly::ListCommand
|
72
107
|
subcommand ['build_cache', 'bc'], 'Build Cache commands', Dockly::BuildCacheCommand
|
73
108
|
end
|
data/lib/dockly/deb.rb
CHANGED
@@ -6,8 +6,8 @@ class Dockly::Deb
|
|
6
6
|
|
7
7
|
logger_prefix '[dockly deb]'
|
8
8
|
dsl_attribute :package_name, :version, :release, :arch, :build_dir,
|
9
|
-
:pre_install, :post_install, :pre_uninstall,
|
10
|
-
:s3_bucket, :files, :app_user
|
9
|
+
:deb_build_dir, :pre_install, :post_install, :pre_uninstall,
|
10
|
+
:post_uninstall, :s3_bucket, :files, :app_user
|
11
11
|
|
12
12
|
dsl_class_attribute :docker, Dockly::Docker
|
13
13
|
dsl_class_attribute :foreman, Dockly::Foreman
|
@@ -15,7 +15,8 @@ class Dockly::Deb
|
|
15
15
|
default_value :version, '0.0'
|
16
16
|
default_value :release, '0'
|
17
17
|
default_value :arch, 'x86_64'
|
18
|
-
default_value :build_dir, 'build
|
18
|
+
default_value :build_dir, 'build'
|
19
|
+
default_value :deb_build_dir, 'deb'
|
19
20
|
default_value :files, []
|
20
21
|
default_value :app_user, 'nobody'
|
21
22
|
|
@@ -24,8 +25,8 @@ class Dockly::Deb
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def create_package!
|
27
|
-
ensure_present! :build_dir
|
28
|
-
FileUtils.mkdir_p(build_dir)
|
28
|
+
ensure_present! :build_dir, :deb_build_dir
|
29
|
+
FileUtils.mkdir_p(File.join(build_dir, deb_build_dir))
|
29
30
|
FileUtils.rm(build_path) if File.exist?(build_path)
|
30
31
|
debug "exporting #{package_name} to #{build_path}"
|
31
32
|
build_package
|
@@ -46,8 +47,8 @@ class Dockly::Deb
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def build_path
|
49
|
-
ensure_present! :build_dir
|
50
|
-
|
50
|
+
ensure_present! :build_dir, :deb_build_dir
|
51
|
+
File.join(build_dir, deb_build_dir, output_filename)
|
51
52
|
end
|
52
53
|
|
53
54
|
def exists?
|
@@ -63,7 +64,7 @@ class Dockly::Deb
|
|
63
64
|
|
64
65
|
def upload_to_s3
|
65
66
|
return if s3_bucket.nil?
|
66
|
-
|
67
|
+
raise "Package wasn't created!" unless File.exist?(build_path)
|
67
68
|
info "uploading package to s3"
|
68
69
|
Dockly::AWS.s3.put_bucket(s3_bucket) rescue nil
|
69
70
|
Dockly::AWS.s3.put_object(s3_bucket, s3_object_name, File.new(build_path))
|
@@ -81,16 +82,26 @@ class Dockly::Deb
|
|
81
82
|
"#{package_name}_#{version}.#{release}_#{arch}.deb"
|
82
83
|
end
|
83
84
|
|
85
|
+
def startup_script
|
86
|
+
scripts = []
|
87
|
+
bb = Dockly::BashBuilder.new
|
88
|
+
scripts << bb.normalize_for_dockly
|
89
|
+
scripts << bb.get_and_install_deb(s3_url, "/opt/dockly/#{File.basename(s3_url)}")
|
90
|
+
|
91
|
+
scripts.join("\n")
|
92
|
+
end
|
93
|
+
|
84
94
|
private
|
85
95
|
def build_package
|
86
96
|
ensure_present! :package_name, :version, :release, :arch
|
87
97
|
|
88
98
|
info "building #{package_name}"
|
89
99
|
@dir_package = FPM::Package::Dir.new
|
90
|
-
add_docker(@dir_package)
|
91
100
|
add_foreman(@dir_package)
|
92
101
|
add_files(@dir_package)
|
93
102
|
add_docker_auth_config(@dir_package)
|
103
|
+
add_docker(@dir_package)
|
104
|
+
add_startup_script(@dir_package)
|
94
105
|
|
95
106
|
debug "converting to deb"
|
96
107
|
@deb_package = @dir_package.convert(FPM::Package::Deb)
|
@@ -119,18 +130,6 @@ private
|
|
119
130
|
package.attributes[:prefix] = nil
|
120
131
|
end
|
121
132
|
|
122
|
-
def add_docker(package)
|
123
|
-
return if docker.nil?
|
124
|
-
info "adding docker image"
|
125
|
-
docker.generate!
|
126
|
-
return unless docker.registry.nil?
|
127
|
-
package.attributes[:prefix] = docker.package_dir
|
128
|
-
Dir.chdir(File.dirname(docker.tar_path)) do
|
129
|
-
package.input(File.basename(docker.tar_path))
|
130
|
-
end
|
131
|
-
package.attributes[:prefix] = nil
|
132
|
-
end
|
133
|
-
|
134
133
|
def add_files(package)
|
135
134
|
return if files.empty?
|
136
135
|
info "adding files to package"
|
@@ -144,14 +143,71 @@ private
|
|
144
143
|
end
|
145
144
|
|
146
145
|
def add_docker_auth_config(package)
|
147
|
-
return if
|
146
|
+
return if (registry = get_registry).nil? || !registry.authentication_required?
|
148
147
|
info "adding docker config file"
|
149
148
|
registry.generate_config_file!
|
150
149
|
|
151
|
-
package.attributes[:prefix] =
|
150
|
+
package.attributes[:prefix] = registry.auth_config_file || "~#{app_user}"
|
152
151
|
Dir.chdir(File.dirname(registry.config_file)) do
|
153
152
|
package.input(File.basename(registry.config_file))
|
154
153
|
end
|
155
154
|
package.attributes[:prefix] = nil
|
156
155
|
end
|
156
|
+
|
157
|
+
def add_docker(package)
|
158
|
+
return if docker.nil? || docker.s3_bucket
|
159
|
+
info "adding docker image"
|
160
|
+
docker.generate!
|
161
|
+
return unless docker.registry.nil?
|
162
|
+
package.attributes[:prefix] = docker.package_dir
|
163
|
+
Dir.chdir(File.dirname(docker.tar_path)) do
|
164
|
+
package.input(File.basename(docker.tar_path))
|
165
|
+
end
|
166
|
+
package.attributes[:prefix] = nil
|
167
|
+
end
|
168
|
+
|
169
|
+
def get_registry
|
170
|
+
if docker && registry = docker.registry
|
171
|
+
registry
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def post_startup_script
|
176
|
+
scripts = ["#!/bin/bash"]
|
177
|
+
bb = Dockly::BashBuilder.new
|
178
|
+
scripts << bb.normalize_for_dockly
|
179
|
+
if get_registry
|
180
|
+
scripts << bb.registry_import(docker.repo, docker.tag)
|
181
|
+
elsif docker
|
182
|
+
if docker.s3_bucket.nil?
|
183
|
+
docker_output = File.join(docker.package_dir, docker.export_filename)
|
184
|
+
if docker.tar_diff
|
185
|
+
scripts << bb.file_diff_docker_import(docker.import, docker_output, docker.name, docker.tag)
|
186
|
+
else
|
187
|
+
scripts << bb.file_docker_import(docker_output, docker.name, docker.tag)
|
188
|
+
end
|
189
|
+
else
|
190
|
+
if docker.tar_diff
|
191
|
+
scripts << bb.s3_diff_docker_import(docker.import, docker.s3_url, docker.name, docker.tag)
|
192
|
+
else
|
193
|
+
scripts << bb.s3_docker_import(docker.s3_url, docker.name, docker.tag)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
scripts.join("\n")
|
198
|
+
end
|
199
|
+
|
200
|
+
def add_startup_script(package)
|
201
|
+
ensure_present! :build_dir
|
202
|
+
startup_script_path = File.join(build_dir, "dockly-startup.sh")
|
203
|
+
File.open(startup_script_path, 'w+') do |f|
|
204
|
+
f.write(post_startup_script)
|
205
|
+
f.chmod(0755)
|
206
|
+
end
|
207
|
+
package.attributes[:prefix] = "/opt/dockly"
|
208
|
+
Dir.chdir(build_dir) do
|
209
|
+
package.input("dockly-startup.sh")
|
210
|
+
end
|
211
|
+
package.attributes[:prefix] = nil
|
212
|
+
end
|
157
213
|
end
|
data/lib/dockly/docker.rb
CHANGED
@@ -17,13 +17,16 @@ class Dockly::Docker
|
|
17
17
|
dsl_class_attribute :registry, Dockly::Docker::Registry
|
18
18
|
|
19
19
|
dsl_attribute :name, :import, :git_archive, :build, :tag, :build_dir, :package_dir,
|
20
|
-
:timeout, :cleanup_images, :
|
20
|
+
:timeout, :cleanup_images, :tar_diff, :s3_bucket, :s3_object_prefix
|
21
21
|
|
22
22
|
default_value :tag, nil
|
23
23
|
default_value :build_dir, 'build/docker'
|
24
24
|
default_value :package_dir, '/opt/docker'
|
25
25
|
default_value :cleanup_images, false
|
26
26
|
default_value :timeout, 60
|
27
|
+
default_value :tar_diff, false
|
28
|
+
default_value :s3_bucket, nil
|
29
|
+
default_value :s3_object_prefix, ""
|
27
30
|
|
28
31
|
def generate!
|
29
32
|
image = generate_build
|
@@ -171,6 +174,10 @@ class Dockly::Docker
|
|
171
174
|
end
|
172
175
|
end
|
173
176
|
|
177
|
+
def s3_url
|
178
|
+
"s3://#{s3_bucket}/#{s3_object}"
|
179
|
+
end
|
180
|
+
|
174
181
|
def export_image(image)
|
175
182
|
ensure_present! :name
|
176
183
|
if registry.nil?
|
@@ -178,22 +185,74 @@ class Dockly::Docker
|
|
178
185
|
info "Exporting the image with id #{image.id} to file #{File.expand_path(tar_path)}"
|
179
186
|
container = image.run('true')
|
180
187
|
info "created the container: #{container.id}"
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
system(command)
|
185
|
-
raise "Could not export image, exit code: #{$?}" unless $?.success?
|
188
|
+
|
189
|
+
unless s3_bucket.nil?
|
190
|
+
output = Dockly::AWS::S3Writer.new(connection, s3_bucket, s3_object)
|
186
191
|
else
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
+
output = File.open(tar_path, 'wb')
|
193
|
+
end
|
194
|
+
|
195
|
+
gzip_output = Zlib::GzipWriter.new(output)
|
196
|
+
|
197
|
+
if tar_diff
|
198
|
+
export_image_diff(container, gzip_output)
|
199
|
+
else
|
200
|
+
export_image_whole(container, gzip_output)
|
192
201
|
end
|
193
|
-
info "done writing the docker tar: #{export_filename}"
|
194
202
|
else
|
195
203
|
push_to_registry(image)
|
196
204
|
end
|
205
|
+
rescue
|
206
|
+
if output && !s3_bucket.nil?
|
207
|
+
output.abort_unless_closed
|
208
|
+
end
|
209
|
+
raise
|
210
|
+
ensure
|
211
|
+
gzip_output.close if gzip_output
|
212
|
+
end
|
213
|
+
|
214
|
+
def export_image_whole(container, output)
|
215
|
+
container.export do |chunk, remaining, total|
|
216
|
+
output.write(chunk)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def export_image_diff(container, output)
|
221
|
+
rd, wr = IO.pipe(Encoding::ASCII_8BIT)
|
222
|
+
|
223
|
+
rd.binmode
|
224
|
+
wr.binmode
|
225
|
+
|
226
|
+
thread = Thread.new do
|
227
|
+
begin
|
228
|
+
if Dockly::Util::Tar.is_tar?(fetch_import)
|
229
|
+
base = File.open(fetch_import, 'rb')
|
230
|
+
else
|
231
|
+
base = Zlib::GzipReader.new(File.open(fetch_import, 'rb'))
|
232
|
+
end
|
233
|
+
td = Dockly::TarDiff.new(base, rd, output)
|
234
|
+
td.process
|
235
|
+
info "done writing the docker tar: #{export_filename}"
|
236
|
+
ensure
|
237
|
+
base.close if base
|
238
|
+
rd.close
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
begin
|
243
|
+
container.export do |chunk, remaining, total|
|
244
|
+
wr.write(chunk)
|
245
|
+
end
|
246
|
+
ensure
|
247
|
+
wr.close
|
248
|
+
thread.join
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def s3_object
|
253
|
+
output = "#{s3_object_prefix}"
|
254
|
+
output << "#{Dockly::Util::Git.git_sha}/"
|
255
|
+
output << "#{export_filename}"
|
197
256
|
end
|
198
257
|
|
199
258
|
def push_to_registry(image)
|
@@ -235,6 +294,18 @@ class Dockly::Docker
|
|
235
294
|
path
|
236
295
|
end
|
237
296
|
|
297
|
+
def exists?
|
298
|
+
return false unless s3_bucket
|
299
|
+
debug "#{name}: checking for package: #{s3_url}"
|
300
|
+
Dockly::AWS.s3.head_object(s3_bucket, s3_object)
|
301
|
+
info "#{name}: found package: #{s3_url}"
|
302
|
+
true
|
303
|
+
rescue
|
304
|
+
info "#{name}: could not find package: " +
|
305
|
+
"#{s3_url}"
|
306
|
+
false
|
307
|
+
end
|
308
|
+
|
238
309
|
def repository(value = nil)
|
239
310
|
name(value)
|
240
311
|
end
|