beaker-docker 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Beaker
4
+ # Docker hypervisor for Beaker acceptance testing framework
2
5
  class Docker < Beaker::Hypervisor
3
-
4
6
  # Docker hypvervisor initializtion
5
7
  # Env variables supported:
6
8
  # DOCKER_REGISTRY: Docker registry URL
@@ -10,13 +12,14 @@ module Beaker
10
12
  # or a role (String or Symbol) that identifies one or more hosts.
11
13
  # @param [Hash{Symbol=>String}] options Options to pass on to the hypervisor
12
14
  def initialize(hosts, options)
15
+ super
13
16
  require 'docker'
14
17
  @options = options
15
18
  @logger = options[:logger] || Beaker::Logger.new
16
19
  @hosts = hosts
17
20
 
18
21
  # increase the http timeouts as provisioning images can be slow
19
- default_docker_options = { :write_timeout => 300, :read_timeout => 300 }.merge(::Docker.options || {})
22
+ default_docker_options = { write_timeout: 300, read_timeout: 300 }.merge(::Docker.options || {})
20
23
  # Merge docker options from the entry in hosts file
21
24
  ::Docker.options = default_docker_options.merge(@options[:docker_options] || {})
22
25
 
@@ -37,13 +40,12 @@ module Beaker
37
40
  ::Docker.logger = @logger
38
41
 
39
42
  # Find out what kind of remote instance we are talking against
40
- if /swarm/.match?(@docker_version['Version'])
43
+ if @docker_version['Version'].include?('swarm')
41
44
  @docker_type = 'swarm'
42
- unless ENV['DOCKER_REGISTRY']
43
- raise "Using Swarm with beaker requires a private registry. Please setup the private registry and set the 'DOCKER_REGISTRY' env var"
44
- else
45
- @registry = ENV['DOCKER_REGISTRY']
46
- end
45
+ raise "Using Swarm with beaker requires a private registry. Please setup the private registry and set the 'DOCKER_REGISTRY' env var" unless ENV['DOCKER_REGISTRY']
46
+
47
+ @registry = ENV.fetch('DOCKER_REGISTRY', nil)
48
+
47
49
  elsif ::Docker.respond_to?(:podman?) && ::Docker.podman?
48
50
  @docker_type = 'podman'
49
51
  else
@@ -52,15 +54,15 @@ module Beaker
52
54
  end
53
55
 
54
56
  def install_and_run_ssh(host)
55
- def host.enable_root_login(host,opts)
57
+ def host.enable_root_login(host, _opts)
56
58
  logger.debug("Root login already enabled for #{host}")
57
59
  end
58
60
 
59
61
  # If the container is running ssh as its init process then this method
60
62
  # will cause issues.
61
- if /sshd/.match?(Array(host[:docker_cmd]).first)
63
+ if Array(host[:docker_cmd]).first&.include?('sshd')
62
64
  def host.ssh_service_restart
63
- self[:docker_container].exec(%w(kill -1 1))
65
+ self[:docker_container].exec(%w[kill -1 1])
64
66
  end
65
67
  end
66
68
 
@@ -69,49 +71,45 @@ module Beaker
69
71
 
70
72
  def get_container_opts(host, image_name)
71
73
  container_opts = {}
72
- if host['dockerfile']
73
- container_opts['ExposedPorts'] = {'22/tcp' => {} }
74
- end
75
-
76
- container_opts.merge! ( {
77
- 'Image' => image_name,
78
- 'Hostname' => host.name,
79
- 'HostConfig' => {
80
- 'PortBindings' => {
81
- '22/tcp' => [{ 'HostPort' => rand(1025..9999).to_s, 'HostIp' => '0.0.0.0'}]
82
- },
83
- 'PublishAllPorts' => true,
84
- 'RestartPolicy' => {
85
- 'Name' => 'always'
86
- }
87
- }
88
- } )
74
+ container_opts['ExposedPorts'] = { '22/tcp' => {} } if host['dockerfile']
75
+
76
+ container_opts.merge!({
77
+ 'Image' => image_name,
78
+ 'Hostname' => host.name,
79
+ 'HostConfig' => {
80
+ 'PortBindings' => {
81
+ '22/tcp' => [{ 'HostPort' => rand(1025..9999).to_s, 'HostIp' => '0.0.0.0' }],
82
+ },
83
+ 'PublishAllPorts' => true,
84
+ 'RestartPolicy' => {
85
+ 'Name' => 'always',
86
+ },
87
+ },
88
+ })
89
89
  end
