This repository was archived by the owner on Nov 30, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathRakefile
More file actions
221 lines (185 loc) · 5.75 KB
/
Rakefile
File metadata and controls
221 lines (185 loc) · 5.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
require 'yaml'
require 'json'
require 'fileutils'
require 'tmpdir'
namespace :jobs do
desc "Update job specs"
task :update_spec do
include JobSpecs
update_job_specs
end
end
namespace :images do
desc "Export docker images locally; in Concourse get them via resources"
task :pull, [:image] do |_, args|
include ImageConfig
images(args[:image]).each do |image|
sh "docker pull #{image.name}" if ENV["DOCKER_PULL"]
FileUtils.mkdir_p(source_image_dir(File.dirname(image.tar)))
sh "docker save #{image.name} > #{source_image_dir(image.tar)}"
end
end
desc "Package exported images"
task :package do |_, args|
include DockerImagePackaging
include ImageConfig
# blobs might be in either/or blobs/docker_layers/* or in config/blobs.yml
downloaded_layers = Dir["blobs/docker_layers/*"].map {|b| File.basename(b) }
config_layers = YAML.load_file("config/blobs.yml").keys.
keep_if {|b| b =~ /^docker_layers/}.
map {|b| File.basename(b) }
existing_layers = (downloaded_layers + config_layers).uniq
required_layers = []
images.each do |image|
Dir.mktmpdir do |dir|
required_blobs = repackage_image_blobs(source_image_dir(image.tar), dir, image.name)
required_blobs.each do |b|
unless existing_layers.include?(b.target)
sh "bosh add blob #{b.blob_target(dir)} #{b.prefix}"
end
required_layers << b.target
end
create_package(image.package, required_blobs.map(&:package_spec_path))
end
end
puts "Removing unused blobs:"
remove_layers = existing_layers - required_layers
blobs = YAML.load_file("config/blobs.yml")
remove_layers.each do |layer_file|
puts "Removing #{layer_file}..."
FileUtils.rm_rf(File.join("blobs/docker_layers", layer_file))
blobs.delete(File.join("docker_layers", layer_file))
end
IO.write("config/blobs.yml", blobs.to_yaml)
end
task :cleanout do
FileUtils.rm_rf("blobs/docker_images")
file = "config/blobs.yml"
blobs = YAML.load_file(file)
blobs = blobs.keep_if { |blob, _| !(blob =~ /^(docker_images)/) }
IO.write(file, blobs.to_yaml)
end
end
module CommonDirs
def repo_dir
File.expand_path("../", __FILE__)
end
def source_image_dir(relative_path = "")
image_base_dir = ENV['IMAGE_BASE_DIR'] || File.join(repo_dir, 'tmp')
File.join(image_base_dir, relative_path)
end
def packages_dir(path = "")
File.join(repo_dir, 'packages', path)
end
def jobs_dir(path = "")
File.join(repo_dir, 'jobs', path)
end
end
module ImageConfig
include CommonDirs
def images(image = nil)
@images ||= begin
images = YAML.load_file(File.expand_path('../images.yml', __FILE__))
images.keep_if { |i| i['image'].to_s == image } if image
images.map! { |i| Image.new(i["image"], i["tag"], i["job"]) }
end
end
class Image
attr_reader :job
def initialize(name, tag, job)
@name = name
@tag = tag
@job = job
end
def name
@name + ":" + @tag
end
def package
name.gsub(/[\/\-\:\.]/, '_') + "_image"
end
# file that matches output from concourse docker-image-resource
def tar
"#{package}/image"
end
end
end
module JobSpecs
include CommonDirs
include ImageConfig
def packages_for_job(job)
images.select { |i| i.job == job }.map(&:package)
end
def update_job_specs
jobs = images.collect(&:job).uniq
jobs.each do |job|
file = "jobs/#{job}/spec"
spec = YAML.load_file(file)
spec["packages"] = packages_for_job(job)
IO.write(file, spec.to_yaml)
puts "Updated: #{file}"
end
end
end
module DockerImagePackaging
include CommonDirs
class Blob
attr_reader :source, :target_dir, :prefix
# target_dir is a folder akin to output from concourse/docker-image-resource
# with an +image+ file that is the `docker save` tgz file (see +source_blob+)
def initialize(source, target_name, prefix)
@source = source
@target_name = target_name
@prefix = prefix
end
def target
"#{@target_name}.tgz"
end
def blob_target(dir)
File.join(dir, target)
end
def package_spec_path
"#{@prefix}/#{target}"
end
end
def repackage_image_blobs(image_tar, tmp_layers_dir, image_name)
Dir.chdir(tmp_layers_dir) do
sh "tar -xf #{image_tar}"
sh "tree"
# Add tagging data so the correct tag will be applied on import
manifest = JSON.parse(File.read("manifest.json"))
manifest[0]["RepoTags"] = [image_name]
File.write("manifest.json", JSON.dump(manifest))
# Blob.new(source, target_name, prefix)
blobs = Dir.glob("*/").map! do |d|
Blob.new(d.chop, d.chop, 'docker_layers')
end
Dir.glob("*.json") do |json|
next if json =~ /manifest.json$/
blobs << Blob.new(json, File.basename(json), 'docker_images')
end
blobs << Blob.new('manifest.json', File.basename(File.dirname(image_tar)), 'docker_images')
package_blobs(blobs)
end
end
def package_blobs(blobs)
blobs.each { |b| sh "tar -zcf #{b.target} #{b.source}" }
end
def create_package(name, files)
package_dir = File.expand_path("../packages/#{name}", __FILE__)
FileUtils.mkdir_p package_dir
spec = { "name" => name, "files" => files }
IO.write(File.join(package_dir, 'spec'), spec.to_yaml)
IO.write(File.join(package_dir, 'packaging'), packaging_script)
end
def packaging_script
<<-END.gsub(/^ {6}/, '')
set -e; set -u
mkdir bits
cd bits
for layer in ../docker_layers/*.tgz; do tar -xf "$layer"; done
for layer in ../docker_images/*.tgz; do tar -xf "$layer"; done
tar -zcf image.tgz ./*
cp -a image.tgz $BOSH_INSTALL_TARGET
END
end
end