beaker 1.16.0 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +8 -8
  2. data/CONTRIBUTING.md +90 -0
  3. data/HISTORY.md +654 -2
  4. data/beaker.gemspec +1 -0
  5. data/lib/beaker/answers/version34.rb +4 -0
  6. data/lib/beaker/cli.rb +49 -2
  7. data/lib/beaker/dsl/helpers.rb +356 -196
  8. data/lib/beaker/dsl/install_utils.rb +135 -16
  9. data/lib/beaker/dsl/patterns.rb +37 -0
  10. data/lib/beaker/dsl/roles.rb +29 -0
  11. data/lib/beaker/dsl.rb +2 -1
  12. data/lib/beaker/host/unix.rb +14 -10
  13. data/lib/beaker/host/windows.rb +2 -0
  14. data/lib/beaker/host.rb +96 -1
  15. data/lib/beaker/host_prebuilt_steps.rb +41 -51
  16. data/lib/beaker/hypervisor/aws_sdk.rb +80 -16
  17. data/lib/beaker/hypervisor/ec2_helper.rb +1 -1
  18. data/lib/beaker/logger.rb +17 -0
  19. data/lib/beaker/options/command_line_parser.rb +3 -0
  20. data/lib/beaker/options/hosts_file_parser.rb +7 -4
  21. data/lib/beaker/options/options_hash.rb +2 -2
  22. data/lib/beaker/options/parser.rb +1 -1
  23. data/lib/beaker/options/presets.rb +128 -83
  24. data/lib/beaker/perf.rb +58 -0
  25. data/lib/beaker/shared/host_manager.rb +81 -0
  26. data/lib/beaker/shared.rb +2 -2
  27. data/lib/beaker/ssh_connection.rb +14 -7
  28. data/lib/beaker/test_case.rb +13 -0
  29. data/lib/beaker/test_suite.rb +23 -5
  30. data/lib/beaker/version.rb +1 -1
  31. data/lib/beaker.rb +1 -1
  32. data/spec/beaker/answers_spec.rb +13 -8
  33. data/spec/beaker/dsl/ezbake_utils_spec.rb +8 -9
  34. data/spec/beaker/dsl/helpers_spec.rb +299 -51
  35. data/spec/beaker/dsl/install_utils_spec.rb +75 -10
  36. data/spec/beaker/dsl/roles_spec.rb +36 -1
  37. data/spec/beaker/host_prebuilt_steps_spec.rb +21 -5
  38. data/spec/beaker/host_spec.rb +187 -23
  39. data/spec/beaker/hypervisor/ec2_helper_spec.rb +4 -4
  40. data/spec/beaker/hypervisor/vagrant_spec.rb +1 -1
  41. data/spec/beaker/options/hosts_file_parser_spec.rb +5 -0
  42. data/spec/beaker/options/options_hash_spec.rb +2 -2
  43. data/spec/beaker/options/parser_spec.rb +6 -0
  44. data/spec/beaker/options/presets_spec.rb +18 -2
  45. data/spec/beaker/perf_spec.rb +87 -0
  46. data/spec/beaker/shared/{host_role_parser_spec.rb → host_manager_spec.rb} +36 -5
  47. data/spec/beaker/test_suite_spec.rb +4 -3
  48. data/spec/matchers.rb +31 -3
  49. data/spec/mocks.rb +31 -25
  50. metadata +24 -5
  51. data/lib/beaker/shared/host_role_parser.rb +0 -36
@@ -128,7 +128,7 @@ describe ClassMixedWithEZBakeUtils do
128
128
  RSpec.shared_examples "installs-ezbake-dependencies" do
129
129
  it "installs ezbake dependencies" do
130
130
  expect(subject).to receive(:install_package).
131
- with( kind_of(FakeHost), anything(), anything())
131
+ with( kind_of(Beaker::Host), anything(), anything())
132
132
  subject.install_ezbake_deps host
133
133
  end
134
134
  end
@@ -136,7 +136,7 @@ describe ClassMixedWithEZBakeUtils do
136
136
  describe '#install_ezbake_deps' do
137
137
  let( :platform ) { Beaker::Platform.new('redhat-7-i386') }
138
138
  let(:host) do
139
- FakeHost.new( :options => { 'platform' => platform })
139
+ FakeHost.create('fakevm', platform.to_s)
140
140
  end
141
141
 
142
142
  before do
@@ -164,24 +164,23 @@ describe ClassMixedWithEZBakeUtils do
164
164
  def install_from_ezbake_common_expects
