beaker 1.21.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -0
  4. data/CONTRIBUTING.md +1 -0
  5. data/HISTORY.md +17288 -2
  6. data/Rakefile +6 -2
  7. data/beaker.gemspec +15 -19
  8. data/lib/beaker.rb +2 -5
  9. data/lib/beaker/answers.rb +2 -0
  10. data/lib/beaker/answers/version34.rb +37 -1
  11. data/lib/beaker/cli.rb +4 -0
  12. data/lib/beaker/command.rb +16 -84
  13. data/lib/beaker/command_factory.rb +13 -2
  14. data/lib/beaker/dsl/assertions.rb +25 -2
  15. data/lib/beaker/dsl/ezbake_utils.rb +2 -2
  16. data/lib/beaker/dsl/helpers.rb +66 -12
  17. data/lib/beaker/dsl/install_utils.rb +128 -66
  18. data/lib/beaker/dsl/wrappers.rb +41 -3
  19. data/lib/beaker/host.rb +42 -6
  20. data/lib/beaker/host/mac.rb +62 -0
  21. data/lib/beaker/host/mac/group.rb +96 -0
  22. data/lib/beaker/host/mac/user.rb +93 -0
  23. data/lib/beaker/host/unix/exec.rb +1 -1
  24. data/lib/beaker/host/unix/pkg.rb +11 -11
  25. data/lib/beaker/host/windows.rb +4 -4
  26. data/lib/beaker/host_prebuilt_steps.rb +194 -58
  27. data/lib/beaker/hypervisor.rb +16 -9
  28. data/lib/beaker/hypervisor/aws_sdk.rb +61 -17
  29. data/lib/beaker/hypervisor/docker.rb +14 -2
  30. data/lib/beaker/hypervisor/ec2_helper.rb +15 -3
  31. data/lib/beaker/hypervisor/vagrant.rb +22 -10
  32. data/lib/beaker/hypervisor/vagrant_libvirt.rb +11 -0
  33. data/lib/beaker/hypervisor/vagrant_virtualbox.rb +1 -1
  34. data/lib/beaker/hypervisor/vcloud_pooled.rb +8 -39
  35. data/lib/beaker/logger.rb +15 -9
  36. data/lib/beaker/network_manager.rb +2 -2
  37. data/lib/beaker/options/command_line_parser.rb +1 -1
  38. data/lib/beaker/options/parser.rb +1 -8
  39. data/lib/beaker/options/presets.rb +70 -45
  40. data/lib/beaker/perf.rb +3 -4
  41. data/lib/beaker/platform.rb +2 -1
  42. data/lib/beaker/result.rb +3 -9
  43. data/lib/beaker/ssh_connection.rb +2 -0
  44. data/lib/beaker/test_case.rb +2 -21
  45. data/lib/beaker/test_suite.rb +21 -25
  46. data/lib/beaker/version.rb +1 -1
  47. data/spec/beaker/answers_spec.rb +36 -0
  48. data/spec/beaker/cli_spec.rb +45 -45
  49. data/spec/beaker/command_spec.rb +25 -36
  50. data/spec/beaker/dsl/assertions_spec.rb +20 -27
  51. data/spec/beaker/dsl/ezbake_utils_spec.rb +5 -5
  52. data/spec/beaker/dsl/helpers_spec.rb +293 -208
  53. data/spec/beaker/dsl/install_utils_spec.rb +310 -189
  54. data/spec/beaker/dsl/outcomes_spec.rb +6 -6
  55. data/spec/beaker/dsl/roles_spec.rb +27 -18
  56. data/spec/beaker/dsl/structure_spec.rb +11 -11
  57. data/spec/beaker/dsl/wrappers_spec.rb +35 -11
  58. data/spec/beaker/host/mac/group_spec.rb +124 -0
  59. data/spec/beaker/host/mac/user_spec.rb +134 -0
  60. data/spec/beaker/host/unix/pkg_spec.rb +40 -24
  61. data/spec/beaker/host/windows/group_spec.rb +1 -1
  62. data/spec/beaker/host_prebuilt_steps_spec.rb +194 -68
  63. data/spec/beaker/host_spec.rb +145 -67
  64. data/spec/beaker/hypervisor/aixer_spec.rb +6 -6
  65. data/spec/beaker/hypervisor/aws_sdk_spec.rb +22 -7
  66. data/spec/beaker/hypervisor/docker_spec.rb +71 -50
  67. data/spec/beaker/hypervisor/ec2_helper_spec.rb +25 -4
  68. data/spec/beaker/hypervisor/fusion_spec.rb +2 -2
  69. data/spec/beaker/hypervisor/hypervisor_spec.rb +20 -27
  70. data/spec/beaker/hypervisor/hypervisor_spec.rb.orig +80 -0
  71. data/spec/beaker/hypervisor/solaris_spec.rb +8 -8
  72. data/spec/beaker/hypervisor/vagrant_fusion_spec.rb +6 -8
  73. data/spec/beaker/hypervisor/vagrant_libvirt_spec.rb +34 -0
  74. data/spec/beaker/hypervisor/vagrant_spec.rb +34 -33
  75. data/spec/beaker/hypervisor/vagrant_virtualbox_spec.rb +18 -8
  76. data/spec/beaker/hypervisor/vagrant_workstation_spec.rb +6 -8
  77. data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +8 -8
  78. data/spec/beaker/hypervisor/vcloud_spec.rb +10 -10
  79. data/spec/beaker/hypervisor/vsphere_helper_spec.rb +8 -8
  80. data/spec/beaker/hypervisor/vsphere_spec.rb +1 -1
  81. data/spec/beaker/logger_spec.rb +45 -31
  82. data/spec/beaker/options/command_line_parser_spec.rb +10 -2
  83. data/spec/beaker/options/hosts_file_parser_spec.rb +9 -2
  84. data/spec/beaker/options/options_hash_spec.rb +2 -2
  85. data/spec/beaker/options/parser_spec.rb +2 -2
  86. data/spec/beaker/options/pe_version_scaper_spec.rb +6 -1
  87. data/spec/beaker/options/presets_spec.rb +11 -1
  88. data/spec/beaker/shared/error_handler_spec.rb +5 -5
  89. data/spec/beaker/shared/host_manager_spec.rb +3 -2
  90. data/spec/beaker/shared/repetition_spec.rb +18 -18
  91. data/spec/beaker/ssh_connection_spec.rb +33 -4
  92. data/spec/beaker/test_case_spec.rb +9 -9
  93. data/spec/beaker/test_suite_spec.rb +14 -14
  94. data/spec/helpers.rb +4 -4
  95. data/spec/matchers.rb +4 -4
  96. data/spec/mocks.rb +5 -1
  97. data/spec/spec_helper.rb +2 -8
  98. metadata +114 -80
  99. data/lib/beaker/hypervisor/blimper.rb +0 -108
  100. data/spec/beaker/hypervisor/blimper_spec.rb +0 -42
  101. data/spec/beaker/options/data/LATEST +0 -1
  102. data/spec/beaker/puppet_command_spec.rb +0 -161
  103. data/spec/mock_blimpy.rb +0 -48
