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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 6a95374c06ba06495a8435b46bc6427516e3b42d
4
- data.tar.gz: 233b9029a46dcdb030de83c4d55014032c4d2538
2
+ SHA256:
3
+ metadata.gz: 02eaf00011bdb77e04d6c2ba218c0d6cb2f0337f03ea9e8770bbc132e8532d78
4
+ data.tar.gz: 1df91fb159aca545ae67ece3c5b4dfc326a81ef5ee8ce307acf21ab16fa4459f
5
5
  SHA512:
6
- metadata.gz: 76f9a3904d76439386ea3e7576a49c7d574592199526dcbe5e4acc7ef379352b30a83e007aa12578d1bc5b7777be2121599769c9b39c5856e1968d2425c6d48b
7
- data.tar.gz: fb07544d1b3d2de996d0ddae9a664632180ba5a6eeef3473f244b95cbca9fe0730bdfbac145be268825e9251503fae41057fa1a5571e6727f06f45d244ae4583
6
+ metadata.gz: 312bf63f3ea66c8d75921c4314912b6451b2457e31452b5cf05b2edbd43c671cefc9c0157f89ea01fb1ed8bcd49769be5770c0c18c559f6ccc47df39620e7e60
7
+ data.tar.gz: e087e4e649f2e31db3425ffefa0c83532e89ae4b8c6d7fab090989a511ced8b3f71133d9e211ae15358312ff0106c82ebd050245feb3e9743fe6caa60aafda02
@@ -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,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
@@ -0,0 +1,5 @@
1
+ group :acceptance_testing do
2
+ # Needed for podman testing
3
+ gem "docker-api", :git => 'https://github.com/trevor-vaughan/docker-api', :branch => 'podman-compat'
4
+ gem "beaker-rspec"
5
+ end
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
 
@@ -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
- "--tests", beaker_test_base_dir,
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
- 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,29 @@ HOSTS:
12
12
  - classifier
13
13
  - default
14
14
  docker_cmd: '["/sbin/init"]'
15
- dockeropts:
16
- Labels:
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: ubuntu:16.04
18
+ image: centos:7
23
19
  roles:
24
20
  - agent
25
- docker_cmd: '["/sbin/init"]'
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
- Labels:
32
- one: '3'
33
- two: '4'
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
@@ -0,0 +1,10 @@
1
+ require 'beaker'
2
+ require 'beaker-rspec'
3
+
4
+ RSpec.describe 'it can connect' do
5
+ hosts.each do |host|
6
+ context "on #{host}" do
7
+ on(host, 'ls /tmp')
8
+ end
9
+ end
10
+ end
@@ -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
- # 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
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
 
@@ -1,3 +1,3 @@
1
1
  module BeakerDocker
2
- VERSION = '0.6.0'
2
+ VERSION = '0.8.2'
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,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
- a << mount['opts'] if mount.has_key?('opts')
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
- container = ::Docker::Container.create(container_opts)
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
- @logger.info("Using docker server at #{ip}")
216
- port = container.json["NetworkSettings"]["Ports"]["22/tcp"][0]["HostPort"]
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
- # Update host metadata
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 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@#{ip} -p #{port}")
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 += <<-EOF
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
- EOF
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 += <<-EOF
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
- EOF
485
+ EOF
383
486
  when /fedora-(2[2-9])/
384
- dockerfile += <<-EOF
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
- EOF
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 += <<-EOF
392
- RUN yum clean all
393
- RUN yum install -y sudo openssh-server openssh-clients #{Beaker::HostPrebuiltSteps::RHEL8_PACKAGES.join(' ')}
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
- EOF
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 += <<-EOF
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
- EOF
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 += <<-EOF
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
- EOF
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 += <<-EOF
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
- EOF
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 += <<-EOF
533
+ dockerfile += <<~EOF
427
534
  RUN mkdir -p /var/run/sshd
428
535
  RUN echo root:#{root_password} | chpasswd
429
- EOF
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 += <<-EOF
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
- EOF
545
+ EOF
439
546
 
440
547
 
441
548
  # Any extra commands specified for the host