beaker-docker 1.4.0 → 2.0.0

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.
@@ -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 @docker_version['Version'] =~ /swarm/
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 host[:docker_cmd] =~ /sshd/
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,86 +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
153
+ gw = network_settings['Gateway']
154
+ ip = gw unless gw.nil? || gw.empty?
155
+ else
156
+ # The many faces of container networking
161
157
 
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
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?
167
161
 
168
- ip = port22[0]['HostIp'] if port22
169
- port = port22[0]['HostPort'] if port22
162
+ ip = port22[0]['HostIp'] if port22
163
+ port = port22[0]['HostPort'] if port22
170
164
 
171
- # Container to container
172
- unless ip && port
173
- ip = nil
174
- port = nil
165
+ # Container to container
166
+ unless ip && port
167
+ ip = network_settings['IPAddress']
168
+ port = ip && !ip.empty? ? 22 : nil
169
+ end
175
170
 
176
- ip = network_settings['IPAddress']
177
- port = 22 if ip && !ip.empty?
178
- end
171
+ # Container through gateway
172
+ unless ip && port
173
+ ip = network_settings['Gateway']
179
174
 
180
- # Container through gateway
181
- unless ip && port
182
- ip = nil
175
+ if ip && !ip.empty?
176
+ port22 = network_settings.dig('PortBindings', '22/tcp')
177
+ port = port22[0]['HostPort'] if port22
178
+ else
183
179
  port = nil
184
-
185
- ip = network_settings['Gateway']
186
-
187
- if ip && !ip.empty?
188
- port22 = network_settings.dig('PortBindings','22/tcp')
189
- port = port22[0]['HostPort'] if port22
190
- end
191
180
  end
181
+ end
192
182
 
193
- # Legacy fallback
194
- unless ip && port
195
- port22 = network_settings.dig('Ports','22/tcp')
196
- ip = port22[0]["HostIp"] if port22
197
- port = port22[0]['HostPort'] if port22
198
- end
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
199
188
  end
200
189
  end
201
190
 
202
191
  if host_config['NetworkMode'] != 'slirp4netns' && network_settings['IPAddress'] && !network_settings['IPAddress'].empty?
203
192
  ip = network_settings['IPAddress'] if ip.nil?
204
193
  else
205
- port22 = network_settings.dig('Ports','22/tcp')
194
+ port22 = network_settings.dig('Ports', '22/tcp')
206
195
  port = port22[0]['HostPort'] if port22
207
196
  end
208
197
 
209
- 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
210
199
  ssh_connection_info[:port] = port || '22'
211
200
  ssh_connection_info
212
201
  end
213
202
 
214
203
  def provision
215
- @logger.notify "Provisioning docker"
204
+ @logger.notify 'Provisioning docker'
216
205
 
217
206
  @hosts.each do |host|
218
207
  @logger.notify "provisioning #{host.name}"
219
208
 
220
209
  image = get_container_image(host)
221
210
 
222
- if host['tag']
223
- image.tag({:repo => host['tag']})
224
- end
211
+ image.tag({ repo: host['tag'] }) if host['tag']
225
212
 
226
213
  if @docker_type == 'swarm'
227
214
  image_name = "#{@registry}/beaker/#{image.id}"
228
- ret = ::Docker::Image.search(:term => image_name)
215
+ ret = ::Docker::Image.search(term: image_name)
229
216
  if ret.first.nil?
230
- @logger.debug("Image does not exist on registry. Pushing.")
231
- 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 })
232
219
  image.push
233
220
  end
234
221
  else
@@ -239,8 +226,8 @@ module Beaker
239
226
 
240
227
  container_opts = get_container_opts(host, image_name)
241
228
  if host['dockeropts'] || @options[:dockeropts]
242
- dockeropts = host['dockeropts'] ? host['dockeropts'] : @options[:dockeropts]
243
- dockeropts.each do |k,v|
229
+ dockeropts = host['dockeropts'] || @options[:dockeropts]
230
+ dockeropts.each do |k, v|
244
231
  container_opts[k] = v
245
232
  end
246
233
  end
@@ -255,12 +242,12 @@ module Beaker
255
242
  container_opts['HostConfig']['Binds'] = host['mount_folders'].values.map do |mount|