@@ -129,7 +129,7 @@ module Beaker
129
129
  commands = ["cd #{target}",
130
130
  "remote rm origin",
131
131
  "remote add origin #{repo}",
132
- "fetch origin",
132
+ "fetch origin +refs/pull/*:refs/remotes/origin/pr/* +refs/heads/*:refs/remotes/origin/*",
133
133
  "clean -fdx",
134
134
  "checkout -f #{rev}"]
135
135
  on host, commands.join(" && git ")
@@ -169,23 +169,39 @@ module Beaker
169
169
  log_file = "#{File.basename(host['working_dir'])}.log"
170
170
  pe_debug = host[:pe_debug] || opts[:pe_debug] ? " && cat #{log_file}" : ''
171
171
  "cd #{host['working_dir']} && cmd /C 'start /w msiexec.exe /qn /L*V #{log_file} /i #{host['dist']}.msi PUPPET_MASTER_SERVER=#{master} PUPPET_AGENT_CERTNAME=#{host}'#{pe_debug}"
172
- elsif host['platform'] =~ /osx/
173
- version = host['pe_ver'] || opts[:pe_ver]
174
- pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -verboseR' : ''
175
- "cd #{host['working_dir']} && hdiutil attach #{host['dist']}.dmg && installer#{pe_debug} -pkg /Volumes/puppet-enterprise-#{version}/puppet-enterprise-installer-#{version}.pkg -target /"
176
172
 