90
90
 
91
91
  def get_container_image(host)
92
- @logger.debug("Creating image")
92
+ @logger.debug('Creating image')
93
93
 
94
- if host['use_image_as_is']
95
- return ::Docker::Image.create('fromImage' => host['image'])
96
- end
94
+ return ::Docker::Image.create('fromImage' => host['image']) if host['use_image_as_is']
97
95
 
98
96
  dockerfile = host['dockerfile']
99
97
  if dockerfile
100
98
  # assume that the dockerfile is in the repo and tests are running
101
99
  # from the root of the repo; maybe add support for external Dockerfiles
102
100
  # with external build dependencies later.
103
- if File.exist?(dockerfile)
104
- dir = File.expand_path(dockerfile).chomp(dockerfile)
105
- return ::Docker::Image.build_from_dir(
106
- dir,
107
- { 'dockerfile' => dockerfile,
108
- :rm => true,
109
- :buildargs => buildargs_for(host)
110
- }
111
- )
112
- else
113
- raise "Unable to find dockerfile at #{dockerfile}"
114
- end
101
+ raise "Unable to find dockerfile at #{dockerfile}" unless File.exist?(dockerfile)
102
+
103
+ dir = File.expand_path(dockerfile).chomp(dockerfile)
104
+ return ::Docker::Image.build_from_dir(
105
+ dir,
106
+ {
107
+ 'dockerfile' => dockerfile,
108
+ :rm => true,
109
+ :buildargs => buildargs_for(host),
110
+ },
111
+ )
112
+
115
113
  elsif host['use_image_entry_point']
116
114
  df = <<-DF
117
115
  FROM #{host['image']}
@@ -123,13 +121,12 @@ module Beaker
123
121
  return ::Docker::Image.build(df, { rm: true, buildargs: buildargs_for(host) })
124
122
  end
125
123
 
126
- return ::Docker::Image.build(dockerfile_for(host),
127
- { rm: true, buildargs: buildargs_for(host) })
124
+ ::Docker::Image.build(dockerfile_for(host), { rm: true, buildargs: buildargs_for(host) })
128
125
  end
129
126
 
130
127
  # Nested Docker scenarios
131
128
  def nested_docker?
132
- ENV['DOCKER_IN_DOCKER'] || ENV['WSLENV']
129
+ ENV['DOCKER_IN_DOCKER'] || ENV.fetch('WSLENV', nil)
133
130
  end
134
131
 
135
132
  # Find out where the ssh port is from the container
@@ -139,7 +136,7 @@ module Beaker
139
136
  def get_ssh_connection_info(container)
140
137
  ssh_connection_info = {
141
138
  ip: nil,
142
- port: nil
139
+ port: nil,
143
140
  }
144
141
 
145
142
  container_json = container.json
@@ -149,82 +146,76 @@ module Beaker
149
146
  ip = nil
150
147
  port = nil
151
148
  # Talking against a remote docker host which is a normal docker host
152
- if @docker_type == 'docker' && ENV['DOCKER_HOST'] && !ENV.fetch('DOCKER_HOST','').include?(':///') && !nested_docker?
153
- ip = URI.parse(ENV['DOCKER_HOST']).host
154
- else
149
+ if @docker_type == 'docker' && ENV.fetch('DOCKER_HOST', nil) && !ENV.fetch('DOCKER_HOST', '').include?(':///') && !nested_docker?
150
+ ip = URI.parse(ENV.fetch('DOCKER_HOST', nil)).host
151
+ elsif in_container? && !nested_docker?
155
152
  # Swarm or local docker host
