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.
Files changed (88) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.simplecov +14 -0
  5. data/DOCUMENTING.md +167 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE +17 -0
  8. data/README.md +332 -0
  9. data/Rakefile +121 -0
  10. data/beaker.gemspec +42 -0
  11. data/beaker.rb +10 -0
  12. data/bin/beaker +9 -0
  13. data/lib/beaker.rb +36 -0
  14. data/lib/beaker/answers.rb +29 -0
  15. data/lib/beaker/answers/version28.rb +104 -0
  16. data/lib/beaker/answers/version30.rb +194 -0
  17. data/lib/beaker/cli.rb +113 -0
  18. data/lib/beaker/command.rb +241 -0
  19. data/lib/beaker/command_factory.rb +21 -0
  20. data/lib/beaker/dsl.rb +85 -0
  21. data/lib/beaker/dsl/assertions.rb +87 -0
  22. data/lib/beaker/dsl/helpers.rb +625 -0
  23. data/lib/beaker/dsl/install_utils.rb +299 -0
  24. data/lib/beaker/dsl/outcomes.rb +99 -0
  25. data/lib/beaker/dsl/roles.rb +97 -0
  26. data/lib/beaker/dsl/structure.rb +63 -0
  27. data/lib/beaker/dsl/wrappers.rb +100 -0
  28. data/lib/beaker/host.rb +193 -0
  29. data/lib/beaker/host/aix.rb +15 -0
  30. data/lib/beaker/host/aix/file.rb +16 -0
  31. data/lib/beaker/host/aix/group.rb +35 -0
  32. data/lib/beaker/host/aix/user.rb +32 -0
  33. data/lib/beaker/host/unix.rb +54 -0
  34. data/lib/beaker/host/unix/exec.rb +15 -0
  35. data/lib/beaker/host/unix/file.rb +16 -0
  36. data/lib/beaker/host/unix/group.rb +40 -0
  37. data/lib/beaker/host/unix/pkg.rb +22 -0
  38. data/lib/beaker/host/unix/user.rb +32 -0
  39. data/lib/beaker/host/windows.rb +44 -0
  40. data/lib/beaker/host/windows/exec.rb +18 -0
  41. data/lib/beaker/host/windows/file.rb +15 -0
  42. data/lib/beaker/host/windows/group.rb +36 -0
  43. data/lib/beaker/host/windows/pkg.rb +26 -0
  44. data/lib/beaker/host/windows/user.rb +32 -0
  45. data/lib/beaker/hypervisor.rb +37 -0
  46. data/lib/beaker/hypervisor/aixer.rb +52 -0
  47. data/lib/beaker/hypervisor/blimper.rb +123 -0
  48. data/lib/beaker/hypervisor/fusion.rb +56 -0
  49. data/lib/beaker/hypervisor/solaris.rb +65 -0
  50. data/lib/beaker/hypervisor/vagrant.rb +118 -0
  51. data/lib/beaker/hypervisor/vcloud.rb +175 -0
  52. data/lib/beaker/hypervisor/vsphere.rb +80 -0
  53. data/lib/beaker/hypervisor/vsphere_helper.rb +200 -0
  54. data/lib/beaker/logger.rb +167 -0
  55. data/lib/beaker/network_manager.rb +73 -0
  56. data/lib/beaker/options_parsing.rb +323 -0
  57. data/lib/beaker/result.rb +55 -0
  58. data/lib/beaker/shared.rb +15 -0
  59. data/lib/beaker/shared/error_handler.rb +17 -0
  60. data/lib/beaker/shared/host_handler.rb +46 -0
  61. data/lib/beaker/shared/repetition.rb +28 -0
  62. data/lib/beaker/ssh_connection.rb +198 -0
  63. data/lib/beaker/test_case.rb +225 -0
  64. data/lib/beaker/test_config.rb +148 -0
  65. data/lib/beaker/test_suite.rb +288 -0
  66. data/lib/beaker/utils.rb +7 -0
  67. data/lib/beaker/utils/ntp_control.rb +42 -0
  68. data/lib/beaker/utils/repo_control.rb +92 -0
  69. data/lib/beaker/utils/setup_helper.rb +77 -0
  70. data/lib/beaker/utils/validator.rb +27 -0
  71. data/spec/beaker/command_spec.rb +94 -0
  72. data/spec/beaker/dsl/assertions_spec.rb +104 -0
  73. data/spec/beaker/dsl/helpers_spec.rb +230 -0
  74. data/spec/beaker/dsl/install_utils_spec.rb +70 -0
  75. data/spec/beaker/dsl/outcomes_spec.rb +43 -0
  76. data/spec/beaker/dsl/roles_spec.rb +86 -0
  77. data/spec/beaker/dsl/structure_spec.rb +60 -0
  78. data/spec/beaker/dsl/wrappers_spec.rb +52 -0
  79. data/spec/beaker/host_spec.rb +95 -0
  80. data/spec/beaker/logger_spec.rb +117 -0
  81. data/spec/beaker/options_parsing_spec.rb +37 -0
  82. data/spec/beaker/puppet_command_spec.rb +128 -0
  83. data/spec/beaker/ssh_connection_spec.rb +39 -0
  84. data/spec/beaker/test_case_spec.rb +6 -0
  85. data/spec/beaker/test_suite_spec.rb +44 -0
  86. data/spec/mocks_and_helpers.rb +34 -0
  87. data/spec/spec_helper.rb +15 -0
  88. 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