beaker-docker 0.6.0 → 0.8.2
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/release.yml +24 -0
- data/.github/workflows/test.yml +105 -0
- data/Gemfile.local +5 -0
- data/README.md +94 -13
- data/Rakefile +8 -4
- data/acceptance/config/nodes/hosts.yaml +21 -14
- data/acceptance/tests/00_default_spec.rb +10 -0
- data/beaker-docker.gemspec +3 -8
- data/lib/beaker-docker/version.rb +1 -1
- data/lib/beaker/hypervisor/docker.rb +158 -51
- data/spec/beaker/hypervisor/docker_spec.rb +509 -479
- metadata +16 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 02eaf00011bdb77e04d6c2ba218c0d6cb2f0337f03ea9e8770bbc132e8532d78
|
4
|
+
data.tar.gz: 1df91fb159aca545ae67ece3c5b4dfc326a81ef5ee8ce307acf21ab16fa4459f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 312bf63f3ea66c8d75921c4314912b6451b2457e31452b5cf05b2edbd43c671cefc9c0157f89ea01fb1ed8bcd49769be5770c0c18c559f6ccc47df39620e7e60
|
7
|
+
data.tar.gz: e087e4e649f2e31db3425ffefa0c83532e89ae4b8c6d7fab090989a511ced8b3f71133d9e211ae15358312ff0106c82ebd050245feb3e9743fe6caa60aafda02
|
@@ -0,0 +1,24 @@
|
|
1
|
+
name: Release
|
2
|
+
|
3
|
+
on:
|
4
|
+
create:
|
5
|
+
ref_type: tag
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
release:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
if: github.repository == 'voxpupuli/beaker-docker'
|
11
|
+
env:
|
12
|
+
BUNDLE_WITHOUT: release
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v2
|
15
|
+
- name: Install Ruby 2.7
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: '2.7'
|
19
|
+
- name: Build gem
|
20
|
+
run: gem build *.gemspec
|
21
|
+
- name: Publish gem
|
22
|
+
run: gem push *.gem
|
23
|
+
env:
|
24
|
+
GEM_HOST_API_KEY: '${{ secrets.RUBYGEMS_AUTH_TOKEN }}'
|
@@ -0,0 +1,105 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- test_me_github
|
7
|
+
pull_request:
|
8
|
+
branches:
|
9
|
+
- main
|
10
|
+
- master
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
rspec:
|
14
|
+
runs-on: ubuntu-latest
|
15
|
+
strategy:
|
16
|
+
fail-fast: true
|
17
|
+
matrix:
|
18
|
+
ruby:
|
19
|
+
- "2.4"
|
20
|
+
- "2.5"
|
21
|
+
- "2.6"
|
22
|
+
- "2.7"
|
23
|
+
env:
|
24
|
+
BUNDLE_WITHOUT: release
|
25
|
+
name: RSpec - Ruby ${{ matrix.ruby }}
|
26
|
+
steps:
|
27
|
+
- uses: actions/checkout@v2
|
28
|
+
- name: Install Ruby ${{ matrix.ruby }}
|
29
|
+
uses: ruby/setup-ruby@v1
|
30
|
+
with:
|
31
|
+
ruby-version: ${{ matrix.ruby }}
|
32
|
+
bundler-cache: true
|
33
|
+
- name: install bundler
|
34
|
+
run: |
|
35
|
+
gem install bundler -v '~> 1.17.3'
|
36
|
+
bundle update
|
37
|
+
- name: spec tests
|
38
|
+
run: bundle exec rake test:spec
|
39
|
+
|
40
|
+
docker:
|
41
|
+
runs-on: ubuntu-latest
|
42
|
+
strategy:
|
43
|
+
fail-fast: true
|
44
|
+
matrix:
|
45
|
+
ruby:
|
46
|
+
- "2.6"
|
47
|
+
env:
|
48
|
+
BUNDLE_WITHOUT: release
|
49
|
+
name: Docker - Ruby ${{ matrix.ruby }}
|
50
|
+
steps:
|
51
|
+
- uses: actions/checkout@v2
|
52
|
+
- name: Install Ruby ${{ matrix.ruby }}
|
53
|
+
uses: ruby/setup-ruby@v1
|
54
|
+
with:
|
55
|
+
ruby-version: ${{ matrix.ruby }}
|
56
|
+
bundler-cache: true
|
57
|
+
- name: install bundler
|
58
|
+
run: |
|
59
|
+
gem install bundler -v '~> 1.17.3'
|
60
|
+
bundle update
|
61
|
+
- name: install container runtime
|
62
|
+
run: |
|
63
|
+
sudo apt-get remove -y docker docker-engine docker.io containerd runc ||:
|
64
|
+
sudo apt-get update -y
|
65
|
+
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
|
66
|
+
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
67
|
+
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
68
|
+
sudo apt-get update -y
|
69
|
+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
70
|
+
sudo systemctl start docker
|
71
|
+
- name: Run acceptance tests
|
72
|
+
run: bundle exec rake test:acceptance
|
73
|
+
|
74
|
+
podman:
|
75
|
+
runs-on: ubuntu-latest
|
76
|
+
strategy:
|
77
|
+
fail-fast: true
|
78
|
+
matrix:
|
79
|
+
ruby:
|
80
|
+
- "2.6"
|
81
|
+
env:
|
82
|
+
BUNDLE_WITHOUT: release
|
83
|
+
name: Podman - Ruby ${{ matrix.ruby }}
|
84
|
+
steps:
|
85
|
+
- uses: actions/checkout@v2
|
86
|
+
- name: Install Ruby ${{ matrix.ruby }}
|
87
|
+
uses: ruby/setup-ruby@v1
|
88
|
+
with:
|
89
|
+
ruby-version: ${{ matrix.ruby }}
|
90
|
+
bundler-cache: true
|
91
|
+
- name: install bundler
|
92
|
+
run: |
|
93
|
+
gem install bundler -v '~> 1.17.3'
|
94
|
+
bundle update
|
95
|
+
# We need the latest version of podman for this to work
|
96
|
+
- name: install container runtime
|
97
|
+
run: |
|
98
|
+
. /etc/os-release
|
99
|
+
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key | sudo apt-key add -
|
100
|
+
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/podman.list > /dev/null
|
101
|
+
sudo apt-get update
|
102
|
+
sudo apt-get -y install podman
|
103
|
+
sudo systemctl start podman
|
104
|
+
- name: Run acceptance tests
|
105
|
+
run: bundle exec rake test:acceptance
|
data/Gemfile.local
ADDED
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
|
|
@@ -32,11 +32,15 @@ A quick acceptance test, named because it has no pre-suites to run
|
|
32
32
|
beaker_test_base_dir = File.join(beaker_gem_dir, 'acceptance/tests/base')
|
33
33
|
load_path_option = File.join(beaker_gem_dir, 'acceptance/lib')
|
34
34
|
|
35
|
+
ENV['BEAKER_setfile'] = 'acceptance/config/nodes/hosts.yaml'
|
35
36
|
sh("beaker",
|
36
37
|
"--hosts", "acceptance/config/nodes/hosts.yaml",
|
37
|
-
|
38
|
+
# We can't run these tests until the rsync support in the main
|
39
|
+
# beaker/host.rb is updated to work with passwords.
|
40
|
+
# "--tests", beaker_test_base_dir,
|
41
|
+
# "--load-path", load_path_option,
|
42
|
+
"--tests", 'acceptance/tests/',
|
38
43
|
"--log-level", "debug",
|
39
|
-
"--load-path", load_path_option,
|
40
44
|
"--debug")
|
41
45
|
end
|
42
46
|
|
@@ -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,29 @@ HOSTS:
|
|
12
12
|
- classifier
|
13
13
|
- default
|
14
14
|
docker_cmd: '["/sbin/init"]'
|
15
|
-
|
16
|
-
|
17
|
-
one: '1'
|
18
|
-
two: '2'
|
19
|
-
ubuntu1604-64-2:
|
20
|
-
platform: ubuntu-1604-x86_64
|
15
|
+
centos7:
|
16
|
+
platform: el-7-x86_64
|
21
17
|
hypervisor: docker
|
22
|
-
image:
|
18
|
+
image: centos:7
|
23
19
|
roles:
|
24
20
|
- agent
|
25
|
-
docker_cmd: '
|
21
|
+
docker_cmd: '/usr/sbin/sshd -D -E /var/log/sshd.log'
|
22
|
+
use_image_entrypoint: true
|
26
23
|
CONFIG:
|
27
24
|
nfs_server: none
|
28
25
|
consoleport: 443
|
29
26
|
log_level: verbose
|
27
|
+
# Ubuntu runners need to run with full privileges
|
28
|
+
# RHEL derivitives just need the docker cap AUDIT_WRITE
|
30
29
|
dockeropts:
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
HostConfig:
|
31
|
+
Privileged: true
|
32
|
+
# docker_cap_add:
|
33
|
+
# - AUDIT_WRITE
|
34
|
+
type: aio
|
35
|
+
ssh:
|
36
|
+
verify_host_key: false
|
37
|
+
user_known_hosts_file: '/dev/null'
|
38
|
+
password: root
|
39
|
+
auth_methods:
|
40
|
+
- password
|
data/beaker-docker.gemspec
CHANGED
@@ -20,19 +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
28
|
# Run time dependencies
|
34
29
|
s.add_runtime_dependency 'stringify-hash', '~> 0.0.0'
|
35
|
-
s.add_runtime_dependency 'docker-api'
|
30
|
+
s.add_runtime_dependency 'docker-api', '< 3.0.0'
|
36
31
|
|
37
32
|
end
|
38
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,48 @@ 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
|
+
container_json = container.json
|
139
|
+
network_settings = container_json['NetworkSettings']
|
140
|
+
host_config = container_json['HostConfig']
|
141
|
+
|
142
|
+
ip = nil
|
143
|
+
port = nil
|
144
|
+
# Talking against a remote docker host which is a normal docker host
|
145
|
+
if @docker_type == 'docker' && ENV['DOCKER_HOST'] && !ENV.fetch('DOCKER_HOST','').include?(':///')
|
146
|
+
ip = URI.parse(ENV['DOCKER_HOST']).host
|
147
|
+
else
|
148
|
+
# Swarm or local docker host
|
149
|
+
if in_container?
|
150
|
+
gw = network_settings['Gateway']
|
151
|
+
ip = gw unless (gw.nil? || gw.empty?)
|
152
|
+
else
|
153
|
+
port22 = network_settings.dig('Ports','22/tcp')
|
154
|
+
ip = port22[0]["HostIp"] if port22
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
if host_config['NetworkMode'] != 'slirp4netns' && network_settings['IPAddress'] && !network_settings['IPAddress'].empty?
|
159
|
+
ip = network_settings['IPAddress']
|
160
|
+
else
|
161
|
+
port22 = network_settings.dig('Ports','22/tcp')
|
162
|
+
port = port22[0]['HostPort'] if port22
|
163
|
+
end
|
164
|
+
|
165
|
+
ssh_connection_info[:ip] = (ip == '0.0.0.0') ? '127.0.0.1' : ip
|
166
|
+
ssh_connection_info[:port] = port || '22'
|
167
|
+
ssh_connection_info
|
168
|
+
end
|
169
|
+
|
112
170
|
def provision
|
113
171
|
@logger.notify "Provisioning docker"
|
114
172
|
|
@@ -134,6 +192,8 @@ module Beaker
|
|
134
192
|
image_name = image.id
|
135
193
|
end
|
136
194
|
|
195
|
+
### BEGIN CONTAINER OPTIONS MANGLING ###
|
196
|
+
|
137
197
|
container_opts = get_container_opts(host, image_name)
|
138
198
|
if host['dockeropts'] || @options[:dockeropts]
|
139
199
|
dockeropts = host['dockeropts'] ? host['dockeropts'] : @options[:dockeropts]
|
@@ -156,7 +216,12 @@ module Beaker
|
|
156
216
|
host_path = "/" + host_path.gsub(/^.\:/, host_path[/^(.)/].downcase)
|
157
217
|
end
|
158
218
|
a = [ host_path, mount['container_path'] ]
|
159
|
-
|
219
|
+
if mount.has_key?('opts')
|
220
|
+
a << mount['opts'] if mount.has_key?('opts')
|
221
|
+
else
|
222
|
+
a << mount['opts'] = 'z'
|
223
|
+
end
|
224
|
+
|
160
225
|
a.join(':')
|
161
226
|
end
|
162
227
|
end
|
@@ -165,16 +230,46 @@ module Beaker
|
|
165
230
|
container_opts['Env'] = host['docker_env']
|
166
231
|
end
|
167
232
|
|
233
|
+
# Fixup privileges
|
234
|
+
#
|
235
|
+
# If the user has specified CAPs, then we cannot be privileged
|
236
|
+
#
|
237
|
+
# If the user has not specified CAPs, we will default to privileged for
|
238
|
+
# compatibility with worst practice
|
168
239
|
if host['docker_cap_add']
|
169
240
|
container_opts['HostConfig']['CapAdd'] = host['docker_cap_add']
|
241
|
+
container_opts['HostConfig'].delete('Privileged')
|
242
|
+
else
|
243
|
+
container_opts['HostConfig']['Privileged'] = container_opts['HostConfig']['Privileged'].nil? ? true : container_opts['HostConfig']['Privileged']
|
170
244
|
end
|
171
245
|
|
172
246
|
if host['docker_container_name']
|
173
247
|
container_opts['name'] = host['docker_container_name']
|
248
|
+
else
|
249
|
+
container_opts['name'] = ['beaker', host.name, SecureRandom.uuid.split('-').last].join('-')
|
174
250
|
end
|
175
251
|
|
252
|
+
### END CONTAINER OPTIONS MANGLING ###
|
253
|
+
|
176
254
|
@logger.debug("Creating container from image #{image_name}")
|
177
|
-
|
255
|
+
|
256
|
+
ok=false
|
257
|
+
retries=0
|
258
|
+
while(!ok && (retries < 5))
|
259
|
+
container = ::Docker::Container.create(container_opts)
|
260
|
+
|
261
|
+
ssh_info = get_ssh_connection_info(container)
|
262
|
+
if ssh_info[:ip] == '127.0.0.1' && (ssh_info[:port].to_i < 1024) && (Process.uid != 0)
|
263
|
+
@logger.debug("#{host} was given a port less than 1024 but you are not running as root, retrying")
|
264
|
+
|
265
|
+
container.delete
|
266
|
+
|
267
|
+
retries+=1
|
268
|
+
next
|
269
|
+
end
|
270
|
+
|
271
|
+
ok=true
|
272
|
+
end
|
178
273
|
else
|
179
274
|
host['use_existing_container'] = true
|
180
275
|
end
|
@@ -189,52 +284,55 @@ module Beaker
|
|
189
284
|
@logger.debug("Starting container #{container.id}")
|
190
285
|
container.start
|
191
286
|
|
287
|
+
begin
|
288
|
+
container.stats
|
289
|
+
rescue StandardError => e
|
290
|
+
container.delete
|
291
|
+
raise "Container '#{container.id}' in a bad state: #{e}"
|
292
|
+
end
|
293
|
+
|
294
|
+
# Preserve the ability to talk directly to the underlying API
|
295
|
+
#
|
296
|
+
# You can use any method defined by the docker-api gem on this object
|
297
|
+
# https://github.com/swipely/docker-api
|
298
|
+
host[:docker_container] = container
|
299
|
+
|
192
300
|
if install_and_run_ssh(host)
|
193
301
|
@logger.notify("Installing ssh components and starting ssh daemon in #{host} container")
|
194
302
|
install_ssh_components(container, host)
|
195
303
|
# run fixssh to configure and start the ssh service
|
196
304
|
fix_ssh(container, host)
|
197
305
|
end
|
198
|
-
# Find out where the ssh port is from the container
|
199
|
-
# When running on swarm DOCKER_HOST points to the swarm manager so we have to get the
|
200
|
-
# IP of the swarm slave via the container data
|
201
|
-
# When we are talking to a normal docker instance DOCKER_HOST can point to a remote docker instance.
|
202
|
-
|
203
|
-
# Talking against a remote docker host which is a normal docker host
|
204
|
-
if @docker_type == 'docker' && ENV['DOCKER_HOST']
|
205
|
-
ip = URI.parse(ENV['DOCKER_HOST']).host
|
206
|
-
else
|
207
|
-
# Swarm or local docker host
|
208
|
-
if in_container?
|
209
|
-
ip = container.json["NetworkSettings"]["Gateway"]
|
210
|
-
else
|
211
|
-
ip = container.json["NetworkSettings"]["Ports"]["22/tcp"][0]["HostIp"]
|
212
|
-
end
|
213
|
-
end
|
214
306
|
|
215
|
-
|
216
|
-
|
307
|
+
ssh_connection_info = get_ssh_connection_info(container)
|
308
|
+
|
309
|
+
ip = ssh_connection_info[:ip]
|
310
|
+
port = ssh_connection_info[:port]
|
311
|
+
|
312
|
+
@logger.info("Using container connection at #{ip}:#{port}")
|
217
313
|
|
218
314
|
forward_ssh_agent = @options[:forward_ssh_agent] || false
|
219
315
|
|
220
|
-
|
221
|
-
host['ip'] = ip
|
316
|
+
host['ip'] = ip
|
222
317
|
host['port'] = port
|
223
318
|
host['ssh'] = {
|
224
319
|
:password => root_password,
|
225
320
|
:port => port,
|
226
321
|
:forward_agent => forward_ssh_agent,
|
322
|
+
:auth_methods => ['password', 'publickey', 'hostbased', 'keyboard-interactive']
|
227
323
|
}
|
228
324
|
|
229
|
-
@logger.debug("node available as
|
325
|
+
@logger.debug("node available as ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@#{ip} -p #{port}")
|
230
326
|
host['docker_container_id'] = container.id
|
231
327
|
host['docker_image_id'] = image.id
|
232
328
|
host['vm_ip'] = container.json["NetworkSettings"]["IPAddress"].to_s
|
233
329
|
|
330
|
+
def host.reboot
|
331
|
+
@logger.warn("Rebooting containers is ineffective...ignoring")
|
332
|
+
end
|
234
333
|
end
|
235
334
|
|
236
335
|
hack_etc_hosts @hosts, @options
|
237
|
-
|
238
336
|
end
|
239
337
|
|
240
338
|
# This sideloads sshd after a container starts
|
@@ -243,19 +341,23 @@ module Beaker
|
|
243
341
|
when /ubuntu/, /debian/
|
244
342
|
container.exec(%w(apt-get update))
|
245
343
|
container.exec(%w(apt-get install -y openssh-server openssh-client))
|
344
|
+
container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
|
246
345
|
when /cumulus/
|
247
346
|
container.exec(%w(apt-get update))
|
248
347
|
container.exec(%w(apt-get install -y openssh-server openssh-client))
|
348
|
+
container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
|
249
349
|
when /fedora-(2[2-9])/
|
250
350
|
container.exec(%w(dnf clean all))
|
251
351
|
container.exec(%w(dnf install -y sudo openssh-server openssh-clients))
|
252
352
|
container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
|
253
353
|
container.exec(%w(ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key))
|
354
|
+
container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
|
254
355
|
when /^el-/, /centos/, /fedora/, /redhat/, /eos/
|
255
356
|
container.exec(%w(yum clean all))
|
256
357
|
container.exec(%w(yum install -y sudo openssh-server openssh-clients))
|
257
358
|
container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
|
258
359
|
container.exec(%w(ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key))
|
360
|
+
container.exec(%w(sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*))
|
259
361
|
when /opensuse/, /sles/
|
260
362
|
container.exec(%w(zypper -n in openssh))
|
261
363
|
container.exec(%w(ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key))
|
@@ -371,71 +473,76 @@ module Beaker
|
|
371
473
|
case host['platform']
|
372
474
|
when /ubuntu/, /debian/
|
373
475
|
service_name = "ssh"
|
374
|
-
dockerfile +=
|
476
|
+
dockerfile += <<~EOF
|
375
477
|
RUN apt-get update
|
376
478
|
RUN apt-get install -y openssh-server openssh-client #{Beaker::HostPrebuiltSteps::DEBIAN_PACKAGES.join(' ')}
|
377
|
-
|
479
|
+
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
|
480
|
+
EOF
|
378
481
|
when /cumulus/
|
379
|
-
dockerfile +=
|
482
|
+
dockerfile += <<~EOF
|
380
483
|
RUN apt-get update
|
381
484
|
RUN apt-get install -y openssh-server openssh-client #{Beaker::HostPrebuiltSteps::CUMULUS_PACKAGES.join(' ')}
|
382
|
-
|
485
|
+
EOF
|
383
486
|
when /fedora-(2[2-9])/
|
384
|
-
dockerfile +=
|
487
|
+
dockerfile += <<~EOF
|
385
488
|
RUN dnf clean all
|
386
489
|
RUN dnf install -y sudo openssh-server openssh-clients #{Beaker::HostPrebuiltSteps::UNIX_PACKAGES.join(' ')}
|
387
490
|
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
|
388
491
|
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
|
389
|
-
|
492
|
+
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
|
493
|
+
EOF
|
390
494
|
when /el-8/
|
391
|
-
dockerfile +=
|
392
|
-
RUN
|
393
|
-
RUN
|
495
|
+
dockerfile += <<~EOF
|
496
|
+
RUN dnf clean all
|
497
|
+
RUN dnf install -y sudo openssh-server openssh-clients #{Beaker::HostPrebuiltSteps::RHEL8_PACKAGES.join(' ')}
|
394
498
|
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
|
395
499
|
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
|
396
|
-
|
500
|
+
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
|
501
|
+
EOF
|
397
502
|
when /^el-/, /centos/, /fedora/, /redhat/, /eos/
|
398
|
-
dockerfile +=
|
503
|
+
dockerfile += <<~EOF
|
399
504
|
RUN yum clean all
|
400
505
|
RUN yum install -y sudo openssh-server openssh-clients #{Beaker::HostPrebuiltSteps::UNIX_PACKAGES.join(' ')}
|
401
506
|
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
|
402
507
|
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
|
403
|
-
|
508
|
+
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
|
509
|
+
EOF
|
404
510
|
when /opensuse/, /sles/
|
405
|
-
dockerfile +=
|
511
|
+
dockerfile += <<~EOF
|
406
512
|
RUN zypper -n in openssh #{Beaker::HostPrebuiltSteps::SLES_PACKAGES.join(' ')}
|
407
513
|
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
|
408
514
|
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
|
409
515
|
RUN sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config
|
410
|
-
|
516
|
+
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
|
517
|
+
EOF
|
411
518
|
when /archlinux/
|
412
|
-
dockerfile +=
|
519
|
+
dockerfile += <<~EOF
|
413
520
|
RUN pacman --noconfirm -Sy archlinux-keyring
|
414
521
|
RUN pacman --noconfirm -Syu
|
415
522
|
RUN pacman -S --noconfirm openssh #{Beaker::HostPrebuiltSteps::ARCHLINUX_PACKAGES.join(' ')}
|
416
523
|
RUN ssh-keygen -A
|
417
524
|
RUN sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config
|
418
525
|
RUN systemctl enable sshd
|
419
|
-
|
526
|
+
EOF
|
420
527
|
else
|
421
528
|
# TODO add more platform steps here
|
422
529
|
raise "platform #{host['platform']} not yet supported on docker"
|
423
530
|
end
|
424
531
|
|
425
532
|
# Make sshd directory, set root password
|
426
|
-
dockerfile +=
|
533
|
+
dockerfile += <<~EOF
|
427
534
|
RUN mkdir -p /var/run/sshd
|
428
535
|
RUN echo root:#{root_password} | chpasswd
|
429
|
-
|
536
|
+
EOF
|
430
537
|
|
431
538
|
# Configure sshd service to allowroot login using password
|
432
539
|
# Also, disable reverse DNS lookups to prevent every. single. ssh
|
433
540
|
# operation taking 30 seconds while the lookup times out.
|
434
|
-
dockerfile +=
|
541
|
+
dockerfile += <<~EOF
|
435
542
|
RUN sed -ri 's/^#?PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config
|
436
543
|
RUN sed -ri 's/^#?PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
437
544
|
RUN sed -ri 's/^#?UseDNS .*/UseDNS no/' /etc/ssh/sshd_config
|
438
|
-
|
545
|
+
EOF
|
439
546
|
|
440
547
|
|
441
548
|
# Any extra commands specified for the host
|