156
- if in_container? && !nested_docker?
157
- gw = network_settings['Gateway']
158
- ip = gw unless (gw.nil? || gw.empty?)
159
- else
160
- # The many faces of container networking
161
-
162
- # Host to Container
163
- port22 = network_settings.dig('PortBindings','22/tcp')
164
- if port22.nil? && network_settings.key?('Ports') && !nested_docker?
165
- port22 = network_settings.dig('Ports','22/tcp')
166
- end
153
+ gw = network_settings['Gateway']
154
+ ip = gw unless gw.nil? || gw.empty?
155
+ else
156
+ # The many faces of container networking
167
157
 
168
- ip = port22[0]['HostIp'] if port22
169
- port = port22[0]['HostPort'] if port22
158
+ # Host to Container
159
+ port22 = network_settings.dig('PortBindings', '22/tcp')
160
+ port22 = network_settings.dig('Ports', '22/tcp') if port22.nil? && network_settings.key?('Ports') && !nested_docker?
170
161
 
171
- # Container to container
172
- unless ip && port
173
- ip = network_settings['IPAddress']
174
- port = ip && !ip.empty? ? 22 : nil
175
- end
162
+ ip = port22[0]['HostIp'] if port22
163
+ port = port22[0]['HostPort'] if port22
176
164
 
177
- # Container through gateway
178
- unless ip && port
179
- ip = network_settings['Gateway']
165
+ # Container to container
166
+ unless ip && port
167
+ ip = network_settings['IPAddress']
168
+ port = ip && !ip.empty? ? 22 : nil
169
+ end
180
170
 
181
- if ip && !ip.empty?
182
- port22 = network_settings.dig('PortBindings','22/tcp')
183
- port = port22[0]['HostPort'] if port22
184
- else
185
- port = nil
186
- end
187
- end
171
+ # Container through gateway
172
+ unless ip && port
173
+ ip = network_settings['Gateway']
188
174
 
189
- # Legacy fallback
190
- unless ip && port
191
- port22 = network_settings.dig('Ports','22/tcp')
192
- ip = port22[0]["HostIp"] if port22
175
+ if ip && !ip.empty?
176
+ port22 = network_settings.dig('PortBindings', '22/tcp')
193
177
  port = port22[0]['HostPort'] if port22
178
+ else
179
+ port = nil
194
180
  end
195
181
  end
182
+
183
+ # Legacy fallback
184
+ unless ip && port
185
+ port22 = network_settings.dig('Ports', '22/tcp')
186
+ ip = port22[0]['HostIp'] if port22
187
+ port = port22[0]['HostPort'] if port22
188
+ end
196
189
  end
197
190
 
198
191
  if host_config['NetworkMode'] != 'slirp4netns' && network_settings['IPAddress'] && !network_settings['IPAddress'].empty?
199
192
  ip = network_settings['IPAddress'] if ip.nil?
200
193
  else
201
- port22 = network_settings.dig('Ports','22/tcp')
194
+ port22 = network_settings.dig('Ports', '22/tcp')
202
195
  port = port22[0]['HostPort'] if port22
203
196
  end
204
197
 
205
- ssh_connection_info[:ip] = (ip == '0.0.0.0') ? '127.0.0.1' : ip
198
+ ssh_connection_info[:ip] = ip == '0.0.0.0' ? '127.0.0.1' : ip
206
199
  ssh_connection_info[:port] = port || '22'
207
200
  ssh_connection_info
208
201
  end
209
202
 
210
203
  def provision
211
- @logger.notify "Provisioning docker"
204
+ @logger.notify 'Provisioning docker'
212
205
 
213
206
  @hosts.each do |host|
214
207
  @logger.notify "provisioning #{host.name}"
215
208
 
216
209
  image = get_container_image(host)
217
210
 
218
- if host['tag']
219
- image.tag({:repo => host['tag']})
220
- end
211
+ image.tag({ repo: host['tag'] }) if host['tag']
221
212
 
222
213
  if @docker_type == 'swarm'
223
214
  image_name = "#{@registry}/beaker/#{image.id}"
224
- ret = ::Docker::Image.search(:term => image_name)
215
+ ret = ::Docker::Image.search(term: image_name)
225
216
  if ret.first.nil?
