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