beaker 1.7.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -205,6 +205,7 @@ module Beaker
205
205
  else
206
206
  the_answers[h.name] = host_answers(h, master_certname, master, database, dashboard, options)
207
207
  end
208
+ h[:answers] = the_answers[h.name]
208
209
  end
209
210
  return the_answers
210
211
  end
@@ -21,7 +21,9 @@ module Beaker
21
21
  # awesome.
22
22
  the_answers[dashboard.name][:q_upgrade_with_unknown_disk_space] = 'y'
23
23
  end
24
-
24
+ hosts.each do |h|
25
+ h[:answers] = the_answers[h.name]
26
+ end
25
27
  return the_answers
26
28
  end
27
29
  end
@@ -70,7 +70,10 @@ module Beaker
70
70
  # @raise [FailTest] Raises an exception if *command* obviously fails.
71
71
  def on(host, command, opts = {}, &block)
72
72
  unless command.is_a? Command
73
- cmd_opts = opts[:environment] ? { 'ENV' => opts.delete(:environment) } : Hash.new
73
+ cmd_opts = {}
74
+ if opts[:environment]
75
+ cmd_opts['ENV'] = opts[:environment]
76
+ end
74
77
  command = Command.new(command.to_s, [], cmd_opts)
75
78
  end
76
79
  if host.is_a? String or host.is_a? Symbol
@@ -82,7 +85,16 @@ module Beaker
82
85
  @result = host.exec(command, opts)
83
86
 
84
87
  # Also, let additional checking be performed by the caller.
85
- yield self if block_given?
88
+ if block_given?
89
+ case block.arity
90
+ #block with arity of 0, just hand back yourself
91
+ when 0
92
+ yield self
93
+ #block with arity of 1 or greater, hand back the result object
94
+ else
95
+ yield @result
96
+ end
97
+ end
86
98
 
87
99
  return @result
88
100
  end
@@ -453,7 +465,8 @@ module Beaker
453
465
  # @api dsl
454
466
  def with_puppet_running_on host, conf_opts, testdir = host.tmpdir(File.basename(@path)), &block
455
467
  raise(ArgumentError, "with_puppet_running_on's conf_opts must be a Hash. You provided a #{conf_opts.class}: '#{conf_opts}'") if !conf_opts.kind_of?(Hash)
456
- cmdline_args = conf_opts.delete(:__commandline_args__)
468
+ cmdline_args = conf_opts[:__commandline_args__]
469
+ conf_opts = conf_opts.reject { |k,v| k == :__commandline_args__ }
457
470
 
458
471
  begin
459
472
  backup_file = backup_the_file(host, host['puppetpath'], testdir, 'puppet.conf')
@@ -486,6 +499,14 @@ module Beaker
486
499
  end
487
500
 
488
501
  rescue Exception => teardown_exception
502
+ begin
503
+ if !host.is_pe?
504
+ dump_puppet_log(host)
505
+ end
506
+ rescue Exception => dumping_exception
507
+ logger.error("Raised during attempt to dump puppet logs: #{dumping_exception}")
508
+ end
509
+
489
510
  if original_exception
490
511
  logger.error("Raised during attempt to teardown with_puppet_running_on: #{teardown_exception}\n---\n")
491
512
  raise original_exception
@@ -453,10 +453,10 @@ module Beaker
453
453
  hosts.each do |host|
454
454
  host['pe_dir'] ||= options[:pe_dir]
455
455
  if host['platform'] =~ /windows/
456
- host['pe_ver'] = host['pe_ver'] ||
456
+ host['pe_ver'] = host['pe_ver'] || options['pe_ver'] ||
457
457
  Beaker::Options::PEVersionScraper.load_pe_version(host[:pe_dir], options[:pe_version_file_win])
458
458
  else
459
- host['pe_ver'] = host['pe_ver'] ||
459
+ host['pe_ver'] = host['pe_ver'] || options['pe_ver'] ||
460
460
  Beaker::Options::PEVersionScraper.load_pe_version(host[:pe_dir], options[:pe_version_file])
461
461
  end
462
462
  end
@@ -478,9 +478,11 @@ module Beaker
478
478
  hosts.each do |host|
479
479
  host['pe_dir'] = host['pe_upgrade_dir'] || path
480
480
  if host['platform'] =~ /windows/