226
- @logger.debug("Image does not exist on registry. Pushing.")
227
- image.tag({:repo => image_name, :force => true})
217
+ @logger.debug('Image does not exist on registry. Pushing.')
218
+ image.tag({ repo: image_name, force: true })
228
219
  image.push
229
220
  end
230
221
  else
@@ -235,8 +226,8 @@ module Beaker
235
226
 
236
227
  container_opts = get_container_opts(host, image_name)
237
228
  if host['dockeropts'] || @options[:dockeropts]
238
- dockeropts = host['dockeropts'] ? host['dockeropts'] : @options[:dockeropts]
239
- dockeropts.each do |k,v|
229
+ dockeropts = host['dockeropts'] || @options[:dockeropts]
230
+ dockeropts.each do |k, v|
240
231
  container_opts[k] = v
241
232
  end
242
233
  end
@@ -251,12 +242,12 @@ module Beaker
251
242
  container_opts['HostConfig']['Binds'] = host['mount_folders'].values.map do |mount|
252
243
  host_path = File.expand_path(mount['host_path'])
253
244
  # When using docker_toolbox and getting a "(Driveletter):/" path, convert windows path to VM mount
254
- if ENV['DOCKER_TOOLBOX_INSTALL_PATH'] && host_path =~ /^.\:\//
255
- host_path = "/" + host_path.gsub(/^.\:/, host_path[/^(.)/].downcase)
256
- end
257
- a = [ host_path, mount['container_path'] ]
258
- if mount.has_key?('opts')
259
- a << mount['opts'] if mount.has_key?('opts')
245
+ host_path = "/#{host_path.gsub(/^.:/, host_path[/^(.)/].downcase)}" if ENV['DOCKER_TOOLBOX_INSTALL_PATH'] && host_path =~ %r{^.:/}
246
+ a = [host_path, mount['container_path']]
247
+
248
+ # TODO: rewrite this part
249
+ if mount.key?('opts')
250
+ a << mount['opts'] if mount.key?('opts')
260
251
  else
261
252
  a << mount['opts'] = 'z'
262
253
  end
@@ -265,9 +256,7 @@ module Beaker
265
256
  end
266
257
  end
267
258
 
268
- if host['docker_env']
269
- container_opts['Env'] = host['docker_env']
270
- end
259
+ container_opts['Env'] = host['docker_env'] if host['docker_env']
271
260
 
272
261
  # Fixup privileges
273
262
  #
@@ -282,11 +271,7 @@ module Beaker
282
271
  container_opts['HostConfig']['Privileged'] = container_opts['HostConfig']['Privileged'].nil? ? true : container_opts['HostConfig']['Privileged']
283
272
  end
284
273
 
285
- if host['docker_container_name']
286
- container_opts['name'] = host['docker_container_name']
287
- else
288
- container_opts['name'] = ['beaker', host.name, SecureRandom.uuid.split('-').last].join('-')
289
- end
274
+ container_opts['name'] = (host['docker_container_name'] || ['beaker', host.name, SecureRandom.uuid.split('-').last].join('-'))
290
275
 
291
276
  if host['docker_port_bindings']
292
277
  container_opts['ExposedPorts'] = {} if container_opts['ExposedPorts'].nil?
@@ -300,9 +285,9 @@ module Beaker
300
285
 
301
286
  @logger.debug("Creating container from image #{image_name}")
302
287
 
303
- ok=false
304
- retries=0
305
- while(!ok && (retries < 5))
288
+ ok = false
289
+ retries = 0
290
+ while !ok && (retries < 5)
306
291
  container = ::Docker::Container.create(container_opts)
307
292
 
308
293
  ssh_info = get_ssh_connection_info(container)
@@ -312,19 +297,19 @@ module Beaker
312
297
  container.delete(force: true)
313
298
  container = nil
314
299
 
315
- retries+=1
300
+ retries += 1
316
301
  next
317
302
  end
318
303
 
319
- ok=true
304
+ ok = true
320
305
  end
321
306
  else
322
307
  host['use_existing_container'] = true
323
308
  end
324
309
 
325
310
  if container.nil?
