beaker-docker 1.3.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +10 -0
- data/.github/dependabot.yml +9 -0
- data/.github/workflows/release.yml +1 -1
- data/.github/workflows/test.yml +58 -49
- data/.gitignore +2 -0
- data/.rubocop.yml +48 -0
- data/.rubocop_todo.yml +572 -0
- data/.simplecov +2 -0
- data/CHANGELOG.md +47 -0
- data/Gemfile +7 -5
- data/Rakefile +40 -137
- data/acceptance/tests/00_default_spec.rb +5 -4
- data/beaker-docker.gemspec +24 -18
- data/bin/beaker-docker +8 -10
- data/lib/beaker/hypervisor/docker.rb +90 -111
- data/lib/beaker-docker/version.rb +3 -1
- data/lib/beaker-docker.rb +1 -0
- data/spec/beaker/hypervisor/docker_spec.rb +48 -9
- data/spec/spec_helper.rb +6 -5
- metadata +79 -25
- data/Gemfile.local +0 -3
data/Rakefile
CHANGED
@@ -1,176 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rspec/core/rake_task'
|
2
4
|
|
3
|
-
|
5
|
+
begin
|
6
|
+
require 'rubocop/rake_task'
|
7
|
+
rescue LoadError
|
8
|
+
# RuboCop is an optional group
|
9
|
+
else
|
10
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
11
|
+
# These make the rubocop experience maybe slightly less terrible
|
12
|
+
task.options = ['--display-cop-names', '--display-style-guide', '--extra-details']
|
13
|
+
# Use Rubocop's Github Actions formatter if possible
|
14
|
+
task.formatters << 'github' if ENV['GITHUB_ACTIONS'] == 'true'
|
15
|
+
end
|
16
|
+
end
|
4
17
|
|
18
|
+
namespace :test do
|
5
19
|
namespace :spec do
|
6
|
-
|
7
|
-
desc "Run spec tests"
|
20
|
+
desc 'Run spec tests'
|
8
21
|
RSpec::Core::RakeTask.new(:run) do |t|
|
9
22
|
t.rspec_opts = ['--color', '--format documentation']
|
10
23
|
t.pattern = 'spec/'
|
11
24
|
end
|
12
25
|
|
13
|
-
desc
|
26
|
+
desc 'Run spec tests with coverage'
|
14
27
|
RSpec::Core::RakeTask.new(:coverage) do |t|
|
15
28
|
ENV['BEAKER_DOCKER_COVERAGE'] = 'y'
|
16
29
|
t.rspec_opts = ['--color', '--format documentation']
|
17
30
|
t.pattern = 'spec/'
|
18
31
|
end
|
19
|
-
|
20
32
|
end
|
21
33
|
|
22
34
|
namespace :acceptance do
|
23
|
-
|
24
|
-
desc <<-EOS
|
25
|
-
A quick acceptance test, named because it has no pre-suites to run
|
26
|
-
EOS
|
35
|
+
desc 'A quick acceptance test, named because it has no pre-suites to run'
|
27
36
|
task :quick do
|
28
|
-
|
29
|
-
|
30
|
-
beaker_gem_spec = Gem::Specification.find_by_name('beaker')
|
31
|
-
beaker_gem_dir = beaker_gem_spec.gem_dir
|
32
|
-
beaker_test_base_dir = File.join(beaker_gem_dir, 'acceptance/tests/base')
|
33
|
-
load_path_option = File.join(beaker_gem_dir, 'acceptance/lib')
|
37
|
+
## setup & load_path of beaker's acceptance base and lib directory
|
38
|
+
## see below for the reason why it's commented out atm
|
39
|
+
# beaker_gem_spec = Gem::Specification.find_by_name('beaker')
|
40
|
+
# beaker_gem_dir = beaker_gem_spec.gem_dir
|
41
|
+
# beaker_test_base_dir = File.join(beaker_gem_dir, 'acceptance/tests/base')
|
42
|
+
# load_path_option = File.join(beaker_gem_dir, 'acceptance/lib')
|
34
43
|
|
35
44
|
ENV['BEAKER_setfile'] = 'acceptance/config/nodes/hosts.yaml'
|
36
|
-
sh(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
sh('beaker',
|
46
|
+
'--hosts', 'acceptance/config/nodes/hosts.yaml',
|
47
|
+
## We can't run these tests until the rsync support in the main
|
48
|
+
## beaker/host.rb is updated to work with passwords.
|
49
|
+
# '--tests', beaker_test_base_dir,
|
50
|
+
# '--load-path', load_path_option,
|
51
|
+
'--tests', 'acceptance/tests/',
|
52
|
+
'--log-level', 'debug',
|
53
|
+
'--debug')
|
45
54
|
end
|
46
|
-
|
47
55
|
end
|
48
|
-
|
49
56
|
end
|
50
57
|
|
51
58
|
# namespace-named default tasks.
|
52
59
|
# these are the default tasks invoked when only the namespace is referenced.
|
53
60
|
# they're needed because `task :default` in those blocks doesn't work as expected.
|
54
|
-
task 'test:spec'
|
55
|
-
task 'test:acceptance'
|
61
|
+
task 'test:spec': %i[test:spec:run]
|
62
|
+
task 'test:acceptance': %i[test:acceptance:quick]
|
56
63
|
|
57
64
|
# global defaults
|
58
|
-
task :
|
59
|
-
task :
|
60
|
-
|
61
|
-
###########################################################
|
62
|
-
#
|
63
|
-
# Documentation Tasks
|
64
|
-
#
|
65
|
-
###########################################################
|
66
|
-
DOCS_DAEMON = "yard server --reload --daemon --server thin"
|
67
|
-
FOREGROUND_SERVER = 'bundle exec yard server --reload --verbose --server thin lib/beaker'
|
68
|
-
|
69
|
-
def running?( cmdline )
|
70
|
-
ps = `ps -ef`
|
71
|
-
found = ps.lines.grep( /#{Regexp.quote( cmdline )}/ )
|
72
|
-
if found.length > 1
|
73
|
-
raise StandardError, "Found multiple YARD Servers. Don't know what to do."
|
74
|
-
end
|
75
|
-
|
76
|
-
yes = found.empty? ? false : true
|
77
|
-
return yes, found.first
|
78
|
-
end
|
79
|
-
|
80
|
-
def pid_from( output )
|
81
|
-
output.squeeze(' ').strip.split(' ')[1]
|
82
|
-
end
|
83
|
-
|
84
|
-
desc 'Start the documentation server in the foreground'
|
85
|
-
task :docs => 'docs:clear' do
|
86
|
-
original_dir = Dir.pwd
|
87
|
-
Dir.chdir( File.expand_path(File.dirname(__FILE__)) )
|
88
|
-
sh FOREGROUND_SERVER
|
89
|
-
Dir.chdir( original_dir )
|
90
|
-
end
|
91
|
-
|
92
|
-
namespace :docs do
|
93
|
-
|
94
|
-
desc 'Clear the generated documentation cache'
|
95
|
-
task :clear do
|
96
|
-
original_dir = Dir.pwd
|
97
|
-
Dir.chdir( File.expand_path(File.dirname(__FILE__)) )
|
98
|
-
sh 'rm -rf docs'
|
99
|
-
Dir.chdir( original_dir )
|
100
|
-
end
|
101
|
-
|
102
|
-
desc 'Generate static documentation'
|
103
|
-
task :gen => 'docs:clear' do
|
104
|
-
original_dir = Dir.pwd
|
105
|
-
Dir.chdir( File.expand_path(File.dirname(__FILE__)) )
|
106
|
-
output = `bundle exec yard doc`
|
107
|
-
puts output
|
108
|
-
if output =~ /\[warn\]|\[error\]/
|
109
|
-
fail "Errors/Warnings during yard documentation generation"
|
110
|
-
end
|
111
|
-
Dir.chdir( original_dir )
|
112
|
-
end
|
113
|
-
|
114
|
-
desc 'Run the documentation server in the background, alias `bg`'
|
115
|
-
task :background => 'docs:clear' do
|
116
|
-
yes, output = running?( DOCS_DAEMON )
|
117
|
-
if yes
|
118
|
-
puts "Not starting a new YARD Server..."
|
119
|
-
puts "Found one running with pid #{pid_from( output )}."
|
120
|
-
else
|
121
|
-
original_dir = Dir.pwd
|
122
|
-
Dir.chdir( File.expand_path(File.dirname(__FILE__)) )
|
123
|
-
sh "bundle exec #{DOCS_DAEMON}"
|
124
|
-
Dir.chdir( original_dir )
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
task(:bg) { Rake::Task['docs:background'].invoke }
|
129
|
-
|
130
|
-
desc 'Check the status of the documentation server'
|
131
|
-
task :status do
|
132
|
-
yes, output = running?( DOCS_DAEMON )
|
133
|
-
if yes
|
134
|
-
pid = pid_from( output )
|
135
|
-
puts "Found a YARD Server running with pid #{pid}"
|
136
|
-
else
|
137
|
-
puts "Could not find a running YARD Server."
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
desc "Stop a running YARD Server"
|
142
|
-
task :stop do
|
143
|
-
yes, output = running?( DOCS_DAEMON )
|
144
|
-
if yes
|
145
|
-
pid = pid_from( output )
|
146
|
-
puts "Found a YARD Server running with pid #{pid}"
|
147
|
-
`kill #{pid}`
|
148
|
-
puts "Stopping..."
|
149
|
-
yes, output = running?( DOCS_DAEMON )
|
150
|
-
if yes
|
151
|
-
`kill -9 #{pid}`
|
152
|
-
yes, output = running?( DOCS_DAEMON )
|
153
|
-
if yes
|
154
|
-
puts "Could not Stop Server!"
|
155
|
-
else
|
156
|
-
puts "Server stopped."
|
157
|
-
end
|
158
|
-
else
|
159
|
-
puts "Server stopped."
|
160
|
-
end
|
161
|
-
else
|
162
|
-
puts "Could not find a running YARD Server"
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
65
|
+
task lint: %i[lint:rubocop]
|
66
|
+
task test: %i[test:spec]
|
67
|
+
task default: %i[test]
|
166
68
|
|
167
69
|
begin
|
168
70
|
require 'rubygems'
|
169
71
|
require 'github_changelog_generator/task'
|
170
72
|
rescue LoadError
|
73
|
+
# Do nothing if no required gem installed
|
171
74
|
else
|
172
75
|
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
173
|
-
config.exclude_labels = %w
|
76
|
+
config.exclude_labels = %w[duplicate question invalid wontfix wont-fix skip-changelog]
|
174
77
|
config.user = 'voxpupuli'
|
175
78
|
config.project = 'beaker-docker'
|
176
79
|
gem_version = Gem::Specification.load("#{config.project}.gemspec").version
|
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'beaker'
|
2
|
-
require 'beaker-rspec'
|
3
4
|
|
4
|
-
|
5
|
+
test_name 'Ensure docker container is accessible' do
|
5
6
|
hosts.each do |host|
|
6
|
-
|
7
|
-
on(host, '
|
7
|
+
step "on #{host}" do
|
8
|
+
on(host, 'true')
|
8
9
|
end
|
9
10
|
end
|
10
11
|
end
|
data/beaker-docker.gemspec
CHANGED
@@ -1,35 +1,41 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
3
4
|
require 'beaker-docker/version'
|
4
5
|
|
5
6
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
7
|
+
s.name = 'beaker-docker'
|
7
8
|
s.version = BeakerDocker::VERSION
|
8
9
|
s.authors = [
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
'Vox Pupuli',
|
11
|
+
'Rishi Javia',
|
12
|
+
'Kevin Imber',
|
13
|
+
'Tony Vu',
|
13
14
|
]
|
14
|
-
s.email = [
|
15
|
-
s.homepage =
|
16
|
-
s.summary =
|
17
|
-
s.description =
|
15
|
+
s.email = ['voxpupuli@groups.io']
|
16
|
+
s.homepage = 'https://github.com/voxpupuli/beaker-docker'
|
17
|
+
s.summary = 'Docker hypervisor for Beaker acceptance testing framework'
|
18
|
+
s.description = 'Allows running Beaker tests using Docker'
|
18
19
|
s.license = 'Apache-2.0'
|
19
20
|
|
20
21
|
s.files = `git ls-files`.split("\n")
|
21
22
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
-
s.require_paths = [
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
24
|
+
s.require_paths = ['lib']
|
25
|
+
|
26
|
+
s.required_ruby_version = '>= 2.4', '< 4'
|
24
27
|
|
25
28
|
# Testing dependencies
|
26
|
-
s.add_development_dependency '
|
27
|
-
s.add_development_dependency 'rspec-its', '~> 1.3'
|
28
|
-
s.add_development_dependency 'fakefs', '~> 1.3'
|
29
|
+
s.add_development_dependency 'fakefs', '>= 1.3', '< 3.0'
|
29
30
|
s.add_development_dependency 'rake', '~> 13.0'
|
31
|
+
s.add_development_dependency 'rspec', '~> 3.0'
|
32
|
+
s.add_development_dependency 'rubocop', '~> 1.12.0'
|
33
|
+
s.add_development_dependency 'rubocop-performance', '~> 1.10'
|
34
|
+
s.add_development_dependency 'rubocop-rake', '~> 0.2'
|
35
|
+
s.add_development_dependency 'rubocop-rspec', '>= 1.44'
|
30
36
|
|
31
37
|
# Run time dependencies
|
32
|
-
s.add_runtime_dependency 'stringify-hash', '~> 0.0.0'
|
33
|
-
s.add_runtime_dependency 'docker-api', '~> 2.1'
|
34
38
|
s.add_runtime_dependency 'beaker', '>= 4.34'
|
39
|
+
s.add_runtime_dependency 'docker-api', '~> 2.1'
|
40
|
+
s.add_runtime_dependency 'stringify-hash', '~> 0.0.0'
|
35
41
|
end
|
data/bin/beaker-docker
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'rubygems' unless defined?(Gem)
|
4
5
|
require 'beaker-docker'
|
5
6
|
|
6
|
-
VERSION_STRING =
|
7
|
-
"
|
7
|
+
VERSION_STRING = <<'VER'
|
8
8
|
_ .--.
|
9
9
|
( ` )
|
10
10
|
beaker-docker .-' `--,
|
@@ -14,19 +14,17 @@ VERSION_STRING =
|
|
14
14
|
;| _| _| _| '-'__,--'`--'
|
15
15
|
| _| _| _| _| |
|
16
16
|
_ || _| _| _| _| %s
|
17
|
-
_(
|
17
|
+
_( `--.\_| _| _| _|/
|
18
18
|
.-' )--,| _| _|.`
|
19
19
|
(__, (_ ) )_| _| /
|
20
|
-
`-.__
|
20
|
+
`-.__.\ _,--'\|__|__/
|
21
21
|
;____;
|
22
|
-
|
22
|
+
\YT/
|
23
23
|
||
|
24
|
-
|
24
|
+
|""|
|
25
25
|
'=='
|
26
|
-
|
26
|
+
VER
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
puts BeakerDocker::VERSION
|
28
|
+
puts VERSION_STRING % BeakerDocker::VERSION
|
31
29
|
|
32
30
|
exit 0
|
@@ -30,14 +30,14 @@ module Beaker
|
|
30
30
|
* Check your DOCKER_HOST variable has been set
|
31
31
|
* If you are on OSX or Windows, you might not have Docker Machine setup correctly: https://docs.docker.com/machine/
|
32
32
|
* If you are using rootless podman, you might need to set up your local socket and service
|
33
|
-
|
33
|
+
ERRMSG
|
34
34
|
end
|
35
35
|
|
36
36
|
# Pass on all the logging from docker-api to the beaker logger instance
|
37
37
|
::Docker.logger = @logger
|
38
38
|
|
39
39
|
# Find out what kind of remote instance we are talking against
|
40
|
-
if @docker_version['Version']
|
40
|
+
if /swarm/.match?(@docker_version['Version'])
|
41
41
|
@docker_type = 'swarm'
|
42
42
|
unless ENV['DOCKER_REGISTRY']
|
43
43
|
raise "Using Swarm with beaker requires a private registry. Please setup the private registry and set the 'DOCKER_REGISTRY' env var"
|
@@ -58,7 +58,7 @@ module Beaker
|
|
58
58
|
|
59
59
|
# If the container is running ssh as its init process then this method
|
60
60
|
# will cause issues.
|
61
|
-
if host[:docker_cmd]
|
61
|
+
if /sshd/.match?(Array(host[:docker_cmd]).first)
|
62
62
|
def host.ssh_service_restart
|
63
63
|
self[:docker_container].exec(%w(kill -1 1))
|
64
64
|
end
|
@@ -142,9 +142,9 @@ module Beaker
|
|
142
142
|
port: nil
|
143
143
|
}
|
144
144
|
|
145
|
-
container_json
|
145
|
+
container_json = container.json
|
146
146
|
network_settings = container_json['NetworkSettings']
|
147
|
-
host_config
|
147
|
+
host_config = container_json['HostConfig']
|
148
148
|
|
149
149
|
ip = nil
|
150
150
|
port = nil
|
@@ -161,31 +161,28 @@ module Beaker
|
|
161
161
|
|
162
162
|
# Host to Container
|
163
163
|
port22 = network_settings.dig('PortBindings','22/tcp')
|
164
|
-
if port22.nil? && network_settings.key?('Ports')
|
164
|
+
if port22.nil? && network_settings.key?('Ports') && !nested_docker?
|
165
165
|
port22 = network_settings.dig('Ports','22/tcp')
|
166
166
|
end
|
167
|
+
|
167
168
|
ip = port22[0]['HostIp'] if port22
|
168
169
|
port = port22[0]['HostPort'] if port22
|
169
170
|
|
170
171
|
# Container to container
|
171
172
|
unless ip && port
|
172
|
-
ip = nil
|
173
|
-
port = nil
|
174
|
-
|
175
173
|
ip = network_settings['IPAddress']
|
176
|
-
port =
|
174
|
+
port = ip && !ip.empty? ? 22 : nil
|
177
175
|
end
|
178
176
|
|
179
177
|
# Container through gateway
|
180
178
|
unless ip && port
|
181
|
-
ip = nil
|
182
|
-
port = nil
|
183
|
-
|
184
179
|
ip = network_settings['Gateway']
|
185
180
|
|
186
181
|
if ip && !ip.empty?
|
187
182
|
port22 = network_settings.dig('PortBindings','22/tcp')
|
188
183
|
port = port22[0]['HostPort'] if port22
|
184
|
+
else
|
185
|
+
port = nil
|
189
186
|
end
|
190
187
|
end
|
191
188
|
|
@@ -216,7 +213,6 @@ module Beaker
|
|
216
213
|
@hosts.each do |host|
|
217
214
|
@logger.notify "provisioning #{host.name}"
|
218
215
|
|
219
|
-
|
220
216
|
image = get_container_image(host)
|
221
217
|
|
222
218
|
if host['tag']
|
@@ -510,145 +506,129 @@ module Beaker
|
|
510
506
|
|
511
507
|
def dockerfile_for(host)
|
512
508
|
# specify base image
|
513
|
-
dockerfile =
|
509
|
+
dockerfile = <<~DF
|
514
510
|
FROM #{host['image']}
|
515
511
|
ENV container docker
|
516
|
-
|
512
|
+
DF
|
517
513
|
|
518
514
|
# Commands before any other commands. Can be used for eg. proxy configuration
|
519
|
-
dockerfile += (host['docker_image_first_commands'] || []).map { |
|
520
|
-
"RUN #{command}\n"
|
521
|
-
}.join('')
|
522
|
-
|
523
|
-
# additional options to specify to the sshd
|
524
|
-
# may vary by platform
|
525
|
-
sshd_options = ''
|
515
|
+
dockerfile += (host['docker_image_first_commands'] || []).map { |cmd| "RUN #{cmd}\n" }.join('')
|
526
516
|
|
527
517
|
# add platform-specific actions
|
528
|
-
service_name =
|
518
|
+
service_name = 'sshd'
|
529
519
|
additional_packages = host_packages(host)
|
530
520
|
case host['platform']
|
531
521
|
when /ubuntu/, /debian/
|
532
|
-
service_name =
|
533
|
-
dockerfile += <<~
|
534
|
-
RUN apt-get update
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
when
|
539
|
-
|
540
|
-
RUN apt-get update
|
541
|
-
|
542
|
-
|
522
|
+
service_name = 'ssh'
|
523
|
+
dockerfile += <<~DF
|
524
|
+
RUN apt-get update \
|
525
|
+
&& apt-get install -y openssh-server openssh-client #{additional_packages.join(' ')} \
|
526
|
+
&& sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
|
527
|
+
DF
|
528
|
+
when /cumulus/
|
529
|
+
dockerfile += <<~DF
|
530
|
+
RUN apt-get update \
|
531
|
+
&& apt-get install -y openssh-server openssh-client #{additional_packages.join(' ')}
|
532
|
+
DF
|
543
533
|
when /el-[89]/, /fedora-(2[2-9]|3)/
|
544
|
-
dockerfile += <<~
|
545
|
-
RUN dnf clean all
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
EOF
|
534
|
+
dockerfile += <<~DF
|
535
|
+
RUN dnf clean all \
|
536
|
+
&& dnf install -y sudo openssh-server openssh-clients #{additional_packages.join(' ')} \
|
537
|
+
&& ssh-keygen -A \
|
538
|
+
&& sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
|
539
|
+
DF
|
551
540
|
when /^el-/, /centos/, /fedora/, /redhat/, /eos/
|
552
|
-
dockerfile += <<~
|
553
|
-
RUN yum clean all
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
EOF
|
541
|
+
dockerfile += <<~DF
|
542
|
+
RUN yum clean all \
|
543
|
+
&& yum install -y sudo openssh-server openssh-clients #{additional_packages.join(' ')} \
|
544
|
+
&& ssh-keygen -A \
|
545
|
+
&& sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
|
546
|
+
DF
|
559
547
|
when /opensuse/, /sles/
|
560
|
-
dockerfile += <<~
|
561
|
-
RUN zypper -n in openssh #{additional_packages.join(' ')}
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
EOF
|
548
|
+
dockerfile += <<~DF
|
549
|
+
RUN zypper -n in openssh #{additional_packages.join(' ')} \
|
550
|
+
&& ssh-keygen -A \
|
551
|
+
&& sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config \
|
552
|
+
&& sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/*
|
553
|
+
DF
|
567
554
|
when /archlinux/
|
568
|
-
dockerfile += <<~
|
569
|
-
RUN pacman --sync --refresh --noconfirm archlinux-keyring
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
555
|
+
dockerfile += <<~DF
|
556
|
+
RUN pacman --sync --refresh --noconfirm archlinux-keyring \
|
557
|
+
&& pacman --sync --refresh --noconfirm --sysupgrade \
|
558
|
+
&& pacman --sync --noconfirm #{additional_packages.join(' ')} \
|
559
|
+
&& ssh-keygen -A \
|
560
|
+
&& sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config \
|
561
|
+
&& systemctl enable sshd
|
562
|
+
DF
|
576
563
|
else
|
577
|
-
# TODO add more platform steps here
|
564
|
+
# TODO: add more platform steps here
|
578
565
|
raise "platform #{host['platform']} not yet supported on docker"
|
579
566
|
end
|
580
567
|
|
581
568
|
# Make sshd directory, set root password
|
582
|
-
dockerfile += <<~
|
583
|
-
RUN mkdir -p /var/run/sshd
|
584
|
-
|
585
|
-
|
569
|
+
dockerfile += <<~DF
|
570
|
+
RUN mkdir -p /var/run/sshd \
|
571
|
+
&& echo root:#{root_password} | chpasswd
|
572
|
+
DF
|
586
573
|
|
587
574
|
# Configure sshd service to allowroot login using password
|
588
575
|
# Also, disable reverse DNS lookups to prevent every. single. ssh
|
589
576
|
# operation taking 30 seconds while the lookup times out.
|
590
|
-
|
591
|
-
|
592
|
-
RUN sed -ri
|
593
|
-
|
594
|
-
|
595
|
-
|
577
|
+
# Also unbreak users with a bunch of SSH keys loaded in their keyring.
|
578
|
+
dockerfile += <<~DF
|
579
|
+
RUN sed -ri \
|
580
|
+
-e 's/^#?PermitRootLogin .*/PermitRootLogin yes/' \
|
581
|
+
-e 's/^#?PasswordAuthentication .*/PasswordAuthentication yes/' \
|
582
|
+
-e 's/^#?UseDNS .*/UseDNS no/' \
|
583
|
+
-e 's/^#?MaxAuthTries.*/MaxAuthTries 1000/' \
|
584
|
+
/etc/ssh/sshd_config
|
585
|
+
DF
|
596
586
|
|
597
587
|
# Any extra commands specified for the host
|
598
|
-
dockerfile += (host['docker_image_commands'] || []).map { |
|
599
|
-
"RUN #{command}\n"
|
600
|
-
}.join('')
|
588
|
+
dockerfile += (host['docker_image_commands'] || []).map { |cmd| "RUN #{cmd}\n" }.join('')
|
601
589
|
|
602
590
|
# Override image entrypoint
|
603
|
-
if host['docker_image_entrypoint']
|
604
|
-
dockerfile += "ENTRYPOINT #{host['docker_image_entrypoint']}\n"
|
605
|
-
end
|
591
|
+
dockerfile += "ENTRYPOINT #{host['docker_image_entrypoint']}\n" if host['docker_image_entrypoint']
|
606
592
|
|
607
593
|
# How to start a sshd on port 22. May be an init for more supervision
|
608
594
|
# Ensure that the ssh server can be restarted (done from set_env) and container keeps running
|
609
|
-
cmd = host['docker_cmd'] || [
|
610
|
-
dockerfile +=
|
595
|
+
cmd = host['docker_cmd'] || ['sh', '-c', "service #{service_name} start; tail -f /dev/null"]
|
596
|
+
dockerfile += <<~DF
|
611
597
|
EXPOSE 22
|
612
598
|
CMD #{cmd}
|
613
|
-
|
614
|
-
|
615
|
-
# end
|
599
|
+
DF
|
616
600
|
|
617
601
|
@logger.debug("Dockerfile is #{dockerfile}")
|
618
|
-
|
602
|
+
|
603
|
+
dockerfile
|
619
604
|
end
|
620
605
|
|
621
606
|
# a puppet run may have changed the ssh config which would
|
622
607
|
# keep us out of the container. This is a best effort to fix it.
|
623
608
|
# Optionally pass in a host object to to determine which ssh
|
624
609
|
# restart command we should try.
|
625
|
-
def fix_ssh(container, host=nil)
|
610
|
+
def fix_ssh(container, host = nil)
|
626
611
|
@logger.debug("Fixing ssh on container #{container.id}")
|
627
|
-
container.exec(['sed','-ri',
|
628
|
-
's/^#?PermitRootLogin .*/PermitRootLogin yes/',
|
629
|
-
'/
|
630
|
-
|
631
|
-
|
632
|
-
'/
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
container.exec(%w(/usr/sbin/sshd))
|
645
|
-
else
|
646
|
-
container.exec(%w(service ssh restart))
|
647
|
-
end
|
612
|
+
container.exec(['sed', '-ri',
|
613
|
+
'-e', 's/^#?PermitRootLogin .*/PermitRootLogin yes/',
|
614
|
+
'-e', 's/^#?PasswordAuthentication .*/PasswordAuthentication yes/',
|
615
|
+
'-e', 's/^#?UseDNS .*/UseDNS no/',
|
616
|
+
# Unbreak users with a bunch of SSH keys loaded in their keyring.
|
617
|
+
'-e', 's/^#?MaxAuthTries.*/MaxAuthTries 1000/',
|
618
|
+
'/etc/ssh/sshd_config',])
|
619
|
+
|
620
|
+
return unless host
|
621
|
+
|
622
|
+
case host['platform']
|
623
|
+
when /alpine/
|
624
|
+
container.exec(%w[/usr/sbin/sshd])
|
625
|
+
when /ubuntu/, /debian/
|
626
|
+
container.exec(%w[service ssh restart])
|
627
|
+
else
|
628
|
+
container.exec(%w[service sshd restart])
|
648
629
|
end
|
649
630
|
end
|
650
631
|
|
651
|
-
|
652
632
|
# return the existing container if we're not provisioning
|
653
633
|
# and docker_container_name is set
|
654
634
|
def find_container(host)
|
@@ -679,6 +659,5 @@ module Beaker
|
|
679
659
|
def in_container?
|
680
660
|
return File.file?('/.dockerenv')
|
681
661
|
end
|
682
|
-
|
683
662
|
end
|
684
663
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# frozen_string_literal: true
|