beaker 0.0.0
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 +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.simplecov +14 -0
- data/DOCUMENTING.md +167 -0
- data/Gemfile +3 -0
- data/LICENSE +17 -0
- data/README.md +332 -0
- data/Rakefile +121 -0
- data/beaker.gemspec +42 -0
- data/beaker.rb +10 -0
- data/bin/beaker +9 -0
- data/lib/beaker.rb +36 -0
- data/lib/beaker/answers.rb +29 -0
- data/lib/beaker/answers/version28.rb +104 -0
- data/lib/beaker/answers/version30.rb +194 -0
- data/lib/beaker/cli.rb +113 -0
- data/lib/beaker/command.rb +241 -0
- data/lib/beaker/command_factory.rb +21 -0
- data/lib/beaker/dsl.rb +85 -0
- data/lib/beaker/dsl/assertions.rb +87 -0
- data/lib/beaker/dsl/helpers.rb +625 -0
- data/lib/beaker/dsl/install_utils.rb +299 -0
- data/lib/beaker/dsl/outcomes.rb +99 -0
- data/lib/beaker/dsl/roles.rb +97 -0
- data/lib/beaker/dsl/structure.rb +63 -0
- data/lib/beaker/dsl/wrappers.rb +100 -0
- data/lib/beaker/host.rb +193 -0
- data/lib/beaker/host/aix.rb +15 -0
- data/lib/beaker/host/aix/file.rb +16 -0
- data/lib/beaker/host/aix/group.rb +35 -0
- data/lib/beaker/host/aix/user.rb +32 -0
- data/lib/beaker/host/unix.rb +54 -0
- data/lib/beaker/host/unix/exec.rb +15 -0
- data/lib/beaker/host/unix/file.rb +16 -0
- data/lib/beaker/host/unix/group.rb +40 -0
- data/lib/beaker/host/unix/pkg.rb +22 -0
- data/lib/beaker/host/unix/user.rb +32 -0
- data/lib/beaker/host/windows.rb +44 -0
- data/lib/beaker/host/windows/exec.rb +18 -0
- data/lib/beaker/host/windows/file.rb +15 -0
- data/lib/beaker/host/windows/group.rb +36 -0
- data/lib/beaker/host/windows/pkg.rb +26 -0
- data/lib/beaker/host/windows/user.rb +32 -0
- data/lib/beaker/hypervisor.rb +37 -0
- data/lib/beaker/hypervisor/aixer.rb +52 -0
- data/lib/beaker/hypervisor/blimper.rb +123 -0
- data/lib/beaker/hypervisor/fusion.rb +56 -0
- data/lib/beaker/hypervisor/solaris.rb +65 -0
- data/lib/beaker/hypervisor/vagrant.rb +118 -0
- data/lib/beaker/hypervisor/vcloud.rb +175 -0
- data/lib/beaker/hypervisor/vsphere.rb +80 -0
- data/lib/beaker/hypervisor/vsphere_helper.rb +200 -0
- data/lib/beaker/logger.rb +167 -0
- data/lib/beaker/network_manager.rb +73 -0
- data/lib/beaker/options_parsing.rb +323 -0
- data/lib/beaker/result.rb +55 -0
- data/lib/beaker/shared.rb +15 -0
- data/lib/beaker/shared/error_handler.rb +17 -0
- data/lib/beaker/shared/host_handler.rb +46 -0
- data/lib/beaker/shared/repetition.rb +28 -0
- data/lib/beaker/ssh_connection.rb +198 -0
- data/lib/beaker/test_case.rb +225 -0
- data/lib/beaker/test_config.rb +148 -0
- data/lib/beaker/test_suite.rb +288 -0
- data/lib/beaker/utils.rb +7 -0
- data/lib/beaker/utils/ntp_control.rb +42 -0
- data/lib/beaker/utils/repo_control.rb +92 -0
- data/lib/beaker/utils/setup_helper.rb +77 -0
- data/lib/beaker/utils/validator.rb +27 -0
- data/spec/beaker/command_spec.rb +94 -0
- data/spec/beaker/dsl/assertions_spec.rb +104 -0
- data/spec/beaker/dsl/helpers_spec.rb +230 -0
- data/spec/beaker/dsl/install_utils_spec.rb +70 -0
- data/spec/beaker/dsl/outcomes_spec.rb +43 -0
- data/spec/beaker/dsl/roles_spec.rb +86 -0
- data/spec/beaker/dsl/structure_spec.rb +60 -0
- data/spec/beaker/dsl/wrappers_spec.rb +52 -0
- data/spec/beaker/host_spec.rb +95 -0
- data/spec/beaker/logger_spec.rb +117 -0
- data/spec/beaker/options_parsing_spec.rb +37 -0
- data/spec/beaker/puppet_command_spec.rb +128 -0
- data/spec/beaker/ssh_connection_spec.rb +39 -0
- data/spec/beaker/test_case_spec.rb +6 -0
- data/spec/beaker/test_suite_spec.rb +44 -0
- data/spec/mocks_and_helpers.rb +34 -0
- data/spec/spec_helper.rb +15 -0
- metadata +359 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
module Beaker
|
2
|
+
module Utils
|
3
|
+
class RepoControl
|
4
|
+
|
5
|
+
APT_CFG = %q{ Acquire::http::Proxy "http://proxy.puppetlabs.net:3128/"; }
|
6
|
+
IPS_PKG_REPO="http://solaris-11-internal-repo.delivery.puppetlabs.net"
|
7
|
+
|
8
|
+
def initialize(options, hosts)
|
9
|
+
@options = options.dup
|
10
|
+
@hosts = hosts
|
11
|
+
@logger = options[:logger]
|
12
|
+
@debug_opt = options[:debug] ? 'vh' : ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def epel_info_for! host
|
16
|
+
version = host['platform'].match(/el-(\d+)/)[1]
|
17
|
+
if version == '6'
|
18
|
+
pkg = 'epel-release-6-8.noarch.rpm'
|
19
|
+
url = "http://mirror.itc.virginia.edu/fedora-epel/6/i386/#{pkg}"
|
20
|
+
elsif version == '5'
|
21
|
+
pkg = 'epel-release-5-4.noarch.rpm'
|
22
|
+
url = "http://archive.linux.duke.edu/pub/epel/5/i386/#{pkg}"
|
23
|
+
else
|
24
|
+
raise "I don't understand your platform description!"
|
25
|
+
end
|
26
|
+
return url
|
27
|
+
end
|
28
|
+
|
29
|
+
def apt_get_update
|
30
|
+
@hosts.each do |host|
|
31
|
+
if host['platform'] =~ /ubuntu|debian/
|
32
|
+
host.exec(Command.new("apt-get -y -f -m update"))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def copy_file_to_remote(host, file_path, file_content)
|
38
|
+
Tempfile.open 'beaker' do |tempfile|
|
39
|
+
File.open(tempfile.path, 'w') {|file| file.puts file_content }
|
40
|
+
|
41
|
+
host.do_scp_to(tempfile.path, file_path, @options)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
def proxy_config
|
47
|
+
# repo_proxy
|
48
|
+
# supports ubuntu, debian and solaris platforms
|
49
|
+
@hosts.each do |host|
|
50
|
+
case
|
51
|
+
when host['platform'] =~ /ubuntu/
|
52
|
+
host.exec(Command.new("if test -f /etc/apt/apt.conf; then mv /etc/apt/apt.conf /etc/apt/apt.conf.bk; fi"))
|
53
|
+
copy_file_to_remote(host, '/etc/apt/apt.conf', APT_CFG)
|
54
|
+
apt_get_update
|
55
|
+
when host['platform'] =~ /debian/
|
56
|
+
host.exec(Command.new("if test -f /etc/apt/apt.conf; then mv /etc/apt/apt.conf /etc/apt/apt.conf.bk; fi"))
|
57
|
+
copy_file_to_remote(host, '/etc/apt/apt.conf', APT_CFG)
|
58
|
+
apt_get_update
|
59
|
+
when host['platform'] =~ /solaris-11/
|
60
|
+
host.exec(Command.new("/usr/bin/pkg unset-publisher solaris || :"))
|
61
|
+
host.exec(Command.new(host,"/usr/bin/pkg set-publisher -g %s solaris" % IPS_PKG_REPO))
|
62
|
+
else
|
63
|
+
@logger.debug "#{host}: repo proxy configuration not modified"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
rescue => e
|
67
|
+
report_and_raise(@logger, e, "proxy_config")
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_el_extras
|
71
|
+
#add_el_extras
|
72
|
+
#only supports el-* platforms
|
73
|
+
@hosts.each do |host|
|
74
|
+
case
|
75
|
+
when host['platform'] =~ /el-(5|6)/
|
76
|
+
result = host.exec(Command.new('rpm -qa | grep epel-release'), :acceptable_exit_codes => [0,1])
|
77
|
+
if result.exit_code == 1
|
78
|
+
url = epel_info_for! host
|
79
|
+
host.exec(Command.new("rpm -i#{@debug_opt} #{url}"))
|
80
|
+
host.exec(Command.new('yum clean all && yum makecache'))
|
81
|
+
end
|
82
|
+
else
|
83
|
+
@logger.debug "#{host}: package repo configuration not modified"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
rescue => e
|
87
|
+
report_and_raise(@logger, e, "add_repos")
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Beaker
|
2
|
+
module Utils
|
3
|
+
class SetupHelper
|
4
|
+
|
5
|
+
def initialize(options, hosts)
|
6
|
+
@options = options.dup
|
7
|
+
@hosts = hosts
|
8
|
+
@logger = options[:logger]
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_masters(hosts)
|
12
|
+
hosts.select do |host|
|
13
|
+
host['roles'].include?("master")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_only_master(hosts)
|
18
|
+
m = find_masters(hosts)
|
19
|
+
raise "too many masters, expected one but found #{m.map {|h| h.to_s }}" unless m.length == 1
|
20
|
+
m.first
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_master_entry
|
24
|
+
@logger.notify "Add Master entry to /etc/hosts"
|
25
|
+
master = find_only_master(@hosts)
|
26
|
+
if master["hypervisor"] and master["hypervisor"] =~ /vagrant/
|
27
|
+
@logger.debug "Don't update master entry on vagrant masters"
|
28
|
+
return
|
29
|
+
end
|
30
|
+
@logger.debug "Get ip address of Master #{master}"
|
31
|
+
if master['platform'].include? 'solaris'
|
32
|
+
stdout = master.exec(Command.new("ifconfig -a inet| awk '/broadcast/ {print $2}' | cut -d/ -f1 | head -1")).stdout
|
33
|
+
else
|
34
|
+
stdout = master.exec(Command.new("ip a|awk '/g/{print$2}' | cut -d/ -f1 | head -1")).stdout
|
35
|
+
end
|
36
|
+
ip=stdout.chomp
|
37
|
+
|
38
|
+
path = "/etc/hosts"
|
39
|
+
if master['platform'].include? 'solaris'
|
40
|
+
path = "/etc/inet/hosts"
|
41
|
+
end
|
42
|
+
|
43
|
+
@logger.debug "Update %s on #{master}" % path
|
44
|
+
# Preserve the mode the easy way...
|
45
|
+
master.exec(Command.new("cp %s %s.old" % [path, path]))
|
46
|
+
master.exec(Command.new("cp %s %s.new" % [path, path]))
|
47
|
+
master.exec(Command.new("grep -v '#{ip} #{master}' %s > %s.new" % [path, path]))
|
48
|
+
master.exec(Command.new("echo '#{ip} #{master}' >> %s.new" % path))
|
49
|
+
master.exec(Command.new("mv %s.new %s" % [path, path]))
|
50
|
+
rescue => e
|
51
|
+
report_and_raise(@logger, e, "add_master_entry")
|
52
|
+
end
|
53
|
+
|
54
|
+
def sync_root_keys
|
55
|
+
# JJM This step runs on every system under test right now. We're anticipating
|
56
|
+
# issues on Windows and maybe Solaris. We will likely need to filter this step
|
57
|
+
# but we're deliberately taking the approach of "assume it will work, fix it
|
58
|
+
# when reality dictates otherwise"
|
59
|
+
@logger.notify "Sync root authorized_keys from github"
|
60
|
+
script = "https://raw.github.com/puppetlabs/puppetlabs-sshkeys/master/templates/scripts/manage_root_authorized_keys"
|
61
|
+
setup_root_authorized_keys = "curl -k -o - #{script} | %s"
|
62
|
+
@logger.notify "Sync root authorized_keys from github"
|
63
|
+
@hosts.each do |host|
|
64
|
+
# Allow all exit code, as this operation is unlikely to cause problems if it fails.
|
65
|
+
if host['platform'].include? 'solaris'
|
66
|
+
host.exec(Command.new(setup_root_authorized_keys % "bash"), :acceptable_exit_codes => (0..255))
|
67
|
+
else
|
68
|
+
host.exec(Command.new(setup_root_authorized_keys % "env PATH=/usr/gnu/bin:$PATH bash"), :acceptable_exit_codes => (0..255))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
rescue => e
|
72
|
+
report_and_raise(@logger, e, "sync_root_keys")
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Beaker
|
2
|
+
module Utils
|
3
|
+
module Validator
|
4
|
+
PACKAGES = ['curl']
|
5
|
+
UNIX_PACKAGES = ['ntpdate']
|
6
|
+
|
7
|
+
def self.validate(hosts, logger)
|
8
|
+
hosts.each do |host|
|
9
|
+
PACKAGES.each do |pkg|
|
10
|
+
if not host.check_for_package pkg
|
11
|
+
host.install_package pkg
|
12
|
+
end
|
13
|
+
end
|
14
|
+
if host['platform'] !~ /(windows)|(aix)|(solaris)/
|
15
|
+
UNIX_PACKAGES.each do |pkg|
|
16
|
+
if not host.check_for_package pkg
|
17
|
+
host.install_package pkg
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
rescue => e
|
23
|
+
report_and_raise(logger, e, "validate")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Beaker
|
4
|
+
describe Command do
|
5
|
+
let(:command) { @command || '/bin/ls' }
|
6
|
+
let(:args) { @args || Array.new }
|
7
|
+
let(:options) { @options || Hash.new }
|
8
|
+
subject(:cmd) { Command.new( command, args, options ) }
|
9
|
+
let(:host) { Hash.new }
|
10
|
+
|
11
|
+
it 'creates a new Command object' do
|
12
|
+
@command = '/usr/bin/blah'
|
13
|
+
@args = [ 'to', 'the', 'baz' ]
|
14
|
+
@options = { :foo => 'bar' }
|
15
|
+
|
16
|
+
expect( cmd.options ).to be == @options
|
17
|
+
expect( cmd.args ).to be == @args
|
18
|
+
expect( cmd.command ).to be == @command
|
19
|
+
|
20
|
+
expect( cmd.args_string ).to be == 'to the baz'
|
21
|
+
expect( cmd.options_string ).to be == '--foo=bar'
|
22
|
+
expect( cmd.environment_string_for(host) ).to be == ''
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#options_string' do
|
27
|
+
it 'parses things' do
|
28
|
+
subject.options = { :v => nil, :test => nil,
|
29
|
+
:server => 'master', :a => 'answers.txt' }
|
30
|
+
expect( subject.options_string ).to match /-v/
|
31
|
+
expect( subject.options_string ).to match /--test/
|
32
|
+
expect( subject.options_string ).to match /--server=master/
|
33
|
+
expect( subject.options_string ).to match /-a=answers\.txt/
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#args_string' do
|
38
|
+
it 'joins an array' do
|
39
|
+
subject.args = ['my/command and', nil, 'its args and opts']
|
40
|
+
expect( subject.args_string ).to be == 'my/command and its args and opts'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#environment_string_for' do
|
45
|
+
it 'returns a blank string if theres no env' do
|
46
|
+
expect( subject.environment_string_for({}) ).to be == ''
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'takes an env hash with var_name/value pairs' do
|
50
|
+
expect( subject.environment_string_for({}, {:HOME => '/'}) ).
|
51
|
+
to be == 'env HOME="/"'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'takes an env hash with var_name/value[Array] pairs' do
|
55
|
+
expect( subject.environment_string_for({}, {:LD_PATH => ['/', '/tmp']}) ).
|
56
|
+
to be == 'env LD_PATH="/:/tmp"'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'takes var_names where there is an array of default values' do
|
60
|
+
env = {:PATH => { :default => [ '/bin', '/usr/bin' ] } }
|
61
|
+
expect( subject.environment_string_for({}, env) ).
|
62
|
+
to be == 'env PATH="/bin:/usr/bin"'
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'takes var_names where there is an array of host specific values' do
|
67
|
+
host = { 'pe_path' => '/opt/puppet/bin', 'foss_path' => '/usr/bin' }
|
68
|
+
env = {:PATH => { :host => [ 'pe_path', 'foss_path' ] } }
|
69
|
+
expect( subject.environment_string_for( host, env ) ).
|
70
|
+
to be == 'env PATH="/opt/puppet/bin:/usr/bin"'
|
71
|
+
|
72
|
+
end
|
73
|
+
it 'when using an array of values it allows to specify the separator' do
|
74
|
+
host = { 'whoosits_separator' => ' **sparkles** ' }
|
75
|
+
env = {
|
76
|
+
:WHOOSITS => {
|
77
|
+
:default => [ 'whatsits', 'wonkers' ],
|
78
|
+
:opts => {:separator => {:host => 'whoosits_separator' } }
|
79
|
+
}
|
80
|
+
}
|
81
|
+
expect( subject.environment_string_for( host, env ) ).
|
82
|
+
to be == 'env WHOOSITS="whatsits **sparkles** wonkers"'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#parse_env_hash_for' do
|
87
|
+
it 'has too many responsiblities' do
|
88
|
+
env = { :PATH => { :default => [ '/bin', '/usr/bin' ] } }
|
89
|
+
var_array = cmd.parse_env_hash_for host, env
|
90
|
+
expect( var_array ).to be == [ 'PATH="/bin:/usr/bin"' ]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ClassMixedWithDSLAssertions
|
4
|
+
include Beaker::DSL::Assertions
|
5
|
+
end
|
6
|
+
|
7
|
+
describe ClassMixedWithDSLAssertions do
|
8
|
+
describe '#assert_output' do
|
9
|
+
it 'defaults to checking stdout' do
|
10
|
+
stdout = <<CONSOLE
|
11
|
+
This should not have space infront of it
|
12
|
+
While this should have two spaces infront of it
|
13
|
+
And this 3, all lines should be to stdout
|
14
|
+
CONSOLE
|
15
|
+
|
16
|
+
expectation = <<CONSOLE
|
17
|
+
This should not have space infront of it
|
18
|
+
While this should have two spaces infront of it
|
19
|
+
And this 3, all lines should be to stdout
|
20
|
+
CONSOLE
|
21
|
+
|
22
|
+
result = double
|
23
|
+
result.should_receive( :nil? ).at_least( :once ).and_return( false )
|
24
|
+
result.should_receive( :stdout ).and_return( stdout )
|
25
|
+
result.should_receive( :output ).and_return( stdout )
|
26
|
+
result.should_receive( :stderr ).and_return( '' )
|
27
|
+
|
28
|
+
subject.should_receive( :result ).at_least( :once ).and_return( result )
|
29
|
+
expect { subject.assert_output expectation }.to_not raise_error
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'allows specifying stream markers' do
|
33
|
+
output = <<OUTPUT
|
34
|
+
This is on stdout
|
35
|
+
While this is on stderr
|
36
|
+
And THIS is again on stdout
|
37
|
+
OUTPUT
|
38
|
+
|
39
|
+
stdout = <<STDOUT
|
40
|
+
This is on stdout
|
41
|
+
And THIS is again on stdout
|
42
|
+
STDOUT
|
43
|
+
|
44
|
+
stderr = <<STDERR
|
45
|
+
While this is on stderr
|
46
|
+
STDERR
|
47
|
+
|
48
|
+
expectation = <<EXPECT
|
49
|
+
STDOUT> This is on stdout
|
50
|
+
STDERR> While this is on stderr
|
51
|
+
STDOUT> And THIS is again on stdout
|
52
|
+
EXPECT
|
53
|
+
|
54
|
+
result = double
|
55
|
+
result.should_receive( :nil? ).at_least( :once ).and_return( false )
|
56
|
+
result.should_receive( :stdout ).and_return( stdout )
|
57
|
+
result.should_receive( :output ).and_return( output )
|
58
|
+
result.should_receive( :stderr ).and_return( stderr )
|
59
|
+
|
60
|
+
subject.should_receive( :result ).at_least( :once ).and_return( result )
|
61
|
+
expect { subject.assert_output expectation }.to_not raise_error
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'raises an approriate error when output does not match expectations' do
|
65
|
+
output = <<OUTPUT
|
66
|
+
This is on stdout
|
67
|
+
Holy Crap, what HAPPENED!?!?!?
|
68
|
+
And THIS is again on stdout
|
69
|
+
OUTPUT
|
70
|
+
|
71
|
+
stdout = <<STDOUT
|
72
|
+
This is on stdout
|
73
|
+
And THIS is again on stdout
|
74
|
+
STDOUT
|
75
|
+
|
76
|
+
stderr = <<STDERR
|
77
|
+
Holy Crap, what HAPPENED!?!?!?
|
78
|
+
STDERR
|
79
|
+
|
80
|
+
expectation = <<EXPECT
|
81
|
+
STDOUT> This is on stdout
|
82
|
+
STDERR> While this is on stderr
|
83
|
+
STDOUT> And THIS is again on stdout
|
84
|
+
EXPECT
|
85
|
+
|
86
|
+
require 'rbconfig'
|
87
|
+
ruby_conf = defined?(RbConfig) ? RbConfig::CONFIG : Config::CONFIG
|
88
|
+
if ruby_conf['MINOR'].to_i == 8
|
89
|
+
exception = Test::Unit::AssertionFailedError
|
90
|
+
else
|
91
|
+
exception = MiniTest::Assertion
|
92
|
+
end
|
93
|
+
|
94
|
+
result = double
|
95
|
+
result.should_receive( :nil? ).at_least( :once ).and_return( false )
|
96
|
+
result.should_receive( :stdout ).any_number_of_times.and_return( stdout )
|
97
|
+
result.should_receive( :output ).any_number_of_times.and_return( output )
|
98
|
+
result.should_receive( :stderr ).any_number_of_times.and_return( stderr )
|
99
|
+
|
100
|
+
subject.should_receive( :result ).at_least( :once ).and_return( result )
|
101
|
+
expect { subject.assert_output expectation }.to raise_error( exception )
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ClassMixedWithDSLHelpers
|
4
|
+
include Beaker::DSL::Helpers
|
5
|
+
end
|
6
|
+
|
7
|
+
describe ClassMixedWithDSLHelpers do
|
8
|
+
describe '#on' do
|
9
|
+
it 'allows the environment the command is run within to be specified' do
|
10
|
+
host = double.as_null_object
|
11
|
+
|
12
|
+
Beaker::Command.should_receive( :new ).
|
13
|
+
with( 'ls ~/.bin', [], {'ENV' => { :HOME => '/tmp/test_home' }} )
|
14
|
+
|
15
|
+
subject.on( host, 'ls ~/.bin', :environment => {:HOME => '/tmp/test_home' } )
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'delegates to itself for each host passed' do
|
19
|
+
hosts = [ double, double, double ]
|
20
|
+
|
21
|
+
hosts.each_with_index do |host, i|
|
22
|
+
host.should_receive( :exec ).and_return( i )
|
23
|
+
end
|
24
|
+
|
25
|
+
results = subject.on( hosts, 'ls' )
|
26
|
+
expect( results ).to be == [ 0, 1, 2 ]
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'yields to a given block' do
|
30
|
+
host = double.as_null_object
|
31
|
+
|
32
|
+
subject.on host, 'ls' do |containing_class|
|
33
|
+
expect( containing_class ).
|
34
|
+
to be_an_instance_of( ClassMixedWithDSLHelpers )
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns the result of the action' do
|
39
|
+
host = double.as_null_object
|
40
|
+
|
41
|
+
host.should_receive( :exec ).and_return( 'my_result' )
|
42
|
+
|
43
|
+
expect( subject.on( host, 'ls' ) ).to be == 'my_result'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#scp_from' do
|
48
|
+
it 'delegates to the host' do
|
49
|
+
hosts = [ double, double, double ]
|
50
|
+
result = double
|
51
|
+
|
52
|
+
subject.should_receive( :logger ).exactly( 3 ).times
|
53
|
+
result.should_receive( :log ).exactly( 3 ).times
|
54
|
+
hosts.each do |host|
|
55
|
+
host.should_receive( :do_scp_from ).and_return( result )
|
56
|
+
end
|
57
|
+
|
58
|
+
subject.scp_from( hosts, '/var/log/my.log', 'log/my.log' )
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#scp_to' do
|
63
|
+
it 'delegates to the host' do
|
64
|
+
hosts = [ double, double, double ]
|
65
|
+
result = double
|
66
|
+
|
67
|
+
subject.should_receive( :logger ).exactly( 3 ).times
|
68
|
+
result.should_receive( :log ).exactly( 3 ).times
|
69
|
+
hosts.each do |host|
|
70
|
+
host.should_receive( :do_scp_to ).and_return( result )
|
71
|
+
end
|
72
|
+
|
73
|
+
subject.scp_to( hosts, '/var/log/my.log', 'log/my.log' )
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#create_remote_file' do
|
78
|
+
it 'scps the contents passed in to the hosts' do
|
79
|
+
hosts = [ 'uno.example.org', 'dos.example.org' ]
|
80
|
+
my_opts = { :silent => true }
|
81
|
+
tmpfile = double
|
82
|
+
|
83
|
+
tmpfile.should_receive( :path ).exactly( 2 ).times.
|
84
|
+
and_return( '/local/path/to/blah' )
|
85
|
+
Tempfile.should_receive( :open ).and_yield( tmpfile )
|
86
|
+
File.should_receive( :open )
|
87
|
+
subject.should_receive( :scp_to ).
|
88
|
+
with( hosts, '/local/path/to/blah', '/remote/path', my_opts )
|
89
|
+
|
90
|
+
subject.create_remote_file( hosts, '/remote/path', 'blah', my_opts )
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#run_script_on' do
|
95
|
+
it 'scps the script to a tmpdir and executes it on host(s)' do
|
96
|
+
subject.should_receive( :scp_to )
|
97
|
+
subject.should_receive( :on )
|
98
|
+
subject.run_script_on( 'host', '~/.bin/make-enterprisy' )
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
#let(:host_param) { @host_param || Array.new }
|
103
|
+
#let(:logger_param) { double('logger').as_null_object }
|
104
|
+
#let(:config_param) { Hash.new }
|
105
|
+
#let(:options_param) { Hash.new }
|
106
|
+
#let(:path_param) { '/file/path/string' }
|
107
|
+
#let(:test_case) do
|
108
|
+
# TestCase.new( host_param, logger_param, config_param, options_param, path_param )
|
109
|
+
#end
|
110
|
+
|
111
|
+
describe 'confine' do
|
112
|
+
let(:logger) { double.as_null_object }
|
113
|
+
before do
|
114
|
+
subject.should_receive( :logger ).any_number_of_times.and_return( logger )
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'skips the test if there are no applicable hosts' do
|
118
|
+
subject.should_receive( :hosts ).any_number_of_times.and_return( [] )
|
119
|
+
subject.should_receive( :hosts= ).any_number_of_times
|
120
|
+
logger.should_receive( :warn )
|
121
|
+
subject.should_receive( :skip_test ).
|
122
|
+
with( 'No suitable hosts found' )
|
123
|
+
|
124
|
+
subject.confine( :to, {} )
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'raises when given mode is not :to or :except' do
|
128
|
+
subject.should_receive( :hosts ).any_number_of_times
|
129
|
+
subject.should_receive( :hosts= ).any_number_of_times
|
130
|
+
|
131
|
+
expect {
|
132
|
+
subject.confine( :regardless, {:thing => 'value'} )
|
133
|
+
}.to raise_error( 'Unknown option regardless' )
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'rejects hosts that do not meet simple hash criteria' do
|
137
|
+
hosts = [ {'thing' => 'foo'}, {'thing' => 'bar'} ]
|
138
|
+
|
139
|
+
subject.should_receive( :hosts ).and_return( hosts )
|
140
|
+
subject.should_receive( :hosts= ).
|
141
|
+
with( [ {'thing' => 'foo'} ] )
|
142
|
+
|
143
|
+
subject.confine :to, :thing => 'foo'
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'rejects hosts that match a list of criteria' do
|
147
|
+
hosts = [ {'thing' => 'foo'}, {'thing' => 'bar'}, {'thing' => 'baz'} ]
|
148
|
+
|
149
|
+
subject.should_receive( :hosts ).and_return( hosts )
|
150
|
+
subject.should_receive( :hosts= ).
|
151
|
+
with( [ {'thing' => 'bar'} ] )
|
152
|
+
|
153
|
+
subject.confine :except, :thing => ['foo', 'baz']
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'rejects hosts when a passed block returns true' do
|
157
|
+
host1 = {'platform' => 'solaris'}
|
158
|
+
host2 = {'platform' => 'solaris'}
|
159
|
+
host3 = {'platform' => 'windows'}
|
160
|
+
ret1 = (Struct.new('Result1', :stdout)).new(':global')
|
161
|
+
ret2 = (Struct.new('Result2', :stdout)).new('a_zone')
|
162
|
+
hosts = [ host1, host2, host3 ]
|
163
|
+
|
164
|
+
subject.should_receive( :hosts ).and_return( hosts )
|
165
|
+
subject.should_receive( :on ).
|
166
|
+
with( host1, '/sbin/zonename' ).
|
167
|
+
and_return( ret1 )
|
168
|
+
subject.should_receive( :on ).
|
169
|
+
with( host1, '/sbin/zonename' ).
|
170
|
+
and_return( ret2 )
|
171
|
+
|
172
|
+
subject.should_receive( :hosts= ).with( [ host1 ] )
|
173
|
+
|
174
|
+
subject.confine :to, :platform => 'solaris' do |host|
|
175
|
+
subject.on( host, '/sbin/zonename' ).stdout =~ /:global/
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe '#apply_manifest_on' do
|
181
|
+
it 'allows acceptable exit codes through :catch_failures' do
|
182
|
+
subject.should_receive( :puppet ).
|
183
|
+
with( 'apply', '--verbose', '--trace', '--detailed-exitcodes' ).
|
184
|
+
and_return( 'puppet_command' )
|
185
|
+
|
186
|
+
subject.should_receive( :on ).
|
187
|
+
with( 'my_host', 'puppet_command',
|
188
|
+
:acceptable_exit_codes => [4,0,2],
|
189
|
+
:stdin => "class { \"boo\": }\n" )
|
190
|
+
|
191
|
+
subject.apply_manifest_on( 'my_host',
|
192
|
+
'class { "boo": }',
|
193
|
+
:acceptable_exit_codes => [4],
|
194
|
+
:trace => true,
|
195
|
+
:catch_failures => true )
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe '#stub_hosts_on' do
|
200
|
+
it 'executes puppet on the host passed and ensures it is reverted' do
|
201
|
+
logger = double.as_null_object
|
202
|
+
|
203
|
+
subject.should_receive( :logger ).any_number_of_times.and_return( logger )
|
204
|
+
subject.should_receive( :on ).twice
|
205
|
+
subject.should_receive( :teardown ).and_yield
|
206
|
+
subject.should_receive( :puppet ).once.
|
207
|
+
with( 'resource', 'host',
|
208
|
+
'puppetlabs.com',
|
209
|
+
'ensure=present', 'ip=127.0.0.1' )
|
210
|
+
subject.should_receive( :puppet ).once.
|
211
|
+
with( 'resource', 'host',
|
212
|
+
'puppetlabs.com',
|
213
|
+
'ensure=absent' )
|
214
|
+
|
215
|
+
subject.stub_hosts_on( 'my_host', 'puppetlabs.com' => '127.0.0.1' )
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe '#stub_forge_on' do
|
220
|
+
it 'stubs forge.puppetlabs.com with the value of `forge`' do
|
221
|
+
subject.should_receive( :forge ).and_return( 'my_forge.example.com' )
|
222
|
+
Resolv.should_receive( :getaddress ).
|
223
|
+
with( 'my_forge.example.com' ).and_return( '127.0.0.1' )
|
224
|
+
subject.should_receive( :stub_hosts_on ).
|
225
|
+
with( 'my_host', 'forge.puppetlabs.com' => '127.0.0.1' )
|
226
|
+
|
227
|
+
subject.stub_forge_on( 'my_host' )
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|