326
- raise RuntimeError, 'Cannot continue because no existing container ' +
327
- 'could be found and provisioning is disabled.'
311
+ raise 'Cannot continue because no existing container ' \
312
+ 'could be found and provisioning is disabled.'
328
313
  end
329
314
 
330
315
  fix_ssh(container) if @options[:provision] == false
@@ -364,19 +349,19 @@ module Beaker
364
349
  host['ip'] = ip
365
350
  host['port'] = port
366
351
  host['ssh'] = {
367
- :password => root_password,
368
- :port => port,
369
- :forward_agent => forward_ssh_agent,
370
- :auth_methods => ['password', 'publickey', 'hostbased', 'keyboard-interactive']
352
+ password: root_password,
353
+ port: port,
354
+ forward_agent: forward_ssh_agent,
355
+ auth_methods: %w[password publickey hostbased keyboard-interactive],
371
356
  }
372
357
 
373
358
  @logger.debug("node available as ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@#{ip} -p #{port}")
374
359
  host['docker_container_id'] = container.id
375
360
  host['docker_image_id'] = image.id
376
- host['vm_ip'] = container.json["NetworkSettings"]["IPAddress"].to_s
361
+ host['vm_ip'] = container.json['NetworkSettings']['IPAddress'].to_s
377
362
 
378
363
  def host.reboot
379
- @logger.warn("Rebooting containers is ineffective...ignoring")
364
+ @logger.warn('Rebooting containers is ineffective...ignoring')
380
365
  end
381
366
  end
382
367
 
@@ -386,92 +371,88 @@ module Beaker
386
371
  # This sideloads sshd after a container starts
387
372
  def install_ssh_components(container, host)
388
373
  case host['platform']
389
- when /ubuntu/, /debian/
390
- container.exec(%w(apt-get update))
391
- container.exec(%w(apt-get install -y openssh-server openssh-client))
392
- container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
393
- when /cumulus/
394
- container.exec(%w(apt-get update))
395
- container.exec(%w(apt-get install -y openssh-server openssh-client))
396
- container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
374
+ when /ubuntu/, /debian/, /cumulus/
375
+ container.exec(%w[apt-get update])
376
+ container.exec(%w[apt-get install -y openssh-server openssh-client])
377
+ container.exec(%w[sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*])
397
378
  when /el-[89]/, /fedora-(2[2-9]|3[0-9])/
398
- container.exec(%w(dnf clean all))
399
- container.exec(%w(dnf install -y sudo openssh-server openssh-clients))
400
- container.exec(%w(ssh-keygen -A))
401
- container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
379
+ container.exec(%w[dnf clean all])
380
+ container.exec(%w[dnf install -y sudo openssh-server openssh-clients])
381
+ container.exec(%w[ssh-keygen -A])
382
+ container.exec(%w[sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*])
402
383
  when /^el-/, /centos/, /fedora/, /redhat/, /eos/
403
- container.exec(%w(yum clean all))
404
- container.exec(%w(yum install -y sudo openssh-server openssh-clients))
405
- container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
406
- container.exec(%w(ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key))
407
- container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
384
+ container.exec(%w[yum clean all])
385
+ container.exec(%w[yum install -y sudo openssh-server openssh-clients])
386
+ container.exec(%w[ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key])
387
+ container.exec(%w[ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key])
388
+ container.exec(%w[sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*])
408
389
  when /opensuse/, /sles/
409
- container.exec(%w(zypper -n in openssh))
410
- container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
411
- container.exec(%w(ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key))
412
- container.exec(%w(sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config))
390
+ container.exec(%w[zypper -n in openssh])
391
+ container.exec(%w[ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key])
392
+ container.exec(%w[ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key])
393
+ container.exec(%w[sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config])
413
394
  when /archlinux/
414
- container.exec(%w(pacman --noconfirm -Sy archlinux-keyring))
415
- container.exec(%w(pacman --noconfirm -Syu))
416
- container.exec(%w(pacman -S --noconfirm openssh))
417
- container.exec(%w(ssh-keygen -A))
418
- container.exec(%w(sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config))
419
- container.exec(%w(systemctl enable sshd))
395
+ container.exec(%w[pacman --noconfirm -Sy archlinux-keyring])
396
+ container.exec(%w[pacman --noconfirm -Syu])
397
+ container.exec(%w[pacman -S --noconfirm openssh])
398
+ container.exec(%w[ssh-keygen -A])
399
+ container.exec(%w[sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config])
400
+ container.exec(%w[systemctl enable sshd])
420
401
  when /alpine/
