beaker 0.0.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +8 -0
  3. data/README.md +6 -6
  4. data/beaker.gemspec +6 -2
  5. data/lib/beaker.rb +1 -1
  6. data/lib/beaker/answers.rb +34 -7
  7. data/lib/beaker/answers/version20.rb +124 -0
  8. data/lib/beaker/answers/version28.rb +21 -0
  9. data/lib/beaker/answers/version30.rb +24 -5
  10. data/lib/beaker/cli.rb +55 -41
  11. data/lib/beaker/command.rb +2 -2
  12. data/lib/beaker/dsl/helpers.rb +320 -106
  13. data/lib/beaker/dsl/install_utils.rb +202 -81
  14. data/lib/beaker/dsl/roles.rb +40 -0
  15. data/lib/beaker/host.rb +28 -20
  16. data/lib/beaker/host/unix.rb +7 -4
  17. data/lib/beaker/host/unix/pkg.rb +42 -12
  18. data/lib/beaker/host/windows.rb +9 -5
  19. data/lib/beaker/host/windows/group.rb +1 -1
  20. data/lib/beaker/host/windows/pkg.rb +41 -8
  21. data/lib/beaker/hypervisor.rb +23 -10
  22. data/lib/beaker/hypervisor/aixer.rb +15 -19
  23. data/lib/beaker/hypervisor/blimper.rb +71 -72
  24. data/lib/beaker/hypervisor/fusion.rb +11 -10
  25. data/lib/beaker/hypervisor/solaris.rb +17 -23
  26. data/lib/beaker/hypervisor/vagrant.rb +27 -12
  27. data/lib/beaker/hypervisor/vcloud.rb +154 -138
  28. data/lib/beaker/hypervisor/vcloud_pooled.rb +97 -0
  29. data/lib/beaker/hypervisor/vsphere.rb +8 -5
  30. data/lib/beaker/hypervisor/vsphere_helper.rb +43 -33
  31. data/lib/beaker/network_manager.rb +16 -12
  32. data/lib/beaker/options/command_line_parser.rb +199 -0
  33. data/lib/beaker/options/hosts_file_parser.rb +39 -0
  34. data/lib/beaker/options/options_file_parser.rb +45 -0
  35. data/lib/beaker/options/options_hash.rb +294 -0
  36. data/lib/beaker/options/parser.rb +288 -0
  37. data/lib/beaker/options/pe_version_scraper.rb +35 -0
  38. data/lib/beaker/options/presets.rb +70 -0
  39. data/lib/beaker/shared.rb +2 -1
  40. data/lib/beaker/shared/host_handler.rb +7 -2
  41. data/lib/beaker/shared/repetition.rb +1 -0
  42. data/lib/beaker/shared/timed.rb +14 -0
  43. data/lib/beaker/test_case.rb +2 -38
  44. data/lib/beaker/test_suite.rb +11 -25
  45. data/lib/beaker/utils/repo_control.rb +6 -8
  46. data/lib/beaker/utils/setup_helper.rb +9 -20
  47. data/spec/beaker/answers_spec.rb +109 -0
  48. data/spec/beaker/command_spec.rb +2 -2
  49. data/spec/beaker/dsl/assertions_spec.rb +1 -3
  50. data/spec/beaker/dsl/helpers_spec.rb +519 -84
  51. data/spec/beaker/dsl/install_utils_spec.rb +265 -16
  52. data/spec/beaker/dsl/roles_spec.rb +31 -10
  53. data/spec/beaker/host/windows/group_spec.rb +55 -0
  54. data/spec/beaker/host_spec.rb +130 -40
  55. data/spec/beaker/hypervisor/aixer_spec.rb +34 -0
  56. data/spec/beaker/hypervisor/blimper_spec.rb +77 -0
  57. data/spec/beaker/hypervisor/fusion_spec.rb +26 -0
  58. data/spec/beaker/hypervisor/hypervisor_spec.rb +66 -0
  59. data/spec/beaker/hypervisor/solaris_spec.rb +39 -0
  60. data/spec/beaker/hypervisor/vagrant_spec.rb +105 -0
  61. data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +60 -0
  62. data/spec/beaker/hypervisor/vcloud_spec.rb +70 -0
  63. data/spec/beaker/hypervisor/vsphere_helper_spec.rb +162 -0
  64. data/spec/beaker/hypervisor/vsphere_spec.rb +76 -0
  65. data/spec/beaker/options/command_line_parser_spec.rb +25 -0
  66. data/spec/beaker/options/data/LATEST +1 -0
  67. data/spec/beaker/options/data/badyaml.cfg +21 -0
  68. data/spec/beaker/options/data/hosts.cfg +21 -0
  69. data/spec/beaker/options/data/opts.txt +6 -0
  70. data/spec/beaker/options/hosts_file_parser_spec.rb +30 -0
  71. data/spec/beaker/options/options_file_parser_spec.rb +23 -0
  72. data/spec/beaker/options/options_hash_spec.rb +111 -0
  73. data/spec/beaker/options/parser_spec.rb +172 -0
  74. data/spec/beaker/options/pe_version_scaper_spec.rb +15 -0
  75. data/spec/beaker/options/presets_spec.rb +24 -0
  76. data/spec/beaker/puppet_command_spec.rb +54 -21
  77. data/spec/beaker/shared/error_handler_spec.rb +40 -0
  78. data/spec/beaker/shared/host_handler_spec.rb +104 -0
  79. data/spec/beaker/shared/repetition_spec.rb +72 -0
  80. data/spec/beaker/test_suite_spec.rb +3 -16
  81. data/spec/beaker/utils/ntp_control_spec.rb +42 -0
  82. data/spec/beaker/utils/repo_control_spec.rb +168 -0
  83. data/spec/beaker/utils/setup_helper_spec.rb +82 -0
  84. data/spec/beaker/utils/validator_spec.rb +58 -0
  85. data/spec/helpers.rb +97 -0
  86. data/spec/matchers.rb +39 -0
  87. data/spec/mock_blimpy.rb +48 -0
  88. data/spec/mock_fission.rb +60 -0
  89. data/spec/mock_vsphere.rb +310 -0
  90. data/spec/mock_vsphere_helper.rb +183 -0
  91. data/spec/mocks.rb +83 -0
  92. data/spec/spec_helper.rb +8 -1
  93. metadata +106 -13
  94. data/beaker.rb +0 -10
  95. data/lib/beaker/options_parsing.rb +0 -323
  96. data/lib/beaker/test_config.rb +0 -148
  97. data/spec/beaker/options_parsing_spec.rb +0 -37
  98. data/spec/mocks_and_helpers.rb +0 -34