177
173
  # Frictionless install didn't exist pre-3.2.0, so in that case we fall
178
174
  # through and do a regular install.
179
175
  elsif host['roles'].include? 'frictionless' and ! version_is_less(version, '3.2.0')
176
+ # PE 3.4 introduced the ability to pass in config options to the bash script in the form
177
+ # of <section>:<key>=<value>
178
+ frictionless_install_opts = []
179
+ if host.has_key?('frictionless_options') and ! version_is_less(version, '3.4.0')
180
+ # since we have options to pass in, we need to tell the bash script
181
+ host['frictionless_options'].each do |section, settings|
182
+ settings.each do |key, value|
183
+ frictionless_install_opts << "#{section}:#{key}=#{value}"
184
+ end
185
+ end
186
+ end
187
+
180
188
  pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -x' : ''
181
- "cd #{host['working_dir']} && curl -kO https://#{master}:8140/packages/#{version}/install.bash && bash#{pe_debug} install.bash"
189
+ "cd #{host['working_dir']} && curl --tlsv1 -kO https://#{master}:8140/packages/#{version}/install.bash && bash#{pe_debug} install.bash #{frictionless_install_opts.join(' ')}".strip
190
+ elsif host['platform'] =~ /osx/
191
+ version = host['pe_ver'] || opts[:pe_ver]
192
+ pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -verboseR' : ''
193
+ "cd #{host['working_dir']} && hdiutil attach #{host['dist']}.dmg && installer#{pe_debug} -pkg /Volumes/puppet-enterprise-#{version}/puppet-enterprise-installer-#{version}.pkg -target /"
194
+ elsif host['platform'] =~ /eos/
195
+ commands = ['enable', "extension puppet-enterprise-#{version}-#{host['platform']}.swix"]
196
+ command = commands.join("\n")
197
+ "Cli -c '#{command}'"
182
198
  else
183
199
  pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -D' : ''
184
200
  "cd #{host['working_dir']}/#{host['dist']} && ./#{host['pe_installer']}#{pe_debug} -a #{host['working_dir']}/answers"
185
201
  end
186
202
  end
187
203
 
188
- #Create the Higgs install command string based upon the host and options settings. Installation command will be run as a
204
+ #Create the Higgs install command string based upon the host and options settings. Installation command will be run as a
189
205
  #background process. The output of the command will be stored in the provided host['higgs_file'].
190
206
  # @param [Host] host The host that Higgs is to be installed on
191
207
  # The host object must have the 'working_dir', 'dist' and 'pe_installer' field set correctly.
@@ -359,14 +375,24 @@ module Beaker
359
375
  on host, "cd #{host['working_dir']}; tar -xvf #{filename}.tar"
360
376
  end
361
377
  else
362
- extension = link_exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
378
+ if host['platform'] =~ /eos/
379
+ extension = '.swix'
380
+ else
381
+ extension = link_exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
382
+ end
363
383
  if not link_exists?("#{path}/#{filename}#{extension}")
364
384
  raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
365
385
  end
366
- unpack = 'tar -xvf -'
367
- unpack = extension =~ /gz/ ? 'gunzip | ' + unpack : unpack
368
386
 
369
- on host, "cd #{host['working_dir']}; curl #{path}/#{filename}#{extension} | #{unpack}"
387
+ if host['platform'] =~ /eos/
388
+ commands = ['enable', "copy #{path}/#{filename}#{extension} extension:"]
389
+ command = commands.join("\n")
390
+ on host, "Cli -c '#{command}'"
391
+ else
392
+ unpack = 'tar -xvf -'
393
+ unpack = extension =~ /gz/ ? 'gunzip | ' + unpack : unpack
394
+ on host, "cd #{host['working_dir']}; curl #{path}/#{filename}#{extension} | #{unpack}"
395
+ end
370
396
  end
371
397
  end
372
398
 
@@ -384,7 +410,7 @@ module Beaker
384
410
  def fetch_puppet(hosts, opts)
385
411
  hosts.each do |host|
386
412
  # We install Puppet from the master for frictionless installs, so we don't need to *fetch* anything
387
- next if host['roles'].include? 'frictionless' and ! version_is_less(opts[:pe_ver] || host['pe_ver'], '3.2.0')
413
+ next if host['roles'].include?('frictionless') && (! version_is_less(opts[:pe_ver] || host['pe_ver'], '3.2.0'))
388
414
 
