beaker 1.12.2 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
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?