@@ -19,7 +19,7 @@ module Beaker
19
19
 
20
20
  expect( cmd.args_string ).to be == 'to the baz'
21
21
  expect( cmd.options_string ).to be == '--foo=bar'
22
- expect( cmd.environment_string_for(host) ).to be == ''
22
+ expect( cmd.environment_string_for(host, cmd.environment) ).to be == ''
23
23
 
24
24
  end
25
25
 
@@ -43,7 +43,7 @@ module Beaker
43
43
 
44
44
  describe '#environment_string_for' do
45
45
  it 'returns a blank string if theres no env' do
46
- expect( subject.environment_string_for({}) ).to be == ''
46
+ expect( subject.environment_string_for({}, {}) ).to be == ''
47
47
  end
48
48
 
49
49
  it 'takes an env hash with var_name/value pairs' do
@@ -93,9 +93,7 @@ EXPECT
93
93
 
94
94
  result = double
95
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 )
96
+ result.should_receive( :output ).and_return( output )
99
97
 
100
98
  subject.should_receive( :result ).at_least( :once ).and_return( result )
101
99
  expect { subject.assert_output expectation }.to raise_error( exception )
@@ -2,12 +2,35 @@ require 'spec_helper'
2
2
 
3
3
  class ClassMixedWithDSLHelpers
4
4
  include Beaker::DSL::Helpers
5
+ include Beaker::DSL::Wrappers
6
+ include Beaker::DSL::Roles
7
+
8
+ def logger
9
+ @logger ||= RSpec::Mocks::Mock.new('logger').as_null_object
10
+ end
5
11
  end
6
12
 
7
13
  describe ClassMixedWithDSLHelpers do
14
+ let( :command ) { 'ls' }
15
+ let( :host ) { double.as_null_object }
16
+ let( :result ) { Beaker::Result.new( host, command ) }
17
+
18
+ let( :master ) { make_host( 'master', :roles => %w( master agent ) ) }
19
+ let( :agent ) { make_host( 'agent', :roles => %w( agent ) ) }
20
+ let( :custom ) { make_host( 'custom', :roles => %w( custom agent ) ) }
21
+ let( :dash ) { make_host( 'console', :roles => %w( dashboard agent ) ) }
22
+ let( :db ) { make_host( 'db', :roles => %w( database agent ) ) }
23
+ let( :hosts ) { [ master, agent, dash, db, custom ] }
24
+
8
25
  describe '#on' do