421
- container.exec(%w(apk add --update openssh))
422
- container.exec(%w(ssh-keygen -A))
402
+ container.exec(%w[apk add --update openssh])
403
+ container.exec(%w[ssh-keygen -A])
423
404
  else
424
- # TODO add more platform steps here
405
+ # TODO: add more platform steps here
425
406
  raise "platform #{host['platform']} not yet supported on docker"
426
407
  end
427
408
 
428
409
  # Make sshd directory, set root password
429
- container.exec(%w(mkdir -p /var/run/sshd))
410
+ container.exec(%w[mkdir -p /var/run/sshd])
430
411
  container.exec(['/bin/sh', '-c', "echo root:#{root_password} | chpasswd"])
431
412
  end
432
413
 
433
414
  def cleanup
434
- @logger.notify "Cleaning up docker"
415
+ @logger.notify 'Cleaning up docker'
435
416
  @hosts.each do |host|
436
417
  # leave the container running if docker_preserve_container is set
437
418
  # setting docker_preserve_container also implies docker_preserve_image
438
419
  # is set, since you can't delete an image that's the base of a running
439
420
  # container
440
- unless host['docker_preserve_container']
441
- container = find_container(host)
442
- if container
443
- @logger.debug("stop container #{container.id}")
444
- begin
445
- container.kill
446
- sleep 2 # avoid a race condition where the root FS can't unmount
447
- rescue Excon::Errors::ClientError => e
448
- @logger.warn("stop of container #{container.id} failed: #{e.response.body}")
449
- end
450
- @logger.debug("delete container #{container.id}")
451
- begin
452
- container.delete(force: true)
453
- rescue Excon::Errors::ClientError => e
454
- @logger.warn("deletion of container #{container.id} failed: #{e.response.body}")
455
- end
421
+ next if host['docker_preserve_container']
422
+
423
+ container = find_container(host)
424
+ if container
425
+ @logger.debug("stop container #{container.id}")
426
+ begin
427
+ container.kill
428
+ sleep 2 # avoid a race condition where the root FS can't unmount
429
+ rescue Excon::Errors::ClientError => e
430
+ @logger.warn("stop of container #{container.id} failed: #{e.response.body}")
431
+ end
432
+ @logger.debug("delete container #{container.id}")
433
+ begin
434
+ container.delete(force: true)
435
+ rescue Excon::Errors::ClientError => e
436
+ @logger.warn("deletion of container #{container.id} failed: #{e.response.body}")
456
437
  end
438
+ end
457
439
 
458
- # Do not remove the image if docker_preserve_image is set to true, otherwise remove it
459
- unless host['docker_preserve_image']
460
- image_id = host['docker_image_id']
461
-
462
- if image_id
463
- @logger.debug("deleting image #{image_id}")
464
- begin
465
- ::Docker::Image.remove(image_id)
466
- rescue Excon::Errors::ClientError => e
467
- @logger.warn("deletion of image #{image_id} failed: #{e.response.body}")
468
- rescue ::Docker::Error::DockerError => e
469
- @logger.warn("deletion of image #{image_id} caused internal Docker error: #{e.message}")
470
- end
471
- else
472
- @logger.warn("Intended to delete the host's docker image, but host['docker_image_id'] was not set")
473
- end
440
+ # Do not remove the image if docker_preserve_image is set to true, otherwise remove it
441
+ next if host['docker_preserve_image']
442
+
443
+ image_id = host['docker_image_id']
444
+
445
+ if image_id
446
+ @logger.debug("deleting image #{image_id}")
447
+ begin
448
+ ::Docker::Image.remove(image_id)
449
+ rescue Excon::Errors::ClientError => e
450
+ @logger.warn("deletion of image #{image_id} failed: #{e.response.body}")
451
+ rescue ::Docker::Error::DockerError => e
452
+ @logger.warn("deletion of image #{image_id} caused internal Docker error: #{e.message}")
474
453
  end
