Class: PicsolveDockerBuilder::Frame
- Inherits:
-
Object
- Object
- PicsolveDockerBuilder::Frame
show all
- Includes:
- Base
- Defined in:
- lib/picsolve_docker_builder/frame.rb
Overview
Docker image building template rubocop:disable Metrics/ClassLength
Instance Method Summary
collapse
Methods included from Base
#base_dir, #config, #config_file, #config_path, #config_paths, #read_config
Constructor Details
#initialize ⇒ Frame
Returns a new instance of Frame.
14
15
16
17
18
19
20
|
# File 'lib/picsolve_docker_builder/frame.rb', line 14
def initialize
Docker.options[:read_timeout] = 3600
Excon.defaults[:read_timeout] = 3600
config
end
|
Instance Method Details
#asset_build ⇒ Object
143
144
|
# File 'lib/picsolve_docker_builder/frame.rb', line 143
def asset_build
end
|
#asset_image ⇒ Object
387
388
389
|
# File 'lib/picsolve_docker_builder/frame.rb', line 387
def asset_image
@asset_image ||= fetch_asset_image
end
|
#asset_image_build ⇒ Object
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
|
# File 'lib/picsolve_docker_builder/frame.rb', line 353
def asset_image_build
tar_contents = {
'Dockerfile' => asset_image_dockerfile.join("\n"),
'.gitconfig' => [
'[user]',
'name = Jenkins London Picsolve',
'email = [email protected]'
].join("\n")
}
tar_contents['ssh_known_hosts'] = ssh_known_hosts if ssh_auth_forwarding?
tar = StringIO.new Docker::Util.create_tar(tar_contents)
begin
Docker::Image.build_from_tar(tar) do |stream|
s = JSON.parse(stream)['stream']
log.debug s.strip unless s.nil?
end
rescue StandardError => e
log.fatal "asset building failed: #{e}"
exit 1
end
end
|
#asset_image_dockerfile ⇒ Object
339
340
341
342
343
344
345
346
347
348
349
350
351
|
# File 'lib/picsolve_docker_builder/frame.rb', line 339
def asset_image_dockerfile
[
"FROM #{image_name}",
'MAINTAINER Picsolve Onlineops <[email protected]>',
dockerfile_hooks_asset_build_early,
"RUN useradd -m -d #{build_user_home} \\",
" -u #{build_user_uid} #{build_user}",
"ADD .gitconfig #{File.join(build_user_home, '.gitconfig')}",
ssh_auth_forwarding_dockerfile,
"RUN chown -cR #{build_user} #{build_user_home}",
dockerfile_hooks_asset_build_late
]
end
|
#build ⇒ Object
146
147
148
149
150
151
152
153
|
# File 'lib/picsolve_docker_builder/frame.rb', line 146
def build
asset_build
if dest_image_name.nil?
log.info 'Skip building docker image as no dest_image is set'
return
end
docker_build
end
|
#build_dir ⇒ Object
236
237
238
|
# File 'lib/picsolve_docker_builder/frame.rb', line 236
def build_dir
'/_build'
end
|
#build_mode ⇒ Object
46
47
48
49
50
51
52
|
# File 'lib/picsolve_docker_builder/frame.rb', line 46
def build_mode
return :template unless image_name.nil?
return :dockerfile if dockerfile_exists?
log.fatal 'No image_name configured and no Dockerfile present'
end
|
#build_user ⇒ Object
232
233
234
|
# File 'lib/picsolve_docker_builder/frame.rb', line 232
def build_user
'build'
end
|
#build_user_home ⇒ Object
228
229
230
|
# File 'lib/picsolve_docker_builder/frame.rb', line 228
def build_user_home
'/home/build'
end
|
#build_user_uid ⇒ Object
224
225
226
|
# File 'lib/picsolve_docker_builder/frame.rb', line 224
def build_user_uid
Process.uid.to_s
end
|
#container ⇒ Object
240
241
242
|
# File 'lib/picsolve_docker_builder/frame.rb', line 240
def container
@container ||= create_container
end
|
#create_container ⇒ Object
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
|
# File 'lib/picsolve_docker_builder/frame.rb', line 267
def create_container
command = ['/bin/sleep', '3600']
c = Docker::Container.create(
'Image' => asset_image.id,
'Cmd' => command,
'OpenStdin' => false,
'WorkingDir' => '/_build',
'Env' => environment
)
at_exit do
stop
end
log.debug "created a new container image=#{image_name} " \
"id=#{c.id} cmd=#{command}"
c
end
|
#create_logger ⇒ Object
391
392
393
394
395
|
# File 'lib/picsolve_docker_builder/frame.rb', line 391
def create_logger
log = Logger.new(STDOUT)
log.level = Logger::DEBUG
log
end
|
#default_config ⇒ Object
22
23
24
|
# File 'lib/picsolve_docker_builder/frame.rb', line 22
def default_config
{ 'docker' => {} }
end
|
#dest_image_name ⇒ Object
284
285
286
|
# File 'lib/picsolve_docker_builder/frame.rb', line 284
def dest_image_name
config['docker']['image_name']
end
|
#docker_build ⇒ Object
135
136
137
138
139
140
141
|
# File 'lib/picsolve_docker_builder/frame.rb', line 135
def docker_build
dockerfile
log.info "start docker image building with path #{base_dir}"
@docker_build = docker_build_build
end
|
#docker_build_build ⇒ Object
125
126
127
128
129
130
131
132
133
|
# File 'lib/picsolve_docker_builder/frame.rb', line 125
def docker_build_build
Docker::Image.build_from_dir(base_dir) do |stream|
s = JSON.parse(stream)['stream']
log.debug s.strip unless s.nil?
end
rescue StandardError => e
log.fatal "docker building failed: #{e}"
exit 1
end
|
#dockerfile ⇒ Object
159
160
161
162
163
164
165
166
167
168
|
# File 'lib/picsolve_docker_builder/frame.rb', line 159
def dockerfile
return unless build_mode == :template
File.open('Dockerfile', 'w') do |file|
dockerfile_template.each_line do |line|
log.debug "Dockerfile: #{line.strip}"
end
file.write(dockerfile_template)
end
end
|
#dockerfile_exists? ⇒ Boolean
170
171
172
|
# File 'lib/picsolve_docker_builder/frame.rb', line 170
def dockerfile_exists?
File.exist? dockerfile_path
end
|
#dockerfile_hooks_asset_build_early ⇒ Object
66
67
68
69
70
|
# File 'lib/picsolve_docker_builder/frame.rb', line 66
def dockerfile_hooks_asset_build_early
config['docker']['dockerfile_hooks']['asset_build']['early']
rescue NoMethodError
''
end
|
#dockerfile_hooks_asset_build_late ⇒ Object
72
73
74
75
76
|
# File 'lib/picsolve_docker_builder/frame.rb', line 72
def dockerfile_hooks_asset_build_late
config['docker']['dockerfile_hooks']['asset_build']['late']
rescue NoMethodError
''
end
|
#dockerfile_hooks_docker_build_early ⇒ Object
54
55
56
57
58
|
# File 'lib/picsolve_docker_builder/frame.rb', line 54
def dockerfile_hooks_docker_build_early
config['docker']['dockerfile_hooks']['docker_build']['early']
rescue NoMethodError
''
end
|
#dockerfile_hooks_docker_build_late ⇒ Object
60
61
62
63
64
|
# File 'lib/picsolve_docker_builder/frame.rb', line 60
def dockerfile_hooks_docker_build_late
config['docker']['dockerfile_hooks']['docker_build']['late']
rescue NoMethodError
''
end
|
#dockerfile_path ⇒ Object
155
156
157
|
# File 'lib/picsolve_docker_builder/frame.rb', line 155
def dockerfile_path
File.join(base_dir, 'Dockerfile')
end
|
#dockerfile_template ⇒ Object
174
175
176
|
# File 'lib/picsolve_docker_builder/frame.rb', line 174
def dockerfile_template
fail NotImplementedError
end
|
#dockerignore_template ⇒ Object
178
179
180
|
# File 'lib/picsolve_docker_builder/frame.rb', line 178
def dockerignore_template
fail NotImplementedError
end
|
#environment ⇒ Object
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
|
# File 'lib/picsolve_docker_builder/frame.rb', line 244
def environment
blacklist = %w(
SSH_CLIENT
SSH_CONNECTION
LD_LIBRARY_PATH
PATH
NVM_DIR
NVM_NODEJS_ORG_MIRROR)
keys = ENV.keys
keys = keys.reject do |key|
blacklist.include? key
end
env = keys.map do |key|
"#{key}=#{ENV[key]}"
end
env << "SSH_AUTH_SOCK=#{ssh_auth_forwarding_path}" if ssh_auth_forwarding?
env
end
|
#execute(cmd) ⇒ Object
26
27
28
29
30
31
|
# File 'lib/picsolve_docker_builder/frame.rb', line 26
def execute(cmd)
r = container.exec(cmd)
fail "Execution of cmd=#{cmd} failed" unless r[2] == 0
log.debug "executed container id=#{container.id} cmd=#{cmd} result=#{r}"
r
end
|
#execute_attach(cmd) ⇒ Object
33
34
35
36
37
38
39
40
41
42
43
44
|
# File 'lib/picsolve_docker_builder/frame.rb', line 33
def execute_attach(cmd)
log.debug "execute and attach container id=#{container.id} cmd=#{cmd}"
r = container.exec(
cmd
) do |_stream, chunk|
$stdout.write chunk
$stdout.flush
end
fail "Execution of cmd=#{cmd} failed" unless r[2] == 0
log.debug 'executed and attached container ' \
"id=#{container.id} cmd=#{cmd} exitcode=#{r[2]}"
end
|
#fetch_asset_image ⇒ Object
377
378
379
380
381
382
383
384
385
|
# File 'lib/picsolve_docker_builder/frame.rb', line 377
def fetch_asset_image
log.debug "pulling image '#{image_name}' from registry"
Docker::Image.create(
{ 'fromImage' => image_name },
PicsolveDockerBuilder::Helpers::Registry.creds
)
log.debug "building asset image from '#{image_name}'"
asset_image_build
end
|
#image_name ⇒ Object
300
301
302
303
304
305
306
307
308
309
310
|
# File 'lib/picsolve_docker_builder/frame.rb', line 300
def image_name
name = config['docker']['base_image']
if name.match(/:[a-z0-9\-_]+$/)
name
else
"#{name}:latest"
end
rescue NoMethodError
nil
end
|
#jenkins_build_number ⇒ Object
78
79
80
81
82
|
# File 'lib/picsolve_docker_builder/frame.rb', line 78
def jenkins_build_number
n = ENV['BUILD_NUMBER']
return nil if n.nil?
n.to_i
end
|
#log ⇒ Object
397
398
399
|
# File 'lib/picsolve_docker_builder/frame.rb', line 397
def log
@logger ||= create_logger
end
|
#push ⇒ Object
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
# File 'lib/picsolve_docker_builder/frame.rb', line 102
def push
fail 'No image found to be pushed' if @docker_build.nil?
tags.each do |tag|
repotag = "#{dest_image_name}:#{tag}"
log.info "pushing image with #{repotag}"
@docker_build.push(
PicsolveDockerBuilder::Helpers::Registry.creds,
tag: tag
) do |resp|
resp = JSON.parse resp
if resp.key? 'errorDetail'
message = "pushing image #{repotag} failed: #{resp['errorDetail']}"
log.fatal message
fail message
end
log.info "status pushing image #{repotag}: #{resp['status']}" \
if resp.key? 'status'
end
end
end
|
#runtime_image_name ⇒ Object
288
289
290
291
292
293
294
295
296
297
298
|
# File 'lib/picsolve_docker_builder/frame.rb', line 288
def runtime_image_name
name = config['docker']['runtime_image'] || image_name
if name.match(/:[a-z0-9\-_]+$/)
name
else
"#{name}:latest"
end
rescue NoMethodError
nil
end
|
#ssh_auth_forwarding? ⇒ Boolean
312
313
314
315
|
# File 'lib/picsolve_docker_builder/frame.rb', line 312
def ssh_auth_forwarding?
return true if config['docker']['ssh_auth_forwarding']
false
end
|
#ssh_auth_forwarding_dockerfile ⇒ Object
317
318
319
320
321
|
# File 'lib/picsolve_docker_builder/frame.rb', line 317
def ssh_auth_forwarding_dockerfile
return "\n" unless ssh_auth_forwarding?
"ADD ssh_known_hosts #{File.join(build_user_home, '.ssh/known_hosts')}"
end
|
#ssh_auth_forwarding_path ⇒ Object
323
324
325
|
# File 'lib/picsolve_docker_builder/frame.rb', line 323
def ssh_auth_forwarding_path
'/tmp/ssh_auth_sock/ssh_auth_sock'
end
|
#ssh_known_hosts ⇒ Object
335
336
337
|
# File 'lib/picsolve_docker_builder/frame.rb', line 335
def ssh_known_hosts
File.open(File.join(Dir.home, '.ssh/known_hosts')).read
end
|
#start ⇒ Object
190
191
192
193
194
|
# File 'lib/picsolve_docker_builder/frame.rb', line 190
def start
container.start('Binds' => volumes)
log.debug "started container id=#{container.id} volumes=#{volumes}"
end
|
#stop ⇒ Object
196
197
198
199
200
201
202
203
|
# File 'lib/picsolve_docker_builder/frame.rb', line 196
def stop
return if @container.nil?
container.stop
log.debug "stopped container id=#{container.id}"
container.remove
log.debug "removed container id=#{container.id}"
@container = nil
end
|
#tag ⇒ Object
90
91
92
93
94
95
96
97
98
99
100
|
# File 'lib/picsolve_docker_builder/frame.rb', line 90
def tag
fail 'No image found to tag' if @docker_build.nil?
tags.each do |tag|
log.info "tagging image with #{dest_image_name}:#{tag}"
@docker_build.tag(
repo: dest_image_name,
tag: tag,
force: true
)
end
end
|
84
85
86
87
88
|
# File 'lib/picsolve_docker_builder/frame.rb', line 84
def tags
t = ['latest']
t << "jenkins-#{jenkins_build_number}" unless jenkins_build_number.nil?
t
end
|
#validate_config(c) ⇒ Object
182
183
184
|
# File 'lib/picsolve_docker_builder/frame.rb', line 182
def validate_config(c)
validate_config_docker(c)
end
|
#validate_config_docker(c) ⇒ Object
186
187
188
|
# File 'lib/picsolve_docker_builder/frame.rb', line 186
def validate_config_docker(c)
c
end
|
#volume_ssh_auth_forwarding ⇒ Object
327
328
329
330
331
332
333
|
# File 'lib/picsolve_docker_builder/frame.rb', line 327
def volume_ssh_auth_forwarding
@ssh_auth_forwarding = Helpers::SshAuthForwarding.new
[
@ssh_auth_forwarding.dir,
File.dirname(ssh_auth_forwarding_path)
]
end
|
#volume_workspace ⇒ Object
205
206
207
208
209
210
|
# File 'lib/picsolve_docker_builder/frame.rb', line 205
def volume_workspace
[
base_dir,
build_dir
]
end
|
#volumes ⇒ Object
218
219
220
221
222
|
# File 'lib/picsolve_docker_builder/frame.rb', line 218
def volumes
volumes_array.map do |volume|
volume.join ':'
end
end
|
#volumes_array ⇒ Object
212
213
214
215
216
|
# File 'lib/picsolve_docker_builder/frame.rb', line 212
def volumes_array
volumes = [volume_workspace]
volumes << volume_ssh_auth_forwarding if ssh_auth_forwarding?
volumes
end
|