26
+
27
+ before :each do
28
+ result.stdout = 'stdout'
29
+ result.stderr = 'stderr'
30
+ result.exit_code = 0
31
+ end
32
+
9
33
  it 'allows the environment the command is run within to be specified' do
10
- host = double.as_null_object
11
34
 
12
35
  Beaker::Command.should_receive( :new ).
13
36
  with( 'ls ~/.bin', [], {'ENV' => { :HOME => '/tmp/test_home' }} )
@@ -15,42 +38,137 @@ describe ClassMixedWithDSLHelpers do
15
38
  subject.on( host, 'ls ~/.bin', :environment => {:HOME => '/tmp/test_home' } )
16
39
  end
17
40
 
18
- it 'delegates to itself for each host passed' do
19
- hosts = [ double, double, double ]
41
+ it 'if the host is a String Object, finds the matching hosts with that String as role' do
42
+ subject.stub( :hosts ).and_return( hosts )
43
+
44
+ master.should_receive( :exec ).once
45
+
46
+ subject.on( 'master', 'echo hello')
47
+
48
+ end
49
+
50
+ it 'if the host is a Symbol Object, finds the matching hsots with that Symbol as role' do
51
+ subject.stub( :hosts ).and_return( hosts )
20
52
 
53
+ master.should_receive( :exec ).once
54
+
55
+ subject.on( :master, 'echo hello')
56
+
57
+ end
58
+
59
+ it 'delegates to itself for each host passed' do
60
+ expected = []
21
61
  hosts.each_with_index do |host, i|
62
+ expected << i
22
63
  host.should_receive( :exec ).and_return( i )
23
64
  end
24
65
 
25
- results = subject.on( hosts, 'ls' )
26
- expect( results ).to be == [ 0, 1, 2 ]
66
+ results = subject.on( hosts, command )
67
+ expect( results ).to be == expected
27
68
  end
28
69
 
29
- it 'yields to a given block' do
30
- host = double.as_null_object
70
+ context 'upon command completion' do
71
+ before :each do
72
+ host.should_receive( :exec ).and_return( result )
73
+ @res = subject.on( host, command )
74
+ end
75
+
76
+ it 'returns the result of the action' do
77
+ expect( @res ).to be == result
78
+ end
79
+
80
+ it 'provides access to stdout' do
81
+ expect( @res.stdout ).to be == 'stdout'
82
+ end
83
+
84
+ it 'provides access to stderr' do
85
+ expect( @res.stderr ).to be == 'stderr'
86
+ end
87
+
88
+ it 'provides access to exit_code' do
89
+ expect( @res.exit_code ).to be == 0
90
+ end
91
+ end
92
+
93
+ context 'when passed a block with arity of 1' do
94
+ before :each do
95
+ host.should_receive( :exec ).and_return( result )
96
+ end
97
+
98
+ it 'yields self' do
99
+ subject.on host, command do |containing_class|
100
+ expect( containing_class ).
101
+ to be_an_instance_of( ClassMixedWithDSLHelpers )
102
+ end
103
+ end
104
+
105
+ it 'provides access to stdout' do
106
+ subject.on host, command do |containing_class|
107
+ expect( containing_class.stdout ).to be == 'stdout'
108
+ end
109
+ end
110
+
111
+ it 'provides access to stderr' do
112
+ subject.on host, command do |containing_class|
113
+ expect( containing_class.stderr ).to be == 'stderr'
114
+ end
115
+ end
116
+
117
+ it 'provides access to exit_code' do
118
+ subject.on host, command do |containing_class|
119
+ expect( containing_class.exit_code ).to be == 0
120
+ end
121
+ end
122
+ end
123
+
124
+ context 'when passed a block with arity of 0' do
125
+ before :each do
126
+ host.should_receive( :exec ).and_return( result )
127
+ end
128
+
129
+ it 'yields self' do
130
+ subject.on host, command do
131
+ expect( subject ).
132
+ to be_an_instance_of( ClassMixedWithDSLHelpers )
133
+ end
134
+ end
135
+
136
+ it 'provides access to stdout' do
137
+ subject.on host, command do
138
+ expect( subject.stdout ).to be == 'stdout'
139
+ end
140
+ end
141
+
142
+ it 'provides access to stderr' do
143
+ subject.on host, command do
144
+ expect( subject.stderr ).to be == 'stderr'
145
+ end
146
+ end
31
147
 
