beaker-docker 0.6.0 → 0.8.2
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 +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
|