beaker-docker 0.5.3 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7b9f93de9358670645ea7e0c3bf982a7c822b8ca
4
- data.tar.gz: 19730ee76587c0e098504bf7bae15627c10f1603
2
+ SHA256:
3
+ metadata.gz: f21e88681130028d956057cc5d7e10242d3ab4b0dd3afdddc1e4a77b6a30376e
4
+ data.tar.gz: 27f935f63ebaf20d0eb18afcab7360dccdb6cc7e037cee4d6e9e3a45aed9ef33
5
5
  SHA512:
6
- metadata.gz: 78b6a3d9dda05f73f12861c8f3675647b3265428cfa634de30dbd89da20eac938353ecbf44c900079cdc1a7113a9f7304e13915c78c3f39426e1364be9fee0e8
7
- data.tar.gz: a88c7fe2fa9ec4655e629e1996310baa0154bfc8c69e7294f0111479c447f3ef878305df2cf14b8c4fcd36b272f761c06fa9181bfa330ed943e51a27f63eded5
6
+ metadata.gz: 419eee4542d7283b98c1c9e56fae980816123bd5b4f8f69920180815c0ac61d047f0a8523ac68dc091e6bff6c101d8782905ec18d8a8d571274e62588872f58d
7
+ data.tar.gz: 7aa8635232484d7b4ef171d1714ab59805cd82e1b8c0d44d70174b903805376cf08e8ce48030f33f0efeb8d4ce845b8f2ad6b0f3deeb30bef602ffa86b092387
@@ -0,0 +1,8 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ time: "13:00"
8
+ open-pull-requests-limit: 10
@@ -0,0 +1,32 @@
1
+ name: Test
2
+
3
+ on:
4
+ - pull_request
5
+
6
+ jobs:
7
+ test:
8
+ runs-on: ubuntu-latest
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby:
13
+ - "2.4"
14
+ - "2.5"
15
+ - "2.6"
16
+ - "2.7"
17
+ env:
18
+ BUNDLE_WITHOUT: release
19
+ name: Ruby ${{ matrix.ruby }}
20
+ steps:
21
+ - uses: actions/checkout@v2
22
+ - name: Install Ruby ${{ matrix.ruby }}
23
+ uses: ruby/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{ matrix.ruby }}
26
+ bundler-cache: true
27
+ - name: Run spec tests
28
+ run: bundle exec rake test:spec
29
+ # It seems some additonal setup of Docker may be needed for
30
+ # the acceptance tests to work.
31
+ # - name: Run acceptance tests
32
+ # run: bundle exec rake test:acceptance
data/README.md CHANGED
@@ -6,25 +6,94 @@ Beaker library to use docker hypervisor
6
6
 
