beaker 1.12.2 → 1.13.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 327165664795e4a3418eee13044471c769062bdf
4
- data.tar.gz: 46c4deee7cfdcf64a2f2903246a4a1f54d132b02
5
2
  SHA512:
6
- metadata.gz: 83dd205dea040996a658f04cec6389ba31b8cbccfd38f9dc608fc94bcaee5eca74c718939e0acd7b3794c2aba0236d36a09214279ef678691b903a11c9bb17f0
7
- data.tar.gz: b4c851da76c6e21e4e6a8a5ba3ff229f09b9432dc0a409ccdd52cc221ad9e43868c1c9f3c11e343d57b7ecf18d3dde7601166ad94120cff45c832481b272fb1c
3
+ metadata.gz: 04798de71557fef76c3111cf6726848d4d2210228bf6e25b2a62f4b6d6e9f6dad68941d8a6d1f82bdaac20a17b489c368c7f0eeffb74d737d3d6ab97a5081a9f
4
+ data.tar.gz: b4c13c397bb66622d416b79c89d90e26e2a35375816be593a0a2fbb8a635710d35d5a296fd73189dcf707150cf4cd7e0c0bca2d5a57f4bb41d5237a12819e29e
5
+ SHA1:
6
+ metadata.gz: 78d3632cc61dad21e8198a67510fe578da1be559
7
+ data.tar.gz: a0443c85c98bcbe560d41ad0aa5c4215dceecf49
@@ -41,7 +41,7 @@ Gem::Specification.new do |s|
41
41
  s.add_runtime_dependency 'blimpy', '~> 0.6'
42
42
  s.add_runtime_dependency 'fission', '~> 0.4'
43
43
  s.add_runtime_dependency 'google-api-client', '~> 0.7.1'
44
- s.add_runtime_dependency 'aws-sdk', '~> 1.38'
44
+ s.add_runtime_dependency 'aws-sdk', '1.42.0'
45
45
  s.add_runtime_dependency 'docker-api' unless RUBY_VERSION < '1.9'
46
46
 
47
47
  # These are transitive dependencies that we include or pin to because...
@@ -10,6 +10,7 @@ module Beaker
10
10
  | | | "
11
11
 
12
12
  def initialize
13
+ @timestamp = Time.now
13
14
  @options_parser = Beaker::Options::Parser.new
14
15
  @options = @options_parser.parse_args
15
16
  @logger = Beaker::Logger.new(@options)
@@ -132,7 +133,7 @@ module Beaker
132
133
  return
133
134
  end
134
135
  Beaker::TestSuite.new(
135
- suite_name, @hosts, @options, failure_strategy
136
+ suite_name, @hosts, @options, @timestamp, failure_strategy
136
137
  ).run_and_raise_on_failure
137
138
  end
138
139
 
@@ -273,6 +273,40 @@ module Beaker
273
273
  end
274
274
  end
275
275
 
276
+ # Create a temp directory on remote host owned by specified user.
277
+ #
278
+ # @param [Host] host A single remote host on which to create and adjust
279
+ # the ownership of a temp directory.
280
+ # @param [String] name A remote path prefix for the new temp
281
+ # directory. Default value is '/tmp/beaker'
282
+ # @param [String] user The name of user that should own the temp
283
+ # directory. If no username is specified, use `puppet master
284
+ # --configprint user` to obtain username from master. Raise RuntimeError
285
+ # if this puppet command returns a non-zero exit code.
286
+ #
287
+ # @return [String] Returns the name of the newly-created file.
288
+ def create_tmpdir_for_user(host, name='/tmp/beaker', user=nil)
289
+ if not user
290
+ result = on(host, "puppet master --configprint user")
291
+ if not result.exit_code == 0
292
+ raise "`puppet master --configprint` failed, check that puppet is installed on #{host} or explicitly pass in a user name."
293
+ end
294
+ user = result.stdout.strip
295
+ end
296
+
297
+ if not on(host, "getent passwd #{user}").exit_code == 0
298
+ raise "User #{user} does not exist on #{host}."
299
+ end
300
+
301
+ if defined? host.tmpdir
302
+ dir = host.tmpdir(name)
303
+ on host, "chown #{user}.#{user} #{dir}"
304
+ return dir
305
+ else
306
+ raise "Host platform not supported by `create_tmpdir_for_user`."
307
+ end
308
+ end
309
+
276
310
  # Move a local script to a remote host and execute it
