beaker 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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