256
243
  host_path = File.expand_path(mount['host_path'])
257
244
  # When using docker_toolbox and getting a "(Driveletter):/" path, convert windows path to VM mount
258
- if ENV['DOCKER_TOOLBOX_INSTALL_PATH'] && host_path =~ /^.\:\//
259
- host_path = "/" + host_path.gsub(/^.\:/, host_path[/^(.)/].downcase)
260
- end
261
- a = [ host_path, mount['container_path'] ]
262
- if mount.has_key?('opts')
263
- 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')
264
251
  else
265
252
  a << mount['opts'] = 'z'
266
253
  end
@@ -269,9 +256,7 @@ module Beaker
269
256
  end
270
257
  end
271
258
 
272
- if host['docker_env']
273
- container_opts['Env'] = host['docker_env']
274
- end
259
+ container_opts['Env'] = host['docker_env'] if host['docker_env']
275
260
 
276
261
  # Fixup privileges
277
262
  #
@@ -286,11 +271,7 @@ module Beaker
286
271
  container_opts['HostConfig']['Privileged'] = container_opts['HostConfig']['Privileged'].nil? ? true : container_opts['HostConfig']['Privileged']
287
272
  end
288
273
 
289
- if host['docker_container_name']
290
- container_opts['name'] = host['docker_container_name']
291
- else
292
- container_opts['name'] = ['beaker', host.name, SecureRandom.uuid.split('-').last].join('-')
293
- end
274
+ container_opts['name'] = (host['docker_container_name'] || ['beaker', host.name, SecureRandom.uuid.split('-').last].join('-'))
294
275
 
295
276
  if host['docker_port_bindings']
296
277
  container_opts['ExposedPorts'] = {} if container_opts['ExposedPorts'].nil?
@@ -304,9 +285,9 @@ module Beaker
304
285
 
305
286
  @logger.debug("Creating container from image #{image_name}")
306
287
 
307
- ok=false
308
- retries=0
309
- while(!ok && (retries < 5))
288
+ ok = false
289
+ retries = 0
290
+ while !ok && (retries < 5)
310
291
  container = ::Docker::Container.create(container_opts)
311
292
 
312
293
  ssh_info = get_ssh_connection_info(container)
@@ -316,19 +297,19 @@ module Beaker
316
297
  container.delete(force: true)
317
298
  container = nil
318
299
 
319
- retries+=1
300
+ retries += 1
320
301
  next
321
302
  end
322
303
 
323
- ok=true
304
+ ok = true
324
305
  end
325
306
  else
326
307
  host['use_existing_container'] = true
327
308
  end
328
309
 
329
310
  if container.nil?
330
- raise RuntimeError, 'Cannot continue because no existing container ' +
331
- 'could be found and provisioning is disabled.'
311
+ raise 'Cannot continue because no existing container ' \
312
+ 'could be found and provisioning is disabled.'
332
313
  end
333
314
 
334
315
  fix_ssh(container) if @options[:provision] == false
@@ -368,19 +349,19 @@ module Beaker
368
349
  host['ip'] = ip
369
350
  host['port'] = port
370
351
  host['ssh'] = {
371
- :password => root_password,
372
- :port => port,
373
- :forward_agent => forward_ssh_agent,
374
- :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],
375
356
  }
376
357
 
377
358
  @logger.debug("node available as ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@#{ip} -p #{port}")
378
359
  host['docker_container_id'] = container.id
379
360
  host['docker_image_id'] = image.id
380
- host['vm_ip'] = container.json["NetworkSettings"]["IPAddress"].to_s
361
+ host['vm_ip'] = container.json['NetworkSettings']['IPAddress'].to_s
381
362
 
382
363
  def host.reboot
383
- @logger.warn("Rebooting containers is ineffective...ignoring")
364
+ @logger.warn('Rebooting containers is ineffective...ignoring')
384
365
  end
385
366
  end
386
367
 
@@ -390,92 +371,88 @@ module Beaker
390
371
  # This sideloads sshd after a container starts
391
372
  def install_ssh_components(container, host)
392
373
  case host['platform']