32
- subject.on host, 'ls' do |containing_class|
33
- expect( containing_class ).
34
- to be_an_instance_of( ClassMixedWithDSLHelpers )
148
+ it 'provides access to exit_code' do
149
+ subject.on host, command do
150
+ expect( subject.exit_code ).to be == 0
151
+ end
35
152
  end
36
153
  end
37
154
 
38
- it 'returns the result of the action' do
39
- host = double.as_null_object
155
+ end
156
+
157
+ describe "shell" do
158
+ it 'delegates to #on with the default host' do
159
+ subject.stub( :hosts ).and_return( hosts )
40
160
 
41
- host.should_receive( :exec ).and_return( 'my_result' )
161
+ subject.should_receive( :on ).with( master, "echo hello", {}).once
42
162
 
43
- expect( subject.on( host, 'ls' ) ).to be == 'my_result'
163
+ subject.shell( "echo hello" )
44
164
  end
45
165
  end
46
166
 
47
167
  describe '#scp_from' do
48
168
  it 'delegates to the host' do
49
- hosts = [ double, double, double ]
50
- result = double
169
+ subject.should_receive( :logger ).exactly( hosts.length ).times
170
+ result.should_receive( :log ).exactly( hosts.length ).times
51
171
 
52
- subject.should_receive( :logger ).exactly( 3 ).times
53
- result.should_receive( :log ).exactly( 3 ).times
54
172
  hosts.each do |host|
55
173
  host.should_receive( :do_scp_from ).and_return( result )
56
174
  end
@@ -61,11 +179,9 @@ describe ClassMixedWithDSLHelpers do
61
179
 
62
180
  describe '#scp_to' do
63
181
  it 'delegates to the host' do
64
- hosts = [ double, double, double ]
65
- result = double
182
+ subject.should_receive( :logger ).exactly( hosts.length ).times
183
+ result.should_receive( :log ).exactly( hosts.length ).times
66
184
 
67
- subject.should_receive( :logger ).exactly( 3 ).times
68
- result.should_receive( :log ).exactly( 3 ).times
69
185
  hosts.each do |host|
70
186
  host.should_receive( :do_scp_to ).and_return( result )
71
187
  end
@@ -76,14 +192,16 @@ describe ClassMixedWithDSLHelpers do
76
192
 
77
193
  describe '#create_remote_file' do
78
194
  it 'scps the contents passed in to the hosts' do
79
- hosts = [ 'uno.example.org', 'dos.example.org' ]
80
195
  my_opts = { :silent => true }
81
196
  tmpfile = double
82
197
 
83
198
  tmpfile.should_receive( :path ).exactly( 2 ).times.
84
199
  and_return( '/local/path/to/blah' )
200
+
85
201
  Tempfile.should_receive( :open ).and_yield( tmpfile )
202
+
86
203
  File.should_receive( :open )
204
+
87
205
  subject.should_receive( :scp_to ).
88
206
  with( hosts, '/local/path/to/blah', '/remote/path', my_opts )
89
207
 
@@ -99,83 +217,84 @@ describe ClassMixedWithDSLHelpers do
99
217
  end
100
218
  end
101
219
 
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
220
+ describe '#run_script' do
221
+ it 'delegates to #run_script_on with the default host' do
222
+ subject.stub( :hosts ).and_return( hosts )
110
223
 
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
224
+ subject.should_receive( :run_script_on ).with( master, "/tmp/test.sh", {}).once
225
+
226
+ subject.run_script( '/tmp/test.sh' )
227
+ end
228
+ end
116
229
 
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' )
230
+ describe 'confine' do
231
+ let(:logger) { double.as_null_object }
232
+ before do
233
+ subject.stub( :logger ).and_return( logger )
234
+ end
123
235
 
124
- subject.confine( :to, {} )
125
- end
236
+ it 'skips the test if there are no applicable hosts' do
237
+ subject.stub( :hosts ).and_return( [] )
238
+ subject.stub( :hosts= )
239
+ logger.should_receive( :warn )
240
+ subject.should_receive( :skip_test ).
241
+ with( 'No suitable hosts found' )
126
242
 
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
243
+ subject.confine( :to, {} )
244
+ end
130
245
 
131
- expect {
132
- subject.confine( :regardless, {:thing => 'value'} )
133
- }.to raise_error( 'Unknown option regardless' )
134
- end
246
+ it 'raises when given mode is not :to or :except' do
247
+ subject.stub( :hosts )
248
+ subject.stub( :hosts= )
135
249
 