277
311
  # @note this relies on {#on} and {#scp_to}
278
312
  #
@@ -718,6 +752,10 @@ module Beaker
718
752
  # from Puppet verion 3.2
719
753
  # By default it will use the 'current' parser.
720
754
  #
755
+ # @option opts [Boolean] :noop (false) If this option exists, the
756
+ # the "--noop" command line parameter will be
757
+ # passed to the 'puppet apply' command.
758
+ #
721
759
  # @option opts [String] :modulepath The search path for modules, as
722
760
  # a list of directories separated by the system
723
761
  # path separator character. (The POSIX path separator
@@ -737,36 +775,42 @@ module Beaker
737
775
  on_options = {}
738
776
  on_options[:acceptable_exit_codes] = Array(opts[:acceptable_exit_codes])
739
777
 
740
- args = ["--verbose"]
741
- args << "--parseonly" if opts[:parseonly]
742
- args << "--trace" if opts[:trace]
743
- args << "--parser future" if opts[:future_parser]
744
- args << "--modulepath #{opts[:modulepath]}" if opts[:modulepath]
778
+ puppet_apply_opts = {}
779
+ puppet_apply_opts[:verbose] = nil
780
+ puppet_apply_opts[:parseonly] = nil if opts[:parseonly]
781
+ puppet_apply_opts[:trace] = nil if opts[:trace]
782
+ puppet_apply_opts[:parser] = 'future' if opts[:future_parser]
783
+ puppet_apply_opts[:modulepath] = opts[:modulepath] if opts[:modulepath]
784
+ puppet_apply_opts[:noop] = nil if opts[:noop]
745
785
 
746
786
  # From puppet help:
747
787
  # "... an exit code of '2' means there were changes, an exit code of
748
788
  # '4' means there were failures during the transaction, and an exit
749
789
  # code of '6' means there were both changes and failures."
750
- if [opts[:catch_changes],opts[:catch_failures],opts[:expect_failures],opts[:expect_changes]].select{|x|x}.length > 1
751
- raise(ArgumentError, "Cannot specify more than one of `catch_failures`, `catch_changes`, `expect_failures`, or `expect_changes` for a single manifest")
790
+ if [opts[:catch_changes],opts[:catch_failures],opts[:expect_failures],opts[:expect_changes]].compact.length > 1
791
+ raise(ArgumentError,
792
+ 'Cannot specify more than one of `catch_failures`, ' +
793
+ '`catch_changes`, `expect_failures`, or `expect_changes` ' +
794
+ 'for a single manifest')
752
795
  end
796
+
753
797
  if opts[:catch_changes]
754
- args << '--detailed-exitcodes'
798
+ puppet_apply_opts['detailed-exitcodes'] = nil
755
799
 
756
800
  # We're after idempotency so allow exit code 0 only.
757
801
  on_options[:acceptable_exit_codes] |= [0]
758
802
  elsif opts[:catch_failures]
759
- args << '--detailed-exitcodes'
803
+ puppet_apply_opts['detailed-exitcodes'] = nil
760
804
 
761
805
  # We're after only complete success so allow exit codes 0 and 2 only.
762
806
  on_options[:acceptable_exit_codes] |= [0, 2]
763
807
  elsif opts[:expect_failures]
764
- args << '--detailed-exitcodes'
808
+ puppet_apply_opts['detailed-exitcodes'] = nil
765
809
 
766
810
  # We're after failures specifically so allow exit codes 1, 4, and 6 only.
767
811
  on_options[:acceptable_exit_codes] |= [1, 4, 6]
768
812
  elsif opts[:expect_changes]
769
- args << '--detailed-exitcodes'
813
+ puppet_apply_opts['detailed-exitcodes'] = nil
770
814
 
771
815
  # We're after changes specifically so allow exit code 2 only.
772
816
  on_options[:acceptable_exit_codes] |= [2]
@@ -784,13 +828,17 @@ module Beaker
784
828
  # value of *args to a new hash with just one entry (the value of which
785
829
  # is our environment variables hash)