389
415
  if host['platform'] =~ /windows/
390
416
  fetch_puppet_on_windows(host, opts)
@@ -403,9 +429,9 @@ module Beaker
403
429
  klass = host['platform'].gsub(/-/, '_').gsub(/\./,'')
404
430
  klass = "pe_repo::platform::#{klass}"
405
431
  on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake nodeclass:add[#{klass},skip]"
406
- on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake node:add[#{master}]"
432
+ on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake node:add[#{master},,,skip]"
407
433
  on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake node:addclass[#{master},#{klass}]"
408
- on master, "puppet agent -t", :acceptable_exit_codes => [0,2]
434
+ on master, puppet("agent -t"), :acceptable_exit_codes => [0,2]
409
435
  end
410
436
 
411
437
  #Perform a Puppet Enterprise upgrade or install
@@ -431,6 +457,10 @@ module Beaker
431
457
  pre30database = version_is_less(opts[:pe_ver] || database['pe_ver'], '3.0')
432
458
  pre30master = version_is_less(opts[:pe_ver] || master['pe_ver'], '3.0')
433
459
 
460
+ unless version_is_less(opts[:pe_ver] || master['pe_ver'], '3.4')
461
+ master['puppetservice'] = 'pe-puppetserver'
462
+ end
463
+
434
464
  # Set PE distribution for all the hosts, create working dir
435
465
  use_all_tar = ENV['PE_USE_ALL_TAR'] == 'true'
436
466
  hosts.each do |host|
@@ -466,26 +496,27 @@ module Beaker
466
496
  install_hosts.each do |host|
467
497
  if host['platform'] =~ /windows/
468
498
  on host, installer_cmd(host, opts)
469
- elsif host['platform'] =~ /osx/
470
- on host, installer_cmd(host, opts)
471
- #set the certname and master
472
- on host, puppet("config set server #{master}")
473
- on host, puppet("config set certname #{host}")
474
- #run once to request cert
475
- on host, puppet_agent('-t'), :acceptable_exit_codes => [1]
476
499
  else
477
500
  # We only need answers if we're using the classic installer
478
501
  version = host['pe_ver'] || opts[:pe_ver]
479
- if (! host['roles'].include? 'frictionless') || version_is_less(version, '3.2.0')
480
- answers = Beaker::Answers.create(opts[:pe_ver] || host['pe_ver'], hosts, opts)
481
- create_remote_file host, "#{host['working_dir']}/answers", answers.answer_string(host)
482
- else
502
+ if host['roles'].include?('frictionless') && (! version_is_less(version, '3.2.0'))
483
503
  # If We're *not* running the classic installer, we want
484
504
  # to make sure the master has packages for us.
485
505
  deploy_frictionless_to_master(host)
506
+ on host, installer_cmd(host, opts)
507
+ elsif host['platform'] =~ /osx|eos/
508
+ # If we're not frictionless, we need to run the OSX special-case
509
+ on host, installer_cmd(host, opts)
510
+ #set the certname and master
511
+ on host, puppet("config set server #{master}")
512
+ on host, puppet("config set certname #{host}")
513
+ #run once to request cert
514
+ on host, puppet_agent('-t'), :acceptable_exit_codes => [1]
515
+ else
516
+ answers = Beaker::Answers.create(opts[:pe_ver] || host['pe_ver'], hosts, opts)
517
+ create_remote_file host, "#{host['working_dir']}/answers", answers.answer_string(host)
518
+ on host, installer_cmd(host, opts)
486
519
  end
487
-
488
- on host, installer_cmd(host, opts)
489
520
  end
490
521
 
491
522
  # On each agent, we ensure the certificate is signed then shut down the agent
@@ -531,7 +562,7 @@ module Beaker
531
562
  # @param [Hash{Symbol=>Symbol, String}] opts The options
532
563
  # @option opts [String] :pe_dir Default directory or URL to pull PE package from
533
564
  # (Otherwise uses individual hosts pe_dir)
534
- # @option opts [String] :pe_ver Default PE version to install
565
+ # @option opts [String] :pe_ver Default PE version to install
535
566
  # (Otherwise uses individual hosts pe_ver)
536
567
  # @raise [StandardError] When installation times out
537
568
  #
@@ -597,23 +628,33 @@ module Beaker
597
628
  #Install FOSS based upon host configuration and options
598
629
  # @example will install puppet 3.6.1 from native puppetlabs provided packages wherever possible and will fail over to gem installation when impossible
599
630
  # install_puppet({
600
- # :version => '3.6.1',
601
- # :facter_version => '2.0.1',
602
- # :hiera_version => '1.3.3',
603
- # :default_action => 'gem_install'
631
+ # :version => '3.6.1',
632
+ # :facter_version => '2.0.1',
633
+ # :hiera_version => '1.3.3',
634
+ # :default_action => 'gem_install',
635
+ #
636
+ # })
637
+ #
604
638
  #
605
639
  # @example Will install latest packages on Enterprise Linux and Debian based distros and fail hard on all othere platforms.
606
640
  # install_puppet()
607
641
  #
608
642
  # @note This will attempt to add a repository for apt.puppetlabs.com on
609
- # Debian or Ubuntu machines, or yum.puppetlabs.com on EL or Fedora
643
+ # Debian, Ubuntu, or Cumulus machines, or yum.puppetlabs.com on EL or Fedora
610
644
  # machines, then install the package 'puppet'.
645
+ # @param [Hash{Symbol=>String}] opts
646
+ # @option opts [String] :version Version of puppet to download
647
+ # @option opts [String] :mac_download_url Url to download msi pattern of %url%/puppet-%version%.msi
648
+ # @option opts [String] :win_download_url Url to download dmg pattern of %url%/(puppet|hiera|facter)-%version%.msi
611
649
  #
612
650
  # @api dsl
613
651
  # @return nil
614
652
  # @raise [StandardError] When encountering an unsupported platform by default, or if gem cannot be found when default_action => 'gem_install'
615
653
  # @raise [FailTest] When error occurs during the actual installation process
616
654
  def install_puppet(opts = {})
655
+ default_download_url = 'http://downloads.puppetlabs.com'
656
+ opts = {:win_download_url => "#{default_download_url}/windows",
657
+ :mac_download_url => "#{default_download_url}/mac"}.merge(opts)
617
658
  hosts.each do |host|
618
659
  if host['platform'] =~ /el-(5|6|7)/
619
660
  relver = $1
@@ -621,7 +662,7 @@ module Beaker
621
662
  elsif host['platform'] =~ /fedora-(\d+)/
622
663
  relver = $1
623
664
  install_puppet_from_rpm host, opts.merge(:release => relver, :family => 'fedora')
624
- elsif host['platform'] =~ /(ubuntu|debian)/
665
+ elsif host['platform'] =~ /(ubuntu|debian|cumulus)/
625
666
  install_puppet_from_deb host, opts
626
667
  elsif host['platform'] =~ /windows/
627
668
  relver = opts[:version]
@@ -643,6 +684,22 @@ module Beaker
643
684
  nil
644
685
  end
645
686
 
687
+ # Configure a host entry on the give host
688
+ # @example: will add a host entry for forge.puppetlabs.com
689
+ # add_system32_hosts_entry(host, { :ip => '23.251.154.122', :name => 'forge.puppetlabs.com' })
690
+ #
691
+ # @api dsl
692
+ # @return nil
693
+ def add_system32_hosts_entry(host, opts = {})
694
+ if host['platform'] =~ /windows/
695
+ hosts_file = "C:\\Windows\\System32\\Drivers\\etc\\hosts"
696
+ host_entry = "#{opts['ip']}`t`t#{opts['name']}"
697
+ on host, powershell("\$text = \\\"#{host_entry}\\\"; Add-Content -path '#{hosts_file}' -value \$text")
698
+ else
699
+ raise "nothing to do for #{host.name} on #{host['platform']}"
700
+ end
701
+ end
702
+
646
703
  # Installs Puppet and dependencies using rpm
647
704
  #
648
705
  # @param [Host] host The host to install packages on
@@ -662,7 +719,7 @@ module Beaker
662
719
  def install_puppet_from_rpm( host, opts )
663
720
  release_package_string = "http://yum.puppetlabs.com/puppetlabs-release-#{opts[:family]}-#{opts[:release]}.noarch.rpm"
664
721
 
665
- on host, "rpm -ivh #{release_package_string}"
722
+ on host, "rpm -q --quiet puppetlabs-release || rpm -ivh #{release_package_string}"
666
723
 
667
724
  if opts[:facter_version]
668
725
  on host, "yum install -y facter-#{opts[:facter_version]}"
@@ -720,9 +777,7 @@ module Beaker
720
777
  # @param [Host] host The host to install packages on
721
778
  # @param [Hash{Symbol=>String}] opts An options hash
722
779
  # @option opts [String] :version The version of Puppet to install, required
723
- #
724
- # @return nil
725
- # @api private
780
+ # @option opts [String] :win_download_url The url to download puppet from
726
781
  def install_puppet_from_msi( host, opts )
727
782
  #only install 64bit builds if
728
783
  # - we are on puppet version 3.7+
@@ -734,7 +789,7 @@ module Beaker
734
789
  else
735
790
  host['dist'] = "puppet-#{version}"
736
791
  end
737
- link = "http://downloads.puppetlabs.com/windows/#{host['dist']}.msi"
792
+ link = "#{opts[:win_download_url]}/#{host['dist']}.msi"
738
793
  if not link_exists?( link )
739
794
  raise "Puppet #{version} at #{link} does not exist!"
740
795
  end
@@ -755,6 +810,7 @@ module Beaker
755
810
  # @option opts [String] :version The version of Puppet to install, required
756
811
  # @option opts [String] :facter_version The version of Facter to install, required
757
812
  # @option opts [String] :hiera_version The version of Hiera to install, required
813
+ # @option opts [String] :mac_download_url Url to download msi pattern of %url%/puppet-%version%.msi
758
814
  #
759
815
  # @return nil
760
816
  # @api private
@@ -763,9 +819,9 @@ module Beaker
763
819
  facter_ver = opts[:facter_version]
764
820
  hiera_ver = opts[:hiera_version]
765
821
 
766
- on host, "curl -O http://downloads.puppetlabs.com/mac/puppet-#{puppet_ver}.dmg"
767
- on host, "curl -O http://downloads.puppetlabs.com/mac/facter-#{facter_ver}.dmg"
768
- on host, "curl -O http://downloads.puppetlabs.com/mac/hiera-#{hiera_ver}.dmg"
822
+ on host, "curl -O #{opts[:mac_download_url]}/puppet-#{puppet_ver}.dmg"
823
+ on host, "curl -O #{opts[:mac_download_url]}/facter-#{facter_ver}.dmg"
824
+ on host, "curl -O #{opts[:mac_download_url]}/hiera-#{hiera_ver}.dmg"
769
825
 
770
826
  on host, "hdiutil attach puppet-#{puppet_ver}.dmg"
771
827
  on host, "hdiutil attach facter-#{facter_ver}.dmg"
@@ -806,9 +862,9 @@ module Beaker
806
862
 
807
863
  unless host.check_for_command( 'gem' )
808
864
  gempkg = case host['platform']
809
- when /solaris-11/ then 'ruby-18'
810
- when /ubuntu-14/ then 'ruby'
811
- when /solaris-10|ubuntu|debian|el-/ then 'rubygems'
865
+ when /solaris-11/ then 'ruby-18'
866
+ when /ubuntu-14/ then 'ruby'
867
+ when /solaris-10|ubuntu|debian|el-|cumulus/ then 'rubygems'
812
868
  else
813
869
  raise "install_puppet() called with default_action " +
814
870
  "'gem_install' but program `gem' is " +
@@ -823,7 +879,7 @@ module Beaker
823
879
  on host, 'ln -s /opt/csw/bin/gem /usr/bin/gem'
824
880
  end
825
881
 
826
- if host['platform'] =~ /debian|ubuntu|solaris/
882
+ if host['platform'] =~ /debian|ubuntu|solaris|cumulus/
827
883
  gem_env = YAML.load( on( host, 'gem environment' ).stdout )
828
884
  gem_paths_array = gem_env['RubyGems Environment'].find {|h| h['GEM PATHS'] != nil }['GEM PATHS']
829
885
  path_with_gem = 'export PATH=' + gem_paths_array.join(':') + ':${PATH}'
@@ -930,9 +986,9 @@ module Beaker
930
986
  rpm = options[:release_yum_repo_url] +
931
987
  "/puppetlabs-release-%s-%s.noarch.rpm" % [variant, version]
932
988
 
933
- on host, "rpm -ivh --force #{rpm}"
989
+ on host, "rpm -ivh #{rpm}"
934
990
 
935
- when /^(debian|ubuntu)$/
991
+ when /^(debian|ubuntu|cumulus)$/
936
992
  deb = URI.join(options[:release_apt_repo_url], "puppetlabs-release-%s.deb" % codename)
937
993
 
938
994
  on host, "wget -O /tmp/puppet.deb #{deb}"
@@ -1028,7 +1084,7 @@ module Beaker
1028
1084
 
1029
1085
  on host, find_and_sed
1030
1086
 
1031
- when /^(debian|ubuntu)$/
1087
+ when /^(debian|ubuntu|cumulus)$/
1032
1088
  list = fetch_http_file( "%s/%s/%s/repo_configs/deb/" %
1033
1089
  [ dev_builds_url, package_name, build_version ],
1034
1090
  "pl-%s-%s-%s.list" %
@@ -1131,7 +1187,12 @@ module Beaker
1131
1187
  modname = opts[:module_name]
1132
1188
  end
1133
1189
 
1134
- on h, puppet("module install #{modname} #{version_info}")
1190
+ puppet_opts = {}
1191
+ if host[:default_module_install_opts].respond_to? :merge
1192
+ puppet_opts = host[:default_module_install_opts].merge( puppet_opts )
1193
+ end
1194
+
1195
+ on h, puppet("module install #{modname} #{version_info}", puppet_opts)
1135
1196
  end
1136
1197
  end
1137
1198
 
@@ -1144,7 +1205,7 @@ module Beaker
1144
1205
  # Install local module for acceptance testing
1145
1206
  # should be used as a presuite to ensure local module is copied to the hosts you want, particularly masters
1146
1207
  # @api dsl
1147
- # @param [Host, Array<Host>, String, Symbol] host
1208
+ # @param [Host, Array<Host>, String, Symbol] one_or_more_hosts
1148
1209
  # One or more hosts to act upon,
1149
1210
  # or a role (String or Symbol) that identifies one or more hosts.
1150
1211
  # @option opts [String] :source ('./')
@@ -1160,19 +1221,21 @@ module Beaker
1160
1221
  # @option opts [Array] :ignore_list
1161
1222
  # @raise [ArgumentError] if not host is provided or module_name is not provided and can not be found in Modulefile
1162
1223
  #
1163
- def copy_module_to(host, opts = {})
1164
- opts = {:source => './',
1165
- :target_module_path => host['distmoduledir'],
1166
- :ignore_list => PUPPET_MODULE_INSTALL_IGNORE}.merge(opts)
1167
- ignore_list = build_ignore_list(opts)
1168
- target_module_dir = on( host, "echo #{opts[:target_module_path]}" ).stdout.chomp
1169
- source = File.expand_path( opts[:source] )
1170
- if opts.has_key?(:module_name)
1171
- module_name = opts[:module_name]
1172
- else
1173
- _, module_name = parse_for_modulename( source )
1224
+ def copy_module_to(one_or_more_hosts, opts = {})
1225
+ block_on one_or_more_hosts do |host|
1226
+ opts = {:source => './',
1227
+ :target_module_path => host['distmoduledir'],
1228
+ :ignore_list => PUPPET_MODULE_INSTALL_IGNORE}.merge(opts)
1229
+ ignore_list = build_ignore_list(opts)
1230
+ target_module_dir = on( host, "echo #{opts[:target_module_path]}" ).stdout.chomp
1231
+ source = File.expand_path( opts[:source] )
1232
+ if opts.has_key?(:module_name)
1233
+ module_name = opts[:module_name]
1234
+ else
1235
+ _, module_name = parse_for_modulename( source )
1236
+ end
1237
+ scp_to host, source, File.join(target_module_dir, module_name), {:ignore => ignore_list}
1174
1238
  end
1175
- scp_to host, source, File.join(target_module_dir, module_name), {:ignore => ignore_list}
1176
1239
  end
1177
1240
  alias :copy_root_module_to :copy_module_to
1178
1241
 
@@ -1213,18 +1276,17 @@ module Beaker
1213
1276
  #
1214
1277
  # @return [String,nil]
1215
1278
  def parse_for_moduleroot(possible_module_directory)
1216
- if File.exists?("#{possible_module_directory}/Modulefile")
1279
+ if File.exists?("#{possible_module_directory}/Modulefile") || File.exists?("#{possible_module_directory}/metadata.json")
1217
1280
  possible_module_directory
1218
1281
  elsif possible_module_directory === '/'
1219
1282
  logger.error "At root, can't parse for another directory"
1220
1283
  nil
1221
1284
  else
1222
- logger.debug "No Modulefile found at #{possible_module_directory}, moving up"
1285
+ logger.debug "No Modulefile or metadata.json found at #{possible_module_directory}, moving up"
1223
1286
  parse_for_moduleroot File.expand_path(File.join(possible_module_directory,'..'))
1224
1287
  end
1225
1288
  end
1226
1289
 
1227
-
1228
1290
  #Parse root directory of a module for module name
1229
1291
  # Searches for metadata.json and then if none found, Modulefile and parses for the Name attribute
1230
1292
  # @param [String] root_module_dir
@@ -16,10 +16,22 @@ module Beaker
16
16
  def facter(*args)
17
17
  options = args.last.is_a?(Hash) ? args.pop : {}
18
18
  options['ENV'] ||= {}
19
- options['ENV'] = options['ENV'].merge( Command::DEFAULT_GIT_ENV )
19
+ options[:cmdexe] = true
20
20
  Command.new('facter', args, options )
21
21
  end
22
22
 
23
+ # This is hairy and because of legacy code it will take a bit more
24
+ # work to disentangle all of the things that are being passed into
25
+ # this catchall param.
26
+ #
27
+ # @api dsl
28
+ def cfacter(*args)
29
+ options = args.last.is_a?(Hash) ? args.pop : {}
30
+ options['ENV'] ||= {}
31
+ options[:cmdexe] = true
32
+ Command.new('cfacter', args, options )
33
+ end
34
+
23
35
  # This is hairy and because of legacy code it will take a bit more
24
36
  # work to disentangle all of the things that are being passed into
25
37
  # this catchall param.
@@ -28,7 +40,7 @@ module Beaker
28
40
  def hiera(*args)
29
41
  options = args.last.is_a?(Hash) ? args.pop : {}
30
42
  options['ENV'] ||= {}
31
- options['ENV'] = options['ENV'].merge( Command::DEFAULT_GIT_ENV )
43
+ options[:cmdexe] = true
32
44
  Command.new('hiera', args, options )
33
45
  end
34
46
 
@@ -49,7 +61,7 @@ module Beaker
49
61
  def puppet(*args)
50
62
  options = args.last.is_a?(Hash) ? args.pop : {}
51
63
  options['ENV'] ||= {}
52
- options['ENV'] = options['ENV'].merge( Command::DEFAULT_GIT_ENV )
64
+ options[:cmdexe] = true
53
65
  # we assume that an invocation with `puppet()` will have it's first argument
54
66
  # a face or sub command
55
67
  cmd = "puppet #{args.shift}"
@@ -95,6 +107,32 @@ module Beaker
95
107
  def puppet_filebucket(*args)
96
108
  puppet( 'filebucket', *args )
97
109
  end
110
+
111
+ # Returns a {Beaker::Command} object for executing powershell commands on a host
112
+ #
113
+ # @param [String] command The powershell command to execute
114
+ # @param [Hash] args The commandline paramaeters to be passed to powershell
115
+ #
116
+ # @example Setting the contents of a file
117
+ # powershell("Set-Content -path 'fu.txt' -value 'fu'")
118
+ #
119
+ # @example Using an alternative execution policy
120
+ # powershell("Set-Content -path 'fu.txt' -value 'fu'", {'ExecutionPolicy' => 'Unrestricted'})
121
+ #
122
+ # @return [Command]
123
+ def powershell(command, args={})
124
+ ps_opts = {
125
+ 'ExecutionPolicy' => 'Bypass',
126
+ 'InputFormat' => 'None',
127
+ 'NoLogo' => '',
128
+ 'NoProfile' => '',
129
+ 'NonInteractive' => ''
130
+ }
131
+ ps_opts.merge!(args)
132
+
133
+ arguments = " #{ps_opts.sort.map{|k,v| v.eql?('') ? "-#{k}" : "-#{k} #{v}" }.join(' ')} -Command \"#{command}\""
134
+ Command.new('powershell.exe', arguments, {})
135
+ end
98
136
  end
99
137
  end
100
138
  end