481
- host['pe_ver'] = host['pe_upgrade_ver'] || Options::PEVersionScraper.load_pe_version(host['pe_dir'], options[:pe_version_file_win])
481
+ host['pe_ver'] = host['pe_upgrade_ver'] || options['pe_upgrade_ver'] ||
482
+ Options::PEVersionScraper.load_pe_version(host['pe_dir'], options[:pe_version_file_win])
482
483
  else
483
- host['pe_ver'] = host['pe_upgrade_ver'] || Options::PEVersionScraper.load_pe_version(host['pe_dir'], options[:pe_version_file])
484
+ host['pe_ver'] = host['pe_upgrade_ver'] || options['pe_upgrade_ver'] ||
485
+ Options::PEVersionScraper.load_pe_version(host['pe_dir'], options[:pe_version_file])
484
486
  end
485
487
  if version_is_less(host['pe_ver'], '3.0')
486
488
  host['pe_installer'] ||= 'puppet-enterprise-upgrader'
@@ -180,8 +180,7 @@ module Beaker
180
180
  # exit codes at the host level and then raising...
181
181
  # is it necessary to break execution??
182
182
  unless result.exit_code_in?(Array(options[:acceptable_exit_codes] || 0))
183
- limit = 10
184
- raise CommandFailure, "Host '#{self}' exited with #{result.exit_code} running:\n #{cmdline}\nLast #{limit} lines of output were:\n#{result.formatted_output(limit)}"
183
+ raise CommandFailure, "Host '#{self}' exited with #{result.exit_code} running:\n #{cmdline}\nLast #{@options[:trace_limit]} lines of output were:\n#{result.formatted_output(@options[:trace_limit])}"
185
184
  end
186
185
  end
187
186
  # Danger, so we have to return this result?
@@ -11,6 +11,10 @@ module Beaker
11
11
  @logger = options[:logger]
12
12
  @options = options
13
13
  @fusion_hosts = fusion_hosts
14
+ #check preconditions for fusion
15
+ @fusion_hosts.each do |host|
16
+ raise "You must specify a snapshot for Fusion instances, no snapshot defined for #{host.name}!" unless host["snapshot"]
17
+ end
14
18
  @fission = Fission::VM
15
19
  end
16
20
 
@@ -23,10 +27,14 @@ module Beaker
23
27
  vm = @fission.new vm_name
24
28
  raise "Could not find VM '#{vm_name}' for #{host.name}!" unless vm.exists?
25
29
 
26
- available_snapshots = vm.snapshots.data.sort.join(", ")
30
+ vm_snapshots = vm.snapshots.data
31
+ if vm_snapshots.nil? or vm_snapshots.empty?
32
+ raise "No snapshots available for VM #{host.name} (vmname: '#{vm_name}')"
33
+ end
34
+
35
+ available_snapshots = vm_snapshots.sort.join(", ")
27
36
  @logger.notify "Available snapshots for #{host.name}: #{available_snapshots}"
28
37
  snap_name = host["snapshot"]
29
- raise "No snapshot specified for #{host.name}" unless snap_name
30
38
  raise "Could not find snapshot '#{snap_name}' for host #{host.name}!" unless vm.snapshots.data.include? snap_name
31
39
 
32
40
  @logger.notify "Reverting #{host.name} to snapshot '#{snap_name}'"
@@ -55,6 +55,9 @@ module Beaker
55
55
  start = Time.now
56
56
  try = 1
57
57
  @vcloud_hosts.each_with_index do |h, i|
58
+ if not h['template']
59
+ raise ArgumentError, "You must specify a template name for #{h}"
60
+ end
58
61
  if h['template'] =~ /\//
59
62
  templatefolders = h['template'].split('/')
60
63
  h['template'] = templatefolders.pop
@@ -5,14 +5,12 @@ module Beaker
5
5
  #An Object that parses, merges and normalizes all supported Beaker options and arguments
6
6
  class Parser
7
7
  GITREPO = 'git://github.com/puppetlabs'
8
- #These options can have the form of arg1,arg2 or [arg] or just arg,
8
+ #These options can have the form of arg1,arg2 or [arg] or just arg,
9
9
  #should default to []
10
10
  LONG_OPTS = [:helper, :load_path, :tests, :pre_suite, :post_suite, :install, :modules]