786
830
  if opts.has_key?(:environment)
787
- args << { :environment => opts[:environment]}
831
+ puppet_apply_opts['ENV'] = opts[:environment]
788
832
  end
789
833
 
790
834
  file_path = host.tmpfile('apply_manifest.pp')
791
835
  create_remote_file(host, file_path, manifest + "\n")
792
- args << file_path
793
- on host, puppet( 'apply', *args), on_options, &block
836
+
837
+ if host[:default_apply_opts].respond_to? :merge
838
+ puppet_apply_opts = host[:default_apply_opts].merge( puppet_apply_opts )
839
+ end
840
+
841
+ on host, puppet('apply', file_path, puppet_apply_opts), on_options, &block
794
842
  end
795
843
 
796
844
  # Runs 'puppet apply' on default host, piping manifest through stdin
@@ -916,18 +964,26 @@ module Beaker
916
964
  retry_command(desc, host, "curl -m 1 #{url}", desired_exit_codes, max_retries, retry_interval)
917
965
  end
918
966
 
919
- def retry_command(desc, host, command, desired_exit_codes = 0, max_retries = 60, retry_interval = 1)
967
+ def retry_command(desc, host, command, desired_exit_codes = 0,
968
+ max_retries = 60, retry_interval = 1, verbose = false)
969
+ log_prefix = host.log_prefix
970
+ @logger.debug "\n#{log_prefix} #{Time.new.strftime('%H:%M:%S')}$ #{command}"
971
+ @logger.debug " Trying command #{max_retries} times."
972
+ @logger.debug ".", add_newline=false
920
973
  desired_exit_codes = [desired_exit_codes].flatten
921
- result = on host, command, :acceptable_exit_codes => (0...127)
974
+ result = on host, command, {:acceptable_exit_codes => (0...127), :silent => !verbose}
922
975
  num_retries = 0
923
976
  until desired_exit_codes.include?(result.exit_code)
924
977
  sleep retry_interval
925
- result = on host, command, :acceptable_exit_codes => (0...127)
978
+ result = on host, command, {:acceptable_exit_codes => (0...127), :silent => !verbose}
926
979
  num_retries += 1
980
+ @logger.debug ".", add_newline=false
927
981
  if (num_retries > max_retries)
928
- fail("Unable to #{desc}")
982
+ @logger.debug " Command \`#{command}\` failed."
983
+ fail("Command \`#{command}\` failed.")
929
984
  end
930
985
  end
986
+ @logger.debug "\n#{log_prefix} #{Time.new.strftime('%H:%M:%S')}$ #{command} ostensibly successful."
931
987
  end
932
988
 
933
989
  #Is semver-ish version a less than semver-ish version b
@@ -352,9 +352,11 @@ module Beaker
352
352
 
353
353
  fetch_puppet(hosts, opts)
354
354
 
355
- hosts.each do |host|
356
- # Database host was added in 3.0. Skip it if installing an older version
357
- next if host == database and host != master and host != dashboard and pre30database
355
+ # If we're installing a database version less than 3.0, ignore the database host
356
+ install_hosts = hosts.dup
357
+ install_hosts.delete(database) if pre30database and database != master and database != dashboard
358
+
359
+ install_hosts.each do |host|
358
360
  if host['platform'] =~ /windows/
359
361
  on host, installer_cmd(host, opts)
360
362
  elsif host['platform'] =~ /osx/
@@ -378,14 +380,8 @@ module Beaker
378
380
 
379
381
  on host, installer_cmd(host, opts)
380
382
  end
381
- end
382
383
 
383
- # If we're installing a database version less than 3.0, ignore the database host
384
- install_hosts = hosts.dup
385
- install_hosts.delete(database) if pre30database and database != master and database != dashboard
386
-
387
- # On each agent, we ensure the certificate is signed then shut down the agent
388
- install_hosts.each do |host|
384
+ # On each agent, we ensure the certificate is signed then shut down the agent
389
385
  sign_certificate_for(host)
390
386
  stop_agent_on(host)
391
387
  end
@@ -440,57 +436,194 @@ module Beaker
440
436
  special_nodes + real_agents
441
437
  end
442
438
 
