beaker 0.0.0 → 1.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 (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