393
- when /ubuntu/, /debian/
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/*))
397
- when /cumulus/
398
- container.exec(%w(apt-get update))
399
- container.exec(%w(apt-get install -y openssh-server openssh-client))
400
- 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/*])
401
378
  when /el-[89]/, /fedora-(2[2-9]|3[0-9])/
402
- container.exec(%w(dnf clean all))
403
- container.exec(%w(dnf install -y sudo openssh-server openssh-clients))
404
- container.exec(%w(ssh-keygen -A))
405
- 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/*])
406
383
  when /^el-/, /centos/, /fedora/, /redhat/, /eos/
407
- container.exec(%w(yum clean all))
408
- container.exec(%w(yum install -y sudo openssh-server openssh-clients))
409
- container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
410
- container.exec(%w(ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key))
411
- 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/*])
412
389
  when /opensuse/, /sles/
413
- container.exec(%w(zypper -n in openssh))
414
- container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
415
- container.exec(%w(ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key))
416
- 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])
417
394
  when /archlinux/
418
- container.exec(%w(pacman --noconfirm -Sy archlinux-keyring))
419
- container.exec(%w(pacman --noconfirm -Syu))
420
- container.exec(%w(pacman -S --noconfirm openssh))
421
- container.exec(%w(ssh-keygen -A))
422
- container.exec(%w(sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config))
423
- 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])
424
401
  when /alpine/
425
- container.exec(%w(apk add --update openssh))
426
- container.exec(%w(ssh-keygen -A))
402
+ container.exec(%w[apk add --update openssh])
403
+ container.exec(%w[ssh-keygen -A])
427
404
  else
428
- # TODO add more platform steps here
405
+ # TODO: add more platform steps here
429
406
  raise "platform #{host['platform']} not yet supported on docker"
430
407
  end
431
408
 
432
409
  # Make sshd directory, set root password
433
- container.exec(%w(mkdir -p /var/run/sshd))
410
+ container.exec(%w[mkdir -p /var/run/sshd])
434
411
  container.exec(['/bin/sh', '-c', "echo root:#{root_password} | chpasswd"])
435
412
  end
436
413
 
437
414
  def cleanup
438
- @logger.notify "Cleaning up docker"
415
+ @logger.notify 'Cleaning up docker'
439
416
  @hosts.each do |host|
440
417
  # leave the container running if docker_preserve_container is set
441
418
  # setting docker_preserve_container also implies docker_preserve_image
442
419
  # is set, since you can't delete an image that's the base of a running
443
420
  # container
444
- unless host['docker_preserve_container']
445
- container = find_container(host)
446
- if container
447
- @logger.debug("stop container #{container.id}")
448
- begin
449
- container.kill
450
- sleep 2 # avoid a race condition where the root FS can't unmount
451
- rescue Excon::Errors::ClientError => e
452
- @logger.warn("stop of container #{container.id} failed: #{e.response.body}")
453
- end
454
- @logger.debug("delete container #{container.id}")
455
- begin
456
- container.delete(force: true)
457
- rescue Excon::Errors::ClientError => e
458
- @logger.warn("deletion of container #{container.id} failed: #{e.response.body}")
459
- 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}")
460
437
  end
438
+ end
461
439
 
462
- # Do not remove the image if docker_preserve_image is set to true, otherwise remove it
463
- unless host['docker_preserve_image']
464
- image_id = host['docker_image_id']
465
-
466
- if image_id
467
- @logger.debug("deleting image #{image_id}")
468
- begin
469
- ::Docker::Image.remove(image_id)
470
- rescue Excon::Errors::ClientError => e
471
- @logger.warn("deletion of image #{image_id} failed: #{e.response.body}")
472
- rescue ::Docker::Error::DockerError => e
473
- @logger.warn("deletion of image #{image_id} caused internal Docker error: #{e.message}")
474
- end
475
- else
476
- @logger.warn("Intended to delete the host's docker image, but host['docker_image_id'] was not set")
477
- 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}")
478
453
  end
454
+ else
455
+ @logger.warn("Intended to delete the host's docker image, but host['docker_image_id'] was not set")
479
456
  end
480
457
  end
481
458
  end
@@ -488,22 +465,20 @@ module Beaker
488
465
 
489
466
  def buildargs_for(host)
490
467
  docker_buildargs = {}
491
- docker_buildargs_env = ENV['DOCKER_BUILDARGS']
492
- if docker_buildargs_env != nil
493
- docker_buildargs_env.split(/ +|\t+/).each do |arg|
494
- key,value=arg.split(/=/)
495
- if key
496
- docker_buildargs[key]=value
497
- else
498
- @logger.warn("DOCKER_BUILDARGS environment variable appears invalid, no key found for value #{value}" )
499
- 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}")
500
475
  end
501
476
  end
502
- if docker_buildargs.empty?
503
- buildargs = host['docker_buildargs'] || {}
504
- else
505
- buildargs = docker_buildargs
506
- end
477
+ buildargs = if docker_buildargs.empty?
478
+ host['docker_buildargs'] || {}
479
+ else
480
+ docker_buildargs
481
+ end
507
482
  @logger.debug("Docker build buildargs: #{buildargs}")
508
483
  JSON.generate(buildargs)
509
484
  end
@@ -516,7 +491,7 @@ module Beaker
516
491
  DF
517
492
 
518
493
  # Commands before any other commands. Can be used for eg. proxy configuration
519
- 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
520
495
 
521
496
  # add platform-specific actions
522
497
  service_name = 'sshd'
@@ -538,23 +513,20 @@ module Beaker
538
513
  dockerfile += <<~DF
539
514
  RUN dnf clean all \
540
515
  && dnf install -y sudo openssh-server openssh-clients #{additional_packages.join(' ')} \
541
- && ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key \
542
- && ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key \
516
+ && ssh-keygen -A \
543
517
  && sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
544
518
  DF
545
519
  when /^el-/, /centos/, /fedora/, /redhat/, /eos/
546
520
  dockerfile += <<~DF
547
521
  RUN yum clean all \
548
522
  && yum install -y sudo openssh-server openssh-clients #{additional_packages.join(' ')} \
549
- && ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key \
550
- && ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key \
523
+ && ssh-keygen -A \
551
524
  && sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
552
525
  DF
553
526
  when /opensuse/, /sles/
554
527
  dockerfile += <<~DF
555
528
  RUN zypper -n in openssh #{additional_packages.join(' ')} \
556
- && ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key \
557
- && ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key \
529
+ && ssh-keygen -A \
558
530
  && sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config \
559
531
  && sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
560
532
  DF
@@ -592,7 +564,7 @@ module Beaker
592
564
  DF
593
565
 
594
566
  # Any extra commands specified for the host
595
- dockerfile += (host['docker_image_commands'] || []).map { |cmd| "RUN #{cmd}\n" }.join('')
567
+ dockerfile += (host['docker_image_commands'] || []).map { |cmd| "RUN #{cmd}\n" }.join
596
568
 
597
569
  # Override image entrypoint
598
570
  dockerfile += "ENTRYPOINT #{host['docker_image_entrypoint']}\n" if host['docker_image_entrypoint']
@@ -622,7 +594,7 @@ module Beaker
622
594
  '-e', 's/^#?UseDNS .*/UseDNS no/',