443
- #Install POSS based upon host configuration and options
444
- # @example
445
- # install_puppet
439
+ #Install FOSS based upon host configuration and options
440
+ # @example will install puppet 3.6.1 from native puppetlabs provided packages wherever possible and will fail over to gem installation when impossible
441
+ # install_puppet({
442
+ # :version => '3.6.1',
443
+ # :facter_version => '2.0.1',
444
+ # :hiera_version => '1.3.3',
445
+ # :default_action => 'gem_install'
446
+ #
447
+ # @example Will install latest packages on Enterprise Linux and Debian based distros and fail hard on all othere platforms.
448
+ # install_puppet()
446
449
  #
447
450
  # @note This will attempt to add a repository for apt.puppetlabs.com on
448
451
  # Debian or Ubuntu machines, or yum.puppetlabs.com on EL or Fedora
449
- # machines, then install the package 'puppet'
452
+ # machines, then install the package 'puppet'.
450
453
  #
451
454
  # @api dsl
452
455
  # @return nil
456
+ # @raise [StandardError] When encountering an unsupported platform by default, or if gem cannot be found when default_action => 'gem_install'
457
+ # @raise [FailTest] When error occurs during the actual installation process
453
458
  def install_puppet(opts = {})
454
459
  hosts.each do |host|
455
460
  if host['platform'] =~ /el-(5|6|7)/
456
461
  relver = $1
457
- on host, "rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-el-#{relver}.noarch.rpm"
458
- on host, 'yum install -y puppet'
462
+ install_puppet_from_rpm host, opts.merge(:release => relver, :family => 'el')
459
463
  elsif host['platform'] =~ /fedora-(\d+)/
460
464
  relver = $1
461
- on host, "rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-fedora-#{relver}.noarch.rpm"
462
- on host, 'yum install -y puppet'
465
+ install_puppet_from_rpm host, opts.merge(:release => relver, :family => 'fedora')
463
466
  elsif host['platform'] =~ /(ubuntu|debian)/
464
- if ! host.check_for_package 'lsb-release'
465
- host.install_package('lsb-release')
466
- end
467
- if ! host.check_for_package 'curl'
468
- on host, 'apt-get install -y curl'
469
- end
470
- on host, 'curl -O http://apt.puppetlabs.com/puppetlabs-release-$(lsb_release -c -s).deb'
471
- on host, 'dpkg -i puppetlabs-release-$(lsb_release -c -s).deb'
472
- on host, 'apt-get update'
473
- on host, 'apt-get install -y puppet'
467
+ install_puppet_from_deb host, opts
474
468
  elsif host['platform'] =~ /windows/
475
469
  relver = opts[:version]
476
- on host, "curl -O http://downloads.puppetlabs.com/windows/puppet-#{relver}.msi"
477
- on host, "msiexec /qn /i puppet-#{relver}.msi"
478
-
479
- #Because the msi installer doesn't add Puppet to the environment path
480
- if fact_on(host, 'architecture').eql?('x86_64')
481
- install_dir = '/cygdrive/c/Program Files (x86)/Puppet Labs/Puppet/bin'
470
+ install_puppet_from_msi host, opts
471
+ elsif host['platform'] =~ /osx/
472
+ install_puppet_from_dmg host, opts
473
+ else
474
+ if opts[:default_action] == 'gem_install'
475
+ install_puppet_from_gem host, opts
482
476
  else
483
- install_dir = '/cygdrive/c/Program Files/Puppet Labs/Puppet/bin'
477
+ raise "install_puppet() called for unsupported platform '#{host['platform']}' on '#{host.name}'"
484
478
  end
485
- on host, %Q{ echo 'export PATH=$PATH:"#{install_dir}"' > /etc/bash.bashrc }
486
-
487
- else
488
- raise "install_puppet() called for unsupported platform '#{host['platform']}' on '#{host.name}'"
489
479
  end
490
480
  end
491
481
  nil
492
482
  end
493
483
 