454
+ else
455
+ @logger.warn("Intended to delete the host's docker image, but host['docker_image_id'] was not set")
475
456
  end
476
457
  end
477
458
  end
@@ -484,22 +465,20 @@ module Beaker
484
465
 
485
466
  def buildargs_for(host)
486
467
  docker_buildargs = {}
487
- docker_buildargs_env = ENV['DOCKER_BUILDARGS']
488
- if docker_buildargs_env != nil
489
- docker_buildargs_env.split(/ +|\t+/).each do |arg|
490
- key,value=arg.split(/=/)
491
- if key
492
- docker_buildargs[key]=value
493
- else
494
- @logger.warn("DOCKER_BUILDARGS environment variable appears invalid, no key found for value #{value}" )
495
- end
468
+ docker_buildargs_env = ENV.fetch('DOCKER_BUILDARGS', nil)
469
+ docker_buildargs_env&.split(/ +|\t+/)&.each do |arg|
470
+ key, value = arg.split('=')
471
+ if key
472
+ docker_buildargs[key] = value
473
+ else
474
+ @logger.warn("DOCKER_BUILDARGS environment variable appears invalid, no key found for value #{value}")
496
475
  end
497
476
  end
498
- if docker_buildargs.empty?
499
- buildargs = host['docker_buildargs'] || {}
500
- else
501
- buildargs = docker_buildargs
502
- end
477
+ buildargs = if docker_buildargs.empty?
478
+ host['docker_buildargs'] || {}
479
+ else
480
+ docker_buildargs
481
+ end
503
482
  @logger.debug("Docker build buildargs: #{buildargs}")
504
483
  JSON.generate(buildargs)
505
484
  end
@@ -512,7 +491,7 @@ module Beaker
512
491
  DF
513
492
 
514
493
  # Commands before any other commands. Can be used for eg. proxy configuration
515
- dockerfile += (host['docker_image_first_commands'] || []).map { |cmd| "RUN #{cmd}\n" }.join('')
494
+ dockerfile += (host['docker_image_first_commands'] || []).map { |cmd| "RUN #{cmd}\n" }.join
516
495
 
517
496
  # add platform-specific actions
518
497
  service_name = 'sshd'
@@ -585,7 +564,7 @@ module Beaker
585
564
  DF
586
565
 
587
566
  # Any extra commands specified for the host
588
- dockerfile += (host['docker_image_commands'] || []).map { |cmd| "RUN #{cmd}\n" }.join('')
567
+ dockerfile += (host['docker_image_commands'] || []).map { |cmd| "RUN #{cmd}\n" }.join
589
568
 
590
569
  # Override image entrypoint
591
570
  dockerfile += "ENTRYPOINT #{host['docker_image_entrypoint']}\n" if host['docker_image_entrypoint']
@@ -640,24 +619,25 @@ module Beaker
640
619
 
641
620
  if id
642
621
  @logger.debug("Looking for an existing container with ID #{id}")
643
- container = containers.select { |c| c.id == id }.first
622
+ container = containers.find { |c| c.id == id }
644
623
  end
645
624
 
646
625
  if name && container.nil?
647
626
  @logger.debug("Looking for an existing container with name #{name}")
648
- container = containers.select do |c|
627
+ container = containers.find do |c|
649
628
  c.info['Names'].include? "/#{name}"
650
- end.first
629
+ end
651
630
  end
652
631
 
653
632
  return container unless container.nil?
654
- @logger.debug("Existing container not found")
655
- return nil
633
+
634
+ @logger.debug('Existing container not found')
635
+ nil
656
636
  end
657
637
 
658
638
  # return true if we are inside a docker container
659
639
  def in_container?
660
- return File.file?('/.dockerenv')
640
+ File.file?('/.dockerenv')
661
641
  end
662
642
  end
663
643
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BeakerDocker
4
- VERSION = '1.5.0'
4
+ VERSION = '2.0.0'
5
5
  end