165
165
  expect(subject).to receive(:`).with(/rake package:tar/).ordered
166
166
  expect(subject).to receive(:scp_to).
167
- with( kind_of(FakeHost), anything(), anything()).ordered
167
+ with( kind_of(Beaker::Host), anything(), anything()).ordered
168
168
  expect(subject).to receive(:on).
169
- with( kind_of(FakeHost), /tar -xzf/).ordered
169
+ with( kind_of(Beaker::Host), /tar -xzf/).ordered
170
170
  expect(subject).to receive(:on).
171
- with( kind_of(FakeHost), /make -e install-#{EZBAKE_CONFIG_EXAMPLE[:real_name]}/).ordered
171
+ with( kind_of(Beaker::Host), /make -e install-#{EZBAKE_CONFIG_EXAMPLE[:real_name]}/).ordered
172
172
  end
173
173
 
174
174
  describe '#install_from_ezbake' do
175
175
  let( :platform ) { Beaker::Platform.new('redhat-7-i386') }
176
176
  let(:host) do
177
- FakeHost.new( :options => { 'platform' => platform })
177
+ FakeHost.create('fakevm', platform.to_s)
178
178
  end
179
179
 
180
180
  before do
181
181
  allow(subject).to receive(:ezbake_tools_available?) { true }
182
182
  end
183
183
 
184
-
185
184
  context "for non *nix-like platforms" do
186
185
  let( :platform ) { Beaker::Platform.new('windows-7-i386') }
187
186
  it "raises an exception" do
@@ -212,7 +211,7 @@ describe ClassMixedWithEZBakeUtils do
212
211
  }.ordered
213
212
  install_from_ezbake_common_expects
214
213
  expect(subject).to receive(:on).
215
- with( kind_of(FakeHost), /install-rpm-sysv-init/).ordered
214
+ with( kind_of(Beaker::Host), /install-rpm-sysv-init/).ordered
216
215
  subject.install_from_ezbake host, "blah", "blah"
217
216
  end
218
217
 
@@ -228,7 +227,7 @@ describe ClassMixedWithEZBakeUtils do
228
227
  it "skips ezbake_stage" do
229
228
  install_from_ezbake_common_expects
230
229
  expect(subject).to receive(:on).
231
- with( kind_of(FakeHost), /install-rpm-sysv-init/).ordered
230
+ with( kind_of(Beaker::Host), /install-rpm-sysv-init/).ordered
232
231
  subject.install_from_ezbake host, "blah", "blah"
233
232
  end
234
233
 
@@ -4,6 +4,7 @@ class ClassMixedWithDSLHelpers
4
4
  include Beaker::DSL::Helpers
5
5
  include Beaker::DSL::Wrappers
6
6
  include Beaker::DSL::Roles
7
+ include Beaker::DSL::Patterns
7
8
 
8
9
  def logger
9
10
  @logger ||= RSpec::Mocks::Mock.new('logger').as_null_object
@@ -32,6 +33,7 @@ describe ClassMixedWithDSLHelpers do
32
33
  end
33
34
 
34
35
  it 'allows the environment the command is run within to be specified' do
36
+ subject.stub( :hosts ).and_return( hosts )
35
37
 
36
38
  Beaker::Command.should_receive( :new ).
37
39
  with( 'ls ~/.bin', [], {'ENV' => { :HOME => '/tmp/test_home' }} )
@@ -58,6 +60,7 @@ describe ClassMixedWithDSLHelpers do
58
60
  end
59
61
 
60
62
  it 'delegates to itself for each host passed' do
63
+ subject.stub( :hosts ).and_return( hosts )
61
64
  expected = []
62
65
  hosts.each_with_index do |host, i|
63
66
  expected << i
@@ -70,6 +73,7 @@ describe ClassMixedWithDSLHelpers do
70
73
 
71
74
  context 'upon command completion' do
72
75
  before :each do
76
+ subject.stub( :hosts ).and_return( hosts )
73
77
  host.should_receive( :exec ).and_return( result )
74
78
  @res = subject.on( host, command )
75
79
  end
@@ -93,6 +97,7 @@ describe ClassMixedWithDSLHelpers do
93
97
 
94
98
  context 'when passed a block with arity of 1' do
95
99
  before :each do
100
+ subject.stub( :hosts ).and_return( hosts )
96
101
  host.should_receive( :exec ).and_return( result )
97
102
  end
98
103
 
@@ -124,6 +129,7 @@ describe ClassMixedWithDSLHelpers do
124
129
 
125
130
  context 'when passed a block with arity of 0' do
126
131
  before :each do
132
+ subject.stub( :hosts ).and_return( hosts )
127
133
  host.should_receive( :exec ).and_return( result )
128
134
  end
129
135
 
@@ -167,6 +173,7 @@ describe ClassMixedWithDSLHelpers do
167
173
 
168
174
  describe '#scp_from' do
169
175
  it 'delegates to the host' do
176
+ subject.stub( :hosts ).and_return( hosts )
170
177
  subject.should_receive( :logger ).exactly( hosts.length ).times
171
178
  result.should_receive( :log ).exactly( hosts.length ).times
172
179
 
@@ -180,6 +187,7 @@ describe ClassMixedWithDSLHelpers do
180
187
 
181
188
  describe '#scp_to' do
182
189
  it 'delegates to the host' do
190
+ subject.stub( :hosts ).and_return( hosts )
183
191
  subject.should_receive( :logger ).exactly( hosts.length ).times
184
192
  result.should_receive( :log ).exactly( hosts.length ).times
185
193
 
@@ -384,8 +392,46 @@ describe ClassMixedWithDSLHelpers do
384
392
  end
385
393
  end
386
394
 
395
+ describe '#select_hosts' do
396
+ let(:logger) { double.as_null_object }
397
+ before do
398
+ subject.stub( :logger ).and_return( logger )
399
+ end
400
+
401
+ it 'it returns an empty array if there are no applicable hosts' do
402
+ hosts = [ {'thing' => 'foo'}, {'thing' => 'bar'} ]
403
+
404
+ expect(subject.select_hosts( {'thing' => 'nope'}, hosts )).to be == []
405
+ end
406
+
407
+ it 'selects hosts that match a list of criteria' do
408
+ hosts = [ {'thing' => 'foo'}, {'thing' => 'bar'}, {'thing' => 'baz'} ]
409
+
410
+ expect(subject.select_hosts( {:thing => ['foo', 'baz']}, hosts )).to be == [ {'thing' => 'foo'}, {'thing' => 'baz'} ]
411
+ end
412
+
413
+ it 'selects hosts when a passed block returns true' do
414
+ host1 = {'platform' => 'solaris1'}
415
+ host2 = {'platform' => 'solaris2'}
416
+ host3 = {'platform' => 'windows'}
417
+ ret1 = (Struct.new('Result1', :stdout)).new(':global')
418
+ ret2 = (Struct.new('Result2', :stdout)).new('a_zone')
419
+ hosts = [ host1, host2, host3 ]
420
+ subject.should_receive( :hosts ).and_return( hosts )
421
+
422
+ subject.should_receive( :on ).with( host1, '/sbin/zonename' ).once.and_return( ret1 )
423
+ subject.should_receive( :on ).with( host2, '/sbin/zonename' ).once.and_return( ret2 )
424
+
425
+ selected_hosts = subject.select_hosts 'platform' => 'solaris' do |host|
426
+ subject.on(host, '/sbin/zonename').stdout =~ /:global/
427
+ end
428
+ expect( selected_hosts ).to be == [ host1 ]
429
+ end
430
+ end
431
+
387
432
  describe '#apply_manifest_on' do
388
433
  it 'calls puppet' do
434
+ subject.stub( :hosts ).and_return( hosts )
389
435
  subject.should_receive( :create_remote_file ).and_return( true )
390
436
  subject.should_receive( :puppet ).
391
437
  # with( 'apply', '--verbose', 'agent' ).
@@ -399,6 +445,7 @@ describe ClassMixedWithDSLHelpers do
399
445
  end
400
446
 
401
447
  it 'operates on an array of hosts' do
448
+ subject.stub( :hosts ).and_return( hosts )
402
449
  the_hosts = [master, agent]
403
450
 
404
451
  subject.should_receive( :create_remote_file ).twice.and_return( true )
@@ -415,6 +462,7 @@ describe ClassMixedWithDSLHelpers do
415
462
  end
416
463
 
417
464
  it 'adds acceptable exit codes with :catch_failures' do
465
+ subject.stub( :hosts ).and_return( hosts )
418
466
  subject.should_receive( :create_remote_file ).and_return( true )
419
467
  subject.should_receive( :puppet ).
420
468
  and_return( 'puppet_command' )
@@ -428,6 +476,7 @@ describe ClassMixedWithDSLHelpers do
428
476
  :catch_failures => true )
429
477
  end
430
478
  it 'allows acceptable exit codes through :catch_failures' do
479
+ subject.stub( :hosts ).and_return( hosts )
431
480
  subject.should_receive( :create_remote_file ).and_return( true )
432
481
  subject.should_receive( :puppet ).
433
482
  and_return( 'puppet_command' )
@@ -442,6 +491,7 @@ describe ClassMixedWithDSLHelpers do
442
491
  :catch_failures => true )
443
492
  end
444
493
  it 'enforces a 0 exit code through :catch_changes' do
494
+ subject.stub( :hosts ).and_return( hosts )
445
495
  subject.should_receive( :create_remote_file ).and_return( true )
446
496
  subject.should_receive( :puppet ).
447
497
  and_return( 'puppet_command' )
@@ -459,6 +509,7 @@ describe ClassMixedWithDSLHelpers do
459
509
  )
460
510
  end
461
511
  it 'enforces a 2 exit code through :expect_changes' do
512
+ subject.stub( :hosts ).and_return( hosts )
462
513
  subject.should_receive( :create_remote_file ).and_return( true )
463
514
  subject.should_receive( :puppet ).
464
515
  and_return( 'puppet_command' )
@@ -476,6 +527,7 @@ describe ClassMixedWithDSLHelpers do
476
527
  )
477
528
  end
478
529
  it 'enforces exit codes through :expect_failures' do
530
+ subject.stub( :hosts ).and_return( hosts )
479
531
  subject.should_receive( :create_remote_file ).and_return( true )
480
532
  subject.should_receive( :puppet ).
481
533
  and_return( 'puppet_command' )
@@ -493,6 +545,7 @@ describe ClassMixedWithDSLHelpers do
493
545
  )
494
546
  end
495
547
  it 'enforces exit codes through :expect_failures' do
548
+ subject.stub( :hosts ).and_return( hosts )
496
549
  expect {
497
550
  subject.apply_manifest_on(
498
551
  agent,
@@ -503,6 +556,7 @@ describe ClassMixedWithDSLHelpers do
503
556
  }.to raise_error ArgumentError, /catch_failures.+expect_failures/
504
557
  end
505
558
  it 'enforces added exit codes through :expect_failures' do
559
+ subject.stub( :hosts ).and_return( hosts )
506
560
  subject.should_receive( :create_remote_file ).and_return( true )
507
561
  subject.should_receive( :puppet ).
508
562
  and_return( 'puppet_command' )
@@ -522,6 +576,7 @@ describe ClassMixedWithDSLHelpers do
522
576
  end
523
577
 
524
578
  it 'can set the --parser future flag' do
579
+ subject.stub( :hosts ).and_return( hosts )
525
580
  subject.should_receive( :create_remote_file ).and_return( true )
526
581
 
527
582
  expect( subject ).to receive( :on ).with {|h, command, opts|
@@ -543,6 +598,7 @@ describe ClassMixedWithDSLHelpers do
543
598
  end
544
599
 
545
600
  it 'can set the --noops flag' do
601
+ subject.stub( :hosts ).and_return( hosts )
546
602
  subject.should_receive( :create_remote_file ).and_return( true )
547
603
  expect( subject ).to receive( :on ).with {|h, command, opts|
548
604
  cmdline = command.cmd_line( h )
@@ -575,6 +631,7 @@ describe ClassMixedWithDSLHelpers do
575
631
 
576
632
  describe '#stub_hosts_on' do
577
633
  it 'executes puppet on the host passed and ensures it is reverted' do
634
+ subject.stub( :hosts ).and_return( hosts )
578
635
  logger = double.as_null_object
579
636
 
580
637
  subject.stub( :logger ).and_return( logger )
@@ -589,7 +646,7 @@ describe ClassMixedWithDSLHelpers do
589
646
  'puppetlabs.com',
590
647
  'ensure=absent' )
591
648
 
592
- subject.stub_hosts_on( 'my_host', 'puppetlabs.com' => '127.0.0.1' )
649
+ subject.stub_hosts_on( make_host('my_host', {}), 'puppetlabs.com' => '127.0.0.1' )
593
650
  end
594
651
  end
595
652
 
@@ -606,15 +663,16 @@ describe ClassMixedWithDSLHelpers do
606
663
 
607
664
  describe '#stub_forge_on' do
608
665
  it 'stubs forge.puppetlabs.com with the value of `forge`' do
609
- subject.stub( :options ).and_return( {} )
666
+ subject.stub( :hosts ).and_return( hosts )
667
+ host = make_host('my_host', {})
610
668
  Resolv.should_receive( :getaddress ).
611
669
  with( 'my_forge.example.com' ).and_return( '127.0.0.1' )
612
670
  subject.should_receive( :stub_hosts_on ).
613
- with( 'my_host', 'forge.puppetlabs.com' => '127.0.0.1' )
671
+ with( host, 'forge.puppetlabs.com' => '127.0.0.1' )
614
672
  subject.should_receive( :stub_hosts_on ).
615
- with( 'my_host', 'forgeapi.puppetlabs.com' => '127.0.0.1' )
673
+ with( host, 'forgeapi.puppetlabs.com' => '127.0.0.1' )
616
674
 
617
- subject.stub_forge_on( 'my_host', 'my_forge.example.com' )
675
+ subject.stub_forge_on( host, 'my_forge.example.com' )
618
676
  end
619
677
  end
620
678
 
@@ -675,6 +733,7 @@ describe ClassMixedWithDSLHelpers do
675
733
  deb_agent = make_host( 'deb', :platform => 'debian-7-amd64' )
676
734
  deb_agent.stub( :puppet ).and_return( { 'vardir' => vardir } )
677
735
 
736
+ subject.stub( :hosts ).and_return( hosts )
678
737
  subject.should_receive( :on ).with( deb_agent, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_fail )
679
738
  subject.should_receive( :on ).with( deb_agent, "[ -e /etc/init.d/pe-puppet-agent ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_fail )
680
739
  subject.should_receive( :puppet_resource ).with( "service", "pe-puppet", "ensure=stopped").once
@@ -689,6 +748,7 @@ describe ClassMixedWithDSLHelpers do
689
748
  el_agent = make_host( 'el', :platform => 'el-5-x86_64' )
690
749
  el_agent.stub( :puppet ).and_return( { 'vardir' => vardir } )
691
750
 
751
+ subject.stub( :hosts ).and_return( hosts )
692
752
  subject.should_receive( :on ).with( el_agent, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_fail )
693
753
  subject.should_receive( :on ).with( el_agent, "[ -e /etc/init.d/pe-puppet-agent ]", :acceptable_exit_codes => [0,1] ).once.and_return( result_pass )
694
754
  subject.should_receive( :puppet_resource ).with("service", "pe-puppet-agent", "ensure=stopped").once
@@ -760,16 +820,14 @@ describe ClassMixedWithDSLHelpers do
760
820
  describe '#with_puppet_running_on' do
761
821
  let(:test_case_path) { 'testcase/path' }
762
822
  let(:tmpdir_path) { '/tmp/tmpdir' }
763
- let(:puppet_path) { '/puppet/path' }
764
- let(:puppetservice) { nil }
765
823
  let(:is_pe) { false }
824
+ let(:use_service) { false }
825
+ let(:platform) { 'redhat' }
766
826
  let(:host) do
767
- FakeHost.new(:pe => is_pe,
768
- :options => {
769
- 'puppetpath' => puppet_path,
770
- 'puppetservice' => puppetservice,
771
- 'platform' => 'el'
772
- })
827
+ FakeHost.create('fakevm', "#{platform}-version-arch",
828
+ 'type' => is_pe ? 'pe': 'git',
829
+ 'use-service' => use_service
830
+ )
773
831
  end
774
832
 
775
833
  def stub_host_and_subject_to_allow_the_default_testdir_argument_to_be_created
@@ -781,6 +839,7 @@ describe ClassMixedWithDSLHelpers do
781
839
 
782
840
  before do
783
841
  stub_host_and_subject_to_allow_the_default_testdir_argument_to_be_created
842
+ subject.stub(:curl_with_retries)
784
843
  end
785
844
 
786
845
  it "raises an ArgumentError if you try to submit a String instead of a Hash of options" do
@@ -794,37 +853,150 @@ describe ClassMixedWithDSLHelpers do
794
853
  }.to raise_error(RuntimeError, /puppet conf backup failed/)
795
854
  end
796
855
 
856
+ describe 'with jvm puppet' do
857
+ let(:default_confdir) { "/etc/puppet" }
858
+ let(:default_vardir) { "/var/lib/puppet" }
859
+
860
+ let(:custom_confdir) { "/tmp/etc/puppet" }
861
+ let(:custom_vardir) { "/tmp/var/lib/puppet" }
862
+
863
+ let(:command_line_args) {"--vardir=#{custom_vardir} --confdir=#{custom_confdir}"}
864
+ let(:conf_opts) { {:__commandline_args__ => command_line_args,
865
+ :is_jvm_puppet => true}}
866
+
867
+ let(:default_jvm_puppet_opts) {{ "jruby-puppet" => {
868
+ "master-conf-dir" => default_confdir,
869
+ "master-var-dir" => default_vardir,
870
+ }}}
871
+
872
+ let(:custom_jvm_puppet_opts) {{ "jruby-puppet" => {
873
+ "master-conf-dir" => custom_confdir,
874
+ "master-var-dir" => custom_vardir,
875
+ }}}
876
+
877
+ let(:jvm_puppet_conf) { "/etc/jvm-puppet/conf.d/jvm-puppet.conf" }
878
+ let(:logger) { double }
879
+
880
+ def stub_post_setup
881
+ subject.stub( :restore_puppet_conf_from_backup)
882
+ subject.stub( :bounce_service)
883
+ subject.stub( :stop_puppet_from_source_on)
884
+ subject.stub( :dump_puppet_log)
885
+ subject.stub( :restore_puppet_conf_from_backup)
886
+ subject.stub( :puppet_master_started)
887
+ subject.stub( :start_puppet_from_source_on!)
888
+ subject.stub( :lay_down_new_puppet_conf)
889
+ subject.stub( :logger) .and_return( logger )
890
+ logger.stub( :error)
891
+ logger.stub( :debug)
892
+ end
893
+
894
+ before do
895
+ stub_post_setup
896
+ subject.stub( :options) .and_return( {:is_jvm_puppet => true})
897
+ subject.stub( :modify_tk_config)
898
+ host.stub(:puppet).with('master') .and_return({'confdir' => default_confdir,
899
+ 'vardir' => default_vardir})
900
+ end
901
+
902
+ describe 'and command line args passed' do
903
+ it 'modifies SUT trapperkeeper configuration w/ command line args' do
904
+ subject.should_receive( :modify_tk_config).with(host, jvm_puppet_conf,
905
+ custom_jvm_puppet_opts)
906
+ subject.with_puppet_running_on(host, conf_opts)
907
+ end
908
+ end
909
+
910
+ describe 'and no command line args passed' do
911
+ let(:command_line_args) { nil }
912
+ it 'modifies SUT trapperkeeper configuration w/ puppet defaults' do
913
+ subject.should_receive( :modify_tk_config).with(host, jvm_puppet_conf,
914
+ default_jvm_puppet_opts)
915
+ subject.with_puppet_running_on(host, conf_opts)
916
+ end
917
+ end
918
+ end
919
+
797
920
  describe "with valid arguments" do
798
921
  before do
799
922
  Tempfile.should_receive(:open).with('beaker')
800
923
  end
801
924
 
802
- context 'with puppetservice and service-path defined' do
803
- let(:puppetservice) { 'whatever' }
925
+ context 'for pe hosts' do
926
+ let(:is_pe) { true }
927
+ let(:service_restart) { true }
928
+
929
+ it 'bounces puppet twice' do
930
+ subject.with_puppet_running_on(host, {})
931
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(2).times
932
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
933
+ end
934
+
935
+ it 'yields to a block after bouncing service' do
936
+ execution = 0
937
+ subject.stub(:curl_with_retries)
938
+ expect do
939
+ subject.with_puppet_running_on(host, {}) do
940
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(1).times
941
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(1).times
942
+ execution += 1
943
+ end
944
+ end.to change { execution }.by(1)
945
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(2).times
946
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
947
+ end
948
+ end
949
+
950
+ context 'for foss packaged hosts using passenger' do
951
+ before(:each) do
952
+ host.uses_passenger!
953
+ end
804
954
 
805
955
  it 'bounces puppet twice' do
806
956
  subject.stub(:curl_with_retries)
807
957
  subject.with_puppet_running_on(host, {})
808
- expect(host).to execute_commands_matching(/puppet resource service #{puppetservice} ensure=stopped/).exactly(2).times
809
- expect(host).to execute_commands_matching(/puppet resource service #{puppetservice} ensure=running/).exactly(2).times
958
+ expect(host).to execute_commands_matching(/apache2ctl graceful/).exactly(2).times
810
959
  end
811
960
 
812
- it 'yield to a block after bouncing service' do
961
+ it 'yields to a block after bouncing service' do
813
962
  execution = 0
814
963
  subject.stub(:curl_with_retries)
815
964
  expect do
816
965
  subject.with_puppet_running_on(host, {}) do
817
- expect(host).to execute_commands_matching(/puppet resource service #{puppetservice} ensure=stopped/).once
818
- expect(host).to execute_commands_matching(/puppet resource service #{puppetservice} ensure=running/).once
966
+ expect(host).to execute_commands_matching(/apache2ctl graceful/).once
819
967
  execution += 1
820
968
  end
821
969
  end.to change { execution }.by(1)
822
- expect(host).to execute_commands_matching(/puppet resource service #{puppetservice} ensure=stopped/).exactly(2).times
823
- expect(host).to execute_commands_matching(/puppet resource service #{puppetservice} ensure=running/).exactly(2).times
970
+ expect(host).to execute_commands_matching(/apache2ctl graceful/).exactly(2).times
971
+ end
972
+ end
973
+
974
+ context 'for foss packaged hosts using webrick' do
975
+ let(:use_service) { true }
976
+
977
+ it 'stops and starts master using service scripts' do
978
+ subject.stub(:curl_with_retries)
979
+ subject.with_puppet_running_on(host, {})
980
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(2).times
981
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
982
+ end
983
+
984
+ it 'yields to a block after stopping and starting service' do
985
+ execution = 0
986
+ expect do
987
+ subject.with_puppet_running_on(host, {}) do
988
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).once
989
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).once
990
+ execution += 1
991
+ end
992
+ end.to change { execution }.by(1)
993
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=running/).exactly(2).times
994
+ expect(host).to execute_commands_matching(/puppet resource service #{host['puppetservice']}.*ensure=stopped/).exactly(2).times
824
995
  end
825
996
  end
826
997
 
827
998
  context 'running from source' do
999
+ let('use-service') { false }
828
1000
 
829
1001
  it 'does not try to stop if not started' do
830
1002
  subject.should_receive(:start_puppet_from_source_on!).and_return false
@@ -868,30 +1040,49 @@ describe ClassMixedWithDSLHelpers do
868
1040
  end
869
1041
 
870
1042
  describe 'backup and restore of puppet.conf' do
871
- let(:original_location) { "#{puppet_path}/puppet.conf" }
1043
+ let(:original_location) { "#{host['puppetpath']}/puppet.conf" }
872
1044
  let(:backup_location) { "#{tmpdir_path}/puppet.conf.bak" }
873
1045
  let(:new_location) { "#{tmpdir_path}/puppet.conf" }
874
1046
 
875
- before do
876
- host.should_receive(:port_open?).with(8140).and_return(true)
877
- end
1047
+ context 'when a puppetservice is used' do
1048
+ let(:use_service) { true }
878
1049
 
879
- it 'backs up puppet.conf' do
880
- subject.with_puppet_running_on(host, {})
881
- expect(host).to execute_commands_matching(/cp #{original_location} #{backup_location}/).once
882
- expect(host).to execute_commands_matching(/cat #{new_location} > #{original_location}/).once
1050
+ it 'backs up puppet.conf' do
1051
+ subject.with_puppet_running_on(host, {})
1052
+ expect(host).to execute_commands_matching(/cp #{original_location} #{backup_location}/).once
1053
+ expect(host).to execute_commands_matching(/cat #{new_location} > #{original_location}/).once
1054
+ end
883
1055
 
1056
+ it 'restores puppet.conf before restarting' do
1057
+ subject.with_puppet_running_on(host, {})
1058
+ expect(host).to execute_commands_matching_in_order(/cat '#{backup_location}' > '#{original_location}'/,
1059
+ /ensure=stopped/,
1060
+ /ensure=running/)
1061
+ end
884
1062
  end
885
1063
 
886
- it 'restores puppet.conf' do
887
- subject.with_puppet_running_on(host, {})
888
- expect(host).to execute_commands_matching(/cat '#{backup_location}' > '#{original_location}'/).once
889
- end
1064
+ context 'when a puppetservice is not used' do
1065
+ before do
1066
+ host.should_receive(:port_open?).with(8140).and_return(true)
1067
+ end
890
1068
 
891
- it "doesn't restore a non-existent file" do
892
- subject.stub(:backup_the_file)
893
- subject.with_puppet_running_on(host, {})
894
- expect(host).to execute_commands_matching(/rm -f '#{original_location}'/)
1069
+ it 'backs up puppet.conf' do
1070
+ subject.with_puppet_running_on(host, {})
1071
+ expect(host).to execute_commands_matching(/cp #{original_location} #{backup_location}/).once
1072
+ expect(host).to execute_commands_matching(/cat #{new_location} > #{original_location}/).once
1073
+ end
1074
+
1075
+ it 'restores puppet.conf after restarting when a puppetservice is not used' do
1076
+ subject.with_puppet_running_on(host, {})
1077
+ expect(host).to execute_commands_matching_in_order(/kill [^-]/,
1078
+ /cat '#{backup_location}' > '#{original_location}'/m)
1079
+ end
1080
+
1081
+ it "doesn't restore a non-existent file" do
1082
+ subject.stub(:backup_the_file)
1083
+ subject.with_puppet_running_on(host, {})
1084
+ expect(host).to execute_commands_matching(/rm -f '#{original_location}'/)
1085
+ end
895
1086
  end
896
1087
  end
897
1088
 
@@ -954,11 +1145,24 @@ describe ClassMixedWithDSLHelpers do
954
1145
  end
955
1146
 
956
1147
  describe '#fact_on' do
957
- it 'retreives a fact on host(s)' do
1148
+ it 'retrieves a fact on a single host' do
1149
+ result.stdout = "family\n"
958
1150
  subject.should_receive(:facter).with('osfamily',{}).once
959
1151
  subject.should_receive(:on).and_return(result)
960
1152
 
961
- subject.fact_on('host','osfamily')
1153
+ expect( subject.fact_on('host','osfamily') ).to be === result.stdout.chomp
1154
+ end
1155
+
1156
+ it 'retrieves an array of facts from multiple hosts' do
1157
+ subject.stub( :hosts ).and_return( hosts )
1158
+ times = hosts.length
1159
+ result.stdout = "family\n"
1160
+ hosts.each do |host|
1161
+ host.should_receive(:exec).and_return(result)
1162
+ end
1163
+
1164
+ expect( subject.fact_on(hosts,'osfamily') ).to be === [result.stdout.chomp] * hosts.length
1165
+
962
1166
  end
963
1167
  end
964
1168
 
@@ -971,6 +1175,61 @@ describe ClassMixedWithDSLHelpers do
971
1175
  end
972
1176
  end
973
1177
 
1178
+ describe 'modify_tk_config' do
1179
+ let(:host) { double.as_null_object }
1180
+ let(:config_file_path) { 'existing-file-path'}
1181
+ let(:invalid_config_file_path) { 'nonexisting-file-path'}
1182
+ let(:options_hash) { {:key => 'value'} }
1183
+ let(:replace) { true }
1184
+
1185
+ shared_examples 'modify-tk-config-without-error' do
1186
+ it 'dumps to the SUT config file path' do
1187
+ JSON.stub(:dump)
1188
+ subject.stub(:create_remote_file).with(host, config_file_path, anything())
1189
+ subject.modify_tk_config(host, config_file_path, options_hash, replace)
1190
+ end
1191
+ end
1192
+
1193
+ before do
1194
+ host.stub(:file_exist?).with(invalid_config_file_path).and_return(false)
1195
+ host.stub(:file_exist?).with(config_file_path).and_return(true)
1196
+ end
1197
+
1198
+ describe 'if file does not exist on SUT' do
1199
+ it 'raises Runtime error' do
1200
+ expect do
1201
+ subject.modify_tk_config(host, invalid_config_file_path, options_hash)
1202
+ end.to raise_error(RuntimeError, /.* does not exist on .*/)
1203
+ end
1204
+ end
1205
+
1206
+ describe 'given an empty options hash' do
1207
+ it 'returns nil' do
1208
+ expect(subject.modify_tk_config(host, 'blahblah', {})).to eq(nil)
1209
+ end
1210
+ end
1211
+
1212
+ describe 'given a non-empty options hash' do
1213
+
1214
+ describe 'given a false value to its `replace` parameter' do
1215
+ let(:replace) { false }
1216
+ before do
1217
+ subject.should_receive(:read_tk_config_string).with(anything())
1218
+ end
1219
+ include_examples('modify-tk-config-without-error')
1220
+ end
1221
+
1222
+ describe 'given a true value to its `replace` parameter' do
1223
+ before do
1224
+ JSON.should_receive(:dump)
1225
+ subject.should_receive(:create_remote_file).with(host, config_file_path, anything())
1226
+ end
1227
+ include_examples('modify-tk-config-without-error')
1228
+ end
1229
+
1230
+ end
1231
+
1232
+ end
974
1233
 
975
1234
  describe 'copy_module_to' do
976
1235
  let(:ignore_list){%w(.git .idea .vagrant .vendor acceptance spec tests log . ..)}
@@ -1073,14 +1332,3 @@ describe ClassMixedWithDSLHelpers do
1073
1332
 
1074
1333
  end
1075
1334
  end
1076
-
1077
- module FakeFS
1078
- class File < StringIO
1079
- def self.absolute_path(filepath)
1080
- RealFile.absolute_path(filepath)
1081
- end
1082
- def self.expand_path(filepath)
1083
- RealFile.expand_path(filepath)
1084
- end
1085
- end
1086
- end