7
7
  This gem that allows you to use hosts with [docker](docker.md) hypervisor with [beaker](https://github.com/puppetlabs/beaker).
8
8
 
9
- Beaker will automatically load the appropriate hypervisors for any given hosts file, so as long as your project dependencies are satisfied there's nothing else to do. No need to `require` this library in your tests.
9
+ Beaker will automatically load the appropriate hypervisors for any given hosts
10
+ file, so as long as your project dependencies are satisfied there's nothing else
11
+ to do. No need to `require` this library in your tests.
10
12
 
11
- ## With Beaker 3.x
12
-
13
- This library is included as a dependency of Beaker 3.x versions, so there's nothing to do.
14
-
15
- ## With Beaker 4.x
16
-
17
- As of Beaker 4.0, all hypervisor and DSL extension libraries have been removed and are no longer dependencies. In order to use a specific hypervisor or DSL extension library in your project, you will need to include them alongside Beaker in your Gemfile or project.gemspec. E.g.
13
+ In order to use a specific hypervisor or DSL extension library in your project,
14
+ you will need to include them alongside Beaker in your Gemfile or
15
+ project.gemspec. E.g.
18
16
 
19
17
  ~~~ruby
20
18
  # Gemfile
21
- gem 'beaker', '~>4.0'
22
- gem 'beaker-aws'
19
+ gem 'beaker', '~> 4.0'
20
+ gem 'beaker-docker'
23
21
  # project.gemspec
24
- s.add_runtime_dependency 'beaker', '~>4.0'
25
- s.add_runtime_dependency 'beaker-aws'
22
+ s.add_runtime_dependency 'beaker', '~> 4.0'
23
+ s.add_runtime_dependency 'beaker-docker'
24
+ ~~~
25
+
26
+ ## Nodeset Options
27
+
28
+ The following is a sample nodeset:
29
+
30
+ ~~~yaml
31
+ HOSTS:
32
+ el8:
33
+ platform: el-8-x86_64
34
+ hypervisor: docker
35
+ image: centos:8
36
+ docker_cmd: '["/sbin/init"]'
37
+ # Run arbitrary things
38
+ docker_image_commands:
39
+ - 'touch /tmp/myfile'
40
+ dockeropts:
41
+ Labels:
42
+ thing: 'stuff'
43
+ HostConfig:
44
+ Privileged: true
45
+ el7:
46
+ platform: el-7-x86_64
47
+ hypervisor: docker
48
+ image: centos:7
49
+ # EL7 images do not support nested systemd
50
+ docker_cmd: '/usr/sbin/sshd -D -E /var/log/sshd.log'
51
+ CONFIG:
52
+ docker_cap_add:
53
+ - AUDIT_WRITE
54
+ ~~~
55
+
56
+ ## Privileged containers
57
+
58
+ Containers are **not** run in privileged mode by default for safety.
59
+
60
+ If you wish to enable privileged mode, simply set the following in your node:
61
+
62
+ ~~~yaml
63
+ dockeropts:
64
+ HostConfig:
65
+ Privileged: true
66
+ ~~~
67
+
68
+ ## Cleaning up after tests
69
+
70
+ Containers created by this plugin may not be destroyed unless the tests complete
71
+ successfully. Each container created is prefixed by `beaker-` to make filtering
72
+ for clean up easier.
73
+
74
+ A quick way to clean up all nodes is as follows:
75
+
76
+ ~~~sh
77
+ podman rm -f $( podman ps -q -f name="beaker-*" )
26
78
  ~~~
27
79
 
80
+ # Working with `podman`
81
+
82
+ If you're using a version of `podman` that has API socket support then you
83
+ should be able to simply set `DOCKER_HOST` to your socket and connect as usual.
84
+
85
+ You also need to ensure that you're using a version of the `docker-api` gem that
86
+ supports `podman`.
87
+
88
+ You may find that not all of your tests work as expected. This will be due to
89
+ the tighter system restrictions placed on containers by `podman`. You may need
90
+ to edit the `dockeropts` hash in your nodeset to include different flags in the
91
+ `HostConfig` section.
92
+
93
+ See the
94
+ [HostConfig](https://any-api.com/docker_com/engine/docs/Definitions/HostConfig)
95
+ portion of the docker API for more information.
96
+
28
97
  # Spec tests
29
98
 
30
99
  Spec test live under the `spec` folder. There are the default rake task and therefore can run with a simple command:
@@ -34,7 +103,8 @@ bundle exec rake test:spec
34
103
 
35
104
  # Acceptance tests
36
105
 
37
- There is a simple rake task to invoke acceptance test for the library:
106
+ There is a simple rake task to invoke acceptance test for the library:
107
+
38
108
  ```bash
39
109
  bundle exec rake test:acceptance
40
110
  ```
@@ -42,3 +112,14 @@ bundle exec rake test:acceptance
42
112
  # Contributing
43
113
 
44
114
  Please refer to puppetlabs/beaker's [contributing](https://github.com/puppetlabs/beaker/blob/master/CONTRIBUTING.md) guide.
115
+
116
+ # Releasing
117
+
118
+ To release new versions of beaker-docker, please use this [jenkins job](https://cinext-jenkinsmaster-sre-prod-1.delivery.puppetlabs.net/view/all/job/qe_beaker-docker_init-multijob_master/). This job
119
+ lives on Puppet-internal infrastructure, so you'll need to be a part of the Puppet org to do this.
120
+
121
+ To run the job, click on `Build with Parameters` in the menu on the left. Make
122
+ sure you check the box next to `PUBLIC` and enter the appropriate version. The
123
+ version should adhere to [semantic version standards](https://semver.org).
124
+ When in doubt, consult the [maintainers of Beaker](https://github.com/puppetlabs/beaker/blob/master/CODEOWNERS)
125
+ for guidance.
data/Rakefile CHANGED
@@ -6,14 +6,14 @@ namespace :test do
6
6
 
7
7
  desc "Run spec tests"
8
8
  RSpec::Core::RakeTask.new(:run) do |t|
9
- t.rspec_opts = ['--color']
9
+ t.rspec_opts = ['--color', '--format documentation']
10
10
  t.pattern = 'spec/'
11
11
  end
12
12
 
13
13
  desc "Run spec tests with coverage"
14
14
  RSpec::Core::RakeTask.new(:coverage) do |t|
15
15
  ENV['BEAKER_DOCKER_COVERAGE'] = 'y'
16
- t.rspec_opts = ['--color']
16
+ t.rspec_opts = ['--color', '--format documentation']
17
17
  t.pattern = 'spec/'
18
18
  end
19
19
 
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  HOSTS:
3
- ubuntu1604-64-1:
4
- platform: ubuntu-1604-x86_64
3
+ centos8:
4
+ platform: el-8-x86_64
5
5
  hypervisor: docker
6
- image: ubuntu:16.04
6
+ image: centos:8
7
7
  roles:
8
8
  - master
9
9
  - agent
@@ -12,22 +12,24 @@ HOSTS:
12
12
  - classifier
13
13
  - default
14
14
  docker_cmd: '["/sbin/init"]'
15
+ docker_cap_add:
16
+ - AUDIT_WRITE
15
17
  dockeropts:
16
18
  Labels:
17
19
  one: '1'
18
20
  two: '2'
19
- ubuntu1604-64-2:
20
- platform: ubuntu-1604-x86_64
21
+ centos7:
22
+ platform: el-7-x86_64
21
23
  hypervisor: docker
22
- image: ubuntu:16.04
24
+ image: centos:7
23
25
  roles:
24
26
  - agent
25
- docker_cmd: '["/sbin/init"]'
27
+ docker_cmd: '/usr/sbin/sshd -D -E /var/log/sshd.log'
28
+ use_image_entrypoint: true
29
+ dockeropts:
30
+ HostConfig:
31
+ Privileged: true
26
32
  CONFIG:
27
33
  nfs_server: none
28
34
  consoleport: 443
29
35
  log_level: verbose
30
- dockeropts:
31
- Labels:
32
- one: '3'
33
- two: '4'
@@ -20,24 +20,14 @@ Gem::Specification.new do |s|
20
20
  # Testing dependencies
21
21
  s.add_development_dependency 'rspec', '~> 3.0'
22
22
  s.add_development_dependency 'rspec-its'
23
- # pin fakefs for Ruby < 2.3
24
- if RUBY_VERSION < "2.3"
25
- s.add_development_dependency 'fakefs', '~> 0.6', '< 0.14'
26
- else
27
- s.add_development_dependency 'fakefs', '~> 0.6'
28
- end
29
- s.add_development_dependency 'rake', '~> 10.1'
23
+ s.add_development_dependency 'fakefs', '~> 1.3'
24
+ s.add_development_dependency 'rake', '~> 13.0'
30
25
  s.add_development_dependency 'simplecov'
31
26
  s.add_development_dependency 'pry', '~> 0.10'
32
27
 
33
- # Documentation dependencies
34
- s.add_development_dependency 'yard'
35
- s.add_development_dependency 'markdown'
36
- s.add_development_dependency 'thin'
37
-
38
28
  # Run time dependencies
39
29
  s.add_runtime_dependency 'stringify-hash', '~> 0.0.0'
40
- s.add_runtime_dependency 'docker-api'
30
+ s.add_runtime_dependency 'docker-api', '< 3.0.0'
41
31
 
42
32
  end
43
33
 
@@ -1,3 +1,3 @@
1
1
  module BeakerDocker
2
- VERSION = '0.5.3'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -19,19 +19,25 @@ module Beaker
19
19
  default_docker_options = { :write_timeout => 300, :read_timeout => 300 }.merge(::Docker.options || {})
20
20
  # Merge docker options from the entry in hosts file
21
21
  ::Docker.options = default_docker_options.merge(@options[:docker_options] || {})
22
- # assert that the docker-api gem can talk to your docker
23
- # enpoint. Will raise if there is a version mismatch
22
+
23
+ # Ensure that we can correctly communicate with the docker API
24
24
  begin
25
- ::Docker.validate_version!
25
+ @docker_version = ::Docker.version
26
26
  rescue Excon::Errors::SocketError => e
27
- raise "Docker instance not connectable.\nError was: #{e}\nCheck your DOCKER_HOST variable has been set\nIf you are on OSX or Windows, you might not have Docker Machine setup correctly: https://docs.docker.com/machine/\n"
27
+ raise <<~ERRMSG
28
+ Docker instance not connectable
29
+ Error was: #{e}
30
+ * Check your DOCKER_HOST variable has been set
31
+ * If you are on OSX or Windows, you might not have Docker Machine setup correctly: https://docs.docker.com/machine/
32
+ * If you are using rootless podman, you might need to set up your local socket and service
33
+ ERRMSG
28
34
  end
29
35
 
30
36
  # Pass on all the logging from docker-api to the beaker logger instance
31
37
  ::Docker.logger = @logger
32
38
 
33
39
  # Find out what kind of remote instance we are talking against
34
- if ::Docker.version['Version'] =~ /swarm/
40
+ if @docker_version['Version'] =~ /swarm/
35
41
  @docker_type = 'swarm'
36
42
  unless ENV['DOCKER_REGISTRY']
37
43
  raise "Using Swarm with beaker requires a private registry. Please setup the private registry and set the 'DOCKER_REGISTRY' env var"
@@ -41,10 +47,21 @@ module Beaker
41
47
  else
42
48
  @docker_type = 'docker'
43
49
  end
44
-
45
50
  end
46
51
 
47
52
  def install_and_run_ssh(host)
53
+ def host.enable_root_login(host,opts)
54
+ logger.debug("Root login already enabled for #{host}")
55
+ end
56
+
57
+ # If the container is running ssh as its init process then this method
58
+ # will cause issues.
59
+ if host[:docker_cmd] =~ /sshd/
60
+ def host.ssh_service_restart
61
+ self[:docker_container].exec(%w(kill -1 1))
62
+ end
63
+ end
64
+
48
65
  host['dockerfile'] || host['use_image_entry_point']
49
66
  end
50
67
 
@@ -62,7 +79,6 @@ module Beaker
62
79
  '22/tcp' => [{ 'HostPort' => rand.to_s[2..5], 'HostIp' => '0.0.0.0'}]
63
80
  },
64
81
  'PublishAllPorts' => true,
65
- 'Privileged' => true,
66
82
  'RestartPolicy' => {
67
83
  'Name' => 'always'
68
84
  }
@@ -109,6 +125,45 @@ module Beaker
109
125
  { rm: true, buildargs: buildargs_for(host) })
110
126
  end
111
127
 
128
+ # Find out where the ssh port is from the container
129
+ # When running on swarm DOCKER_HOST points to the swarm manager so we have to get the
130
+ # IP of the swarm slave via the container data
131
+ # When we are talking to a normal docker instance DOCKER_HOST can point to a remote docker instance.
132
+ def get_ssh_connection_info(container)
133
+ ssh_connection_info = {
134
+ ip: nil,
135
+ port: nil
136
+ }
137
+
138
+ # Talking against a remote docker host which is a normal docker host
139
+ if @docker_type == 'docker' && ENV['DOCKER_HOST'] && !ENV.fetch('DOCKER_HOST','').include?(':///')
140
+ ip = URI.parse(ENV['DOCKER_HOST']).host
141
+ else
142
+ # Swarm or local docker host
143
+ if in_container?
144
+ ip = container.json["NetworkSettings"]["Gateway"]
145
+ else
146
+ ip = container.json["NetworkSettings"]["Ports"]["22/tcp"][0]["HostIp"]
147
+ end
148
+ end
149
+
150
+ network_settings = container.json['NetworkSettings']
151
+ host_config = container.json['HostConfig']
152
+
153
+ port = '22'
154
+ if host_config['NetworkMode'] == 'bridge' && network_settings['IPAddress'] && !network_settings['IPAddress'].empty?
155
+ ssh_connection_info[:ip] = network_settings['IPAddress']
156
+ else
157
+ port = network_settings['Ports']['22/tcp'][0]['HostPort']
158
+
159
+ # Update host metadata
160
+ ssh_connection_info[:ip] = (ip == '0.0.0.0') ? '127.0.0.1' : ip
161
+ end
162
+
163
+ ssh_connection_info[:port] = port
164
+ ssh_connection_info
165
+ end
166
+
112
167
  def provision
113
168
  @logger.notify "Provisioning docker"
114
169
 
@@ -144,10 +199,9 @@ module Beaker
144
199
 
145
200
  container = find_container(host)
146
201
 
147
- # Provisioning - Only provision if:
148
- # - provisioning was explicitly requested via options, or
149
- # - the host's container can't be found via its name or ID
150
- if @options[:provision] || container.nil?
202
+ # Provisioning - Only provision if the host's container can't be found
203
+ # via its name or ID
204
+ if container.nil?
151
205
  unless host['mount_folders'].nil?
152
206
  container_opts['HostConfig'] ||= {}
153
207
  container_opts['HostConfig']['Binds'] = host['mount_folders'].values.map do |mount|
@@ -157,21 +211,50 @@ module Beaker
157
211
  host_path = "/" + host_path.gsub(/^.\:/, host_path[/^(.)/].downcase)
158
212
  end
159
213
  a = [ host_path, mount['container_path'] ]
160
- a << mount['opts'] if mount.has_key?('opts')
214
+ if mount.has_key?('opts')
215
+ a << mount['opts'] if mount.has_key?('opts')
216
+ else
217
+ a << mount['opts'] = 'z'
218
+ end
219
+
161
220
  a.join(':')
162
221
  end
163
222
  end
164
223
 
224
+ if host['docker_env']
225
+ container_opts['Env'] = host['docker_env']
226
+ end
227
+
165
228
  if host['docker_cap_add']
166
229
  container_opts['HostConfig']['CapAdd'] = host['docker_cap_add']
167
230
  end
168
231
 
169
232
  if host['docker_container_name']
170
233
  container_opts['name'] = host['docker_container_name']
234
+ else
235
+ container_opts['name'] = ['beaker', host.name, SecureRandom.uuid.split('-').last].join('-')
171
236
  end
172
237
 
173
238
  @logger.debug("Creating container from image #{image_name}")
174
- container = ::Docker::Container.create(container_opts)
239
+
240
+ ok=false
241
+ retries=0
242
+ while(!ok && (retries < 5))
243
+ container = ::Docker::Container.create(container_opts)
244
+
245
+ if (get_ssh_connection_info(container)[:port].to_i < 1024) && (Process.uid != 0)
246
+ @logger.debug("#{host} was given a port less than 1024 but you are not running as root, retrying")
247
+
248
+ container.delete
249
+
250
+ retries+=1
251
+ next
252
+ end
253
+
254
+ ok=true
255
+ end
256
+ else
257
+ host['use_existing_container'] = true
175
258
  end
176
259
 
177
260
  if container.nil?
@@ -184,41 +267,35 @@ module Beaker
184
267
  @logger.debug("Starting container #{container.id}")
185
268
  container.start
186
269
 
270
+ # Preserve the ability to talk directly to the underlying API
271
+ #
272
+ # You can use any method defined by the docker-api gem on this object
273
+ # https://github.com/swipely/docker-api
274
+ host[:docker_container] = container
275
+
276
+ ssh_connection_info = get_ssh_connection_info(container)
277
+
278
+ ip = ssh_connection_info[:ip]
279
+ port = ssh_connection_info[:port]
280
+
281
+ @logger.info("Using container connection at #{ip}:#{port}")
282
+
187
283
  if install_and_run_ssh(host)
188
284
  @logger.notify("Installing ssh components and starting ssh daemon in #{host} container")
189
285
  install_ssh_components(container, host)
190
286
  # run fixssh to configure and start the ssh service
191
287
  fix_ssh(container, host)
192
288
  end
193
- # Find out where the ssh port is from the container
194
- # When running on swarm DOCKER_HOST points to the swarm manager so we have to get the
195
- # IP of the swarm slave via the container data
196
- # When we are talking to a normal docker instance DOCKER_HOST can point to a remote docker instance.
197
-
198
- # Talking against a remote docker host which is a normal docker host
199
- if @docker_type == 'docker' && ENV['DOCKER_HOST']
200
- ip = URI.parse(ENV['DOCKER_HOST']).host
201
- else
202
- # Swarm or local docker host
203
- if in_container?
204
- ip = container.json["NetworkSettings"]["Gateway"]
205
- else
206
- ip = container.json["NetworkSettings"]["Ports"]["22/tcp"][0]["HostIp"]
207
- end
208
- end
209
-
210
- @logger.info("Using docker server at #{ip}")
211
- port = container.json["NetworkSettings"]["Ports"]["22/tcp"][0]["HostPort"]
212
289
 
213
290
  forward_ssh_agent = @options[:forward_ssh_agent] || false
214
291
 
215
- # Update host metadata
216
- host['ip'] = ip
292
+ host['ip'] = ip
217
293
  host['port'] = port
218
294
  host['ssh'] = {
219
295
  :password => root_password,
220
296
  :port => port,
221
297
  :forward_agent => forward_ssh_agent,
298
+ :auth_methods => ['password', 'publickey', 'hostbased', 'keyboard-interactive']
222
299
  }
223
300
 
224
301
  @logger.debug("node available as ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@#{ip} -p #{port}")
@@ -226,10 +303,12 @@ module Beaker
226
303
  host['docker_image_id'] = image.id
227
304
  host['vm_ip'] = container.json["NetworkSettings"]["IPAddress"].to_s
228
305
 
306
+ def host.reboot
307
+ @logger.warn("Rebooting containers is ineffective...ignoring")
308
+ end
229
309
  end
230
310
 
231
311
  hack_etc_hosts @hosts, @options
232
-
233
312
  end
234
313
 
235
314
  # This sideloads sshd after a container starts
@@ -238,19 +317,23 @@ module Beaker
238
317
  when /ubuntu/, /debian/
239
318
  container.exec(%w(apt-get update))
240
319
  container.exec(%w(apt-get install -y openssh-server openssh-client))
320
+ container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
241
321
  when /cumulus/
242
322
  container.exec(%w(apt-get update))
243
323
  container.exec(%w(apt-get install -y openssh-server openssh-client))
324
+ container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
244
325
  when /fedora-(2[2-9])/
245
326
  container.exec(%w(dnf clean all))
246
327
  container.exec(%w(dnf install -y sudo openssh-server openssh-clients))
247
328
  container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
248
329
  container.exec(%w(ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key))
330
+ container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
249
331
  when /^el-/, /centos/, /fedora/, /redhat/, /eos/
250
332
  container.exec(%w(yum clean all))
251
333
  container.exec(%w(yum install -y sudo openssh-server openssh-clients))
252
334
  container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
253
335
  container.exec(%w(ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key))
336
+ container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
254
337
  when /opensuse/, /sles/
255
338
  container.exec(%w(zypper -n in openssh))
256
339
  container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
@@ -279,38 +362,44 @@ module Beaker
279
362
  def cleanup
280
363
  @logger.notify "Cleaning up docker"
281
364
  @hosts.each do |host|
282
- container = find_container(host)
283
- if container
284
- @logger.debug("stop container #{container.id}")
285
- begin
286
- container.kill
287
- sleep 2 # avoid a race condition where the root FS can't unmount
288
- rescue Excon::Errors::ClientError => e
289
- @logger.warn("stop of container #{container.id} failed: #{e.response.body}")
290
- end
291
- @logger.debug("delete container #{container.id}")
292
- begin
293
- container.delete
294
- rescue Excon::Errors::ClientError => e
295
- @logger.warn("deletion of container #{container.id} failed: #{e.response.body}")
296
- end
297
- end
298
-
299
- # Do not remove the image if docker_preserve_image is set to true, otherwise remove it
300
- unless host['docker_preserve_image']
301
- image_id = host['docker_image_id']
302
-
303
- if image_id
304
- @logger.debug("deleting image #{image_id}")
365
+ # leave the container running if docker_preserve_container is set
366
+ # setting docker_preserve_container also implies docker_preserve_image
367
+ # is set, since you can't delete an image that's the base of a running
368
+ # container
369
+ unless host['docker_preserve_container']
370
+ container = find_container(host)
371
+ if container
372
+ @logger.debug("stop container #{container.id}")
305
373
  begin
306
- ::Docker::Image.remove(image_id)
374
+ container.kill
375
+ sleep 2 # avoid a race condition where the root FS can't unmount
307
376
  rescue Excon::Errors::ClientError => e
308
- @logger.warn("deletion of image #{image_id} failed: #{e.response.body}")
309
- rescue ::Docker::Error::DockerError => e
310
- @logger.warn("deletion of image #{image_id} caused internal Docker error: #{e.message}")
377
+ @logger.warn("stop of container #{container.id} failed: #{e.response.body}")
378
+ end
379
+ @logger.debug("delete container #{container.id}")
380
+ begin
381
+ container.delete
382
+ rescue Excon::Errors::ClientError => e
383
+ @logger.warn("deletion of container #{container.id} failed: #{e.response.body}")
384
+ end
385
+ end
386
+
387
+ # Do not remove the image if docker_preserve_image is set to true, otherwise remove it
388
+ unless host['docker_preserve_image']
389
+ image_id = host['docker_image_id']
390
+
391
+ if image_id
392
+ @logger.debug("deleting image #{image_id}")
393
+ begin
394
+ ::Docker::Image.remove(image_id)
395
+ rescue Excon::Errors::ClientError => e
396
+ @logger.warn("deletion of image #{image_id} failed: #{e.response.body}")
397
+ rescue ::Docker::Error::DockerError => e
398
+ @logger.warn("deletion of image #{image_id} caused internal Docker error: #{e.message}")
399
+ end
400
+ else
401
+ @logger.warn("Intended to delete the host's docker image, but host['docker_image_id'] was not set")
311
402
  end
312
- else
313
- @logger.warn("Intended to delete the host's docker image, but host['docker_image_id'] was not set")
314
403
  end
315
404
  end
316
405
  end
@@ -360,64 +449,76 @@ module Beaker
360
449
  case host['platform']
361
450
  when /ubuntu/, /debian/
362
451
  service_name = "ssh"
363
- dockerfile += <<-EOF
452
+ dockerfile += <<~EOF
364
453
  RUN apt-get update
365
454
  RUN apt-get install -y openssh-server openssh-client #{Beaker::HostPrebuiltSteps::DEBIAN_PACKAGES.join(' ')}
366
- EOF
367
- when /cumulus/
368
- dockerfile += <<-EOF
455
+ RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
456
+ EOF
457
+ when /cumulus/
458
+ dockerfile += <<~EOF
369
459
  RUN apt-get update
370
460
  RUN apt-get install -y openssh-server openssh-client #{Beaker::HostPrebuiltSteps::CUMULUS_PACKAGES.join(' ')}
371
- EOF
461
+ EOF
372
462
  when /fedora-(2[2-9])/
373
- dockerfile += <<-EOF
463
+ dockerfile += <<~EOF
374
464
  RUN dnf clean all
375
465
  RUN dnf install -y sudo openssh-server openssh-clients #{Beaker::HostPrebuiltSteps::UNIX_PACKAGES.join(' ')}
376
466
  RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
377
467
  RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
378
- EOF
468
+ RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
469
+ EOF
470
+ when /el-8/
471
+ dockerfile += <<~EOF
472
+ RUN dnf clean all
473
+ RUN dnf install -y sudo openssh-server openssh-clients #{Beaker::HostPrebuiltSteps::RHEL8_PACKAGES.join(' ')}
474
+ RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
475
+ RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
476
+ RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
477
+ EOF
379
478
  when /^el-/, /centos/, /fedora/, /redhat/, /eos/
380
- dockerfile += <<-EOF
479
+ dockerfile += <<~EOF
381
480
  RUN yum clean all
382
481
  RUN yum install -y sudo openssh-server openssh-clients #{Beaker::HostPrebuiltSteps::UNIX_PACKAGES.join(' ')}
383
482
  RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
384
483
  RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
385
- EOF
484
+ RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
485
+ EOF
386
486
  when /opensuse/, /sles/
387
- dockerfile += <<-EOF
487
+ dockerfile += <<~EOF
388
488
  RUN zypper -n in openssh #{Beaker::HostPrebuiltSteps::SLES_PACKAGES.join(' ')}
389
489
  RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
390
490
  RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
391
491
  RUN sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config
392
- EOF
492
+ RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
493
+ EOF
393
494
  when /archlinux/
394
- dockerfile += <<-EOF
495
+ dockerfile += <<~EOF
395
496
  RUN pacman --noconfirm -Sy archlinux-keyring
396
497
  RUN pacman --noconfirm -Syu
397
498
  RUN pacman -S --noconfirm openssh #{Beaker::HostPrebuiltSteps::ARCHLINUX_PACKAGES.join(' ')}
398
499
  RUN ssh-keygen -A
399
500
  RUN sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config
400
501
  RUN systemctl enable sshd
401
- EOF
502
+ EOF
402
503
  else
403
504
  # TODO add more platform steps here
404
505
  raise "platform #{host['platform']} not yet supported on docker"
405
506
  end
406
507
 
407
508
  # Make sshd directory, set root password
408
- dockerfile += <<-EOF
509
+ dockerfile += <<~EOF
409
510
  RUN mkdir -p /var/run/sshd
410
511
  RUN echo root:#{root_password} | chpasswd
411
- EOF
512
+ EOF
412
513
 
413
514
  # Configure sshd service to allowroot login using password
414
515
  # Also, disable reverse DNS lookups to prevent every. single. ssh
415
516
  # operation taking 30 seconds while the lookup times out.
416
- dockerfile += <<-EOF
517
+ dockerfile += <<~EOF
417
518
  RUN sed -ri 's/^#?PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config
418
519
  RUN sed -ri 's/^#?PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config
419
520
  RUN sed -ri 's/^#?UseDNS .*/UseDNS no/' /etc/ssh/sshd_config
420
- EOF
521
+ EOF
421
522
 
422
523
 
423
524
  # Any extra commands specified for the host
@@ -498,6 +599,7 @@ module Beaker
498
599
 
499
600
  return container unless container.nil?
500
601
  @logger.debug("Existing container not found")
602
+ return nil
501
603
  end
502
604
 
503
605
  # return true if we are inside a docker container