11
11
  #These options expand out into an array of .rb files
12
12
  RB_FILE_OPTS = [:tests, :pre_suite, :post_suite]
13
13
 
14
- PLATFORMS = /^(centos|fedora|debian|oracle|redhat|scientific|sles|ubuntu|windows|solaris|aix|el)\-.+\-.+$/
15
-
16
14
  PARSE_ERROR = if RUBY_VERSION > '1.8.7'; then Psych::SyntaxError; else ArgumentError; end
17
15
 
18
16
  #The OptionsHash of all parsed options
@@ -41,7 +39,7 @@ module Beaker
41
39
  # or can become an array of multiple values by splitting arg over ','. If argument is already an
42
40
  # array that array is returned untouched.
43
41
  # @example
44
- # split_arg([1, 2, 3]) == [1, 2, 3]
42
+ # split_arg([1, 2, 3]) == [1, 2, 3]
45
43
  # split_arg(1) == [1]
46
44
  # split_arg("1,2") == ["1", "2"]
47
45
  # split_arg(nil) == []
@@ -71,9 +69,9 @@ module Beaker
71
69
  files = []
72
70
  if not paths.empty?
73
71
  paths.each do |root|
74
- if File.file? root then
72
+ if File.file?(root)
75
73
  files << root
76
- else
74
+ elsif File.directory?(root) #expand and explore
77
75
  discover_files = Dir.glob(
78
76
  File.join(root, "**/*.rb")
79
77
  ).select { |f| File.file?(f) }
@@ -81,6 +79,8 @@ module Beaker
81
79
  parser_error "empty directory used as an option (#{root})!"
82
80
  end
83
81
  files += discover_files.sort
82
+ else #not a file, not a directory, not nothin'
83
+ parser_error "#{root} used as a file option but is not a file or directory!"
84
84
  end
85
85
  end
86
86
  end
@@ -93,9 +93,9 @@ module Beaker
93
93
  #Converts array of paths into array of fully qualified git repo URLS with expanded keywords
94
94
  #
95
95
  #Supports the following keywords
96
- # PUPPET
96
+ # PUPPET
97
97
  # FACTER
98
- # HIERA
98
+ # HIERA
99
99
  # HIERA-PUPPET
100
100
  #@example
101
101
  # opts = ["PUPPET/3.1"]
@@ -142,7 +142,7 @@ module Beaker
142
142
  #NOTE on argument precedence:
143
143
  #
144
144
  # Will use env, then hosts/config file, then command line, then file options
145
- #
145
+ #
146
146
  @options = Beaker::Options::Presets.presets
147
147
  cmd_line_options = @command_line_parser.parse!(args)
148
148
  file_options = Beaker::Options::OptionsFileParser.parse_options_file(cmd_line_options[:options_file])
@@ -150,7 +150,7 @@ module Beaker
150
150
  # overwrite file options with command line options
151
151
  cmd_line_and_file_options = file_options.merge(cmd_line_options)
152
152
  # merge command line and file options with defaults
153
- # overwrite defaults with command line and file options
153
+ # overwrite defaults with command line and file options
154
154
  @options = @options.merge(cmd_line_and_file_options)
155
155
 
156
156
  if not @options[:help] and not @options[:version]
@@ -206,9 +206,7 @@ module Beaker
206
206
  if not @options['HOSTS'][name]['platform']
207
207
  parser_error "Host #{name} does not have a platform specified"
208
208
  else
209
- if not @options['HOSTS'][name]['platform'] =~ PLATFORMS
210
- parser_error "Host #{name} is on unsupported platform #{@options['HOSTS'][name]['platform']}"
211
- end
209
+ @options['HOSTS'][name]['platform'] = Platform.new(@options['HOSTS'][name]['platform'])
212
210
  end
213
211
  end
214
212
 
@@ -231,8 +229,8 @@ module Beaker
231
229
  else
232
230
  @options[opt] = []
233
231
  end
234
- end
235
-
232
+ end
233
+
236
234
  #check for valid type
237
235
  if @options[:type] !~ /(pe)|(git)|(foss)/
238
236
  parser_error "--type must be one of pe, git, or foss, not '#{@options[:type]}'"
@@ -240,7 +238,7 @@ module Beaker
240
238
 
241
239
  #check for valid fail mode
242
240
  if @options[:fail_mode] !~ /stop|fast|slow/
