beaker 3.18.0 → 3.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Rakefile +0 -23
- data/beaker.gemspec +1 -0
- data/lib/beaker/dsl/helpers.rb +3 -4
- data/lib/beaker/dsl/install_utils.rb +2 -7
- data/lib/beaker/dsl/wrappers.rb +0 -87
- data/lib/beaker/host/unix/pkg.rb +56 -17
- data/lib/beaker/hypervisor/docker.rb +26 -1
- data/lib/beaker/options/parser.rb +12 -5
- data/lib/beaker/options/subcommand_options_file_parser.rb +11 -4
- data/lib/beaker/ssh_connection.rb +6 -6
- data/lib/beaker/subcommand.rb +6 -0
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/host/unix/pkg_spec.rb +130 -0
- data/spec/beaker/hypervisor/docker_spec.rb +28 -1
- data/spec/beaker/options/parser_spec.rb +38 -18
- data/spec/beaker/options/subcommand_options_parser_spec.rb +28 -5
- data/spec/beaker/ssh_connection_spec.rb +17 -17
- metadata +16 -28
- data/acceptance/config/puppetgem/acceptance-options.rb +0 -9
- data/acceptance/config/puppetgit/acceptance-options.rb +0 -9
- data/acceptance/config/puppetpkg/acceptance-options.rb +0 -8
- data/acceptance/pre_suite/puppet_gem/install.rb +0 -8
- data/acceptance/pre_suite/puppet_git/install.rb +0 -98
- data/acceptance/pre_suite/puppet_pkg/install.rb +0 -9
- data/acceptance/tests/puppet/README.md +0 -3
- data/acceptance/tests/puppet/install_smoke_test.rb +0 -21
- data/acceptance/tests/puppet/stub_host.rb +0 -47
- data/acceptance/tests/puppet/web_helpers_test.rb +0 -55
- data/acceptance/tests/puppet/with_puppet_running_on.rb +0 -26
- data/lib/beaker/dsl/helpers/puppet_helpers.rb +0 -865
- data/lib/beaker/dsl/helpers/tk_helpers.rb +0 -89
- data/lib/beaker/dsl/install_utils/aio_defaults.rb +0 -93
- data/lib/beaker/dsl/install_utils/ezbake_utils.rb +0 -256
- data/lib/beaker/dsl/install_utils/foss_defaults.rb +0 -211
- data/lib/beaker/dsl/install_utils/foss_utils.rb +0 -1307
- data/lib/beaker/dsl/install_utils/module_utils.rb +0 -244
- data/lib/beaker/dsl/install_utils/puppet_utils.rb +0 -157
- data/lib/beaker/options/homedir_options_file_parser.rb +0 -0
- data/spec/beaker/dsl/helpers/facter_helpers_spec.rb +0 -59
- data/spec/beaker/dsl/helpers/puppet_helpers_spec.rb +0 -1179
- data/spec/beaker/dsl/helpers/tk_helpers_spec.rb +0 -83
- data/spec/beaker/dsl/install_utils/foss_utils_spec.rb +0 -1307
- data/spec/beaker/dsl/install_utils/module_utils_spec.rb +0 -261
- data/spec/beaker/dsl/install_utils/puppet_utils_spec.rb +0 -136
@@ -1,9 +0,0 @@
|
|
1
|
-
{
|
2
|
-
:type => 'foss',
|
3
|
-
:add_el_extras => 'true',
|
4
|
-
:is_puppetserver => false,
|
5
|
-
:puppetservice => 'puppet.service',
|
6
|
-
:pre_suite => 'acceptance/pre_suite/puppet_gem/install.rb',
|
7
|
-
:tests => 'acceptance/tests/puppet',
|
8
|
-
:'master-start-curl-retries' => 30,
|
9
|
-
}.merge(eval File.read('acceptance/config/acceptance-options.rb'))
|
@@ -1,9 +0,0 @@
|
|
1
|
-
{
|
2
|
-
:type => 'foss',
|
3
|
-
:add_el_extras => 'true',
|
4
|
-
:is_puppetserver => false,
|
5
|
-
:puppetservice => 'puppet.service',
|
6
|
-
:pre_suite => 'acceptance/pre_suite/puppet_git/install.rb',
|
7
|
-
:tests => 'acceptance/tests/puppet',
|
8
|
-
:'master-start-curl-retries' => 30,
|
9
|
-
}.merge(eval File.read('acceptance/config/acceptance-options.rb'))
|
@@ -1,8 +0,0 @@
|
|
1
|
-
{
|
2
|
-
:type => 'foss',
|
3
|
-
:is_puppetserver => false,
|
4
|
-
:puppetservice => 'puppet.service',
|
5
|
-
:pre_suite => 'acceptance/pre_suite/puppet_pkg/install.rb',
|
6
|
-
:tests => 'acceptance/tests/puppet',
|
7
|
-
:'master-start-curl-retries' => 30,
|
8
|
-
}.merge(eval File.read('acceptance/config/acceptance-options.rb'))
|
@@ -1,8 +0,0 @@
|
|
1
|
-
hosts.each do |host|
|
2
|
-
install_puppet_from_gem(host, {:version => '3.8.7'})
|
3
|
-
unless host['platform'] =~ /windows/
|
4
|
-
on(host, "touch #{File.join(host.puppet['confdir'],'puppet.conf')}")
|
5
|
-
on(host, puppet('resource user puppet ensure=present'))
|
6
|
-
on(host, puppet('resource group puppet ensure=present'))
|
7
|
-
end
|
8
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib'))
|
3
|
-
require 'beaker/acceptance/install_utils'
|
4
|
-
extend Beaker::Acceptance::InstallUtils
|
5
|
-
end
|
6
|
-
test_name 'Puppet git pre-suite'
|
7
|
-
|
8
|
-
install = [
|
9
|
-
'facter#2.1.0',
|
10
|
-
'hiera#1.3.4',
|
11
|
-
'puppet#3.8.7'
|
12
|
-
]
|
13
|
-
|
14
|
-
SourcePath = Beaker::DSL::InstallUtils::SourcePath
|
15
|
-
|
16
|
-
PACKAGES = {
|
17
|
-
:redhat => [
|
18
|
-
'git',
|
19
|
-
'ruby',
|
20
|
-
'rubygem-json', # :add_el_extras is required to find this package
|
21
|
-
],
|
22
|
-
:debian => [
|
23
|
-
['git', 'git-core'],
|
24
|
-
'ruby',
|
25
|
-
],
|
26
|
-
:debian_ruby18 => [
|
27
|
-
'libjson-ruby',
|
28
|
-
],
|
29
|
-
:solaris_11 => [
|
30
|
-
['git', 'developer/versioning/git'],
|
31
|
-
['ruby', 'runtime/ruby-18'],
|
32
|
-
],
|
33
|
-
:solaris_10 => [
|
34
|
-
'coreutils',
|
35
|
-
'curl', # update curl to fix "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!" issue
|
36
|
-
'git',
|
37
|
-
'ruby19',
|
38
|
-
'ruby19_dev',
|
39
|
-
'gcc4core',
|
40
|
-
],
|
41
|
-
:windows => [
|
42
|
-
'git',
|
43
|
-
# there isn't a need for json on windows because it is bundled in ruby 1.9
|
44
|
-
],
|
45
|
-
:sles => [
|
46
|
-
'git-core',
|
47
|
-
]
|
48
|
-
}
|
49
|
-
|
50
|
-
install_packages_on(hosts, PACKAGES, :check_if_exists => true)
|
51
|
-
|
52
|
-
hosts.each do |host|
|
53
|
-
case host['platform']
|
54
|
-
when /windows/
|
55
|
-
arch = host[:ruby_arch] || 'x86'
|
56
|
-
step "#{host} Selected architecture #{arch}"
|
57
|
-
|
58
|
-
revision = if arch == 'x64'
|
59
|
-
'2.1.x-x64'
|
60
|
-
else
|
61
|
-
'2.1.x-x86'
|
62
|
-
end
|
63
|
-
|
64
|
-
step "#{host} Install ruby from git using revision #{revision}"
|
65
|
-
# TODO remove this step once we are installing puppet from msi packages
|
66
|
-
install_from_git(host, "/opt/puppet-git-repos",
|
67
|
-
:name => 'puppet-win32-ruby',
|
68
|
-
:path => build_giturl('puppet-win32-ruby'),
|
69
|
-
:rev => revision)
|
70
|
-
on host, 'cd /opt/puppet-git-repos/puppet-win32-ruby; cp -r ruby/* /'
|
71
|
-
on host, 'cd /lib; icacls ruby /grant "Everyone:(OI)(CI)(RX)"'
|
72
|
-
on host, 'cd /lib; icacls ruby /reset /T'
|
73
|
-
on host, 'cd /; icacls bin /grant "Everyone:(OI)(CI)(RX)"'
|
74
|
-
on host, 'cd /; icacls bin /reset /T'
|
75
|
-
on host, 'ruby --version'
|
76
|
-
on host, 'cmd /c gem list'
|
77
|
-
when /solaris/
|
78
|
-
on host, 'gem install json'
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
tmp_repos = []
|
83
|
-
install.each do |reponame|
|
84
|
-
tmp_repos << extract_repo_info_from("https://github.com/puppetlabs/#{reponame}")
|
85
|
-
end
|
86
|
-
|
87
|
-
repos = order_packages(tmp_repos)
|
88
|
-
|
89
|
-
hosts.each do |host|
|
90
|
-
repos.each do |repo|
|
91
|
-
install_from_git(host, SourcePath, repo)
|
92
|
-
end
|
93
|
-
unless host['platform'] =~ /windows/
|
94
|
-
on(host, "touch #{File.join(host.puppet['confdir'],'puppet.conf')}")
|
95
|
-
on(host, puppet('resource user puppet ensure=present'))
|
96
|
-
on(host, puppet('resource group puppet ensure=present'))
|
97
|
-
end
|
98
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
# the version is required on windows
|
2
|
-
# all versions are required for osx
|
3
|
-
install_puppet({
|
4
|
-
:version => ENV['BEAKER_PUPPET_VERSION'] || '4.8.0',
|
5
|
-
:puppet_agent_version => ENV['BEAKER_PUPPET_AGENT_VERSION'] || '1.8.0'
|
6
|
-
})
|
7
|
-
|
8
|
-
on(master, puppet('resource user puppet ensure=present'))
|
9
|
-
on(master, puppet('resource group puppet ensure=present'))
|
@@ -1,21 +0,0 @@
|
|
1
|
-
test_name "puppet install smoketest"
|
2
|
-
|
3
|
-
step 'puppet install smoketest: verify \'facter --help\' can be successfully called on all hosts'
|
4
|
-
hosts.each do |host|
|
5
|
-
on host, facter('--help')
|
6
|
-
end
|
7
|
-
|
8
|
-
step 'puppet install smoketest: verify \'hiera --help\' can be successfully called on all hosts'
|
9
|
-
hosts.each do |host|
|
10
|
-
on host, hiera('--help')
|
11
|
-
end
|
12
|
-
|
13
|
-
step 'puppet install smoketest: verify \'puppet help\' can be successfully called on all hosts'
|
14
|
-
hosts.each do |host|
|
15
|
-
on host, puppet('help')
|
16
|
-
end
|
17
|
-
|
18
|
-
step "puppet install smoketest: can get a configprint of the puppet server setting on all hosts"
|
19
|
-
hosts.each do |host|
|
20
|
-
assert(!host.puppet['server'].empty?, "can get a configprint of the puppet server setting")
|
21
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
test_name "validate host stubbing behavior"
|
2
|
-
|
3
|
-
def get_hosts_file(host)
|
4
|
-
if host['platform'] =~ /win/
|
5
|
-
hosts_file = "C:\\\\Windows\\\\System32\\\\Drivers\\\\etc\\\\hosts"
|
6
|
-
else
|
7
|
-
hosts_file = '/etc/hosts'
|
8
|
-
end
|
9
|
-
return hosts_file
|
10
|
-
end
|
11
|
-
|
12
|
-
step 'verify stub_host_on' do
|
13
|
-
step 'should add entry to hosts file' do
|
14
|
-
hosts.each do |host|
|
15
|
-
stub_hosts_on(host, { 'foo' => '1.1.1.1' }, { 'foo' => [ 'bar', 'baz' ] })
|
16
|
-
hosts_file = get_hosts_file(host)
|
17
|
-
result = on host, "cat #{hosts_file}"
|
18
|
-
assert_match %r{foo}, result.stdout
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
step 'stubbed value should be available for other steps in the test' do
|
23
|
-
hosts.each do |host|
|
24
|
-
hosts_file = get_hosts_file(host)
|
25
|
-
result = on host, "cat #{hosts_file}"
|
26
|
-
assert_match %r{foo}, result.stdout
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
step 'verify with_stub_host_on' do
|
32
|
-
step 'should add entry to hosts file' do
|
33
|
-
hosts.each do |host|
|
34
|
-
hosts_file = get_hosts_file(host)
|
35
|
-
result = with_host_stubbed_on(host, { 'sleepy' => '1.1.1.2' }, { 'sleepy' => [ 'grumpy', 'dopey' ] }) { on host, "cat #{hosts_file}" }
|
36
|
-
assert_match %r{sleepy}, result.stdout
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
step 'stubbed value should be reverted after the execution of the block' do
|
41
|
-
hosts.each do |host|
|
42
|
-
hosts_file = get_hosts_file(host)
|
43
|
-
result = on host, "cat #{hosts_file}"
|
44
|
-
assert_no_match %r{sleepy}, result.stdout
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
require 'helpers/test_helper'
|
2
|
-
require 'webrick'
|
3
|
-
require 'webrick/https'
|
4
|
-
|
5
|
-
test_name 'dsl::helpers::web_helpers #link_exists?' do
|
6
|
-
cert_name = [
|
7
|
-
%w[CN localhost],
|
8
|
-
]
|
9
|
-
http_cmd = "ruby -rwebrick -e'WEBrick::HTTPServer.new(:Port => 80, :DocumentRoot => \"/tmp\").start' > /tmp/mylogfile 2>&1 &"
|
10
|
-
https_cmd = "ruby -rwebrick/https -e'WEBrick::HTTPServer.new(:SSLEnable => true, :SSLCertName => #{cert_name}, :Port => 555,:DocumentRoot => \"/tmp\").start' > /tmp/mylogfile 2>&1 &"
|
11
|
-
on(default, http_cmd)
|
12
|
-
on(default, https_cmd)
|
13
|
-
#allow web servers to start up
|
14
|
-
sleep(3)
|
15
|
-
dir = default.tmpdir('test_dir')
|
16
|
-
file = default.tmpfile('test_file')
|
17
|
-
dir.slice! "/tmp"
|
18
|
-
file.slice! "/tmp"
|
19
|
-
dst_dir = 'web_helpers'
|
20
|
-
|
21
|
-
step '#port_open_within? can tell if a port is open' do
|
22
|
-
assert port_open_within?(default,80)
|
23
|
-
end
|
24
|
-
|
25
|
-
step '#link_exists? can tell if a basic link exists' do
|
26
|
-
assert link_exists?("http://#{default}")
|
27
|
-
end
|
28
|
-
|
29
|
-
step '#link_exists? can tell if a basic link does not exist' do
|
30
|
-
assert !link_exists?("http://#{default}/test")
|
31
|
-
end
|
32
|
-
|
33
|
-
step '#link_exists? can use an ssl link' do
|
34
|
-
assert link_exists?("https://#{default}:555")
|
35
|
-
end
|
36
|
-
|
37
|
-
step '#fetch_http_dir can fetch a dir' do
|
38
|
-
assert_equal "#{dst_dir}#{dir}", fetch_http_dir("http://#{default}/#{dir}", dst_dir)
|
39
|
-
end
|
40
|
-
|
41
|
-
step '#fetch_http_dir will raise an error if unable fetch a dir' do
|
42
|
-
exception = assert_raises(RuntimeError) { fetch_http_dir("http://#{default}/tmps", dst_dir) }
|
43
|
-
assert_match /Failed to fetch_remote_dir.*/, exception.message, "#fetch_http_dir raised an unexpected RuntimeError"
|
44
|
-
end
|
45
|
-
|
46
|
-
step '#fetch_http_file can fetch a file' do
|
47
|
-
assert_equal "#{dst_dir}#{file}", fetch_http_file("http://#{default}", file, dst_dir)
|
48
|
-
end
|
49
|
-
|
50
|
-
step '#fetch_http_file will raise an error if unable to fetch a file' do
|
51
|
-
exception = assert_raises(RuntimeError) { fetch_http_file("http://#{default}", "test2.txt", dst_dir) }
|
52
|
-
assert_match /Failed to fetch_remote_file.*/, exception.message, "#fetch_http_dir raised an unexpected RuntimeError"
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
test_name 'skip_test in with_puppet_running_on' do
|
2
|
-
assert_raises SkipTest do
|
3
|
-
with_puppet_running_on(master, {}) do
|
4
|
-
skip_test 'skip rest'
|
5
|
-
assert(false)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
test_name 'pending_test in with_puppet_running_on' do
|
11
|
-
assert_raises PendingTest do
|
12
|
-
with_puppet_running_on(master, {}) do
|
13
|
-
pending_test 'pending appendix prepended'
|
14
|
-
assert(false)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
test_name 'fail_test in with_puppet_running_on' do
|
20
|
-
assert_raises FailTest do
|
21
|
-
with_puppet_running_on(master, {}) do
|
22
|
-
fail_test 'fail_test message'
|
23
|
-
assert(false)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,865 +0,0 @@
|
|
1
|
-
require 'timeout'
|
2
|
-
require 'inifile'
|
3
|
-
require 'resolv'
|
4
|
-
|
5
|
-
module Beaker
|
6
|
-
module DSL
|
7
|
-
module Helpers
|
8
|
-
# Methods that help you interact with your puppet installation, puppet must be installed
|
9
|
-
# for these methods to execute correctly
|
10
|
-
module PuppetHelpers
|
11
|
-
|
12
|
-
# Return the regular expression pattern for an IPv4 address
|
13
|
-
def ipv4_regex
|
14
|
-
return /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/
|
15
|
-
end
|
16
|
-
|
17
|
-
# Return the IP address that given hostname returns when resolved on
|
18
|
-
# the given host.
|
19
|
-
#
|
20
|
-
# @ param [Host] host One object that acts like a Beaker::Host
|
21
|
-
# @ param [String] hostname The hostname to perform a DNS resolution on
|
22
|
-
#
|
23
|
-
# @return [String, nil] An IP address, or nil.
|
24
|
-
def resolve_hostname_on(host, hostname)
|
25
|
-
match = curl_on(host, "--verbose #{hostname}", :accept_all_exit_codes => true).stderr.match(ipv4_regex)
|
26
|
-
return match ? match[0] : nil
|
27
|
-
end
|
28
|
-
|
29
|
-
# @!macro [new] common_opts
|
30
|
-
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
31
|
-
# @option opts [Boolean] :silent (false) Do not produce log output
|
32
|
-
# @option opts [Array<Fixnum>] :acceptable_exit_codes ([0]) An array
|
33
|
-
# (or range) of integer exit codes that should be considered
|
34
|
-
# acceptable. An error will be thrown if the exit code does not
|
35
|
-
# match one of the values in this list.
|
36
|
-
# @option opts [Boolean] :accept_all_exit_codes (false) Consider all
|
37
|
-
# exit codes as passing.
|
38
|
-
# @option opts [Boolean] :dry_run (false) Do not actually execute any
|
39
|
-
# commands on the SUT
|
40
|
-
# @option opts [String] :stdin (nil) Input to be provided during command
|
41
|
-
# execution on the SUT.
|
42
|
-
# @option opts [Boolean] :pty (false) Execute this command in a pseudoterminal.
|
43
|
-
# @option opts [Boolean] :expect_connection_failure (false) Expect this command
|
44
|
-
# to result in a connection failure, reconnect and continue execution.
|
45
|
-
# @option opts [Hash{String=>String}] :environment ({}) These will be
|
46
|
-
# treated as extra environment variables that should be set before
|
47
|
-
# running the command.
|
48
|
-
#
|
49
|
-
|
50
|
-
# Return the name of the puppet user.
|
51
|
-
#
|
52
|
-
# @param [Host] host One object that acts like a Beaker::Host
|
53
|
-
#
|
54
|
-
# @note This method assumes puppet is installed on the host.
|
55
|
-
#
|
56
|
-
def puppet_user(host)
|
57
|
-
return host.puppet('master')['user']
|
58
|
-
end
|
59
|
-
|
60
|
-
# Return the name of the puppet group.
|
61
|
-
#
|
62
|
-
# @param [Host] host One object that acts like a Beaker::Host
|
63
|
-
#
|
64
|
-
# @note This method assumes puppet is installed on the host.
|
65
|
-
#
|
66
|
-
def puppet_group(host)
|
67
|
-
return host.puppet('master')['group']
|
68
|
-
end
|
69
|
-
|
70
|
-
# Test Puppet running in a certain run mode with specific options.
|
71
|
-
# This ensures the following steps are performed:
|
72
|
-
# 1. The pre-test Puppet configuration is backed up
|
73
|
-
# 2. A new Puppet configuraton file is layed down
|
74
|
-
# 3. Puppet is started or restarted in the specified run mode
|
75
|
-
# 4. Ensure Puppet has started correctly
|
76
|
-
# 5. Further tests are yielded to
|
77
|
-
# 6. Revert Puppet to the pre-test state
|
78
|
-
# 7. Testing artifacts are saved in a folder named for the test
|
79
|
-
#
|
80
|
-
# @note Whether Puppet is started or restarted depends on what kind of
|
81
|
-
# server you're running. Passenger and puppetserver are restarted before.
|
82
|
-
# Webrick is started before and stopped after yielding, unless you're using
|
83
|
-
# service scripts, then it'll behave like passenger & puppetserver.
|
84
|
-
# Passenger and puppetserver (or webrick using service scripts)
|
85
|
-
# restart after yielding by default. You can stop this from happening
|
86
|
-
# by setting the :restart_when_done flag of the conf_opts argument.
|
87
|
-
#
|
88
|
-
# @param [Host] host One object that act like Host
|
89
|
-
#
|
90
|
-
# @param [Hash{Symbol=>String}] conf_opts Represents puppet settings.
|
91
|
-
# Sections of the puppet.conf may be
|
92
|
-
# specified, if no section is specified the
|
93
|
-
# a puppet.conf file will be written with the
|
94
|
-
# options put in a section named after [mode]
|
95
|
-
# @option conf_opts [String] :__commandline_args__ A special setting for
|
96
|
-
# command_line arguments such as --debug or
|
97
|
-
# --logdest, which cannot be set in
|
98
|
-
# puppet.conf. For example:
|
99
|
-
#
|
100
|
-
# :__commandline_args__ => '--logdest /tmp/a.log'
|
101
|
-
#
|
102
|
-
# These will only be applied when starting a FOSS
|
103
|
-
# master, as a pe master is just bounced.
|
104
|
-
# @option conf_opts [Hash] :__service_args__ A special setting of options
|
105
|
-
# for controlling how the puppet master service is
|
106
|
-
# handled. The only setting currently is
|
107
|
-
# :bypass_service_script, which if set true will
|
108
|
-
# force stopping and starting a webrick master
|
109
|
-
# using the start_puppet_from_source_* methods,
|
110
|
-
# even if it seems the host has passenger.
|
111
|
-
# This is needed in FOSS tests to initialize
|
112
|
-
# SSL.
|
113
|
-
# @option conf_opts [Boolean] :restart_when_done determines whether a restart
|
114
|
-
# should be run after the test has been yielded to.
|
115
|
-
# Will stop puppet if false. Default behavior
|
116
|
-
# is to restart, but you can override this on the
|
117
|
-
# host or with this option.
|
118
|
-
# (Note: only works for passenger & puppetserver
|
119
|
-
# masters (or webrick using the service scripts))
|
120
|
-
# @param [File] testdir The temporary directory which will hold backup
|
121
|
-
# configuration, and other test artifacts.
|
122
|
-
#
|
123
|
-
# @param [Block] block The point of this method, yields so
|
124
|
-
# tests may be ran. After the block is finished
|
125
|
-
# puppet will revert to a previous state.
|
126
|
-
#
|
127
|
-
# @example A simple use case to ensure a master is running
|
128
|
-
# with_puppet_running_on( master ) do
|
129
|
-
# ...tests that require a master...
|
130
|
-
# end
|
131
|
-
#
|
132
|
-
# @example Fully utilizing the possiblities of config options
|
133
|
-
# with_puppet_running_on( master,
|
134
|
-
# :main => {:logdest => '/var/blah'},
|
135
|
-
# :master => {:masterlog => '/elswhere'},
|
136
|
-
# :agent => {:server => 'localhost'} ) do
|
137
|
-
#
|
138
|
-
# ...tests to be ran...
|
139
|
-
# end
|
140
|
-
#
|
141
|
-
def with_puppet_running_on host, conf_opts, testdir = host.tmpdir(File.basename(@path)), &block
|
142
|
-
raise(ArgumentError, "with_puppet_running_on's conf_opts must be a Hash. You provided a #{conf_opts.class}: '#{conf_opts}'") if !conf_opts.kind_of?(Hash)
|
143
|
-
cmdline_args = conf_opts[:__commandline_args__]
|
144
|
-
service_args = conf_opts[:__service_args__] || {}
|
145
|
-
restart_when_done = true
|
146
|
-
restart_when_done = host[:restart_when_done] if host.has_key?(:restart_when_done)
|
147
|
-
restart_when_done = conf_opts.fetch(:restart_when_done, restart_when_done)
|
148
|
-
conf_opts = conf_opts.reject { |k,v| [:__commandline_args__, :__service_args__, :restart_when_done].include?(k) }
|
149
|
-
|
150
|
-
curl_retries = host['master-start-curl-retries'] || options['master-start-curl-retries']
|
151
|
-
logger.debug "Setting curl retries to #{curl_retries}"
|
152
|
-
|
153
|
-
if options[:is_puppetserver] || host[:is_puppetserver]
|
154
|
-
confdir = host.puppet('master')['confdir']
|
155
|
-
vardir = host.puppet('master')['vardir']
|
156
|
-
|
157
|
-
if cmdline_args
|
158
|
-
split_args = cmdline_args.split()
|
159
|
-
|
160
|
-
split_args.each do |arg|
|
161
|
-
case arg
|
162
|
-
when /--confdir=(.*)/
|
163
|
-
confdir = $1
|
164
|
-
when /--vardir=(.*)/
|
165
|
-
vardir = $1
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
puppetserver_opts = { "jruby-puppet" => {
|
171
|
-
"master-conf-dir" => confdir,
|
172
|
-
"master-var-dir" => vardir,
|
173
|
-
}}
|
174
|
-
|
175
|
-
puppetserver_conf = File.join("#{host['puppetserver-confdir']}", "puppetserver.conf")
|
176
|
-
modify_tk_config(host, puppetserver_conf, puppetserver_opts)
|
177
|
-
end
|
178
|
-
begin
|
179
|
-
backup_file = backup_the_file(host, host.puppet('master')['confdir'], testdir, 'puppet.conf')
|
180
|
-
lay_down_new_puppet_conf host, conf_opts, testdir
|
181
|
-
|
182
|
-
if host.use_service_scripts? && !service_args[:bypass_service_script]
|
183
|
-
bounce_service( host, host['puppetservice'], curl_retries )
|
184
|
-
else
|
185
|
-
puppet_master_started = start_puppet_from_source_on!( host, cmdline_args )
|
186
|
-
end
|
187
|
-
|
188
|
-
yield self if block_given?
|
189
|
-
|
190
|
-
# FIXME: these test-flow-control exceptions should be using throw
|
191
|
-
# they can be caught in test_case. current layout dows not allow it
|
192
|
-
rescue Beaker::DSL::Outcomes::PassTest => early_assertion
|
193
|
-
pass_test(early_assertion)
|
194
|
-
rescue Beaker::DSL::Outcomes::FailTest => early_assertion
|
195
|
-
fail_test(early_assertion)
|
196
|
-
rescue Beaker::DSL::Outcomes::PendingTest => early_assertion
|
197
|
-
pending_test(early_assertion)
|
198
|
-
rescue Beaker::DSL::Outcomes::SkipTest => early_assertion
|
199
|
-
skip_test(early_assertion)
|
200
|
-
rescue Beaker::DSL::Assertions, Minitest::Assertion => early_assertion
|
201
|
-
fail_test(early_assertion)
|
202
|
-
rescue Exception => early_exception
|
203
|
-
original_exception = RuntimeError.new("PuppetAcceptance::DSL::Helpers.with_puppet_running_on failed (check backtrace for location) because: #{early_exception}\n#{early_exception.backtrace.join("\n")}\n")
|
204
|
-
raise(original_exception)
|
205
|
-
|
206
|
-
ensure
|
207
|
-
begin
|
208
|
-
|
209
|
-
if host.use_service_scripts? && !service_args[:bypass_service_script]
|
210
|
-
restore_puppet_conf_from_backup( host, backup_file )
|
211
|
-
if restart_when_done
|
212
|
-
bounce_service( host, host['puppetservice'], curl_retries )
|
213
|
-
else
|
214
|
-
host.exec puppet_resource('service', host['puppetservice'], 'ensure=stopped')
|
215
|
-
end
|
216
|
-
else
|
217
|
-
if puppet_master_started
|
218
|
-
stop_puppet_from_source_on( host )
|
219
|
-
else
|
220
|
-
dump_puppet_log(host)
|
221
|
-
end
|
222
|
-
restore_puppet_conf_from_backup( host, backup_file )
|
223
|
-
end
|
224
|
-
|
225
|
-
rescue Exception => teardown_exception
|
226
|
-
begin
|
227
|
-
if !host.is_pe?
|
228
|
-
dump_puppet_log(host)
|
229
|
-
end
|
230
|
-
rescue Exception => dumping_exception
|
231
|
-
logger.error("Raised during attempt to dump puppet logs: #{dumping_exception}")
|
232
|
-
end
|
233
|
-
|
234
|
-
if original_exception
|
235
|
-
logger.error("Raised during attempt to teardown with_puppet_running_on: #{teardown_exception}\n---\n")
|
236
|
-
raise original_exception
|
237
|
-
else
|
238
|
-
raise teardown_exception
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
# Test Puppet running in a certain run mode with specific options,
|
245
|
-
# on the default host
|
246
|
-
# @see #with_puppet_running_on
|
247
|
-
def with_puppet_running conf_opts, testdir = host.tmpdir(File.basename(@path)), &block
|
248
|
-
with_puppet_running_on(default, conf_opts, testdir, &block)
|
249
|
-
end
|
250
|
-
|
251
|
-
# @!visibility private
|
252
|
-
def restore_puppet_conf_from_backup( host, backup_file )
|
253
|
-
puppet_conf = host.puppet('master')['config']
|
254
|
-
|
255
|
-
if backup_file
|
256
|
-
host.exec( Command.new( "if [ -f '#{backup_file}' ]; then " +
|
257
|
-
"cat '#{backup_file}' > " +
|
258
|
-
"'#{puppet_conf}'; " +
|
259
|
-
"rm -f '#{backup_file}'; " +
|
260
|
-
"fi" ) )
|
261
|
-
else
|
262
|
-
host.exec( Command.new( "rm -f '#{puppet_conf}'" ))
|
263
|
-
end
|
264
|
-
|
265
|
-
end
|
266
|
-
|
267
|
-
# @!visibility private
|
268
|
-
def start_puppet_from_source_on! host, args = ''
|
269
|
-
host.exec( puppet( 'master', args ) )
|
270
|
-
|
271
|
-
logger.debug 'Waiting for the puppet master to start'
|
272
|
-
unless port_open_within?( host, 8140, 10 )
|
273
|
-
raise Beaker::DSL::FailTest, 'Puppet master did not start in a timely fashion'
|
274
|
-
end
|
275
|
-
logger.debug 'The puppet master has started'
|
276
|
-
return true
|
277
|
-
end
|
278
|
-
|
279
|
-
# @!visibility private
|
280
|
-
def stop_puppet_from_source_on( host )
|
281
|
-
pid = host.exec( Command.new('cat `puppet master --configprint pidfile`') ).stdout.chomp
|
282
|
-
host.exec( Command.new( "kill #{pid}" ) )
|
283
|
-
Timeout.timeout(10) do
|
284
|
-
while host.exec( Command.new( "kill -0 #{pid}"), :acceptable_exit_codes => [0,1] ).exit_code == 0 do
|
285
|
-
# until kill -0 finds no process and we know that puppet has finished cleaning up
|
286
|
-
sleep 1
|
287
|
-
end
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
# @!visibility private
|
292
|
-
def dump_puppet_log(host)
|
293
|
-
syslogfile = case host['platform']
|
294
|
-
when /fedora|centos|el|redhat|scientific/ then '/var/log/messages'
|
295
|
-
when /ubuntu|debian|cumulus/ then '/var/log/syslog'
|
296
|
-
else return
|
297
|
-
end
|
298
|
-
|
299
|
-
logger.notify "\n*************************"
|
300
|
-
logger.notify "* Dumping master log *"
|
301
|
-
logger.notify "*************************"
|
302
|
-
host.exec( Command.new( "tail -n 100 #{syslogfile}" ), :acceptable_exit_codes => [0,1])
|
303
|
-
logger.notify "*************************\n"
|
304
|
-
end
|
305
|
-
|
306
|
-
# @!visibility private
|
307
|
-
def lay_down_new_puppet_conf( host, configuration_options, testdir )
|
308
|
-
puppetconf_main = host.puppet('master')['config']
|
309
|
-
puppetconf_filename = File.basename(puppetconf_main)
|
310
|
-
puppetconf_test = File.join(testdir, puppetconf_filename)
|
311
|
-
|
312
|
-
new_conf = puppet_conf_for( host, configuration_options )
|
313
|
-
create_remote_file host, puppetconf_test, new_conf.to_s
|
314
|
-
|
315
|
-
host.exec(
|
316
|
-
Command.new( "cat #{puppetconf_test} > #{puppetconf_main}" ),
|
317
|
-
:silent => true
|
318
|
-
)
|
319
|
-
host.exec( Command.new( "cat #{puppetconf_main}" ) )
|
320
|
-
end
|
321
|
-
|
322
|
-
# @!visibility private
|
323
|
-
def puppet_conf_for host, conf_opts
|
324
|
-
puppetconf = host.exec( Command.new( "cat #{host.puppet('master')['config']}" ) ).stdout
|
325
|
-
new_conf = IniFile.new(content: puppetconf).merge( conf_opts )
|
326
|
-
|
327
|
-
new_conf
|
328
|
-
end
|
329
|
-
|
330
|
-
# Restarts the named puppet service
|
331
|
-
#
|
332
|
-
# @param [Host] host Host the service runs on
|
333
|
-
# @param [String] service Name of the service to restart
|
334
|
-
# @param [Fixnum] curl_retries Number of seconds to wait for the restart to complete before failing
|
335
|
-
# @param [Fixnum] port Port to check status at
|
336
|
-
#
|
337
|
-
# @return [Result] Result of last status check
|
338
|
-
# @!visibility private
|
339
|
-
def bounce_service host, service, curl_retries = nil, port = nil
|
340
|
-
curl_retries = 120 if curl_retries.nil?
|
341
|
-
port = options[:puppetserver_port] if port.nil?
|
342
|
-
if host.graceful_restarts?
|
343
|
-
service = host.check_for_command('apache2ctl') ? 'apache2ctl' : 'apachectl'
|
344
|
-
apachectl_path = host.is_pe? ? "#{host['puppetsbindir']}/#{service}" : service
|
345
|
-
host.exec(Command.new("#{apachectl_path} graceful"))
|
346
|
-
else
|
347
|
-
result = host.exec(Command.new("service #{service} reload"),
|
348
|
-
:acceptable_exit_codes => [0,1,3])
|
349
|
-
if result.exit_code == 0
|
350
|
-
return result
|
351
|
-
else
|
352
|
-
host.exec puppet_resource('service', service, 'ensure=stopped')
|
353
|
-
host.exec puppet_resource('service', service, 'ensure=running')
|
354
|
-
end
|
355
|
-
end
|
356
|
-
curl_with_retries(" #{service} ", host, "https://localhost:#{port}", [35, 60], curl_retries)
|
357
|
-
end
|
358
|
-
|
359
|
-
# Runs 'puppet apply' on a remote host, piping manifest through stdin
|
360
|
-
#
|
361
|
-
# @param [Host] host The host that this command should be run on
|
362
|
-
#
|
363
|
-
# @param [String] manifest The puppet manifest to apply
|
364
|
-
#
|
365
|
-
# @!macro common_opts
|
366
|
-
# @option opts [Boolean] :parseonly (false) If this key is true, the
|
367
|
-
# "--parseonly" command line parameter will
|
368
|
-
# be passed to the 'puppet apply' command.
|
369
|
-
#
|
370
|
-
# @option opts [Boolean] :trace (false) If this key exists in the Hash,
|
371
|
-
# the "--trace" command line parameter will be
|
372
|
-
# passed to the 'puppet apply' command.
|
373
|
-
#
|
374
|
-
# @option opts [Array<Integer>] :acceptable_exit_codes ([0]) The list of exit
|
375
|
-
# codes that will NOT raise an error when found upon
|
376
|
-
# command completion. If provided, these values will
|
377
|
-
# be combined with those used in :catch_failures and
|
378
|
-
# :expect_failures to create the full list of
|
379
|
-
# passing exit codes.
|
380
|
-
#
|
381
|
-
# @option opts [Hash] :environment Additional environment variables to be
|
382
|
-
# passed to the 'puppet apply' command
|
383
|
-
#
|
384
|
-
# @option opts [Boolean] :catch_failures (false) By default `puppet
|
385
|
-
# --apply` will exit with 0, which does not count
|
386
|
-
# as a test failure, even if there were errors or
|
387
|
-
# changes when applying the manifest. This option
|
388
|
-
# enables detailed exit codes and causes a test
|
389
|
-
# failure if `puppet --apply` indicates there was
|
390
|
-
# a failure during its execution.
|
391
|
-
#
|
392
|
-
# @option opts [Boolean] :catch_changes (false) This option enables
|
393
|
-
# detailed exit codes and causes a test failure
|
394
|
-
# if `puppet --apply` indicates that there were
|
395
|
-
# changes or failures during its execution.
|
396
|
-
#
|
397
|
-
# @option opts [Boolean] :expect_changes (false) This option enables
|
398
|
-
# detailed exit codes and causes a test failure
|
399
|
-
# if `puppet --apply` indicates that there were
|
400
|
-
# no resource changes during its execution.
|
401
|
-
#
|
402
|
-
# @option opts [Boolean] :expect_failures (false) This option enables
|
403
|
-
# detailed exit codes and causes a test failure
|
404
|
-
# if `puppet --apply` indicates there were no
|
405
|
-
# failure during its execution.
|
406
|
-
#
|
407
|
-
# @option opts [Boolean] :future_parser (false) This option enables
|
408
|
-
# the future parser option that is available
|
409
|
-
# from Puppet verion 3.2
|
410
|
-
# By default it will use the 'current' parser.
|
411
|
-
#
|
412
|
-
# @option opts [Boolean] :noop (false) If this option exists, the
|
413
|
-
# the "--noop" command line parameter will be
|
414
|
-
# passed to the 'puppet apply' command.
|
415
|
-
#
|
416
|
-
# @option opts [String] :modulepath The search path for modules, as
|
417
|
-
# a list of directories separated by the system
|
418
|
-
# path separator character. (The POSIX path separator
|
419
|
-
# is ‘:’, and the Windows path separator is ‘;’.)
|
420
|
-
#
|
421
|
-
# @option opts [String] :debug (false) If this option exists,
|
422
|
-
# the "--debug" command line parameter
|
423
|
-
# will be passed to the 'puppet apply' command.
|
424
|
-
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
425
|
-
#
|
426
|
-
# @param [Block] block This method will yield to a block of code passed
|
427
|
-
# by the caller; this can be used for additional
|
428
|
-
# validation, etc.
|
429
|
-
#
|
430
|
-
# @return [Array<Result>, Result, nil] An array of results, a result object,
|
431
|
-
# or nil. Check {#run_block_on} for more details on this.
|
432
|
-
def apply_manifest_on(host, manifest, opts = {}, &block)
|
433
|
-
block_on host, opts do | host |
|
434
|
-
on_options = {}
|
435
|
-
on_options[:acceptable_exit_codes] = Array(opts[:acceptable_exit_codes])
|
436
|
-
|
437
|
-
puppet_apply_opts = {}
|
438
|
-
if opts[:debug]
|
439
|
-
puppet_apply_opts[:debug] = nil
|
440
|
-
else
|
441
|
-
puppet_apply_opts[:verbose] = nil
|
442
|
-
end
|
443
|
-
puppet_apply_opts[:parseonly] = nil if opts[:parseonly]
|
444
|
-
puppet_apply_opts[:trace] = nil if opts[:trace]
|
445
|
-
puppet_apply_opts[:parser] = 'future' if opts[:future_parser]
|
446
|
-
puppet_apply_opts[:modulepath] = opts[:modulepath] if opts[:modulepath]
|
447
|
-
puppet_apply_opts[:noop] = nil if opts[:noop]
|
448
|
-
|
449
|
-
# From puppet help:
|
450
|
-
# "... an exit code of '2' means there were changes, an exit code of
|
451
|
-
# '4' means there were failures during the transaction, and an exit
|
452
|
-
# code of '6' means there were both changes and failures."
|
453
|
-
if [opts[:catch_changes],opts[:catch_failures],opts[:expect_failures],opts[:expect_changes]].compact.length > 1
|
454
|
-
raise(ArgumentError,
|
455
|
-
'Cannot specify more than one of `catch_failures`, ' +
|
456
|
-
'`catch_changes`, `expect_failures`, or `expect_changes` ' +
|
457
|
-
'for a single manifest')
|
458
|
-
end
|
459
|
-
|
460
|
-
if opts[:catch_changes]
|
461
|
-
puppet_apply_opts['detailed-exitcodes'] = nil
|
462
|
-
|
463
|
-
# We're after idempotency so allow exit code 0 only.
|
464
|
-
on_options[:acceptable_exit_codes] |= [0]
|
465
|
-
elsif opts[:catch_failures]
|
466
|
-
puppet_apply_opts['detailed-exitcodes'] = nil
|
467
|
-
|
468
|
-
# We're after only complete success so allow exit codes 0 and 2 only.
|
469
|
-
on_options[:acceptable_exit_codes] |= [0, 2]
|
470
|
-
elsif opts[:expect_failures]
|
471
|
-
puppet_apply_opts['detailed-exitcodes'] = nil
|
472
|
-
|
473
|
-
# We're after failures specifically so allow exit codes 1, 4, and 6 only.
|
474
|
-
on_options[:acceptable_exit_codes] |= [1, 4, 6]
|
475
|
-
elsif opts[:expect_changes]
|
476
|
-
puppet_apply_opts['detailed-exitcodes'] = nil
|
477
|
-
|
478
|
-
# We're after changes specifically so allow exit code 2 only.
|
479
|
-
on_options[:acceptable_exit_codes] |= [2]
|
480
|
-
else
|
481
|
-
# Either use the provided acceptable_exit_codes or default to [0]
|
482
|
-
on_options[:acceptable_exit_codes] |= [0]
|
483
|
-
end
|
484
|
-
|
485
|
-
# Not really thrilled with this implementation, might want to improve it
|
486
|
-
# later. Basically, there is a magic trick in the constructor of
|
487
|
-
# PuppetCommand which allows you to pass in a Hash for the last value in
|
488
|
-
# the *args Array; if you do so, it will be treated specially. So, here
|
489
|
-
# we check to see if our caller passed us a hash of environment variables
|
490
|
-
# that they want to set for the puppet command. If so, we set the final
|
491
|
-
# value of *args to a new hash with just one entry (the value of which
|
492
|
-
# is our environment variables hash)
|
493
|
-
if opts.has_key?(:environment)
|
494
|
-
puppet_apply_opts['ENV'] = opts[:environment]
|
495
|
-
end
|
496
|
-
|
497
|
-
file_path = host.tmpfile('apply_manifest.pp')
|
498
|
-
create_remote_file(host, file_path, manifest + "\n")
|
499
|
-
|
500
|
-
if host[:default_apply_opts].respond_to? :merge
|
501
|
-
puppet_apply_opts = host[:default_apply_opts].merge( puppet_apply_opts )
|
502
|
-
end
|
503
|
-
|
504
|
-
on host, puppet('apply', file_path, puppet_apply_opts), on_options, &block
|
505
|
-
end
|
506
|
-
end
|
507
|
-
|
508
|
-
# Runs 'puppet apply' on default host, piping manifest through stdin
|
509
|
-
# @see #apply_manifest_on
|
510
|
-
def apply_manifest(manifest, opts = {}, &block)
|
511
|
-
apply_manifest_on(default, manifest, opts, &block)
|
512
|
-
end
|
513
|
-
|
514
|
-
# @deprecated
|
515
|
-
def run_agent_on(host, arg='--no-daemonize --verbose --onetime --test',
|
516
|
-
options={}, &block)
|
517
|
-
block_on host do | host |
|
518
|
-
on host, puppet_agent(arg), options, &block
|
519
|
-
end
|
520
|
-
end
|
521
|
-
|
522
|
-
# This method using the puppet resource 'host' will setup host aliases
|
523
|
-
# and register the remove of host aliases via Beaker::TestCase#teardown
|
524
|
-
#
|
525
|
-
# A teardown step is also added to make sure unstubbing of the host is
|
526
|
-
# removed always.
|
527
|
-
#
|
528
|
-
# @param [Host, Array<Host>, String, Symbol] machine One or more hosts to act upon,
|
529
|
-
# or a role (String or Symbol) that identifies one or more hosts.
|
530
|
-
# @param ip_spec [Hash{String=>String}] a hash containing the host to ip
|
531
|
-
# mappings
|
532
|
-
# @param alias_spec [Hash{String=>Array[String]] an hash containing the host to alias(es) mappings to apply
|
533
|
-
# @example Stub puppetlabs.com on the master to 127.0.0.1 with an alias example.com
|
534
|
-
# stub_hosts_on(master, {'puppetlabs.com' => '127.0.0.1'}, {'puppetlabs.com' => ['example.com']})
|
535
|
-
def stub_hosts_on(machine, ip_spec, alias_spec={})
|
536
|
-
block_on machine do | host |
|
537
|
-
ip_spec.each do |address, ip|
|
538
|
-
aliases = alias_spec[address] || []
|
539
|
-
manifest =<<-EOS.gsub /^\s+/, ""
|
540
|
-
host { '#{address}':
|
541
|
-
\tensure => present,
|
542
|
-
\tip => '#{ip}',
|
543
|
-
\thost_aliases => #{aliases},
|
544
|
-
}
|
545
|
-
EOS
|
546
|
-
logger.notify("Stubbing address #{address} to IP #{ip} on machine #{host}")
|
547
|
-
apply_manifest_on( host, manifest )
|
548
|
-
end
|
549
|
-
|
550
|
-
teardown do
|
551
|
-
ip_spec.each do |address, ip|
|
552
|
-
logger.notify("Unstubbing address #{address} to IP #{ip} on machine #{host}")
|
553
|
-
on( host, puppet('resource', 'host', address, 'ensure=absent') )
|
554
|
-
end
|
555
|
-
end
|
556
|
-
end
|
557
|
-
end
|
558
|
-
|
559
|
-
# This method accepts a block and using the puppet resource 'host' will
|
560
|
-
# setup host aliases before and after that block.
|
561
|
-
#
|
562
|
-
# @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon,
|
563
|
-
# or a role (String or Symbol) that identifies one or more hosts.
|
564
|
-
# @param ip_spec [Hash{String=>String}] a hash containing the host to ip
|
565
|
-
# mappings
|
566
|
-
# @param alias_spec [Hash{String=>Array[String]] an hash containing the host to alias(es) mappings to apply
|
567
|
-
# @example Stub forgeapi.puppetlabs.com on the master to 127.0.0.1 with an alias forgeapi.example.com
|
568
|
-
# with_host_stubbed_on(master, {'forgeapi.puppetlabs.com' => '127.0.0.1'}, {'forgeapi.puppetlabs.com' => ['forgeapi.example.com']}) do
|
569
|
-
# puppet( "module install puppetlabs-stdlib" )
|
570
|
-
# end
|
571
|
-
def with_host_stubbed_on(host, ip_spec, alias_spec={}, &block)
|
572
|
-
begin
|
573
|
-
block_on host do |host|
|
574
|
-
# this code is duplicated from the `stub_hosts_on` method. The
|
575
|
-
# `stub_hosts_on` method itself is not used here because this
|
576
|
-
# method is used by modules tests using `beaker-rspec`. Since
|
577
|
-
# the `stub_hosts_on` method contains a `teardown` step, it is
|
578
|
-
# incompatible with `beaker_rspec`.
|
579
|
-
ip_spec.each do |address, ip|
|
580
|
-
aliases = alias_spec[address] || []
|
581
|
-
manifest =<<-EOS.gsub /^\s+/, ""
|
582
|
-
host { '#{address}':
|
583
|
-
\tensure => present,
|
584
|
-
\tip => '#{ip}',
|
585
|
-
\thost_aliases => #{aliases},
|
586
|
-
}
|
587
|
-
EOS
|
588
|
-
logger.notify("Stubbing address #{address} to IP #{ip} on machine #{host}")
|
589
|
-
apply_manifest_on( host, manifest )
|
590
|
-
end
|
591
|
-
end
|
592
|
-
|
593
|
-
block.call
|
594
|
-
|
595
|
-
ensure
|
596
|
-
ip_spec.each do |address, ip|
|
597
|
-
logger.notify("Unstubbing address #{address} to IP #{ip} on machine #{host}")
|
598
|
-
on( host, puppet('resource', 'host', address, 'ensure=absent') )
|
599
|
-
end
|
600
|
-
end
|
601
|
-
end
|
602
|
-
|
603
|
-
# This method accepts a block and using the puppet resource 'host' will
|
604
|
-
# setup host aliases before and after that block on the default host
|
605
|
-
#
|
606
|
-
# @example Stub puppetlabs.com on the default host to 127.0.0.1
|
607
|
-
# stub_hosts('puppetlabs.com' => '127.0.0.1')
|
608
|
-
# @see #stub_hosts_on
|
609
|
-
def stub_hosts(ip_spec)
|
610
|
-
stub_hosts_on(default, ip_spec)
|
611
|
-
end
|
612
|
-
|
613
|
-
# This wraps the method `stub_hosts_on` and makes the stub specific to
|
614
|
-
# the forge alias.
|
615
|
-
#
|
616
|
-
# forge api v1 canonical source is forge.puppetlabs.com
|
617
|
-
# forge api v3 canonical source is forgeapi.puppetlabs.com
|
618
|
-
#
|
619
|
-
# @param machine [String] the host to perform the stub on
|
620
|
-
# @param forge_host [String] The URL to use as the forge alias, will default to using :forge_host in the
|
621
|
-
# global options hash
|
622
|
-
def stub_forge_on(machine, forge_host = nil)
|
623
|
-
#use global options hash
|
624
|
-
primary_forge_name = 'forge.puppetlabs.com'
|
625
|
-
forge_host ||= options[:forge_host]
|
626
|
-
forge_ip = resolve_hostname_on(machine, forge_host)
|
627
|
-
raise "Failed to resolve forge host '#{forge_host}'" unless forge_ip
|
628
|
-
@forge_ip ||= forge_ip
|
629
|
-
block_on machine do | host |
|
630
|
-
stub_hosts_on(host, {primary_forge_name => @forge_ip}, {primary_forge_name => ['forge.puppet.com','forgeapi.puppetlabs.com','forgeapi.puppet.com']})
|
631
|
-
end
|
632
|
-
end
|
633
|
-
|
634
|
-
# This wraps the method `with_host_stubbed_on` and makes the stub specific to
|
635
|
-
# the forge alias.
|
636
|
-
#
|
637
|
-
# forge api v1 canonical source is forge.puppetlabs.com
|
638
|
-
# forge api v3 canonical source is forgeapi.puppetlabs.com
|
639
|
-
#
|
640
|
-
# @param host [String] the host to perform the stub on
|
641
|
-
# @param forge_host [String] The URL to use as the forge alias, will default to using :forge_host in the
|
642
|
-
# global options hash
|
643
|
-
def with_forge_stubbed_on( host, forge_host = nil, &block )
|
644
|
-
#use global options hash
|
645
|
-
primary_forge_name = 'forge.puppetlabs.com'
|
646
|
-
forge_host ||= options[:forge_host]
|
647
|
-
forge_ip = resolve_hostname_on(host, forge_host)
|
648
|
-
raise "Failed to resolve forge host '#{forge_host}'" unless forge_ip
|
649
|
-
@forge_ip ||= forge_ip
|
650
|
-
with_host_stubbed_on( host, {primary_forge_name => @forge_ip}, {primary_forge_name => ['forge.puppet.com','forgeapi.puppetlabs.com','forgeapi.puppet.com']}, &block )
|
651
|
-
end
|
652
|
-
|
653
|
-
# This wraps `with_forge_stubbed_on` and provides it the default host
|
654
|
-
# @see with_forge_stubbed_on
|
655
|
-
def with_forge_stubbed( forge_host = nil, &block )
|
656
|
-
with_forge_stubbed_on( default, forge_host, &block )
|
657
|
-
end
|
658
|
-
|
659
|
-
# This wraps the method `stub_hosts` and makes the stub specific to
|
660
|
-
# the forge alias.
|
661
|
-
#
|
662
|
-
# @see #stub_forge_on
|
663
|
-
def stub_forge(forge_host = nil)
|
664
|
-
#use global options hash
|
665
|
-
forge_host ||= options[:forge_host]
|
666
|
-
stub_forge_on(default, forge_host)
|
667
|
-
end
|
668
|
-
|
669
|
-
# Waits until a successful curl check has happened against puppetdb
|
670
|
-
#
|
671
|
-
# @param [Host] host Host puppetdb is on
|
672
|
-
# @param [Fixnum] nonssl_port Port to make the HTTP status check over
|
673
|
-
# @param [Fixnum] ssl_port Port to make the HTTPS status check over
|
674
|
-
#
|
675
|
-
# @return [Result] Result of the last HTTPS status check
|
676
|
-
def sleep_until_puppetdb_started(host, nonssl_port = nil, ssl_port = nil)
|
677
|
-
nonssl_port = options[:puppetdb_port_nonssl] if nonssl_port.nil?
|
678
|
-
ssl_port = options[:puppetdb_port_ssl] if ssl_port.nil?
|
679
|
-
pe_ver = host['pe_ver'] || '0'
|
680
|
-
if version_is_less(pe_ver, '2016.1.0') then
|
681
|
-
# the status endpoint was introduced in puppetdb 4.0. The earliest
|
682
|
-
# PE release with the 4.x pdb version was 2016.1.0
|
683
|
-
endpoint = 'pdb/meta/v1/version'
|
684
|
-
expected_regex = '\"version\" \{0,\}: \{0,\}\"[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\"'
|
685
|
-
else
|
686
|
-
endpoint = 'status/v1/services/puppetdb-status'
|
687
|
-
expected_regex = '\"state\" \{0,\}: \{0,\}\"running\"'
|
688
|
-
end
|
689
|
-
retry_on(host,
|
690
|
-
"curl -m 1 http://localhost:#{nonssl_port}/#{endpoint} | grep '#{expected_regex}'",
|
691
|
-
{:max_retries => 120})
|
692
|
-
curl_with_retries("start puppetdb (ssl)",
|
693
|
-
host, "https://#{host.node_name}:#{ssl_port}", [35, 60])
|
694
|
-
end
|
695
|
-
|
696
|
-
# Waits until a successful curl check has happened against puppetserver
|
697
|
-
#
|
698
|
-
# @param [Host] host Host puppetserver is on
|
699
|
-
# @param [Fixnum] port Port to make the HTTPS status check over
|
700
|
-
#
|
701
|
-
# @return [Result] Result of the last HTTPS status check
|
702
|
-
def sleep_until_puppetserver_started(host, port = nil)
|
703
|
-
port = options[:puppetserver_port] if port.nil?
|
704
|
-
curl_with_retries("start puppetserver (ssl)",
|
705
|
-
host, "https://#{host.node_name}:#{port}", [35, 60])
|
706
|
-
end
|
707
|
-
|
708
|
-
# Waits until a successful curl check has happaned against node classifier
|
709
|
-
#
|
710
|
-
# @param [Host] host Host node classifier is on
|
711
|
-
# @param [Fixnum] port Port to make the HTTPS status check over
|
712
|
-
#
|
713
|
-
# @return [Result] Result of the last HTTPS status check
|
714
|
-
def sleep_until_nc_started(host, port = nil)
|
715
|
-
port = options[:nodeclassifier_port] if port.nil?
|
716
|
-
curl_with_retries("start nodeclassifier (ssl)",
|
717
|
-
host, "https://#{host.node_name}:#{port}", [35, 60])
|
718
|
-
end
|
719
|
-
|
720
|
-
#stops the puppet agent running on the host
|
721
|
-
# @param [Host, Array<Host>, String, Symbol] agent One or more hosts to act upon,
|
722
|
-
# or a role (String or Symbol) that identifies one or more hosts.
|
723
|
-
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
724
|
-
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
725
|
-
def stop_agent_on(agent, opts = {})
|
726
|
-
block_on agent, opts do | host |
|
727
|
-
vardir = host.puppet_configprint['vardir']
|
728
|
-
agent_running = true
|
729
|
-
while agent_running
|
730
|
-
agent_running = host.file_exist?("#{vardir}/state/agent_catalog_run.lock")
|
731
|
-
if agent_running
|
732
|
-
sleep 2
|
733
|
-
end
|
734
|
-
end
|
735
|
-
|
736
|
-
# In 4.0 this was changed to just be `puppet`
|
737
|
-
agent_service = 'puppet'
|
738
|
-
if !aio_version?(host)
|
739
|
-
# The agent service is `pe-puppet` everywhere EXCEPT certain linux distros on PE 2.8
|
740
|
-
# In all the case that it is different, this init script will exist. So we can assume
|
741
|
-
# that if the script doesn't exist, we should just use `pe-puppet`
|
742
|
-
agent_service = 'pe-puppet-agent'
|
743
|
-
agent_service = 'pe-puppet' unless host.file_exist?('/etc/init.d/pe-puppet-agent')
|
744
|
-
end
|
745
|
-
|
746
|
-
# Under a number of stupid circumstances, we can't stop the
|
747
|
-
# agent using puppet. This is usually because of issues with
|
748
|
-
# the init script or system on that particular configuration.
|
749
|
-
avoid_puppet_at_all_costs = false
|
750
|
-
avoid_puppet_at_all_costs ||= host['platform'] =~ /el-4/
|
751
|
-
avoid_puppet_at_all_costs ||= host['pe_ver'] && version_is_less(host['pe_ver'], '3.2') && host['platform'] =~ /sles/
|
752
|
-
|
753
|
-
if avoid_puppet_at_all_costs
|
754
|
-
# When upgrading, puppet is already stopped. On EL4, this causes an exit code of '1'
|
755
|
-
on host, "/etc/init.d/#{agent_service} stop", :acceptable_exit_codes => [0, 1]
|
756
|
-
else
|
757
|
-
on host, puppet_resource('service', agent_service, 'ensure=stopped')
|
758
|
-
end
|
759
|
-
end
|
760
|
-
end
|
761
|
-
|
762
|
-
#stops the puppet agent running on the default host
|
763
|
-
# @see #stop_agent_on
|
764
|
-
def stop_agent
|
765
|
-
stop_agent_on(default)
|
766
|
-
end
|
767
|
-
|
768
|
-
#wait for a given host to appear in the dashboard
|
769
|
-
# @deprecated this method should be removed in the next release since we don't believe the check is necessary.
|
770
|
-
def wait_for_host_in_dashboard(host)
|
771
|
-
|
772
|
-
hostname = host.node_name
|
773
|
-
hostcert = dashboard.puppet['hostcert']
|
774
|
-
key = dashboard.puppet['hostprivkey']
|
775
|
-
cacert = dashboard.puppet['localcacert']
|
776
|
-
retry_on(dashboard, "curl --cert #{hostcert} --key #{key} --cacert #{cacert}\
|
777
|
-
https://#{dashboard}:4433/classifier-api/v1/nodes | grep '\"name\":\"#{hostname}\"'")
|
778
|
-
end
|
779
|
-
|
780
|
-
# Ensure the host has requested a cert, then sign it
|
781
|
-
#
|
782
|
-
# @param [Host, Array<Host>, String, Symbol] host One or more hosts, or a role (String or Symbol)
|
783
|
-
# that identifies one or more hosts to validate certificate signing.
|
784
|
-
# No argument, or an empty array means no validation of success
|
785
|
-
# for specific hosts will be performed. This will always execute
|
786
|
-
# 'cert --sign --all --allow-dns-alt-names' even for a single host.
|
787
|
-
#
|
788
|
-
# @return nil
|
789
|
-
# @raise [FailTest] if process times out
|
790
|
-
def sign_certificate_for(host = [])
|
791
|
-
hostnames = []
|
792
|
-
hosts = host.is_a?(Array) ? host : [host]
|
793
|
-
hosts.each{ |current_host|
|
794
|
-
if [master, dashboard, database].include? current_host
|
795
|
-
|
796
|
-
on current_host, puppet( 'agent -t' ), :acceptable_exit_codes => [0,1,2]
|
797
|
-
on master, puppet( "cert --allow-dns-alt-names sign #{current_host}" ), :acceptable_exit_codes => [0,24]
|
798
|
-
|
799
|
-
else
|
800
|
-
hostnames << Regexp.escape( current_host.node_name )
|
801
|
-
end
|
802
|
-
}
|
803
|
-
if hostnames.size < 1
|
804
|
-
on master, puppet("cert --sign --all --allow-dns-alt-names"),
|
805
|
-
:acceptable_exit_codes => [0,24]
|
806
|
-
return
|
807
|
-
end
|
808
|
-
while hostnames.size > 0
|
809
|
-
last_sleep = 0
|
810
|
-
next_sleep = 1
|
811
|
-
(0..10).each do |i|
|
812
|
-
if i == 10
|
813
|
-
fail_test("Failed to sign cert for #{hostnames}")
|
814
|
-
hostnames.clear
|
815
|
-
end
|
816
|
-
on master, puppet("cert --sign --all --allow-dns-alt-names"), :acceptable_exit_codes => [0,24]
|
817
|
-
out = on(master, puppet("cert --list --all")).stdout
|
818
|
-
if hostnames.all? { |hostname| out =~ /\+ "?#{hostname}"?/ }
|
819
|
-
hostnames.clear
|
820
|
-
break
|
821
|
-
end
|
822
|
-
|
823
|
-
sleep next_sleep
|
824
|
-
(last_sleep, next_sleep) = next_sleep, last_sleep+next_sleep
|
825
|
-
end
|
826
|
-
end
|
827
|
-
host
|
828
|
-
end
|
829
|
-
|
830
|
-
#prompt the master to sign certs then check to confirm the cert for the default host is signed
|
831
|
-
#@see #sign_certificate_for
|
832
|
-
def sign_certificate
|
833
|
-
sign_certificate_for(default)
|
834
|
-
end
|
835
|
-
|
836
|
-
# Create a temp directory on remote host with a user. Default user
|
837
|
-
# is puppet master user.
|
838
|
-
#
|
839
|
-
# @param [Host] host A single remote host on which to create and adjust
|
840
|
-
# the ownership of a temp directory.
|
841
|
-
# @param [String] name A remote path prefix for the new temp
|
842
|
-
# directory. Default value is '/tmp/beaker'
|
843
|
-
# @param [String] user The name of user that should own the temp
|
844
|
-
# directory. If no username is specified, use `puppet master
|
845
|
-
# --configprint user` to obtain username from master. Raise RuntimeError
|
846
|
-
# if this puppet command returns a non-zero exit code.
|
847
|
-
#
|
848
|
-
# @return [String] Returns the name of the newly-created dir.
|
849
|
-
def create_tmpdir_for_user(host, name='/tmp/beaker', user=nil)
|
850
|
-
if not user
|
851
|
-
result = on host, puppet("master --configprint user")
|
852
|
-
if not result.exit_code == 0
|
853
|
-
raise "`puppet master --configprint` failed, check that puppet is installed on #{host} or explicitly pass in a user name."
|
854
|
-
end
|
855
|
-
user = result.stdout.strip
|
856
|
-
end
|
857
|
-
|
858
|
-
create_tmpdir_on(host, name, user)
|
859
|
-
|
860
|
-
end
|
861
|
-
|
862
|
-
end
|
863
|
-
end
|
864
|
-
end
|
865
|
-
end
|