484
+ # Installs Puppet and dependencies using rpm
485
+ #
486
+ # @param [Host] host The host to install packages on
487
+ # @param [Hash{Symbol=>String}] opts An options hash
488
+ # @option opts [String] :version The version of Puppet to install, if nil installs latest version
489
+ # @option opts [String] :facter_version The version of Facter to install, if nil installs latest version
490
+ # @option opts [String] :hiera_version The version of Hiera to install, if nil installs latest version
491
+ # @option opts [String] :default_action What to do if we don't know how to install native packages on host.
492
+ # Valid value is 'gem_install' or nil. If nil raises an exception when
493
+ # on an unsupported platform. When 'gem_install' attempts to install
494
+ # Puppet via gem.
495
+ # @option opts [String] :release The major release of the OS
496
+ # @option opts [String] :family The OS family (one of 'el' or 'fedora')
497
+ #
498
+ # @return nil
499
+ # @api private
500
+ def install_puppet_from_rpm( host, opts )
501
+ release_package_string = "http://yum.puppetlabs.com/puppetlabs-release-#{opts[:family]}-#{opts[:release]}.noarch.rpm"
502
+
503
+ on host, "rpm -ivh #{release_package_string}"
504
+
505
+ if opts[:facter_version]
506
+ on host, "yum install -y facter-#{opts[:facter_version]}"
507
+ end
508
+
509
+ if opts[:hiera_version]
510
+ on host, "yum install -y hiera-#{opts[:hiera_version]}"
511
+ end
512
+
513
+ puppet_pkg = opts[:version] ? "puppet-#{opts[:version]}" : 'puppet'
514
+ on host, "yum install -y #{puppet_pkg}"
515
+ end
516
+
517
+ # Installs Puppet and dependencies from deb
518
+ #
519
+ # @param [Host] host The host to install packages on
520
+ # @param [Hash{Symbol=>String}] opts An options hash
521
+ # @option opts [String] :version The version of Puppet to install, if nil installs latest version
522
+ # @option opts [String] :facter_version The version of Facter to install, if nil installs latest version
523
+ # @option opts [String] :hiera_version The version of Hiera to install, if nil installs latest version
524
+ #
525
+ # @return nil
526
+ # @api private
527
+ def install_puppet_from_deb( host, opts )
528
+ if ! host.check_for_package 'lsb-release'
529
+ host.install_package('lsb-release')
530
+ end
531
+
532
+ if ! host.check_for_package 'curl'
533
+ on host, 'apt-get install -y curl'
534
+ end
535
+
536
+ on host, 'curl -O http://apt.puppetlabs.com/puppetlabs-release-$(lsb_release -c -s).deb'
537
+ on host, 'dpkg -i puppetlabs-release-$(lsb_release -c -s).deb'
538
+ on host, 'apt-get update'
539
+
540
+ if opts[:facter_version]
541
+ on host, "apt-get install -y facter=#{opts[:facter_version]}-1puppetlabs1"
542
+ end
543
+
544
+ if opts[:hiera_version]
545
+ on host, "apt-get install -y hiera=#{opts[:hiera_version]}-1puppetlabs1"
546
+ end
547
+
548
+ puppet_pkg = opts[:version] ? "puppet=#{opts[:version]}-1puppetlabs1" : 'puppet'
549
+ on host, "apt-get install -y #{puppet_pkg}"
550
+ end
551
+
552
+ # Installs Puppet and dependencies from msi
553
+ #
554
+ # @param [Host] host The host to install packages on
555
+ # @param [Hash{Symbol=>String}] opts An options hash
556
+ # @option opts [String] :version The version of Puppet to install, required
557
+ #
558
+ # @return nil
559
+ # @api private
560
+ def install_puppet_from_msi( host, opts )
561
+ on host, "curl -O http://downloads.puppetlabs.com/windows/puppet-#{opts[:version]}.msi"
562
+ on host, "msiexec /qn /i puppet-#{relver}.msi"
563
+
564
+ #Because the msi installer doesn't add Puppet to the environment path
565
+ if fact_on(host, 'architecture').eql?('x86_64')
566
+ install_dir = '/cygdrive/c/Program Files (x86)/Puppet Labs/Puppet/bin'
567
+ else
568
+ install_dir = '/cygdrive/c/Program Files/Puppet Labs/Puppet/bin'
569
+ end
570
+ on host, %Q{ echo 'export PATH=$PATH:"#{install_dir}"' > /etc/bash.bashrc }
571
+ end
572
+
573
+ # Installs Puppet and dependencies from dmg
574
+ #
575
+ # @param [Host] host The host to install packages on
576
+ # @param [Hash{Symbol=>String}] opts An options hash
577
+ # @option opts [String] :version The version of Puppet to install, required
578
+ # @option opts [String] :facter_version The version of Facter to install, required
579
+ # @option opts [String] :hiera_version The version of Hiera to install, required
580
+ #
581
+ # @return nil
582
+ # @api private
583
+ def install_puppet_from_dmg( host, opts )
584
+ puppet_ver = opts[:version]
585
+ facter_ver = opts[:facter_version]
586
+ hiera_ver = opts[:hiera_version]
587
+
588
+ on host, "curl -O http://downloads.puppetlabs.com/mac/puppet-#{puppet_ver}.dmg"
589
+ on host, "curl -O http://downloads.puppetlabs.com/mac/facter-#{facter_ver}.dmg"
590
+ on host, "curl -O http://downloads.puppetlabs.com/mac/hiera-#{hiera_ver}.dmg"
591
+
592
+ on host, "hdiutil attach puppet-#{puppet_ver}.dmg"
593
+ on host, "hdiutil attach facter-#{facter_ver}.dmg"
594
+ on host, "hdiutil attach hiera-#{hiera_ver}.dmg"
595
+
596
+ on host, "installer -pkg /Volumes/puppet-#{puppet_ver}/puppet-#{puppet_ver}.pkg -target /"
597
+ on host, "installer -pkg /Volumes/facter-#{facter_ver}/facter-#{facter_ver}.pkg -target /"
598
+ on host, "installer -pkg /Volumes/hiera-#{hiera_ver}/hiera-#{hiera_ver}.pkg -target /"
599
+ end
600
+
601
+ # Installs Puppet and dependencies from gem
602
+ #
603
+ # @param [Host] host The host to install packages on
604
+ # @param [Hash{Symbol=>String}] opts An options hash
605
+ # @option opts [String] :version The version of Puppet to install, if nil installs latest
606
+ # @option opts [String] :facter_version The version of Facter to install, if nil installs latest
607
+ # @option opts [String] :hiera_version The version of Hiera to install, if nil installs latest
608
+ #
609
+ # @return nil
610
+ # @raise [StandardError] if gem does not exist on target host
611
+ # @api private
612
+ def install_puppet_from_gem( host, opts )
613
+ if host.check_for_package( 'gem' )
614
+ if opts[:facter_version]
615
+ on host, "gem install facter -v#{opts[:facter_version]}"
616
+ end
617
+ if opts[:hiera_version]
618
+ on host, "gem install hiera -v#{opts[:hiera_version]}"
619
+ end
620
+ ver_cmd = opts[:version] ? "-v#{opts[:version]}" : ''
621
+ on host, "gem install puppet #{ver_cmd}"
622
+ else
623
+ raise "install_puppet() called with default_action 'gem_install' but program `gem' not installed on #{host.name}"
624
+ end
625
+ end
626
+
494
627
  #Install PE based upon host configuration and options
495
628
  # @example
496
629
  # install_pe
@@ -12,7 +12,7 @@ module Beaker
12
12
 
13
13
  class CommandFailure < StandardError; end
14
14
 
15
- # This class providers array syntax for using puppet --configprint on a host
15
+ # This class provides array syntax for using puppet --configprint on a host
16
16
  class PuppetConfigReader
17
17
  def initialize(host, command)
18
18
  @host = host
@@ -158,7 +158,7 @@ module Beaker
158
158
  def connection
159
159
  @connection ||= SshConnection.connect( reachable_name,
160
160
  self['user'],
161
- self['ssh'] )
161
+ self['ssh'], { :logger => @logger } )
162
162
  end
163
163
 
164
164
  def close
@@ -186,7 +186,10 @@ module Beaker
186
186
  seconds = Benchmark.realtime {
187
187
  result = connection.execute(cmdline, options, output_callback)
188
188
  }
189
- @logger.debug "\n#{log_prefix} executed in %0.2f seconds" % seconds
189
+
190
+ if not options[:silent]
191
+ @logger.debug "\n#{log_prefix} executed in %0.2f seconds" % seconds
192
+ end
190
193
 
191
194
  unless options[:silent]
192
195
  # What?