beaker-docker 0.5.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/test.yml +32 -0
- data/README.md +94 -13
- data/Rakefile +2 -2
- data/acceptance/config/nodes/hosts.yaml +13 -11
- data/beaker-docker.gemspec +3 -13
- data/lib/beaker-docker/version.rb +1 -1
- data/lib/beaker/hypervisor/docker.rb +183 -81
- data/spec/beaker/hypervisor/docker_spec.rb +504 -479
- metadata +13 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f21e88681130028d956057cc5d7e10242d3ab4b0dd3afdddc1e4a77b6a30376e
|
4
|
+
data.tar.gz: 27f935f63ebaf20d0eb18afcab7360dccdb6cc7e037cee4d6e9e3a45aed9ef33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 419eee4542d7283b98c1c9e56fae980816123bd5b4f8f69920180815c0ac61d047f0a8523ac68dc091e6bff6c101d8782905ec18d8a8d571274e62588872f58d
|
7
|
+
data.tar.gz: 7aa8635232484d7b4ef171d1714ab59805cd82e1b8c0d44d70174b903805376cf08e8ce48030f33f0efeb8d4ce845b8f2ad6b0f3deeb30bef602ffa86b092387
|
@@ -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
|
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
|
-
|
12
|
-
|
13
|
-
|
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-
|
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-
|
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
|
-
|
4
|
-
platform:
|
3
|
+
centos8:
|
4
|
+
platform: el-8-x86_64
|
5
5
|
hypervisor: docker
|
6
|
-
image:
|
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
|
-
|
20
|
-
platform:
|
21
|
+
centos7:
|
22
|
+
platform: el-7-x86_64
|
21
23
|
hypervisor: docker
|
22
|
-
image:
|
24
|
+
image: centos:7
|
23
25
|
roles:
|
24
26
|
- agent
|
25
|
-
docker_cmd: '
|
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'
|
data/beaker-docker.gemspec
CHANGED
@@ -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
|
-
|
24
|
-
|
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
|
|
@@ -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
|
-
|
23
|
-
#
|
22
|
+
|
23
|
+
# Ensure that we can correctly communicate with the docker API
|
24
24
|
begin
|
25
|
-
::Docker.
|
25
|
+
@docker_version = ::Docker.version
|
26
26
|
rescue Excon::Errors::SocketError => e
|
27
|
-
raise
|
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
|
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
|
-
#
|
149
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
@logger.
|
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
|
-
|
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("
|
309
|
-
|
310
|
-
|
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 +=
|
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
|
-
|
367
|
-
|
368
|
-
|
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
|
-
|
461
|
+
EOF
|
372
462
|
when /fedora-(2[2-9])/
|
373
|
-
dockerfile +=
|
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
|
-
|
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 +=
|
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
|
-
|
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 +=
|
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
|
-
|
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 +=
|
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
|
-
|
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 +=
|
509
|
+
dockerfile += <<~EOF
|
409
510
|
RUN mkdir -p /var/run/sshd
|
410
511
|
RUN echo root:#{root_password} | chpasswd
|
411
|
-
|
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 +=
|
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
|
-
|
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
|