243
- parser_error "--fail-mode must be one of fast or slow, not '#{@options[:fail_mode]}'"
241
+ parser_error "--fail-mode must be one of fast or slow, not '#{@options[:fail_mode]}'"
244
242
  end
245
243
 
246
244
  #check for valid preserve_hosts option
@@ -249,8 +247,8 @@ module Beaker
249
247
  end
250
248
 
251
249
  #check for config files necessary for different hypervisors
252
- hypervisors = []
253
- @options[:HOSTS].each_key do |name|
250
+ hypervisors = []
251
+ @options[:HOSTS].each_key do |name|
254
252
  hypervisors << @options[:HOSTS][name][:hypervisor].to_s
255
253
  end
256
254
  hypervisors.uniq!
@@ -266,7 +264,7 @@ module Beaker
266
264
  #check that roles of hosts make sense
267
265
  # - must be one and only one master
268
266
  roles = []
269
- @options[:HOSTS].each_key do |name|
267
+ @options[:HOSTS].each_key do |name|
270
268
  roles << @options[:HOSTS][name][:roles]
271
269
  end
272
270
  master = 0
@@ -299,8 +297,8 @@ module Beaker
299
297
  # @api private
300
298
  def test_host_roles(host_name, host_hash)
301
299
  host_roles = host_hash[:roles]
302
- if (host_roles - ['agent']).size != 0
303
- parser_error "#{host_hash[:platform].to_s} box '#{host_name}' can only have role 'agent', has roles #{host_roles.to_s}"
300
+ if !(host_roles & ['master', 'database', 'dashboard']).empty?
301
+ parser_error "#{host_hash[:platform].to_s} box '#{host_name}' may not have roles 'master', 'dashboard', or 'database'; it has roles #{host_roles.to_s}"
304
302
  end
305
303
  end
306
304
 
@@ -8,7 +8,7 @@ module Beaker
8
8
  #
9
9
  # Currently supports:
10
10
  #
11
- # consoleport, IS_PE, pe_dist_dir, pe_version_file, pe_version_file_win
11
+ # consoleport, IS_PE, pe_dist_dir, pe_version_file, pe_version_file_win, pe_ver
12
12
  #
13
13
  # @return [OptionsHash] The supported environment variables in an OptionsHash,
14
14
  # empty or nil environment variables are removed from the OptionsHash
@@ -20,6 +20,7 @@ module Beaker
20
20
  :pe_dir => ENV['pe_dist_dir'],
21
21
  :pe_version_file => ENV['pe_version_file'],
22
22
  :pe_version_file_win => ENV['pe_version_file'],
23
+ :pe_ver => ENV['pe_ver']
23
24
  }.delete_if {|key, value| value.nil? or value.empty? })
24
25
  end
25
26
 
@@ -30,6 +31,7 @@ module Beaker
30
31
  h = Beaker::Options::OptionsHash.new
