beaker-puppet 0.1.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 (52) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +25 -0
  3. data/.simplecov +9 -0
  4. data/Gemfile +25 -0
  5. data/HISTORY.md +8 -0
  6. data/LICENSE +202 -0
  7. data/README.md +55 -0
  8. data/Rakefile +299 -0
  9. data/acceptance/config/acceptance-options.rb +6 -0
  10. data/acceptance/config/gem/acceptance-options.rb +9 -0
  11. data/acceptance/config/git/acceptance-options.rb +9 -0
  12. data/acceptance/config/nodes/vagrant-ubuntu-1404.yml +8 -0
  13. data/acceptance/config/pkg/acceptance-options.rb +8 -0
  14. data/acceptance/lib/beaker/acceptance/install_utils.rb +58 -0
  15. data/acceptance/pre_suite/gem/install.rb +8 -0
  16. data/acceptance/pre_suite/git/install.rb +97 -0
  17. data/acceptance/pre_suite/pkg/install.rb +9 -0
  18. data/acceptance/tests/README.md +3 -0
  19. data/acceptance/tests/backwards_compatible.rb +19 -0
  20. data/acceptance/tests/install_smoke_test.rb +21 -0
  21. data/acceptance/tests/stub_host.rb +47 -0
  22. data/acceptance/tests/web_helpers_test.rb +54 -0
  23. data/acceptance/tests/with_puppet_running_on.rb +26 -0
  24. data/beaker-puppet.gemspec +38 -0
  25. data/bin/beaker-puppet +32 -0
  26. data/lib/beaker-puppet.rb +46 -0
  27. data/lib/beaker-puppet/helpers/facter_helpers.rb +57 -0
  28. data/lib/beaker-puppet/helpers/puppet_helpers.rb +865 -0
  29. data/lib/beaker-puppet/helpers/tk_helpers.rb +89 -0
  30. data/lib/beaker-puppet/install_utils/aio_defaults.rb +93 -0
  31. data/lib/beaker-puppet/install_utils/ezbake_utils.rb +256 -0
  32. data/lib/beaker-puppet/install_utils/foss_defaults.rb +211 -0
  33. data/lib/beaker-puppet/install_utils/foss_utils.rb +1309 -0
  34. data/lib/beaker-puppet/install_utils/module_utils.rb +244 -0
  35. data/lib/beaker-puppet/install_utils/puppet_utils.rb +157 -0
  36. data/lib/beaker-puppet/version.rb +3 -0
  37. data/lib/beaker-puppet/wrappers.rb +93 -0
  38. data/lib/beaker/dsl/helpers/facter_helpers.rb +1 -0
  39. data/lib/beaker/dsl/helpers/puppet_helpers.rb +1 -0
  40. data/lib/beaker/dsl/helpers/tk_helpers.rb +1 -0
  41. data/lib/beaker/dsl/install_utils/aio_defaults.rb +1 -0
  42. data/lib/beaker/dsl/install_utils/ezbake_utils.rb +1 -0
  43. data/lib/beaker/dsl/install_utils/foss_defaults.rb +1 -0
  44. data/lib/beaker/dsl/install_utils/foss_utils.rb +1 -0
  45. data/lib/beaker/dsl/install_utils/module_utils.rb +1 -0
  46. data/lib/beaker/dsl/install_utils/puppet_utils.rb +1 -0
  47. data/spec/beaker-puppet/helpers/facter_helpers_spec.rb +64 -0
  48. data/spec/beaker-puppet/helpers/puppet_helpers_spec.rb +1287 -0
  49. data/spec/beaker-puppet/helpers/tk_helpers_spec.rb +86 -0
  50. data/spec/helpers.rb +109 -0
  51. data/spec/spec_helper.rb +23 -0
  52. metadata +249 -0