136
- it 'rejects hosts that do not meet simple hash criteria' do
137
- hosts = [ {'thing' => 'foo'}, {'thing' => 'bar'} ]
250
+ expect {
251
+ subject.confine( :regardless, {:thing => 'value'} )
252
+ }.to raise_error( 'Unknown option regardless' )
253
+ end
138
254
 
139
- subject.should_receive( :hosts ).and_return( hosts )
140
- subject.should_receive( :hosts= ).
141
- with( [ {'thing' => 'foo'} ] )
255
+ it 'rejects hosts that do not meet simple hash criteria' do
256
+ hosts = [ {'thing' => 'foo'}, {'thing' => 'bar'} ]
142
257
 
143
- subject.confine :to, :thing => 'foo'
144
- end
258
+ subject.should_receive( :hosts ).and_return( hosts )
259
+ subject.should_receive( :hosts= ).
260
+ with( [ {'thing' => 'foo'} ] )
145
261
 
146
- it 'rejects hosts that match a list of criteria' do
147
- hosts = [ {'thing' => 'foo'}, {'thing' => 'bar'}, {'thing' => 'baz'} ]
262
+ subject.confine :to, :thing => 'foo'
263
+ end
148
264
 
149
- subject.should_receive( :hosts ).and_return( hosts )
150
- subject.should_receive( :hosts= ).
151
- with( [ {'thing' => 'bar'} ] )
265
+ it 'rejects hosts that match a list of criteria' do
266
+ hosts = [ {'thing' => 'foo'}, {'thing' => 'bar'}, {'thing' => 'baz'} ]
152
267
 
153
- subject.confine :except, :thing => ['foo', 'baz']
154
- end
268
+ subject.should_receive( :hosts ).and_return( hosts )
269
+ subject.should_receive( :hosts= ).
270
+ with( [ {'thing' => 'bar'} ] )
155
271
 
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 ]
272
+ subject.confine :except, :thing => ['foo', 'baz']
273
+ end
163
274
 
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 )
275
+ it 'rejects hosts when a passed block returns true' do
276
+ host1 = {'platform' => 'solaris'}
277
+ host2 = {'platform' => 'solaris'}
278
+ host3 = {'platform' => 'windows'}
279
+ ret1 = (Struct.new('Result1', :stdout)).new(':global')
280
+ ret2 = (Struct.new('Result2', :stdout)).new('a_zone')
281
+ hosts = [ host1, host2, host3 ]
171
282
 
172
- subject.should_receive( :hosts= ).with( [ host1 ] )
283
+ subject.should_receive( :hosts ).and_return( hosts )
284
+ subject.should_receive( :on ).
285
+ with( host1, '/sbin/zonename' ).
286
+ and_return( ret1 )
287
+ subject.should_receive( :on ).
288
+ with( host1, '/sbin/zonename' ).
289
+ and_return( ret2 )
173
290
 
174
- subject.confine :to, :platform => 'solaris' do |host|
175
- subject.on( host, '/sbin/zonename' ).stdout =~ /:global/
176
- end
291
+ subject.should_receive( :hosts= ).with( [ host1 ] )
292
+
293
+ subject.confine :to, :platform => 'solaris' do |host|
294
+ subject.on( host, '/sbin/zonename' ).stdout =~ /:global/
177
295
  end
178
296
  end
297
+ end
179
298
 
180
299
  describe '#apply_manifest_on' do
181
300
  it 'allows acceptable exit codes through :catch_failures' do
@@ -196,11 +315,22 @@ describe ClassMixedWithDSLHelpers do
196
315
  end
197
316
  end
198
317
 
318
+ describe "#apply_manifest" do
319
+ it "delegates to #apply_manifest_on with the default host" do
320
+ subject.stub( :hosts ).and_return( hosts )
321
+
322
+ subject.should_receive( :apply_manifest_on ).with( master, 'manifest', {:opt => 'value'}).once
323
+
324
+ subject.apply_manifest( 'manifest', {:opt => 'value'} )
325
+
326
+ end
327
+ end
328
+
199
329
  describe '#stub_hosts_on' do
200
330
  it 'executes puppet on the host passed and ensures it is reverted' do
201
331
  logger = double.as_null_object
202
332
 
203
- subject.should_receive( :logger ).any_number_of_times.and_return( logger )
333
+ subject.stub( :logger ).and_return( logger )
204
334
  subject.should_receive( :on ).twice
205
335
  subject.should_receive( :teardown ).and_yield
206
336
  subject.should_receive( :puppet ).once.