623
595
  # Unbreak users with a bunch of SSH keys loaded in their keyring.
624
596
  '-e', 's/^#?MaxAuthTries.*/MaxAuthTries 1000/',
625
- '/etc/ssh/sshd_config'])
597
+ '/etc/ssh/sshd_config',])
626
598
 
627
599
  return unless host
628
600
 
@@ -647,24 +619,25 @@ module Beaker
647
619
 
648
620
  if id
649
621
  @logger.debug("Looking for an existing container with ID #{id}")
650
- container = containers.select { |c| c.id == id }.first
622
+ container = containers.find { |c| c.id == id }
651
623
  end
652
624
 
653
625
  if name && container.nil?
654
626
  @logger.debug("Looking for an existing container with name #{name}")
655
- container = containers.select do |c|
627
+ container = containers.find do |c|
656
628
  c.info['Names'].include? "/#{name}"
657
- end.first
629
+ end
658
630
  end
659
631
 
660
632
  return container unless container.nil?
661
- @logger.debug("Existing container not found")
662
- return nil
633
+
634
+ @logger.debug('Existing container not found')
635
+ nil
663
636
  end
664
637
 
665
638
  # return true if we are inside a docker container
666
639
  def in_container?
667
- return File.file?('/.dockerenv')
640
+ File.file?('/.dockerenv')
668
641
  end
669
642
  end
670
643
  end