beaker 1.16.0 → 1.17.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 (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