@@ -216,6 +346,17 @@ describe ClassMixedWithDSLHelpers do
216
346
  end
217
347
  end
218
348
 
349
+ describe "#stub_hosts" do
350
+ it "delegates to #stub_hosts_on with the default host" do
351
+ subject.stub( :hosts ).and_return( hosts )
352
+
353
+ subject.should_receive( :stub_hosts_on ).with( master, 'ipspec' ).once
354
+
355
+ subject.stub_hosts( 'ipspec' )
356
+
357
+ end
358
+ end
359
+
219
360
  describe '#stub_forge_on' do
220
361
  it 'stubs forge.puppetlabs.com with the value of `forge`' do
221
362
  subject.should_receive( :forge ).and_return( 'my_forge.example.com' )
@@ -227,4 +368,298 @@ describe ClassMixedWithDSLHelpers do
227
368
  subject.stub_forge_on( 'my_host' )
228
369
  end
229
370
  end
371
+
372
+ describe "#stub_forge" do
373
+ it "delegates to #stub_forge_on with the default host" do
374
+ subject.stub( :hosts ).and_return( hosts )
375
+
376
+ subject.should_receive( :stub_forge_on ).with( master ).once
377
+
378
+ subject.stub_forge( )
379
+
380
+ end
381
+ end
382
+
383
+ describe "#stop_agent_on" do
384
+ let( :result_fail ) { Beaker::Result.new( [], "" ) }
385
+ let( :result_pass ) { Beaker::Result.new( [], "" ) }
386
+ before :each do
387
+ subject.stub( :sleep ).and_return( true )
388
+ result_fail.stdout = 'stdout'
389
+ result_fail.stderr = 'stderr'
390
+ result_fail.exit_code = 1
391
+ result_pass.stdout = 'stdout'
392
+ result_pass.stderr = 'stderr'
393
+ result_pass.exit_code = 0
394
+ end
395
+
396
+ it 'runs the correct command on solaris' do
397
+ vardir = '/var'
398
+ solaris_agent = make_host( 'solaris', :platform => 'solaris' )
399
+ solaris_agent.stub( :puppet ).and_return( { 'vardir' => vardir } )
400
+
401
+ subject.should_receive( :on ).with( solaris_agent, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_fail )
402
+ subject.should_receive( :on ).with( solaris_agent, '/usr/sbin/svcadm disable -s svc:/network/pe-puppet:default' ).once
403
+
404
+ subject.stop_agent_on( solaris_agent )
405
+
406
+ end
407
+
408
+ it 'runs the correct command on aix' do
409
+ vardir = '/var'
410
+ aix_agent = make_host( 'aix', :platform => 'aix' )
411
+ aix_agent.stub( :puppet ).and_return( { 'vardir' => vardir } )
412
+
413
+ subject.should_receive( :on ).with( aix_agent, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_fail )
414
+ subject.should_receive( :on ).with( aix_agent, '/usr/bin/stopsrc -s pe-puppet' ).once
415
+
416
+ subject.stop_agent_on( aix_agent )
417
+
418
+ end
419
+
420
+ it 'runs the correct command on windows' do
421
+ vardir = '/var'
422
+ win_agent = make_host( 'win', :platform => 'windows' )
423
+ win_agent.stub( :puppet ).and_return( { 'vardir' => vardir } )
424
+
425
+ subject.should_receive( :on ).with( win_agent, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_fail )
426
+ subject.should_receive( :on ).with( win_agent, 'net stop pe-puppet', :acceptable_exit_codes => [0,2] ).once
427
+
428
+ subject.stop_agent_on( win_agent )
429
+
430
+ end
431
+
432
+ it 'runs the pe-puppet on a unix system without pe-puppet-agent' do
433
+ vardir = '/var'
434
+ deb_agent = make_host( 'deb', :platform => 'debian-7-amd64' )
435
+ deb_agent.stub( :puppet ).and_return( { 'vardir' => vardir } )
436
+
437
+ subject.should_receive( :on ).with( deb_agent, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_fail )
438
+ subject.should_receive( :on ).with( deb_agent, "[ -e /etc/init.d/pe-puppet-agent ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_fail )
439
+ subject.should_receive( :on ).with( deb_agent, "/etc/init.d/pe-puppet stop" ).once
440
+
441
+ subject.stop_agent_on( deb_agent )
442
+
443
+ end
444
+
445
+ it 'runs the pe-puppet-agent on a unix system with pe-puppet-agent' do
446
+ vardir = '/var'
447
+ el_agent = make_host( 'el', :platform => 'el-5-x86_64' )
448
+ el_agent.stub( :puppet ).and_return( { 'vardir' => vardir } )
449
+
450
+ subject.should_receive( :on ).with( el_agent, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_fail )
451
+ subject.should_receive( :on ).with( el_agent, "[ -e /etc/init.d/pe-puppet-agent ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_pass )
452
+ subject.should_receive( :on ).with( el_agent, "/etc/init.d/pe-puppet-agent stop" ).once
453
+
454
+ subject.stop_agent_on( el_agent )
455
+ end
456
+
457
+ end
458
+
459
+ describe "#stop_agent" do
460
+ it 'delegates to #stop_agent_on with default host' do
461
+ subject.stub( :hosts ).and_return( hosts )
462
+
463
+ subject.should_receive( :stop_agent_on ).with( master ).once
464
+
465
+ subject.stop_agent( )
466
+
467
+ end
468
+ end
469
+
470
+ describe "#sign_certificate_for" do
471
+ it 'signs certs' do
472
+ subject.stub( :sleep ).and_return( true )
473
+
474
+ result.stdout = "+ \"#{agent}\""
475
+ subject.stub( :hosts ).and_return( hosts )
476
+
477
+ subject.stub( :puppet ) do |arg|
478
+ arg
479
+ end
480
+
481
+ subject.should_receive( :on ).with( master, "cert --sign --all", :acceptable_exit_codes => [0,24]).once
482
+ subject.should_receive( :on ).with( master, "cert --list --all").once.and_return( result )
483
+
484
+
485
+ subject.sign_certificate_for( agent )
486
+ end
487
+
488
+ it 'retries 11 times before quitting' do
489
+ subject.stub( :sleep ).and_return( true )
490
+
491
+ result.stdout = " \"#{agent}\""
492
+ subject.stub( :hosts ).and_return( hosts )
493
+
494
+ subject.stub( :puppet ) do |arg|
495
+ arg
496
+ end
497
+
498
+ subject.should_receive( :on ).with( master, "cert --sign --all", :acceptable_exit_codes => [0,24]).exactly( 11 ).times
499
+ subject.should_receive( :on ).with( master, "cert --list --all").exactly( 11 ).times.and_return( result )
500
+ subject.should_receive( :fail_test ).once
501
+
502
+ subject.sign_certificate_for( agent )
503
+ end
504
+
505
+ end
506
+
507
+ describe "#sign_certificate" do
508
+ it 'delegates to #sign_certificate_for with the default host' do
509
+ subject.stub( :hosts ).and_return( hosts )
510
+
511
+ subject.should_receive( :sign_certificate_for ).with( master ).once
512
+
513
+ subject.sign_certificate( )
514
+ end
515
+ end
516
+
517
+ describe '#with_puppet_running_on' do
518
+ let(:is_pe) { false }
519
+ let(:host) { FakeHost.new(:pe => is_pe) }
520
+ let(:test_case_path) { 'testcase/path' }
521
+ let(:tmpdir_path) { '/tmp/tmpdir' }
522
+ let(:puppet_path) { '/puppet/path' }
523
+
524
+ def stub_host_and_subject_to_allow_the_default_testdir_argument_to_be_created
525
+ subject.instance_variable_set(:@path, test_case_path)
526
+ host.stub(:tmpdir).and_return(tmpdir_path)
527
+ end
528
+
529
+ before do
530
+ stub_host_and_subject_to_allow_the_default_testdir_argument_to_be_created
531
+ host.stub(:[]).and_return(puppet_path)
532
+ end
533
+
534
+ it "raises an ArgumentError if you try to submit a String instead of a Hash of options" do
535
+ expect { subject.with_puppet_running_on(host, '--foo --bar') }.to raise_error(ArgumentError, /conf_opts must be a Hash. You provided a String: '--foo --bar'/)
536
+ end
537
+
538
+ describe "with valid arguments" do
539
+ before do
540
+ Tempfile.should_receive(:open).with('beaker')
541
+ end
542
+
543
+ context 'as pe' do
544
+ let(:is_pe) { true }
545
+
546
+ it 'bounces puppet twice' do
547
+ subject.with_puppet_running_on(host, {})
548
+ expect(host).to execute_commands_matching(/pe-httpd restart/).exactly(2).times
549
+ end
550
+
551
+ it 'yield to a block after bouncing service' do
552
+ execution = 0
553
+ expect do
554
+ subject.with_puppet_running_on(host, {}) do
555
+ expect(host).to execute_commands_matching(/pe-httpd restart/).once
556
+ execution += 1
557
+ end
558
+ end.to change { execution }.by(1)
559
+ expect(host).to execute_commands_matching(/pe-httpd restart/).exactly(2).times
560
+ end
561
+ end
562
+
563
+ context 'running from source' do
564
+
565
+ it 'does not try to stop if not started' do
566
+ subject.should_receive(:start_puppet_from_source_on!).and_return false
567
+ subject.should_not_receive(:stop_puppet_from_source_on)
568
+
569
+ subject.with_puppet_running_on(host, {})
570
+ end
571
+
572
+ context 'successfully' do
573
+ before do
574
+ host.should_receive(:port_open?).with(8140).and_return(true)
575
+ end
576
+
577
+ it 'starts puppet from source' do
578
+ subject.with_puppet_running_on(host, {})
579
+ end
580
+
581
+ it 'stops puppet from source' do
582
+ subject.with_puppet_running_on(host, {})
583
+ expect(host).to execute_commands_matching(/^kill [^-]/).once
584
+ expect(host).to execute_commands_matching(/^kill -0/).once
585
+ end
586
+
587
+ it 'yields between starting and stopping' do
588
+ execution = 0
589
+ expect do
590
+ subject.with_puppet_running_on(host, {}) do
591
+ expect(host).to execute_commands_matching(/^puppet master/).once
592
+ execution += 1
593
+ end
594
+ end.to change { execution }.by(1)
595
+ expect(host).to execute_commands_matching(/^kill [^-]/).once
596
+ expect(host).to execute_commands_matching(/^kill -0/).once
597
+ end
598
+
599
+ it 'passes on commandline args' do
600
+ subject.with_puppet_running_on(host, {:__commandline_args__ => '--with arg'})
601
+ expect(host).to execute_commands_matching(/^puppet master --with arg/).once
602
+ end
603
+ end
604
+ end
605
+
606
+ describe 'backup and restore of puppet.conf' do
607
+ let(:original_location) { "#{puppet_path}/puppet.conf" }
608
+ let(:backup_location) { "#{tmpdir_path}/puppet.conf.bak" }
609
+ let(:new_location) { "#{tmpdir_path}/puppet.conf" }
610
+
611
+ before do
612
+ host.should_receive(:port_open?).with(8140).and_return(true)
613
+ end
614
+
615
+ it 'backs up puppet.conf' do
616
+ subject.with_puppet_running_on(host, {})
617
+ expect(host).to execute_commands_matching(/cp #{original_location} #{backup_location}/).once
618
+ expect(host).to execute_commands_matching(/cat #{new_location} > #{original_location}/).once
619
+
620
+ end
621
+
622
+ it 'restores puppet.conf' do
623
+ subject.with_puppet_running_on(host, {})
624
+ expect(host).to execute_commands_matching(/cat '#{backup_location}' > '#{original_location}'/).once
625
+ end
626
+ end
627
+
628
+ describe 'handling failures' do
629
+ before do
630
+ subject.should_receive(:stop_puppet_from_source_on).and_raise(RuntimeError.new('Also failed in teardown.'))
631
+ end
632
+
633
+ it 'does not swallow an exception raised from within test block if ensure block also fails' do
634
+ host.should_receive(:port_open?).with(8140).and_return(true)
635
+
636
+ subject.logger.should_receive(:error).with(/Raised during attempt to teardown.*Also failed in teardown/)
637
+
638
+ expect do
639
+ subject.with_puppet_running_on(host, {}) { raise 'Failed while yielding.' }
640
+ end.to raise_error(RuntimeError, /failed.*because.*Failed while yielding./)
641
+ end
642
+
643
+ it 'does not swallow a teardown exception if no earlier exception was raised' do
644
+ host.should_receive(:port_open?).with(8140).and_return(true)
645
+ subject.logger.should_not_receive(:error)
646
+ expect do
647
+ subject.with_puppet_running_on(host, {})
648
+ end.to raise_error(RuntimeError, 'Also failed in teardown.')
649
+ end
650
+ end
651
+ end
652
+ end
653
+
654
+ describe '#with_puppet_running' do
655
+ it 'delegates to #with_puppet_running_on with the default host' do
656
+ subject.stub( :hosts ).and_return( hosts )
657
+
658
+ subject.should_receive( :with_puppet_running_on ).with( master, {:opt => 'value'}, '/dir').once
659
+
660
+ subject.with_puppet_running( {:opt => 'value'}, '/dir' )
661
+
662
+
663
+ end
664
+ end
230
665
  end