31
32
  h.merge({
32
33
  :log_level => 'verbose',
34
+ :trace_limit => 10,
33
35
  :hosts_file => 'sample.cfg',
34
36
  :options_file => nil,
35
37
  :type => 'pe',
@@ -0,0 +1,59 @@
1
+ module Beaker
2
+ class Platform < String
3
+ #supported platforms
4
+ PLATFORMS = /^(centos|fedora|debian|oracle|redhat|scientific|sles|ubuntu|windows|solaris|aix|el)\-.+\-.+$/
5
+
6
+ PLATFORM_VERSION_CODES =
7
+ { :debian => { "wheezy" => "7",
8
+ "squeeze" => "6",
9
+ },
10
+ :ubuntu => { "trusty" => "1404",
11
+ "saucy" => "1310",
12
+ "raring" => "1304",
13
+ "quantal" => "1210",
14
+ "precise" => "1204",
15
+ },
16
+ }
17
+
18
+ def initialize(name)
19
+ if name !~ PLATFORMS
20
+ raise ArgumentError, "Unsupported platform name #{name}"
21
+ end
22
+ super
23
+ end
24
+
25
+ def with_version_codename
26
+ name, version, extra = self.split('-', 3)
27
+ PLATFORM_VERSION_CODES.each_key do |platform|
28
+ if name =~ /#{platform}/
29
+ PLATFORM_VERSION_CODES[platform].each do |version_codename, version_number|
30
+ #remove '.' from version number
31
+ if version.delete('.') =~ /#{version_number}/
32
+ version = version_codename
33
+ break
34
+ end
35
+ end
36
+ break
37
+ end
38
+ end
39
+ [name, version, extra].join('-')
40
+ end
41
+
42
+ def with_version_number
43
+ name, version, extra = self.split('-', 3)
44
+ PLATFORM_VERSION_CODES.each_key do |platform|
45
+ if name =~ /#{platform}/
46
+ PLATFORM_VERSION_CODES[platform].each do |version_codename, version_number|
47
+ if version =~ /#{version_codename}/
48
+ version = version_number
49
+ break
50
+ end
51
+ end
52
+ break
53
+ end
54
+ end
55
+ [name, version, extra].join('-')
56
+ end
57
+
58
+ end
59
+ end
@@ -174,6 +174,7 @@ module Beaker
174
174
  # Net::Scp always returns 0, so just set the return code to 0.
175
175
  result.exit_code = 0
176
176
 
177
+ result.finalize!
177
178
  return result
178
179
  end
179
180
 
@@ -192,6 +193,7 @@ module Beaker
192
193
  # Net::Scp always returns 0, so just set the return code to 0.
193
194
  result.exit_code = 0
194
195
 
196
+ result.finalize!
195
197
  result
196
198
  end
197
199
  end
@@ -2,6 +2,8 @@ module Beaker
2
2
  module Utils
3
3
  class NTPControl
4
4
  NTPSERVER = 'pool.ntp.org'
5
+ SLEEPWAIT = 5
6
+ TRIES = 5
5
7
  def initialize(options, hosts)
6
8
  @options = options.dup
7
9
  @hosts = hosts
@@ -12,31 +14,44 @@ module Beaker
12
14
  @logger.notify "Update system time sync"
13
15
  @logger.notify "run ntpdate against NTP pool systems"
14
16
  @hosts.each do |host|
15
- success=FALSE
16
- if host['platform'].include? 'solaris-10'
17
- host.exec(Command.new("sleep 10 && ntpdate -w #{NTPSERVER}"))
18
- elsif host['platform'].include? 'windows'
17
+ if host['platform'].include? 'windows'
19
18
  # The exit code of 5 is for Windows 2008 systems where the w32tm /register command
20
19
  # is not actually necessary.
21
20
  host.exec(Command.new("w32tm /register"), :acceptable_exit_codes => [0,5])
22
21
  host.exec(Command.new("net start w32time"), :acceptable_exit_codes => [0,2])
23
22
  host.exec(Command.new("w32tm /config /manualpeerlist:#{NTPSERVER} /syncfromflags:manual /update"))
24
23
  host.exec(Command.new("w32tm /resync"))
24
+ @logger.notify "NTP date succeeded on #{host}"
25
25
  else
26
- count=0
27
- until success do
28
- count+=1
29
- raise "ntp time sync failed after #{count} tries" and break if count > 3
30
- if host.exec(Command.new("ntpdate -t 20 #{NTPSERVER}")).exit_code == 0
31
- success=TRUE
26
+ case
27
+ when host['platform'] =~ /solaris-10/
28
+ ntp_command = "sleep 10 && ntpdate -w #{NTPSERVER}"
29
+ when host['platform'] =~ /sles-/
30
+ ntp_command = "sntp #{NTPSERVER}"
31
+ else
32
+ ntp_command = "ntpdate -t 20 #{NTPSERVER}"
33
+ end
34
+ success=false
35
+ try = 0
36
+ until try >= TRIES do
37
+ try += 1
38
+ if host.exec(Command.new(ntp_command), :acceptable_exit_codes => (0..255)).exit_code == 0
39
+ success=true
40
+ break
32
41
  end
42
+ sleep SLEEPWAIT
43
+ end
44
+ if success
45
+ @logger.notify "NTP date succeeded on #{host} after #{try} tries"
46
+ else
47
+ raise "NTP date was not successful after #{try} tries"
33
48
  end
34
- @logger.notify "NTP date succeeded after #{count} tries"
35
49
  end
36
50
  end
37
51
  rescue => e
38
52
  report_and_raise(@logger, e, "timesync (--ntp)")
39
53
  end
54
+
40
55
  end
41
56
  end
42
57
  end