@@ -0,0 +1 @@
1
+ require 'beaker-puppet'
@@ -0,0 +1 @@
1
+ require 'beaker-puppet'
@@ -0,0 +1 @@
1
+ require 'beaker-puppet'
@@ -0,0 +1 @@
1
+ require 'beaker-puppet'
@@ -0,0 +1 @@
1
+ require 'beaker-puppet'
@@ -0,0 +1 @@
1
+ require 'beaker-puppet'
@@ -0,0 +1 @@
1
+ require 'beaker-puppet'
@@ -0,0 +1 @@
1
+ require 'beaker-puppet'
@@ -0,0 +1 @@
1
+ require 'beaker-puppet'
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ class ClassMixedWithDSLHelpers
4
+ include Beaker::DSL::Helpers
5
+ include Beaker::DSL::Wrappers
6
+ include Beaker::DSL::Roles
7
+ include Beaker::DSL::Patterns
8
+ # include Beaker::DSL::Helpers::FacterHelpers
9
+ # include Beaker::DSL::Wrappers
10
+ # include BeakerTestHelpers
11
+
12
+ def logger
13
+ RSpec::Mocks::Double.new('logger').as_null_object
14
+ end
15
+
16
+ end
17
+
18
+ describe ClassMixedWithDSLHelpers do
19
+ let( :command ){ 'ls' }
20
+ let( :host ) { double.as_null_object }
21
+ let( :result ) { Beaker::Result.new( host, command ) }
22
+
23
+ let( :master ) { make_host( 'master', :roles => %w( master agent default) ) }
24
+ let( :agent ) { make_host( 'agent', :roles => %w( agent ) ) }
25
+ let( :custom ) { make_host( 'custom', :roles => %w( custom agent ) ) }
26
+ let( :dash ) { make_host( 'console', :roles => %w( dashboard agent ) ) }
27
+ let( :db ) { make_host( 'db', :roles => %w( database agent ) ) }
28
+ let( :hosts ) { [ master, agent, dash, db, custom ] }
29
+
30
+ before :each do
31
+ allow( subject ).to receive( :hosts ).and_return( hosts )
32
+ end
33
+
34
+ describe '#fact_on' do
35
+ it 'retrieves a fact on a single host' do
36
+ result.stdout = "family\n"
37
+ expect( subject ).to receive(:facter).with('osfamily',{}).once
38
+ expect( subject ).to receive(:on).and_return(result)
39
+
40
+ expect( subject.fact_on('host','osfamily') ).to be === result.stdout.chomp
41
+ end
42
+
43
+ it 'chomps correctly when it receives an array of results from #on' do
44
+ result.stdout = "family\n"
45
+ times = hosts.length
46
+ results_array = [result] * times
47
+ chomped_array = [result.stdout.chomp] * times
48
+ allow( subject ).to receive( :on ).and_return( results_array )
49
+
50
+ expect( subject.fact_on(hosts,'osfamily') ).to be === chomped_array
51
+
52
+ end
53
+ end
54
+
55
+ describe '#fact' do
56
+ it 'delegates to #fact_on with the default host' do
57
+ expect( subject ).to receive(:fact_on).with(anything,"osfamily",{}).once
58
+ expect( subject ).to receive(:default)
59
+
60
+ subject.fact('osfamily')
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,1287 @@
1
+ require 'spec_helper'
2
+
3
+ class ClassMixedWithDSLHelpers
4
+ include Beaker::DSL::Helpers
5
+ include Beaker::DSL::Wrappers
6
+ include Beaker::DSL::Roles
7
+ include Beaker::DSL::Patterns
8
+ include Beaker::DSL::Outcomes
9
+ include Beaker::DSL::Helpers::PuppetHelpers
10
+ # include Beaker::DSL::Wrappers
11
+ # include BeakerTestHelpers
12
+
13
+ def logger
14
+ RSpec::Mocks::Double.new('logger').as_null_object
15
+ end
16
+
17
+ end
18
+
19
+ describe ClassMixedWithDSLHelpers do
20
+ let( :opts ) { Beaker::Options::Presets.env_vars }
21
+ let( :command ){ 'ls' }
22
+ let( :host ) { double.as_null_object }
23
+ let( :result ) { Beaker::Result.new( host, command ) }
24
+
25
+ let( :master ) { make_host( 'master', :roles => %w( master agent default) ) }
26
+ let( :agent ) { make_host( 'agent', :roles => %w( agent ) ) }
27
+ let( :custom ) { make_host( 'custom', :roles => %w( custom agent ) ) }
28
+ let( :dash ) { make_host( 'console', :roles => %w( dashboard agent ) ) }
29
+ let( :db ) { make_host( 'db', :roles => %w( database agent ) ) }
30
+ let( :hosts ) { [ master, agent, dash, db, custom ] }
31
+
32
+
33
+ describe '#create_tmpdir_for_user' do
34
+ let(:host) { {} }
35
+ let(:result) { double.as_null_object }
36
+
37
+ before :each do
38
+ allow(host).to receive(:result).and_return(result)
39
+ allow(result).to receive(:exit_code).and_return(0)
40
+ allow(result).to receive(:stdout).and_return('puppet')
41
+ end
42
+
43
+ context 'with no user argument' do
44
+
45
+ context 'with no path name argument' do
46
+ context 'without puppet installed on host' do
47
+ it 'raises an error' do
48
+ cmd = "the command"
49
+ allow(result).to receive(:exit_code).and_return(1)
50
+ expect(Beaker::Command).to receive(:new).with(/puppet master --configprint user/, [], {"ENV"=>{}, :cmdexe=>true}).and_return(cmd)
51
+ expect(subject).to receive(:on).with(host, cmd).and_return(result)
52
+ expect{
53
+ subject.create_tmpdir_for_user host
54
+ }.to raise_error(RuntimeError, /`puppet master --configprint` failed,/)
55
+ end
56
+ end
57
+ context 'with puppet installed on host' do
58
+ it 'executes chown once' do
59
+ cmd = "the command"
60
+ expect(Beaker::Command).to receive(:new).with(/puppet master --configprint user/, [], {"ENV"=>{}, :cmdexe=>true}).and_return(cmd)
61
+ expect(subject).to receive(:on).with(host, cmd).and_return(result)
62
+ expect(subject).to receive(:create_tmpdir_on).with(host, /\/tmp\/beaker/, /puppet/)
63
+ subject.create_tmpdir_for_user(host)
64
+ end
65
+ end
66
+ end
67
+
68
+ context 'with path name argument' do
69
+ it 'executes chown once' do
70
+ cmd = "the command"
71
+ expect(Beaker::Command).to receive(:new).with(/puppet master --configprint user/, [], {"ENV"=>{}, :cmdexe=>true}).and_return(cmd)
72
+ expect(subject).to receive(:on).with(host, cmd).and_return(result)
73
+ expect(subject).to receive(:create_tmpdir_on).with(host, /\/tmp\/bogus/, /puppet/)
74
+ subject.create_tmpdir_for_user(host, "/tmp/bogus")
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+
83
+ describe '#apply_manifest_on' do
84
+
85
+ before :each do
86
+ hosts.each do |host|
87
+ allow( host ).to receive( :tmpfile )
88
+ end
89
+ end
90
+
91
+ it 'calls puppet' do
92
+ allow( subject ).to receive( :hosts ).and_return( hosts )
93
+ expect( subject ).to receive( :create_remote_file ).and_return( true )
94
+ expect( subject ).to receive( :puppet ).
95
+ # with( 'apply', '--verbose', 'agent' ).
96
+ and_return( 'puppet_command' )
97
+
98
+ expect( subject ).to receive( :on ).
99
+ with( agent, 'puppet_command',
100
+ :acceptable_exit_codes => [0] )
101
+
102
+ subject.apply_manifest_on( agent, 'class { "boo": }')
103
+ end
104
+
105
+ it 'operates on an array of hosts' do
106
+ allow( subject ).to receive( :hosts ).and_return( hosts )
107
+ the_hosts = [master, agent]
108
+
109
+ expect( subject ).to receive( :create_remote_file ).twice.and_return( true )
110
+ the_hosts.each do |host|
111
+ expect( subject ).to receive( :puppet ).
112
+ and_return( 'puppet_command' )
113
+
114
+ expect( subject ).to receive( :on ).
115
+ with( host, 'puppet_command', :acceptable_exit_codes => [0] )
116
+ end
117
+
118
+ result = subject.apply_manifest_on( the_hosts, 'include foobar' )
119
+ expect(result).to be_an(Array)
120
+ end
121
+
122
+ it 'operates on an array of hosts' do
123
+ InParallel::InParallelExecutor.logger = logger
124
+ FakeFS.deactivate!
125
+ # This will only get hit if forking processes is supported and at least 2 items are being submitted to run in parallel
126
+ # expect( InParallel::InParallelExecutor ).to receive(:_execute_in_parallel).with(any_args).and_call_original.exactly(2).times
127
+ allow( subject ).to receive( :hosts ).and_return( hosts )
128
+ the_hosts = [master, agent]
129
+
130
+ allow( subject ).to receive( :create_remote_file ).and_return( true )
131
+ allow( subject ).to receive( :puppet ).
132
+ and_return( 'puppet_command' )
133
+ the_hosts.each do |host|
134
+ allow( subject ).to receive( :on ).
135
+ with( host, 'puppet_command', :acceptable_exit_codes => [0] )
136
+ end
137
+
138
+ result = nil
139
+ result = subject.apply_manifest_on( the_hosts, 'include foobar' )
140
+ expect(result).to be_an(Array)
141
+ end
142
+
143
+ it 'runs block_on in parallel if set' do
144
+ InParallel::InParallelExecutor.logger = logger
145
+ FakeFS.deactivate!
146
+ allow( subject ).to receive( :hosts ).and_return( hosts )
147
+ the_hosts = [master, agent]
148
+
149
+ allow( subject ).to receive( :create_remote_file ).and_return( true )
150
+ allow( subject ).to receive( :puppet ).
151
+ and_return( 'puppet_command' )
152
+ the_hosts.each do |host|
153
+ allow( subject ).to receive( :on ).
154
+ with( host, 'puppet_command', :acceptable_exit_codes => [0] )
155
+ end
156
+ expect( subject ).to receive( :block_on ).with(
157
+ anything,
158
+ :run_in_parallel => true
159
+ )
160
+
161
+ subject.apply_manifest_on( the_hosts, 'include foobar', { :run_in_parallel => true } )
162
+ end
163
+
164
+ it 'adds acceptable exit codes with :catch_failures' do
165
+ allow( subject ).to receive( :hosts ).and_return( hosts )
166
+ expect( subject ).to receive( :create_remote_file ).and_return( true )
167
+ expect( subject ).to receive( :puppet ).
168
+ and_return( 'puppet_command' )
169
+
170
+ expect( subject ).to receive( :on ).
171
+ with( agent, 'puppet_command',
172
+ :acceptable_exit_codes => [0,2] )
173
+
174
+ subject.apply_manifest_on( agent,
175
+ 'class { "boo": }',
176
+ :catch_failures => true )
177
+ end
178
+ it 'allows acceptable exit codes through :catch_failures' do
179
+ allow( subject ).to receive( :hosts ).and_return( hosts )
180
+ expect( subject ).to receive( :create_remote_file ).and_return( true )
181
+ expect( subject ).to receive( :puppet ).
182
+ and_return( 'puppet_command' )
183
+
184
+ expect( subject ).to receive( :on ).
185
+ with( agent, 'puppet_command',
186
+ :acceptable_exit_codes => [4,0,2] )
187
+
188
+ subject.apply_manifest_on( agent,
189
+ 'class { "boo": }',
190
+ :acceptable_exit_codes => [4],
191
+ :catch_failures => true )
192
+ end
193
+ it 'enforces a 0 exit code through :catch_changes' do
194
+ allow( subject ).to receive( :hosts ).and_return( hosts )
195
+ expect( subject ).to receive( :create_remote_file ).and_return( true )
196
+ expect( subject ).to receive( :puppet ).
197
+ and_return( 'puppet_command' )
198
+
199
+ expect( subject ).to receive( :on ).with(
200
+ agent,
201
+ 'puppet_command',
202
+ :acceptable_exit_codes => [0]
203
+ )
204
+
205
+ subject.apply_manifest_on(
206
+ agent,
207
+ 'class { "boo": }',
208
+ :catch_changes => true
209
+ )
210
+ end
211
+ it 'enforces a 2 exit code through :expect_changes' do
212
+ allow( subject ).to receive( :hosts ).and_return( hosts )
213
+ expect( subject ).to receive( :create_remote_file ).and_return( true )
214
+ expect( subject ).to receive( :puppet ).
215
+ and_return( 'puppet_command' )
216
+
217
+ expect( subject ).to receive( :on ).with(
218
+ agent,
219
+ 'puppet_command',
220
+ :acceptable_exit_codes => [2]
221
+ )
222
+
223
+ subject.apply_manifest_on(
224
+ agent,
225
+ 'class { "boo": }',
226
+ :expect_changes => true
227
+ )
228
+ end
229
+ it 'enforces exit codes through :expect_failures' do
230
+ allow( subject ).to receive( :hosts ).and_return( hosts )
231
+ expect( subject ).to receive( :create_remote_file ).and_return( true )
232
+ expect( subject ).to receive( :puppet ).
233
+ and_return( 'puppet_command' )
234
+
235
+ expect( subject ).to receive( :on ).with(
236
+ agent,
237
+ 'puppet_command',
238
+ :acceptable_exit_codes => [1,4,6]
239
+ )
240
+
241
+ subject.apply_manifest_on(
242
+ agent,
243
+ 'class { "boo": }',
244
+ :expect_failures => true
245
+ )
246
+ end
247
+ it 'enforces exit codes through :expect_failures' do
248
+ allow( subject ).to receive( :hosts ).and_return( hosts )
249
+ expect {
250
+ subject.apply_manifest_on(
251
+ agent,
252
+ 'class { "boo": }',
253
+ :expect_failures => true,
254
+ :catch_failures => true
255
+ )
256
+ }.to raise_error ArgumentError, /catch_failures.+expect_failures/
257
+ end
258
+ it 'enforces added exit codes through :expect_failures' do
259
+ allow( subject ).to receive( :hosts ).and_return( hosts )
260
+ expect( subject ).to receive( :create_remote_file ).and_return( true )
261
+ expect( subject ).to receive( :puppet ).
262
+ and_return( 'puppet_command' )
263
+
264
+ expect( subject ).to receive( :on ).with(
265
+ agent,
266
+ 'puppet_command',
267
+ :acceptable_exit_codes => [1,2,3,4,5,6]
268
+ )
269
+
270
+ subject.apply_manifest_on(
271
+ agent,
272
+ 'class { "boo": }',
273
+ :acceptable_exit_codes => (1..5),
274
+ :expect_failures => true
275
+ )
276
+ end
277
+
278
+ it 'can set the --parser future flag' do
279
+ allow( subject ).to receive( :hosts ).and_return( hosts )
280
+ expect( subject ).to receive( :create_remote_file ).and_return( true )
281
+
282
+ expect( subject ).to receive( :puppet ).with(
283
+ 'apply',
284
+ anything,
285
+ include(
286
+ :parser => 'future',
287
+ 'detailed-exitcodes' => nil,
288
+ :verbose => nil
289
+ )
290
+ )
291
+
292
+ allow( subject ).to receive( :on )
293
+ hosts.each do |host|
294
+ allow( host ).to receive( :tmpfile ).and_return( 'pants' )
295
+ end
296
+
297
+ subject.apply_manifest_on(
298
+ agent,
299
+ 'class { "boo": }',
300
+ :acceptable_exit_codes => (1..5),
301
+ :future_parser => true,
302
+ :expect_failures => true
303
+ )
304
+ end
305
+
306
+ it 'can set the --noops flag' do
307
+ allow( subject ).to receive( :hosts ).and_return( hosts )
308
+ expect( subject ).to receive( :create_remote_file ).and_return( true )
309
+
310
+ expect( subject ).to receive( :puppet ).with(
311
+ 'apply',
312
+ anything,
313
+ include(
314
+ :noop => nil,
315
+ 'detailed-exitcodes' => nil,
316
+ :verbose => nil
317
+ )
318
+ )
319
+
320
+ allow( subject ).to receive( :on )
321
+ hosts.each do |host|
322
+ allow( host ).to receive( :tmpfile ).and_return( 'pants' )
323
+ end
324
+
325
+ subject.apply_manifest_on(
326
+ agent,
327
+ 'class { "boo": }',
328
+ :acceptable_exit_codes => (1..5),
329
+ :noop => true,
330
+ :expect_failures => true
331
+ )
332
+ end
333
+ end
334
+
335
+ it 'can set the --debug flag' do
336
+ allow( subject ).to receive( :hosts ).and_return( hosts )
337
+ allow( subject ).to receive( :create_remote_file ).and_return( true )
338
+ allow( agent ).to receive( :tmpfile )
339
+ allow( subject ).to receive( :on )
340
+
341
+ expect( subject ).to receive( :puppet ).with(
342
+ 'apply',
343
+ anything,
344
+ include( :debug => nil )
345
+ )
346
+
347
+ subject.apply_manifest_on(
348
+ agent,
349
+ 'class { "boo": }',
350
+ :debug => true,
351
+ )
352
+ end
353
+
354
+ describe "#apply_manifest" do
355
+ it "delegates to #apply_manifest_on with the default host" do
356
+ allow( subject ).to receive( :hosts ).and_return( hosts )
357
+ # allow( subject ).to receive( :default ).and_return( master )
358
+
359
+ expect( subject ).to receive( :default ).and_return( master )
360
+ expect( subject ).to receive( :apply_manifest_on ).with( master, 'manifest', {:opt => 'value'}).once
361
+
362
+ subject.apply_manifest( 'manifest', {:opt => 'value'} )
363
+
364
+ end
365
+ end
366
+
367
+ describe '#stub_hosts_on' do
368
+ it 'executes puppet on the host passed and ensures it is reverted' do
369
+ test_host = make_host('my_host', {})
370
+ allow( subject ).to receive( :hosts ).and_return( hosts )
371
+ logger = double.as_null_object
372
+
373
+ expect( subject ).to receive( :on ).once
374
+ allow( subject ).to receive( :logger ).and_return( logger )
375
+ expect( subject ).to receive( :teardown ).and_yield
376
+ manifest =<<-EOS.gsub /^\s+/, ""
377
+ host { 'puppetlabs.com':
378
+ \tensure => present,
379
+ \tip => '127.0.0.1',
380
+ \thost_aliases => [],
381
+ }
382
+ EOS
383
+ expect( subject ).to receive( :apply_manifest_on ).once.
384
+ with( test_host, manifest )
385
+ expect( subject ).to receive( :puppet ).once.
386
+ with( 'resource', 'host',
387
+ 'puppetlabs.com',
388
+ 'ensure=absent' )
389
+
390
+ subject.stub_hosts_on( test_host, {'puppetlabs.com' => '127.0.0.1'} )
391
+ end
392
+ it 'adds aliases to defined hostname' do
393
+ test_host = make_host('my_host', {})
394
+ allow( subject ).to receive( :hosts ).and_return( hosts )
395
+ logger = double.as_null_object
396
+
397
+ expect( subject ).to receive( :on ).once
398
+ allow( subject ).to receive( :logger ).and_return( logger )
399
+ expect( subject ).to receive( :teardown ).and_yield
400
+ manifest =<<-EOS.gsub /^\s+/, ""
401
+ host { 'puppetlabs.com':
402
+ \tensure => present,
403
+ \tip => '127.0.0.1',
404
+ \thost_aliases => [\"foo\", \"bar\"],
405
+ }
406
+ EOS
407
+ expect( subject ).to receive( :apply_manifest_on ).once.
408
+ with( test_host, manifest )
409
+
410
+ subject.stub_hosts_on( test_host, {'puppetlabs.com' => '127.0.0.1'}, {'puppetlabs.com' => ['foo','bar']} )
411
+ end
412
+ end
413
+
414
+ describe "#stub_hosts" do
415
+ it "delegates to stub_hosts_on with the default host" do
416
+ allow( subject ).to receive( :hosts ).and_return( hosts )
417
+
418
+ expect( subject ).to receive( :default ).and_return( master )
419
+ expect( subject ).to receive( :stub_hosts_on ).with( master, 'ipspec' ).once
420
+
421
+ subject.stub_hosts( 'ipspec' )
422
+
423
+ end
424
+ end
425
+
426
+ describe '#stub_forge_on' do
427
+ it 'stubs forge.puppetlabs.com with the value of `forge`' do
428
+ allow( subject ).to receive( :resolve_hostname_on ).and_return ( '127.0.0.1' )
429
+ host = make_host('my_host', {})
430
+ expect( subject ).to receive( :stub_hosts_on ).
431
+ with( host, {'forge.puppetlabs.com' => '127.0.0.1'}, {'forge.puppetlabs.com' => ['forge.puppet.com','forgeapi.puppetlabs.com','forgeapi.puppet.com']} )
432
+
433
+ subject.stub_forge_on( host, 'my_forge.example.com' )
434
+ end
435
+ end
436
+
437
+ describe "#stub_forge" do
438
+ it "delegates to stub_forge_on with the default host" do
439
+ allow( subject ).to receive( :options ).and_return( {} )
440
+ allow( subject ).to receive( :hosts ).and_return( hosts )
441
+
442
+ expect( subject ).to receive( :default ).and_return( master )
443
+ expect( subject ).to receive( :stub_forge_on ).with( master, nil ).once
444
+
445
+ subject.stub_forge( )
446
+
447
+ end
448
+ end
449
+
450
+ describe "#stop_agent_on" do
451
+ let( :result_fail ) { Beaker::Result.new( [], "" ) }
452
+ let( :result_pass ) { Beaker::Result.new( [], "" ) }
453
+ before :each do
454
+ allow( subject ).to receive( :sleep ).and_return( true )
455
+ end
456
+
457
+ it 'runs the pe-puppet on a system without pe-puppet-agent' do
458
+ vardir = '/var'
459
+ deb_agent = make_host( 'deb', :platform => 'debian-7-amd64', :pe_ver => '3.7' )
460
+ allow( deb_agent ).to receive( :puppet_configprint ).and_return( { 'vardir' => vardir } )
461
+
462
+ expect( deb_agent ).to receive( :file_exist? ).with("/var/state/agent_catalog_run.lock").and_return(false)
463
+ expect( deb_agent ).to receive( :file_exist? ).with("/etc/init.d/pe-puppet-agent").and_return(false)
464
+
465
+ expect( subject ).to receive( :aio_version? ).with( deb_agent ).and_return( false )
466
+ expect( subject ).to receive( :version_is_less ).with( deb_agent[:pe_ver], '3.2' ).and_return( false )
467
+ expect( subject ).to receive( :puppet_resource ).with( "service", "pe-puppet", "ensure=stopped").once
468
+ expect( subject ).to receive( :on ).once
469
+
470
+ subject.stop_agent_on( deb_agent )
471
+
472
+ end
473
+
474
+ it 'runs the pe-puppet-agent on a unix system with pe-puppet-agent' do
475
+ vardir = '/var'
476
+ el_agent = make_host( 'el', :platform => 'el-5-x86_64', :pe_ver => '3.7' )
477
+ allow( el_agent ).to receive( :puppet_configprint ).and_return( { 'vardir' => vardir } )
478
+
479
+ expect( el_agent ).to receive( :file_exist? ).with("/var/state/agent_catalog_run.lock").and_return(false)
480
+ expect( el_agent ).to receive( :file_exist? ).with("/etc/init.d/pe-puppet-agent").and_return(true)
481
+
482
+ expect( subject ).to receive( :aio_version? ).with( el_agent ).and_return( false )
483
+ expect( subject ).to receive( :version_is_less ).with( el_agent[:pe_ver], '3.2' ).and_return( false )
484
+ expect( subject ).to receive( :puppet_resource ).with( "service", "pe-puppet-agent", "ensure=stopped").once
485
+ expect( subject ).to receive( :on ).once
486
+
487
+ subject.stop_agent_on( el_agent )
488
+ end
489
+
490
+ it 'runs puppet on a unix system 4.0 or newer' do
491
+ vardir = '/var'
492
+ el_agent = make_host( 'el', :platform => 'el-5-x86_64', :pe_ver => '4.0' )
493
+ allow( el_agent ).to receive( :puppet_configprint ).and_return( { 'vardir' => vardir } )
494
+
495
+ expect( el_agent ).to receive( :file_exist? ).with("/var/state/agent_catalog_run.lock").and_return(false)
496
+
497
+ expect( subject ).to receive( :aio_version? ).with( el_agent ).and_return( true )
498
+ expect( subject ).to receive( :version_is_less ).with( el_agent[:pe_ver], '3.2' ).and_return( false )
499
+ expect( subject ).to receive( :puppet_resource ).with( "service", "puppet", "ensure=stopped").once
500
+ expect( subject ).to receive( :on ).once
501
+
502
+ subject.stop_agent_on( el_agent )
503
+ end
504
+
505
+ it 'can run on an array of hosts' do
506
+ vardir = '/var'
507
+ el_agent = make_host( 'el', :platform => 'el-5-x86_64', :pe_ver => '4.0' )
508
+ el_agent2 = make_host( 'el', :platform => 'el-5-x86_64', :pe_ver => '4.0' )
509
+
510
+ allow( el_agent ).to receive( :puppet_configprint ).and_return( { 'vardir' => vardir } )
511
+ expect( el_agent ).to receive( :file_exist? ).with("/var/state/agent_catalog_run.lock").and_return(false)
512
+ expect( subject ).to receive( :aio_version? ).with( el_agent ).and_return( true )
513
+ expect( subject ).to receive( :version_is_less ).with( el_agent[:pe_ver], '3.2' ).and_return( false )
514
+
515
+ allow( el_agent2 ).to receive( :puppet_configprint ).and_return( { 'vardir' => vardir } )
516
+ expect( el_agent2 ).to receive( :file_exist? ).with("/var/state/agent_catalog_run.lock").and_return(false)
517
+ expect( subject ).to receive( :aio_version? ).with( el_agent2 ).and_return( true )
518
+ expect( subject ).to receive( :version_is_less ).with( el_agent2[:pe_ver], '3.2' ).and_return( false )
519
+
520
+ expect( subject ).to receive( :puppet_resource ).with( "service", "puppet", "ensure=stopped").twice
521
+ expect( subject ).to receive( :on ).twice
522
+
523
+ subject.stop_agent_on( [el_agent, el_agent2] )
524
+ end
525
+
526
+ it 'runs in parallel with run_in_parallel=true' do
527
+ InParallel::InParallelExecutor.logger = logger
528
+ FakeFS.deactivate!
529
+ vardir = '/var'
530
+ el_agent = make_host( 'el', :platform => 'el-5-x86_64', :pe_ver => '4.0' )
531
+ el_agent2 = make_host( 'el', :platform => 'el-5-x86_64', :pe_ver => '4.0' )
532
+
533
+ allow( el_agent ).to receive( :puppet_configprint ).and_return( { 'vardir' => vardir } )
534
+ allow( el_agent ).to receive( :file_exist? ).with("/var/state/agent_catalog_run.lock").and_return(false)
535
+
536
+ allow( el_agent2 ).to receive( :puppet_configprint ).and_return( { 'vardir' => vardir } )
537
+ allow( el_agent2 ).to receive( :file_exist? ).with("/var/state/agent_catalog_run.lock").and_return(false)
538
+
539
+ # This will only get hit if forking processes is supported and at least 2 items are being submitted to run in parallel
540
+ expect( subject ).to receive( :block_on ).with(
541
+ anything,
542
+ include( :run_in_parallel => true )
543
+ )
544
+
545
+ subject.stop_agent_on( [el_agent, el_agent2], { :run_in_parallel => true} )
546
+ end
547
+
548
+ end
549
+
550
+ describe "#stop_agent" do
551
+ it 'delegates to #stop_agent_on with default host' do
552
+ allow( subject ).to receive( :hosts ).and_return( hosts )
553
+
554
+ expect( subject ).to receive( :default ).and_return( master )
555
+ expect( subject ).to receive( :stop_agent_on ).with( master ).once
556
+
557
+ subject.stop_agent( )
558
+
559
+ end
560
+ end
561
+
562
+ describe "#sign_certificate_for" do
563
+
564
+ before :each do
565
+ allow( subject ).to receive( :hosts ).and_return( hosts )
566
+ allow( subject ).to receive( :master ).and_return( master )
567
+ allow( subject ).to receive( :dashboard ).and_return( dash )
568
+ allow( subject ).to receive( :database ).and_return( db )
569
+ hosts.each do |host|
570
+ allow( host ).to receive( :node_name ).and_return( '' )
571
+ end
572
+ end
573
+
574
+ it 'signs certs' do
575
+ allow( subject ).to receive( :sleep ).and_return( true )
576
+
577
+ result.stdout = "+ \"#{agent}\""
578
+
579
+ allow( subject ).to receive( :puppet ) do |arg|
580
+ arg
581
+ end
582
+
583
+ expect( subject ).to receive( :on ).with( master, "cert --sign --all --allow-dns-alt-names", :acceptable_exit_codes => [0,24]).once
584
+ expect( subject ).to receive( :on ).with( master, "cert --list --all").once.and_return( result )
585
+
586
+ subject.sign_certificate_for( agent )
587
+ end
588
+
589
+ it 'retries 11 times before quitting' do
590
+ allow( subject ).to receive( :sleep ).and_return( true )
591
+
592
+ result.stdout = " \"#{agent}\""
593
+ allow( subject ).to receive( :hosts ).and_return( hosts )
594
+
595
+ allow( subject ).to receive( :puppet ) do |arg|
596
+ arg
597
+ end
598
+
599
+ expect( subject ).to receive( :on ).with( master, "cert --sign --all --allow-dns-alt-names", :acceptable_exit_codes => [0,24]).exactly( 11 ).times
600
+ expect( subject ).to receive( :on ).with( master, "cert --list --all").exactly( 11 ).times.and_return( result )
601
+ expect( subject ).to receive( :fail_test ).once
602
+
603
+ subject.sign_certificate_for( agent )
604
+ end
605
+
606
+ it 'accepts an array of hosts to validate' do
607
+ allow( subject ).to receive( :sleep ).and_return( true )
608
+
609
+ result.stdout = "+ \"#{agent}\" + \"#{custom}\""
610
+ allow( subject ).to receive( :hosts ).and_return( hosts )
611
+
612
+ allow( subject ).to receive( :puppet ) do |arg|
613
+ arg
614
+ end
615
+ expect( subject ).to receive( :on ).with( master, "agent -t", :acceptable_exit_codes => [0, 1, 2]).once
616
+ expect( subject ).to receive( :on ).with( master, "cert --allow-dns-alt-names sign master", :acceptable_exit_codes => [0, 24]).once
617
+ expect( subject ).to receive( :on ).with( master, "cert --sign --all --allow-dns-alt-names", :acceptable_exit_codes => [0,24]).once
618
+ expect( subject ).to receive( :on ).with( master, "cert --list --all").once.and_return( result )
619
+
620
+ subject.sign_certificate_for( [master, agent, custom] )
621
+ end
622
+ end
623
+
624
+ describe "#sign_certificate" do
625
+ it 'delegates to #sign_certificate_for with the default host' do
626
+ allow( subject ).to receive( :hosts ).and_return( hosts )
627
+ expect( subject ).to receive( :default ).and_return( master )
628
+
629
+ expect( subject ).to receive( :sign_certificate_for ).with( master ).once
630
+
631
+ subject.sign_certificate( )
632
+ end
633
+ end
634
+
635
+ describe '#with_puppet_running_on' do
636
+ let(:test_case_path) { 'testcase/path' }
637
+ let(:tmpdir_path) { '/tmp/tmpdir' }
638
+ let(:is_pe) { false }
639
+ let(:use_service) { false }
640
+ let(:platform) { 'redhat' }
641
+ let(:host) {
642
+ FakeHost.create('fakevm', "#{platform}-version-arch",
643
+ 'type' => is_pe ? 'pe': 'git',
644
+ 'use-service' => use_service
645
+ )
646
+ }
647
+
648
+ def stub_host_and_subject_to_allow_the_default_testdir_argument_to_be_created
649
+ subject.instance_variable_set(:@path, test_case_path)
650
+ allow( host ).to receive(:tmpdir).and_return(tmpdir_path)
651
+ allow( host ).to receive(:file_exist?).and_return(true)
652
+ allow( subject ).to receive( :options ).and_return( {} )
653
+ end
654
+
655
+ before do
656
+ stub_host_and_subject_to_allow_the_default_testdir_argument_to_be_created
657
+ allow( subject ).to receive(:curl_with_retries)
658
+ end
659
+
660
+ it "raises an ArgumentError if you try to submit a String instead of a Hash of options" do
661
+ 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'/)
662
+ end
663
+
664
+ it 'raises the early_exception if backup_the_file fails' do
665
+ allow( host ).to receive( :use_service_scripts? )
666
+ allow( subject ).to receive( :restore_puppet_conf_from_backup )
667
+ expect( subject ).to receive(:backup_the_file).and_raise(RuntimeError.new('puppet conf backup failed'))
668
+ expect {
669
+ subject.with_puppet_running_on(host, {})
670
+ }.to raise_error(RuntimeError, /puppet conf backup failed/)
671
+ end
672
+
673
+ it 'receives a Minitest::Assertion and fails the test correctly' do
674
+ allow( subject ).to receive( :backup_the_file ).and_raise( Minitest::Assertion.new('assertion failed!') )
675
+ allow( host ).to receive( :puppet ).and_return( {} )
676
+ allow( subject ).to receive( :restore_puppet_conf_from_backup )
677
+ allow( host ).to receive( :use_service_scripts? )
678
+ expect( subject ).to receive( :fail_test )
679
+ subject.with_puppet_running_on(host, {})
680
+ end
681
+
682
+ context 'with test flow exceptions' do
683
+ it 'can pass_test' do
684
+ expect( subject ).to receive(:backup_the_file).and_raise(Beaker::DSL::Outcomes::PassTest)
685
+ expect {
686
+ subject.with_puppet_running_on(host, {}).to receive(:pass_test)
687
+ }.to raise_error(Beaker::DSL::Outcomes::PassTest)
688
+ end
689
+ it 'can fail_test' do
690
+ expect( subject ).to receive(:backup_the_file).and_raise(Beaker::DSL::Outcomes::FailTest)
691
+ expect {
692
+ subject.with_puppet_running_on(host, {}).to receive(:fail_test)
693
+ }.to raise_error(Beaker::DSL::Outcomes::FailTest)
694
+ end
695
+ it 'can skip_test' do
696
+ expect( subject ).to receive(:backup_the_file).and_raise(Beaker::DSL::Outcomes::SkipTest)
697
+ expect {
698
+ subject.with_puppet_running_on(host, {}).to receive(:skip_test)
699
+ }.to raise_error(Beaker::DSL::Outcomes::SkipTest)
700
+ end
701
+ it 'can pending_test' do
702
+ expect( subject ).to receive(:backup_the_file).and_raise(Beaker::DSL::Outcomes::PendingTest)
703
+ expect {
704
+ subject.with_puppet_running_on(host, {}).to receive(:pending_test)
705
+ }.to raise_error(Beaker::DSL::Outcomes::PendingTest)
706
+ end
707
+ end
708
+
709
+ describe 'with puppet-server' do
710
+ let(:default_confdir) { "/etc/puppet" }
711
+ let(:default_vardir) { "/var/lib/puppet" }
712
+
713
+ let(:custom_confdir) { "/tmp/etc/puppet" }
714
+ let(:custom_vardir) { "/tmp/var/lib/puppet" }
715
+
716
+ let(:command_line_args) {"--vardir=#{custom_vardir} --confdir=#{custom_confdir}"}
717
+ let(:conf_opts) { {:__commandline_args__ => command_line_args,
718
+ :is_puppetserver => true}}
719
+
720
+ let(:default_puppetserver_opts) {{ "jruby-puppet" => {
721
+ "master-conf-dir" => default_confdir,
722
+ "master-var-dir" => default_vardir,
723
+ }}}
724
+
725
+ let(:custom_puppetserver_opts) {{ "jruby-puppet" => {
726
+ "master-conf-dir" => custom_confdir,
727
+ "master-var-dir" => custom_vardir,
728
+ }}}
729
+
730
+ let(:puppetserver_conf) { "/etc/puppetserver/conf.d/puppetserver.conf" }
731
+ let(:logger) { double }
732
+
733
+ def stub_post_setup
734
+ allow( subject ).to receive( :restore_puppet_conf_from_backup)
735
+ allow( subject ).to receive( :bounce_service)
736
+ allow( subject ).to receive( :stop_puppet_from_source_on)
737
+ allow( subject ).to receive( :dump_puppet_log)
738
+ allow( subject ).to receive( :restore_puppet_conf_from_backup)
739
+ allow( subject ).to receive( :puppet_master_started)
740
+ allow( subject ).to receive( :start_puppet_from_source_on!)
741
+ allow( subject ).to receive( :lay_down_new_puppet_conf)
742
+ allow( subject ).to receive( :logger) .and_return( logger )
743
+ allow( logger ).to receive( :error)
744
+ allow( logger ).to receive( :debug)
745
+ end
746
+
747
+ before do
748
+ stub_post_setup
749
+ allow( subject ).to receive( :options) .and_return( {:is_puppetserver => true})
750
+ allow( subject ).to receive( :modify_tk_config)
751
+ allow( host ).to receive(:puppet).with( any_args ).and_return({
752
+ 'confdir' => default_confdir,
753
+ 'vardir' => default_vardir,
754
+ 'config' => "#{default_confdir}/puppet.conf"
755
+ })
756
+ end
757
+
758
+ describe 'when the global option for :is_puppetserver is false' do
759
+ it 'checks the option for the host object' do
760
+ allow( subject ).to receive( :options) .and_return( {:is_puppetserver => false})
761
+ host[:is_puppetserver] = true
762
+ expect( subject ).to receive( :modify_tk_config)
763
+ subject.with_puppet_running_on(host, conf_opts)
764
+ end
765
+ end
766
+
767
+ describe 'and command line args passed' do
768
+ it 'modifies SUT trapperkeeper configuration w/ command line args' do
769
+ host['puppetserver-confdir'] = '/etc/puppetserver/conf.d'
770
+ expect( subject ).to receive( :modify_tk_config).with(host, puppetserver_conf,
771
+ custom_puppetserver_opts)
772
+ subject.with_puppet_running_on(host, conf_opts)
773
+ end
774
+ end
775
+
776
+ describe 'and no command line args passed' do
777
+ let(:command_line_args) { nil }
778
+ it 'modifies SUT trapperkeeper configuration w/ puppet defaults' do
779
+ host['puppetserver-confdir'] = '/etc/puppetserver/conf.d'
780
+ expect( subject ).to receive( :modify_tk_config).with(host, puppetserver_conf,
781
+ default_puppetserver_opts)
782
+ subject.with_puppet_running_on(host, conf_opts)
783
+ end
784
+ end
785
+ end
786
+
787
+ describe "with valid arguments" do
788
+ before do
789
+ expect( Tempfile ).to receive(:open).with('beaker')
790
+ end
791
+
792
+ context 'for pe hosts' do
793
+ let(:is_pe) { true }
794
+ let(:service_restart) { true }
795
+
796
+ it 'bounces puppet twice' do
797
+ subject.with_puppet_running_on(host, {})
798
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(2).times
799
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
800
+ end
801
+
802
+ it 'yields to a block in between bouncing service calls' do
803
+ execution = 0
804
+ allow( subject ).to receive(:curl_with_retries)
805
+ expect do
806
+ subject.with_puppet_running_on(host, {}) do
807
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(1).times
808
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(1).times
809
+ execution += 1
810
+ end
811
+ end.to change { execution }.by(1)
812
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(2).times
813
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
814
+ end
815
+
816
+ context ':restart_when_done flag set false' do
817
+ it 'starts puppet once, stops it twice' do
818
+ subject.with_puppet_running_on(host, { :restart_when_done => false })
819
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).once
820
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
821
+ end
822
+
823
+ it 'can be set globally in options' do
824
+ host[:restart_when_done] = false
825
+
826
+ subject.with_puppet_running_on(host, {})
827
+
828
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).once
829
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
830
+ end
831
+
832
+ it 'yields to a block after bouncing service' do
833
+ execution = 0
834
+ allow( subject ).to receive(:curl_with_retries)
835
+ expect do
836
+ subject.with_puppet_running_on(host, { :restart_when_done => false }) do
837
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(1).times
838
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(1).times
839
+ execution += 1
840
+ end
841
+ end.to change { execution }.by(1)
842
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
843
+ end
844
+ end
845
+ end
846
+
847
+ context 'for foss packaged hosts using passenger' do
848
+ before(:each) do
849
+ host.uses_passenger!
850
+ end
851
+ it 'bounces puppet twice' do
852
+ allow( subject ).to receive(:curl_with_retries)
853
+ subject.with_puppet_running_on(host, {})
854
+ expect(host).to execute_commands_matching(/apachectl graceful/).exactly(2).times
855
+ end
856
+
857
+ it 'gracefully restarts using apache2ctl' do
858
+ allow(host).to receive( :check_for_command ).and_return( true )
859
+ allow( subject ).to receive(:curl_with_retries)
860
+ subject.with_puppet_running_on(host, {})
861
+ expect(host).to execute_commands_matching(/apache2ctl graceful/).exactly(2).times
862
+ end
863
+
864
+ it 'gracefully restarts using apachectl' do
865
+ allow(host).to receive( :check_for_command ).and_return( false )
866
+ allow( subject ).to receive(:curl_with_retries)
867
+ subject.with_puppet_running_on(host, {})
868
+ expect(host).to execute_commands_matching(/apachectl graceful/).exactly(2).times
869
+ end
870
+
871
+ it 'yields to a block after bouncing service' do
872
+ execution = 0
873
+ allow( subject ).to receive(:curl_with_retries)
874
+ expect do
875
+ subject.with_puppet_running_on(host, {}) do
876
+ expect(host).to execute_commands_matching(/apachectl graceful/).once
877
+ execution += 1
878
+ end
879
+ end.to change { execution }.by(1)
880
+ expect(host).to execute_commands_matching(/apachectl graceful/).exactly(2).times
881
+ end
882
+
883
+ context ':restart_when_done flag set false' do
884
+ it 'bounces puppet once' do
885
+ allow( subject ).to receive(:curl_with_retries)
886
+ subject.with_puppet_running_on(host, { :restart_when_done => false })
887
+ expect(host).to execute_commands_matching(/apachectl graceful/).once
888
+ end
889
+
890
+ it 'yields to a block after bouncing service' do
891
+ execution = 0
892
+ allow( subject ).to receive(:curl_with_retries)
893
+ expect do
894
+ subject.with_puppet_running_on(host, { :restart_when_done => false }) do
895
+ expect(host).to execute_commands_matching(/apachectl graceful/).once
896
+ execution += 1
897
+ end
898
+ end.to change { execution }.by(1)
899
+ end
900
+ end
901
+ end
902
+
903
+ context 'for foss packaged hosts using webrick' do
904
+ let(:use_service) { true }
905
+
906
+ it 'stops and starts master using service scripts twice' do
907
+ allow( subject ).to receive(:curl_with_retries)
908
+ subject.with_puppet_running_on(host, {})
909
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(2).times
910
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
911
+ end
912
+
913
+ it 'yields to a block in between bounce calls for the service' do
914
+ execution = 0
915
+ expect do
916
+ subject.with_puppet_running_on(host, {}) do
917
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).once
918
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).once
919
+ execution += 1
920
+ end
921
+ end.to change { execution }.by(1)
922
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(2).times
923
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
924
+ end
925
+
926
+ context ':restart_when_done flag set false' do
927
+ it 'stops (twice) and starts (once) master using service scripts' do
928
+ allow( subject ).to receive(:curl_with_retries)
929
+ subject.with_puppet_running_on(host, { :restart_when_done => false })
930
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).once
931
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
932
+ end
933
+
934
+ it 'yields to a block after stopping and starting service' do
935
+ execution = 0
936
+ expect do
937
+ subject.with_puppet_running_on(host, { :restart_when_done => false }) do
938
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).once
939
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).once
940
+ execution += 1
941
+ end
942
+ end.to change { execution }.by(1)
943
+ end
944
+ end
945
+ end
946
+
947
+ context 'running from source' do
948
+ let('use-service') { false }
949
+
950
+ it 'does not try to stop if not started' do
951
+ expect( subject ).to receive(:start_puppet_from_source_on!).and_return false
952
+ expect( subject ).to_not receive(:stop_puppet_from_source_on)
953
+
954
+ subject.with_puppet_running_on(host, {})
955
+ end
956
+
957
+ context 'successfully' do
958
+ before do
959
+ expect( host ).to receive(:port_open?).with(8140).and_return(true)
960
+ end
961
+
962
+ it 'starts puppet from source' do
963
+ subject.with_puppet_running_on(host, {})
964
+ end
965
+
966
+ it 'stops puppet from source' do
967
+ subject.with_puppet_running_on(host, {})
968
+ expect(host).to execute_commands_matching(/^kill [^-]/).once
969
+ expect(host).to execute_commands_matching(/^kill -0/).once
970
+ end
971
+
972
+ it 'yields between starting and stopping' do
973
+ execution = 0
974
+ expect do
975
+ subject.with_puppet_running_on(host, {}) do
976
+ expect(host).to execute_commands_matching(/^puppet master/).exactly(4).times
977
+ execution += 1
978
+ end
979
+ end.to change { execution }.by(1)
980
+ expect(host).to execute_commands_matching(/^kill [^-]/).once
981
+ expect(host).to execute_commands_matching(/^kill -0/).once
982
+ end
983
+
984
+ it 'passes on commandline args' do
985
+ subject.with_puppet_running_on(host, {:__commandline_args__ => '--with arg'})
986
+ expect(host).to execute_commands_matching(/^puppet master --with arg/).once
987
+ end
988
+
989
+ it 'is not affected by the :restart_when_done flag' do
990
+ execution = 0
991
+ expect do
992
+ subject.with_puppet_running_on(host, { :restart_when_done => true }) do
993
+ expect(host).to execute_commands_matching(/^puppet master/).exactly(4).times
994
+ execution += 1
995
+ end
996
+ end.to change { execution }.by(1)
997
+ expect(host).to execute_commands_matching(/^kill [^-]/).once
998
+ expect(host).to execute_commands_matching(/^kill -0/).once
999
+ end
1000
+ end
1001
+ end
1002
+
1003
+ describe 'backup and restore of puppet.conf' do
1004
+ before :each do
1005
+ mock_puppetconf_reader = Object.new
1006
+ allow( mock_puppetconf_reader ).to receive( :[] ).with( 'config' ).and_return( '/root/mock/puppet.conf' )
1007
+ allow( mock_puppetconf_reader ).to receive( :[] ).with( 'confdir' ).and_return( '/root/mock' )
1008
+ allow( host ).to receive( :puppet ).with( any_args ).and_return( mock_puppetconf_reader )
1009
+ end
1010
+
1011
+ let(:original_location) { host.puppet['config'] }
1012
+ let(:backup_location) {
1013
+ filename = File.basename(host.puppet['config'])
1014
+ File.join(tmpdir_path, "#{filename}.bak")
1015
+ }
1016
+ let(:new_location) {
1017
+ filename = File.basename(host.puppet['config'])
1018
+ File.join(tmpdir_path, filename)
1019
+ }
1020
+
1021
+ context 'when a puppetservice is used' do
1022
+ let(:use_service) { true }
1023
+
1024
+ it 'backs up puppet.conf' do
1025
+ subject.with_puppet_running_on(host, {})
1026
+ expect(host).to execute_commands_matching(/cp #{original_location} #{backup_location}/).once
1027
+ expect(host).to execute_commands_matching(/cat #{new_location} > #{original_location}/).once
1028
+ end
1029
+
1030
+ it 'restores puppet.conf before restarting' do
1031
+ subject.with_puppet_running_on(host, { :restart_when_done => true })
1032
+ expect(host).to execute_commands_matching_in_order(/cat '#{backup_location}' > '#{original_location}'/,
1033
+ /ensure=stopped/,
1034
+ /ensure=running/)
1035
+ end
1036
+ end
1037
+
1038
+ context 'when a puppetservice is not used' do
1039
+ before do
1040
+ expect( host ).to receive(:port_open?).with(8140).and_return(true)
1041
+ end
1042
+
1043
+ it 'backs up puppet.conf' do
1044
+ subject.with_puppet_running_on(host, {})
1045
+ expect(host).to execute_commands_matching(/cp #{original_location} #{backup_location}/).once
1046
+ expect(host).to execute_commands_matching(/cat #{new_location} > #{original_location}/).once
1047
+ end
1048
+
1049
+ it 'restores puppet.conf after restarting when a puppetservice is not used' do
1050
+ subject.with_puppet_running_on(host, {})
1051
+ expect(host).to execute_commands_matching_in_order(/kill [^-]/,
1052
+ /cat '#{backup_location}' > '#{original_location}'/m)
1053
+ end
1054
+
1055
+ it "doesn't restore a non-existent file" do
1056
+ allow( subject ).to receive(:backup_the_file)
1057
+ subject.with_puppet_running_on(host, {})
1058
+ expect(host).to execute_commands_matching(/rm -f '#{original_location}'/)
1059
+ end
1060
+ end
1061
+ end
1062
+
1063
+ let(:logger) { double.as_null_object }
1064
+ describe 'handling failures' do
1065
+
1066
+ before do
1067
+ allow( subject ).to receive( :logger ).and_return( logger )
1068
+ expect( subject ).to receive(:stop_puppet_from_source_on).and_raise(RuntimeError.new('Also failed in teardown.'))
1069
+ expect( host ).to receive(:port_open?).with(8140).and_return(true)
1070
+ end
1071
+
1072
+ it 'does not swallow an exception raised from within test block if ensure block also fails' do
1073
+ expect( subject.logger ).to receive(:error).with(/Raised during attempt to teardown.*Also failed in teardown/)
1074
+
1075
+ expect do
1076
+ subject.with_puppet_running_on(host, {}) { raise 'Failed while yielding.' }
1077
+ end.to raise_error(RuntimeError, /failed.*because.*Failed while yielding./)
1078
+ end
1079
+
1080
+ it 'dumps the puppet logs if there is an error in the teardown' do
1081
+ expect( subject.logger ).to receive(:notify).with(/Dumping master log/)
1082
+
1083
+ expect do
1084
+ subject.with_puppet_running_on(host, {})
1085
+ end.to raise_error(RuntimeError, /Also failed in teardown/)
1086
+ end
1087
+
1088
+ it 'does not mask the teardown error with an error from dumping the logs' do
1089
+ expect( subject.logger ).to receive(:notify).with(/Dumping master log/).and_raise("Error from dumping logs")
1090
+
1091
+ expect do
1092
+ subject.with_puppet_running_on(host, {})
1093
+ end.to raise_error(RuntimeError, /Also failed in teardown/)
1094
+ end
1095
+
1096
+ it 'does not swallow a teardown exception if no earlier exception was raised' do
1097
+ expect( subject.logger).to_not receive(:error)
1098
+ expect do
1099
+ subject.with_puppet_running_on(host, {})
1100
+ end.to raise_error(RuntimeError, 'Also failed in teardown.')
1101
+ end
1102
+
1103
+ end
1104
+
1105
+ end
1106
+ end
1107
+
1108
+ describe '#with_puppet_running' do
1109
+ it 'delegates to #with_puppet_running_on with the default host' do
1110
+ allow( subject ).to receive( :hosts ).and_return( hosts )
1111
+ expect( subject ).to receive( :default ).and_return( master )
1112
+
1113
+ expect( subject ).to receive( :with_puppet_running_on ).with( master, {:opt => 'value'}, '/dir' ).once
1114
+
1115
+ subject.with_puppet_running( {:opt => 'value'}, '/dir' )
1116
+
1117
+
1118
+ end
1119
+ end
1120
+
1121
+ describe '#bounce_service' do
1122
+ # let( :options ) {
1123
+ # opts = StringifyHash.new
1124
+ # opts
1125
+ # }
1126
+ let( :options ) { Beaker::Options::Presets.new.presets }
1127
+ let( :result ) { double.as_null_object }
1128
+ before :each do
1129
+ allow( subject ).to receive( :options ) { options }
1130
+ end
1131
+
1132
+ it 'requests a reload but not a restart if the reload is successful' do
1133
+ host = FakeHost.create
1134
+ allow( result ).to receive( :exit_code ).and_return( 0 )
1135
+ allow( host ).to receive( :any_exec_result ).and_return( result )
1136
+ allow( host ).to receive( :graceful_restarts? ).and_return( false )
1137
+
1138
+ expect( Beaker::Command ).to receive( :new ).with(
1139
+ /service not_real_service reload/
1140
+ ).once
1141
+ expect( subject ).to receive( :puppet_resource ).never
1142
+ subject.bounce_service( host, 'not_real_service')
1143
+ end
1144
+
1145
+ it 'requests a restart if the reload fails' do
1146
+ host = FakeHost.create
1147
+ allow( result ).to receive( :exit_code ).and_return( 1 )
1148
+ allow( host ).to receive( :exec ).and_return( result )
1149
+ expect( subject ).to receive( :curl_with_retries )
1150
+ expect( subject ).to receive( :puppet_resource ).with(
1151
+ anything, 'not_real_service', anything
1152
+ ).exactly( 2 ).times
1153
+ subject.bounce_service( host, 'not_real_service' )
1154
+ end
1155
+
1156
+ it 'uses the default port argument if none given' do
1157
+ host = FakeHost.create
1158
+ expect( host ).to receive( :graceful_restarts? ).and_return( false )
1159
+ allow( result ).to receive( :exit_code ).and_return( 1 )
1160
+ expect( subject ).to receive( :curl_with_retries ).with(
1161
+ anything, anything, /8140/, anything, anything
1162
+ )
1163
+ subject.bounce_service( host, 'not_real_service')
1164
+ end
1165
+
1166
+ it 'takes the port argument' do
1167
+ host = FakeHost.create
1168
+ expect( host ).to receive( :graceful_restarts? ).and_return( false )
1169
+ allow( result ).to receive( :exit_code ).and_return( 1 )
1170
+ expect( subject ).to receive( :curl_with_retries ).with(
1171
+ anything, anything, /8000/, anything, anything
1172
+ )
1173
+ subject.bounce_service( host, 'not_real_service', nil, 8000)
1174
+ end
1175
+ end
1176
+
1177
+ describe '#sleep_until_puppetdb_started' do
1178
+ let( :options ) {
1179
+ opts = StringifyHash.new # defaults from presets.rb
1180
+ opts[:puppetdb_port_nonssl] = 8080
1181
+ opts[:puppetdb_port_ssl] = 8081
1182
+ opts
1183
+ }
1184
+ before :each do
1185
+ allow( subject ).to receive( :options ) { options }
1186
+ allow( hosts[0] ).to receive( :node_name ).and_return( '' )
1187
+ allow( subject ).to receive( :version_is_less ).and_return( true )
1188
+ end
1189
+
1190
+ it 'uses the default ports if none given' do
1191
+ host = hosts[0]
1192
+ expect( subject ).to receive( :retry_on ).with( anything(), /8080/, anything() ).once.ordered
1193
+ expect( subject ).to receive( :curl_with_retries ).with( anything(), anything(), /8081/, anything() ).once.ordered
1194
+ subject.sleep_until_puppetdb_started( host )
1195
+ end
1196
+
1197
+ it 'allows setting the nonssl_port' do
1198
+ host = hosts[0]
1199
+ expect( subject ).to receive( :retry_on ).with( anything(), /8084/, anything() ).once.ordered
1200
+ expect( subject ).to receive( :curl_with_retries ).with( anything(), anything(), /8081/, anything() ).once.ordered
1201
+
1202
+ subject.sleep_until_puppetdb_started( host, 8084 )
1203
+ end
1204
+
1205
+ it 'allows setting the ssl_port' do
1206
+ host = hosts[0]
1207
+ expect( subject ).to receive( :retry_on ).with( anything(), /8080/, anything() ).once.ordered
1208
+ expect( subject ).to receive( :curl_with_retries ).with( anything(), anything(), /8085/, anything() ).once.ordered
1209
+
1210
+ subject.sleep_until_puppetdb_started( host, nil, 8085 )
1211
+ end
1212
+
1213
+ context 'when pe_ver is less than 2016.1.0' do
1214
+ it 'uses the version endpoint' do
1215
+ host = hosts[0]
1216
+ host['pe_ver'] = '2015.3.3'
1217
+ expect( subject ).to receive( :retry_on ).with( anything(), /pdb\/meta\/v1\/version/, anything() ).once.ordered
1218
+ expect( subject ).to receive( :curl_with_retries ).with( anything(), anything(), /8081/, anything() ).once.ordered
1219
+
1220
+ expect( subject ).to receive( :version_is_less ).with( host['pe_ver'], '2016.1.0' ).and_return( true )
1221
+ subject.sleep_until_puppetdb_started( host )
1222
+ end
1223
+ end
1224
+
1225
+ context 'when pe_ver is greater than 2015.9.9' do
1226
+ it 'uses the status endpoint' do
1227
+ host = hosts[0]
1228
+ host['pe_ver'] = '2016.1.0'
1229
+ expect( subject ).to receive( :retry_on ).with( anything(), /status\/v1\/services\/puppetdb-status/, anything() ).once.ordered
1230
+ expect( subject ).to receive( :curl_with_retries ).with( anything(), anything(), /8081/, anything() ).once.ordered
1231
+
1232
+ expect( subject ).to receive( :version_is_less ).with( host['pe_ver'], '2016.1.0' ).and_return( false )
1233
+ subject.sleep_until_puppetdb_started( host )
1234
+ end
1235
+ end
1236
+
1237
+ end
1238
+
1239
+ describe '#sleep_until_puppetserver_started' do
1240
+ let( :options ) {
1241
+ opts = StringifyHash.new
1242
+ opts[:puppetserver_port] = 8140
1243
+ opts
1244
+ }
1245
+ before :each do
1246
+ allow( subject ).to receive( :options ) { options }
1247
+ allow( hosts[0] ).to receive( :node_name )
1248
+ end
1249
+
1250
+ it 'uses the default port if none given' do
1251
+ host = hosts[0]
1252
+ expect( subject ).to receive( :curl_with_retries ).with( anything(), anything(), /8140/, anything() ).once.ordered
1253
+ subject.sleep_until_puppetserver_started( host )
1254
+ end
1255
+
1256
+ it 'allows setting the port' do
1257
+ host = hosts[0]
1258
+ expect( subject ).to receive( :curl_with_retries ).with( anything(), anything(), /8147/, anything() ).once.ordered
1259
+ subject.sleep_until_puppetserver_started( host, 8147 )
1260
+ end
1261
+ end
1262
+
1263
+ describe '#sleep_until_nc_started' do
1264
+ let( :options ) { # defaults from presets.rb
1265
+ opts = StringifyHash.new
1266
+ opts[:nodeclassifier_port] = 4433
1267
+ opts
1268
+ }
1269
+ before :each do
1270
+ allow( subject ).to receive( :options ) { options }
1271
+ allow( hosts[0] ).to receive( :node_name )
1272
+ end
1273
+
1274
+ it 'uses the default port if none given' do
1275
+ host = hosts[0]
1276
+ expect( subject ).to receive( :curl_with_retries ).with( anything(), anything(), /4433/, anything() ).once.ordered
1277
+ subject.sleep_until_nc_started( host )
1278
+ end
1279
+
1280
+ it 'allows setting the port' do
1281
+ host = hosts[0]
1282
+ expect( subject ).to receive( :curl_with_retries ).with( anything(), anything(), /4435/, anything() ).once.ordered
1283
+ subject.sleep_until_nc_started( host, 4435 )
1284
+ end
1285
+ end
1286
+
1287
+ end