beaker-docker 0.5.2 → 0.7.1
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/README.md +11 -0
- data/beaker-docker.gemspec +1 -6
- data/lib/beaker-docker/version.rb +1 -1
- data/lib/beaker/hypervisor/docker.rb +124 -89
- data/spec/beaker/hypervisor/docker_spec.rb +14 -0
- metadata +8 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1656bc0ada39719991d068356033f018e0e8a2d3ad36b9fb8abc7285f2bf4e0f
|
4
|
+
data.tar.gz: b2207cae132edc1bf03e4b6dd0f5bf34139e30868f20e6e6f585291a72cf310e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9054afd2e705cd0cdf2910bb243aa4e103aa58e9575c11b23b3192fa0215d7fe90465544b679e805f89f311c337cbd5af2acf92c3d0123e93e00e23a99d8647b
|
7
|
+
data.tar.gz: d5f352ca1ccc5a37ac60c76344fdcc2265fde3120f2c9c68ec963149c081b9477a490a84eaf926139274c30d27d59f3f37cefd593f17465edcc2038045ada7a2
|
data/README.md
CHANGED
@@ -42,3 +42,14 @@ bundle exec rake test:acceptance
|
|
42
42
|
# Contributing
|
43
43
|
|
44
44
|
Please refer to puppetlabs/beaker's [contributing](https://github.com/puppetlabs/beaker/blob/master/CONTRIBUTING.md) guide.
|
45
|
+
|
46
|
+
# Releasing
|
47
|
+
|
48
|
+
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
|
49
|
+
lives on Puppet-internal infrastructure, so you'll need to be a part of the Puppet org to do this.
|
50
|
+
|
51
|
+
To run the job, click on `Build with Parameters` in the menu on the left. Make
|
52
|
+
sure you check the box next to `PUBLIC` and enter the appropriate version. The
|
53
|
+
version should adhere to [semantic version standards](https://semver.org).
|
54
|
+
When in doubt, consult the [maintainers of Beaker](https://github.com/puppetlabs/beaker/blob/master/CODEOWNERS)
|
55
|
+
for guidance.
|
data/beaker-docker.gemspec
CHANGED
@@ -30,14 +30,9 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.add_development_dependency 'simplecov'
|
31
31
|
s.add_development_dependency 'pry', '~> 0.10'
|
32
32
|
|
33
|
-
# Documentation dependencies
|
34
|
-
s.add_development_dependency 'yard'
|
35
|
-
s.add_development_dependency 'markdown'
|
36
|
-
s.add_development_dependency 'thin'
|
37
|
-
|
38
33
|
# Run time dependencies
|
39
34
|
s.add_runtime_dependency 'stringify-hash', '~> 0.0.0'
|
40
|
-
s.add_runtime_dependency 'docker-api'
|
35
|
+
s.add_runtime_dependency 'docker-api', '< 2.0.0'
|
41
36
|
|
42
37
|
end
|
43
38
|
|
@@ -44,56 +44,84 @@ module Beaker
|
|
44
44
|
|
45
45
|
end
|
46
46
|
|
47
|
+
def install_and_run_ssh(host)
|
48
|
+
host['dockerfile'] || host['use_image_entry_point']
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_container_opts(host, image_name)
|
52
|
+
container_opts = {}
|
53
|
+
if host['dockerfile']
|
54
|
+
container_opts['ExposedPorts'] = {'22/tcp' => {} }
|
55
|
+
end
|
56
|
+
|
57
|
+
container_opts.merge! ( {
|
58
|
+
'Image' => image_name,
|
59
|
+
'Hostname' => host.name,
|
60
|
+
'HostConfig' => {
|
61
|
+
'PortBindings' => {
|
62
|
+
'22/tcp' => [{ 'HostPort' => rand.to_s[2..5], 'HostIp' => '0.0.0.0'}]
|
63
|
+
},
|
64
|
+
'PublishAllPorts' => true,
|
65
|
+
'Privileged' => true,
|
66
|
+
'RestartPolicy' => {
|
67
|
+
'Name' => 'always'
|
68
|
+
}
|
69
|
+
}
|
70
|
+
} )
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_container_image(host)
|
74
|
+
@logger.debug("Creating image")
|
75
|
+
|
76
|
+
if host['use_image_as_is']
|
77
|
+
return ::Docker::Image.create('fromImage' => host['image'])
|
78
|
+
end
|
79
|
+
|
80
|
+
dockerfile = host['dockerfile']
|
81
|
+
if dockerfile
|
82
|
+
# assume that the dockerfile is in the repo and tests are running
|
83
|
+
# from the root of the repo; maybe add support for external Dockerfiles
|
84
|
+
# with external build dependencies later.
|
85
|
+
if File.exist?(dockerfile)
|
86
|
+
dir = File.expand_path(dockerfile).chomp(dockerfile)
|
87
|
+
return ::Docker::Image.build_from_dir(
|
88
|
+
dir,
|
89
|
+
{ 'dockerfile' => dockerfile,
|
90
|
+
:rm => true,
|
91
|
+
:buildargs => buildargs_for(host)
|
92
|
+
}
|
93
|
+
)
|
94
|
+
else
|
95
|
+
raise "Unable to find dockerfile at #{dockerfile}"
|
96
|
+
end
|
97
|
+
elsif host['use_image_entry_point']
|
98
|
+
df = <<-DF
|
99
|
+
FROM #{host['image']}
|
100
|
+
EXPOSE 22
|
101
|
+
DF
|
102
|
+
|
103
|
+
cmd = host['docker_cmd']
|
104
|
+
df += cmd if cmd
|
105
|
+
return ::Docker::Image.build(df, { rm: true, buildargs: buildargs_for(host) })
|
106
|
+
end
|
107
|
+
|
108
|
+
return ::Docker::Image.build(dockerfile_for(host),
|
109
|
+
{ rm: true, buildargs: buildargs_for(host) })
|
110
|
+
end
|
111
|
+
|
47
112
|
def provision
|
48
113
|
@logger.notify "Provisioning docker"
|
49
114
|
|
50
115
|
@hosts.each do |host|
|
51
116
|
@logger.notify "provisioning #{host.name}"
|
52
117
|
|
53
|
-
container_opts = {}
|
54
|
-
@logger.debug("Creating image")
|
55
|
-
|
56
|
-
dockerfile = host['dockerfile']
|
57
|
-
if dockerfile
|
58
|
-
install_and_run_ssh = true
|
59
|
-
container_opts['ExposedPorts'] = {'22/tcp' => {} }
|
60
|
-
# assume that the dockerfile is in the repo and tests are running
|
61
|
-
# from the root of the repo; maybe add support for external Dockerfiles
|
62
|
-
# with external build dependencies later.
|
63
|
-
if File.exist?(dockerfile)
|
64
|
-
dir = File.expand_path(dockerfile).chomp(dockerfile)
|
65
|
-
image = ::Docker::Image.build_from_dir(
|
66
|
-
dir,
|
67
|
-
{ 'dockerfile' => dockerfile,
|
68
|
-
:rm => true,
|
69
|
-
:buildargs => buildargs_for(host)
|
70
|
-
}
|
71
|
-
)
|
72
|
-
else
|
73
|
-
raise "Unable to find dockerfile at #{dockerfile}"
|
74
|
-
end
|
75
|
-
elsif host['use_image_entry_point']
|
76
|
-
install_and_run_ssh = true
|
77
|
-
df = <<-DF
|
78
|
-
FROM #{host['image']}
|
79
|
-
EXPOSE 22
|
80
|
-
DF
|
81
|
-
|
82
|
-
cmd = host['docker_cmd']
|
83
|
-
df += cmd if cmd
|
84
|
-
|
85
|
-
image = ::Docker::Image.build(df, { rm: true, buildargs: buildargs_for(host) })
|
86
118
|
|
87
|
-
|
119
|
+
image = get_container_image(host)
|
88
120
|
|
89
|
-
|
90
|
-
|
121
|
+
if host['tag']
|
122
|
+
image.tag({:repo => host['tag']})
|
91
123
|
end
|
92
124
|
|
93
|
-
if host['tag']
|
94
|
-
image.tag({:repo => host['tag']})
|
95
|
-
end
|
96
|
-
|
97
125
|
if @docker_type == 'swarm'
|
98
126
|
image_name = "#{@registry}/beaker/#{image.id}"
|
99
127
|
ret = ::Docker::Image.search(:term => image_name)
|
@@ -106,20 +134,7 @@ module Beaker
|
|
106
134
|
image_name = image.id
|
107
135
|
end
|
108
136
|
|
109
|
-
container_opts
|
110
|
-
'Image' => image_name,
|
111
|
-
'Hostname' => host.name,
|
112
|
-
'HostConfig' => {
|
113
|
-
'PortBindings' => {
|
114
|
-
'22/tcp' => [{ 'HostPort' => rand.to_s[2..5], 'HostIp' => '0.0.0.0'}]
|
115
|
-
},
|
116
|
-
'PublishAllPorts' => true,
|
117
|
-
'Privileged' => true,
|
118
|
-
'RestartPolicy' => {
|
119
|
-
'Name' => 'always'
|
120
|
-
}
|
121
|
-
}
|
122
|
-
} )
|
137
|
+
container_opts = get_container_opts(host, image_name)
|
123
138
|
if host['dockeropts'] || @options[:dockeropts]
|
124
139
|
dockeropts = host['dockeropts'] ? host['dockeropts'] : @options[:dockeropts]
|
125
140
|
dockeropts.each do |k,v|
|
@@ -129,10 +144,9 @@ module Beaker
|
|
129
144
|
|
130
145
|
container = find_container(host)
|
131
146
|
|
132
|
-
# Provisioning - Only provision if
|
133
|
-
#
|
134
|
-
|
135
|
-
if @options[:provision] || container.nil?
|
147
|
+
# Provisioning - Only provision if the host's container can't be found
|
148
|
+
# via its name or ID
|
149
|
+
if container.nil?
|
136
150
|
unless host['mount_folders'].nil?
|
137
151
|
container_opts['HostConfig'] ||= {}
|
138
152
|
container_opts['HostConfig']['Binds'] = host['mount_folders'].values.map do |mount|
|
@@ -147,6 +161,10 @@ module Beaker
|
|
147
161
|
end
|
148
162
|
end
|
149
163
|
|
164
|
+
if host['docker_env']
|
165
|
+
container_opts['Env'] = host['docker_env']
|
166
|
+
end
|
167
|
+
|
150
168
|
if host['docker_cap_add']
|
151
169
|
container_opts['HostConfig']['CapAdd'] = host['docker_cap_add']
|
152
170
|
end
|
@@ -157,6 +175,8 @@ module Beaker
|
|
157
175
|
|
158
176
|
@logger.debug("Creating container from image #{image_name}")
|
159
177
|
container = ::Docker::Container.create(container_opts)
|
178
|
+
else
|
179
|
+
host['use_existing_container'] = true
|
160
180
|
end
|
161
181
|
|
162
182
|
if container.nil?
|
@@ -169,7 +189,7 @@ module Beaker
|
|
169
189
|
@logger.debug("Starting container #{container.id}")
|
170
190
|
container.start
|
171
191
|
|
172
|
-
if install_and_run_ssh
|
192
|
+
if install_and_run_ssh(host)
|
173
193
|
@logger.notify("Installing ssh components and starting ssh daemon in #{host} container")
|
174
194
|
install_ssh_components(container, host)
|
175
195
|
# run fixssh to configure and start the ssh service
|
@@ -204,6 +224,7 @@ module Beaker
|
|
204
224
|
:password => root_password,
|
205
225
|
:port => port,
|
206
226
|
:forward_agent => forward_ssh_agent,
|
227
|
+
:auth_methods => ['password', 'publickey', 'hostbased', 'keyboard-interactive']
|
207
228
|
}
|
208
229
|
|
209
230
|
@logger.debug("node available as ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@#{ip} -p #{port}")
|
@@ -264,38 +285,44 @@ module Beaker
|
|
264
285
|
def cleanup
|
265
286
|
@logger.notify "Cleaning up docker"
|
266
287
|
@hosts.each do |host|
|
267
|
-
container
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
@logger.
|
275
|
-
end
|
276
|
-
@logger.debug("delete container #{container.id}")
|
277
|
-
begin
|
278
|
-
container.delete
|
279
|
-
rescue Excon::Errors::ClientError => e
|
280
|
-
@logger.warn("deletion of container #{container.id} failed: #{e.response.body}")
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
# Do not remove the image if docker_preserve_image is set to true, otherwise remove it
|
285
|
-
unless host['docker_preserve_image']
|
286
|
-
image_id = host['docker_image_id']
|
287
|
-
|
288
|
-
if image_id
|
289
|
-
@logger.debug("deleting image #{image_id}")
|
288
|
+
# leave the container running if docker_preserve_container is set
|
289
|
+
# setting docker_preserve_container also implies docker_preserve_image
|
290
|
+
# is set, since you can't delete an image that's the base of a running
|
291
|
+
# container
|
292
|
+
unless host['docker_preserve_container']
|
293
|
+
container = find_container(host)
|
294
|
+
if container
|
295
|
+
@logger.debug("stop container #{container.id}")
|
290
296
|
begin
|
291
|
-
|
297
|
+
container.kill
|
298
|
+
sleep 2 # avoid a race condition where the root FS can't unmount
|
292
299
|
rescue Excon::Errors::ClientError => e
|
293
|
-
@logger.warn("
|
294
|
-
|
295
|
-
|
300
|
+
@logger.warn("stop of container #{container.id} failed: #{e.response.body}")
|
301
|
+
end
|
302
|
+
@logger.debug("delete container #{container.id}")
|
303
|
+
begin
|
304
|
+
container.delete
|
305
|
+
rescue Excon::Errors::ClientError => e
|
306
|
+
@logger.warn("deletion of container #{container.id} failed: #{e.response.body}")
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
# Do not remove the image if docker_preserve_image is set to true, otherwise remove it
|
311
|
+
unless host['docker_preserve_image']
|
312
|
+
image_id = host['docker_image_id']
|
313
|
+
|
314
|
+
if image_id
|
315
|
+
@logger.debug("deleting image #{image_id}")
|
316
|
+
begin
|
317
|
+
::Docker::Image.remove(image_id)
|
318
|
+
rescue Excon::Errors::ClientError => e
|
319
|
+
@logger.warn("deletion of image #{image_id} failed: #{e.response.body}")
|
320
|
+
rescue ::Docker::Error::DockerError => e
|
321
|
+
@logger.warn("deletion of image #{image_id} caused internal Docker error: #{e.message}")
|
322
|
+
end
|
323
|
+
else
|
324
|
+
@logger.warn("Intended to delete the host's docker image, but host['docker_image_id'] was not set")
|
296
325
|
end
|
297
|
-
else
|
298
|
-
@logger.warn("Intended to delete the host's docker image, but host['docker_image_id'] was not set")
|
299
326
|
end
|
300
327
|
end
|
301
328
|
end
|
@@ -349,7 +376,7 @@ module Beaker
|
|
349
376
|
RUN apt-get update
|
350
377
|
RUN apt-get install -y openssh-server openssh-client #{Beaker::HostPrebuiltSteps::DEBIAN_PACKAGES.join(' ')}
|
351
378
|
EOF
|
352
|
-
|
379
|
+
when /cumulus/
|
353
380
|
dockerfile += <<-EOF
|
354
381
|
RUN apt-get update
|
355
382
|
RUN apt-get install -y openssh-server openssh-client #{Beaker::HostPrebuiltSteps::CUMULUS_PACKAGES.join(' ')}
|
@@ -361,6 +388,13 @@ module Beaker
|
|
361
388
|
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
|
362
389
|
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
|
363
390
|
EOF
|
391
|
+
when /el-8/
|
392
|
+
dockerfile += <<-EOF
|
393
|
+
RUN yum clean all
|
394
|
+
RUN yum install -y sudo openssh-server openssh-clients #{Beaker::HostPrebuiltSteps::RHEL8_PACKAGES.join(' ')}
|
395
|
+
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
|
396
|
+
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
|
397
|
+
EOF
|
364
398
|
when /^el-/, /centos/, /fedora/, /redhat/, /eos/
|
365
399
|
dockerfile += <<-EOF
|
366
400
|
RUN yum clean all
|
@@ -483,6 +517,7 @@ module Beaker
|
|
483
517
|
|
484
518
|
return container unless container.nil?
|
485
519
|
@logger.debug("Existing container not found")
|
520
|
+
return nil
|
486
521
|
end
|
487
522
|
|
488
523
|
# return true if we are inside a docker container
|
@@ -100,6 +100,7 @@ module Beaker
|
|
100
100
|
allow( ::Docker ).to receive(:logger=)
|
101
101
|
allow( ::Docker ).to receive(:version).and_return(version)
|
102
102
|
allow( ::Docker::Image ).to receive(:build).and_return(image)
|
103
|
+
allow( ::Docker::Image ).to receive(:create).and_return(image)
|
103
104
|
allow( ::Docker::Container ).to receive(:create).and_return(container)
|
104
105
|
allow_any_instance_of( ::Docker::Container ).to receive(:start)
|
105
106
|
end
|
@@ -244,6 +245,19 @@ module Beaker
|
|
244
245
|
end
|
245
246
|
end
|
246
247
|
|
248
|
+
it 'should call image create for hosts when use_image_as_is is defined' do
|
249
|
+
hosts.each do |host|
|
250
|
+
host['use_image_as_is'] = true
|
251
|
+
expect( docker ).not_to receive(:install_ssh_components)
|
252
|
+
expect( docker ).not_to receive(:fix_ssh)
|
253
|
+
expect( ::Docker::Image ).to receive(:create).with('fromImage' => host['image']) #once per host
|
254
|
+
expect( ::Docker::Image ).not_to receive(:build)
|
255
|
+
expect( ::Docker::Image ).not_to receive(:build_from_dir)
|
256
|
+
end
|
257
|
+
|
258
|
+
docker.provision
|
259
|
+
end
|
260
|
+
|
247
261
|
it 'should call dockerfile_for with all the hosts' do
|
248
262
|
hosts.each do |host|
|
249
263
|
expect( docker ).not_to receive(:install_ssh_components)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beaker-docker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rishi Javia, Kevin Imber, Tony Vu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -94,48 +94,6 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.10'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: yard
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: markdown
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: thin
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
139
97
|
- !ruby/object:Gem::Dependency
|
140
98
|
name: stringify-hash
|
141
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -154,16 +112,16 @@ dependencies:
|
|
154
112
|
name: docker-api
|
155
113
|
requirement: !ruby/object:Gem::Requirement
|
156
114
|
requirements:
|
157
|
-
- - "
|
115
|
+
- - "<"
|
158
116
|
- !ruby/object:Gem::Version
|
159
|
-
version:
|
117
|
+
version: 2.0.0
|
160
118
|
type: :runtime
|
161
119
|
prerelease: false
|
162
120
|
version_requirements: !ruby/object:Gem::Requirement
|
163
121
|
requirements:
|
164
|
-
- - "
|
122
|
+
- - "<"
|
165
123
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
124
|
+
version: 2.0.0
|
167
125
|
description: For use for the Beaker acceptance testing tool
|
168
126
|
email:
|
169
127
|
- rishi.javia@puppet.com, kevin.imber@puppet.com, tony.vu@puppet.com
|
@@ -172,6 +130,7 @@ executables:
|
|
172
130
|
extensions: []
|
173
131
|
extra_rdoc_files: []
|
174
132
|
files:
|
133
|
+
- ".github/dependabot.yml"
|
175
134
|
- ".gitignore"
|
176
135
|
- ".simplecov"
|
177
136
|
- Gemfile
|
@@ -205,8 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
205
164
|
- !ruby/object:Gem::Version
|
206
165
|
version: '0'
|
207
166
|
requirements: []
|
208
|
-
|
209
|
-
rubygems_version: 2.5.1
|
167
|
+
rubygems_version: 3.0.8
|
210
168
|
signing_key:
|
211
169
|
specification_version: 4
|
212
170
|
summary: Beaker DSL Extension Helpers!
|