beaker 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/beaker/host.rb CHANGED
@@ -48,7 +48,7 @@ module Beaker
48
48
  # a explict relationship between our defaults, our setup steps and how they're
49
49
  # related through 'type' and the differences between the assumption of our two
50
50
  # configurations we have for many of our products
51
- type = is_pe? ? :pe : :foss
51
+ type = @options.get_type
52
52
  @defaults = merge_defaults_for_type @options, type
53
53
  pkg_initialize
54
54
  end
@@ -312,7 +312,7 @@ module Beaker
312
312
  ignore_re = nil
313
313
  if has_ignore
314
314
  ignore_arr = Array(options[:ignore]).map do |entry|
315
- "((\/|\\A)#{entry}(\/|\\z))".sub(/\./, "\.")
315
+ "((\/|\\A)#{entry}(\/|\\z))".gsub(/\./, '\.')
316
316
  end
317
317
  ignore_re = Regexp.new(ignore_arr.join('|'))
318
318
  end
@@ -358,9 +358,9 @@ module Beaker
358
358
  dir_source.each do |s|
359
359
  s_path = Pathname.new(s)
360
360
  if s_path.absolute?
361
- file_path = File.join(target, s.gsub(source,''))
361
+ file_path = File.join(target, File.dirname(s).gsub(source,''))
362
362
  else
363
- file_path = File.join(target, s)
363
+ file_path = File.join(target, File.dirname(s))
364
364
  end
365
365
  result = connection.scp_to(s, file_path, options, $dry_run)
366
366
  @logger.trace result.stdout
@@ -55,5 +55,16 @@ module Unix
55
55
  'pathseparator' => ':',
56
56
  })
57
57
  end
58
+
59
+ def self.aio_defaults
60
+ h = self.foss_defaults
61
+ h['puppetbindir'] = '/opt/puppetlabs/agent/bin'
62
+ h['puppetpath'] = '/opt/puppetlabs/agent'
63
+ h['puppetvardir'] = '/opt/puppetlabs/agent/cache'
64
+ h['distmoduledir'] = '/opt/puppetlabs/agent/modules'
65
+ h['sitemoduledir'] = '/etc/puppetlabs/agent/modules'
66
+ h['hieraconf'] = ' /etc/puppetlabs/agent/hiera.conf'
67
+ h
68
+ end
58
69
  end
59
70
  end
@@ -1,3 +1,5 @@
1
+ require 'pathname'
2
+
1
3
  [ 'command', "dsl/patterns" ].each do |lib|
2
4
  require "beaker/#{lib}"
3
5
  end
@@ -18,7 +20,7 @@ module Beaker
18
20
  ETC_HOSTS_PATH = "/etc/hosts"
19
21
  ETC_HOSTS_PATH_SOLARIS = "/etc/inet/hosts"
20
22
  ROOT_KEYS_SCRIPT = "https://raw.githubusercontent.com/puppetlabs/puppetlabs-sshkeys/master/templates/scripts/manage_root_authorized_keys"
21
- ROOT_KEYS_SYNC_CMD = "curl -k -o - -L #{ROOT_KEYS_SCRIPT} %s"
23
+ ROOT_KEYS_SYNC_CMD = "curl -k -o - -L #{ROOT_KEYS_SCRIPT} | %s"
22
24
  APT_CFG = %q{ Acquire::http::Proxy "http://proxy.puppetlabs.net:3128/"; }
23
25
  IPS_PKG_REPO="http://solaris-11-internal-repo.delivery.puppetlabs.net"
24
26
 
@@ -126,18 +128,10 @@ module Beaker
126
128
  block_on host do |host|
127
129
  logger.notify "Sync root authorized_keys from github on #{host.name}"
128
130
  # Allow all exit code, as this operation is unlikely to cause problems if it fails.
129
- if host['platform'].include? 'solaris'
130
- host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "| bash"), :acceptable_exit_codes => (0..255))
131
- elsif host['platform'].include? 'eos'
132
- # this is a terrible terrible thing that I'm already in the process of fixing
133
- # the only reason that I include this terrible implementation is that the
134
- # fix relies on changes in another repo, so I'm not sure how long it'll take
135
- # to get those in
136
- host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "> manage_root_authorized_keys"), :acceptable_exit_codes => (0..255))
137
- host.exec(Command.new("sed -i 's|mv -f $SSH_HOME/authorized_keys.tmp $SSH_HOME/authorized_keys|cp -f $SSH_HOME/authorized_keys.tmp $SSH_HOME/authorized_keys|' manage_root_authorized_keys"), :acceptable_exit_codes => (0..255))
138
- host.exec(Command.new("bash manage_root_authorized_keys"), :acceptable_exit_codes => (0..255))
131
+ if host['platform'] =~ /solaris|eos/
132
+ host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "bash"), :acceptable_exit_codes => (0..255))
139
133
  else
140
- host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "| env PATH=/usr/gnu/bin:$PATH bash"), :acceptable_exit_codes => (0..255))
134
+ host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "env PATH=/usr/gnu/bin:$PATH bash"), :acceptable_exit_codes => (0..255))
141
135
  end
142
136
  end
143
137
  rescue => e
@@ -344,7 +338,7 @@ module Beaker
344
338
  if host['platform'] =~ /debian|ubuntu|cumulus/
345
339
  host.exec(Command.new("sudo su -c \"service ssh restart\""), {:pty => true})
346
340
  elsif host['platform'] =~ /centos|el-|redhat|fedora|eos/
347
- host.exec(Command.new("sudo -E service sshd restart"))
341
+ host.exec(Command.new("sudo -E /sbin/service sshd restart"))
348
342
  else
349
343
  @logger.warn("Attempting to update ssh on non-supported platform: #{host.name}: #{host['platform']}")
350
344
  end
@@ -479,39 +473,44 @@ module Beaker
479
473
  logger.debug("setting local environment on #{host.name}")
480
474
  case host['platform']
481
475
  when /windows/
482
- host.exec(Command.new("echo 'PermitUserEnvironment yes\n' >> /etc/sshd_config"))
476
+ host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/sshd_config"))
483
477
  host.exec(Command.new("cygrunsrv -E sshd"))
484
478
  host.exec(Command.new("cygrunsrv -S sshd"))
485
479
  env['CYGWIN'] = 'nodosfilewarning'
486
480
  when /osx/
487
- host.exec(Command.new("echo 'PermitUserEnvironment yes\n' >> /etc/sshd_config"))
481
+ host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/sshd_config"))
488
482
  host.exec(Command.new("launchctl unload /System/Library/LaunchDaemons/ssh.plist"))
489
483
  host.exec(Command.new("launchctl load /System/Library/LaunchDaemons/ssh.plist"))
490
484
  when /debian|ubuntu|cumulus/
491
- host.exec(Command.new("echo 'PermitUserEnvironment yes\n' >> /etc/ssh/sshd_config"))
485
+ host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
492
486
  host.exec(Command.new("service ssh restart"))
493
487
  when /el-|centos|fedora|redhat|oracle|scientific|eos/
494
- host.exec(Command.new("echo 'PermitUserEnvironment yes\n' >> /etc/ssh/sshd_config"))
495
- host.exec(Command.new("service sshd restart"))
488
+ host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
489
+ host.exec(Command.new("/sbin/service sshd restart"))
496
490
  when /sles/
497
- host.exec(Command.new("echo 'PermitUserEnvironment yes\n' >> /etc/ssh/sshd_config"))
491
+ host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
498
492
  host.exec(Command.new("rcsshd restart"))
499
493
  when /solaris/
500
- host.exec(Command.new("echo 'PermitUserEnvironment yes\n' >> /etc/ssh/sshd_config"))
494
+ host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
501
495
  host.exec(Command.new("svcadm restart svc:/network/ssh:default"))
502
496
  when /aix/
503
- host.exec(Command.new("echo 'PermitUserEnvironment yes\n' >> /etc/ssh/sshd_config"))
497
+ host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
504
498
  host.exec(Command.new("stopsrc -g ssh"))
505
499
  host.exec(Command.new("startsrc -g ssh"))
506
500
  end
501
+
507
502
  #ensure that ~/.ssh/environment exists
503
+ host.exec(Command.new("mkdir -p #{Pathname.new(host[:ssh_env_file]).dirname}"))
504
+ host.exec(Command.new("chmod 0600 #{Pathname.new(host[:ssh_env_file]).dirname}"))
508
505
  host.exec(Command.new("touch #{host[:ssh_env_file]}"))
506
+
509
507
  #add the constructed env vars to this host
510
508
  host.add_env_var('RUBYLIB', '$RUBYLIB')
511
509
  host.add_env_var('PATH', '$PATH')
512
510
  env.each_pair do |var, value|
513
511
  host.add_env_var(var, value)
514
512
  end
513
+
515
514
  #close the host to re-establish the connection with the new sshd settings
516
515
  host.close
517
516
  end
@@ -95,6 +95,7 @@ module Beaker
95
95
  #Default configuration steps to be run for a given hypervisor. Any additional configuration to be done
96
96
  #to the provided SUT for test execution to be successful.
97
97
  def configure
98
+ return unless @options[:configure]
98
99
  if @options[:timesync]
99
100
  timesync(@hosts, @options)
100
101
  end
@@ -5,7 +5,7 @@ require 'beaker/hypervisor/ec2_helper'
5
5
 
6
6
  module Beaker
7
7
  # This is an alternate EC2 driver that implements direct API access using
8
- # Amazon's AWS-SDK library: http://aws.amazon.com/documentation/sdkforruby/
8
+ # Amazon's AWS-SDK library: {http://aws.amazon.com/documentation/sdkforruby/ SDK For Ruby}
9
9
  #
10
10
  # It is built for full control, to reduce any other layers beyond the pure
11
11
  # vendor API.
@@ -116,7 +116,7 @@ module Beaker
116
116
  end
117
117
 
118
118
  # Provided an id return an instance object.
119
- # Instance object will respond to methods described here: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/EC2/Instance.html
119
+ # Instance object will respond to methods described here: {http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/EC2/Instance.html AWS Instance Object}.
120
120
  # @param [String] id The id of the instance to return
121
121
  # @return [AWS::EC2::Instance] An AWS::EC2 instance object
122
122
  def instance_by_id(id)
@@ -124,11 +124,42 @@ module Beaker
124
124
  end
125
125
 
126
126
  # Return all instances currently on ec2.
127
+ # @see AwsSdk#instance_by_id
127
128
  # @return [Array<AWS::EC2::Instance>] An array of AWS::EC2 instance objects
128
129
  def instances
129
130
  @ec2.instances
130
131
  end
131
132
 
133
+ # Provided an id return a VPC object.
134
+ # VPC object will respond to methods described here: {http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/EC2/VPC.html AWS VPC Object}.
135
+ # @param [String] id The id of the VPC to return
136
+ # @return [AWS::EC2::VPC] An AWS::EC2 vpc object
137
+ def vpc_by_id(id)
138
+ @ec2.vpcs[id]
139
+ end
140
+
141
+ # Return all VPCs currently on ec2.
142
+ # @see AwsSdk#vpc_by_id
143
+ # @return [Array<AWS::EC2::VPC>] An array of AWS::EC2 vpc objects
144
+ def vpcs
145
+ @ec2.vpcs
146
+ end
147
+
148
+ # Provided an id return a security group object
149
+ # Security object will respond to methods described here: {http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/EC2/SecurityGroup.html AWS SecurityGroup Object}.
150
+ # @param [String] id The id of the security group to return
151
+ # @return [AWS::EC2::SecurityGroup] An AWS::EC2 security group object
152
+ def security_group_by_id(id)
153
+ @ec2.security_groups[id]
154
+ end
155
+
156
+ # Return all security groups currently on ec2.
157
+ # @see AwsSdk#security_goup_by_id
158
+ # @return [Array<AWS::EC2::SecurityGroup>] An array of AWS::EC2 security group objects
159
+ def security_groups
160
+ @ec2.security_groups
161
+ end
162
+
132
163
  # Shutdown and destroy ec2 instances idenfitied by key that have been alive
133
164
  # longer than ZOMBIE hours.
134
165
  #
@@ -138,7 +169,6 @@ module Beaker
138
169
  @logger.notify("aws-sdk: Kill Zombies! (keyname: #{key}, age: #{max_age} hrs)")
139
170
  #examine all available regions
140
171
  kill_count = 0
141
- volume_count = 0
142
172
  time_now = Time.now.getgm #ec2 uses GM time
143
173
  @ec2.regions.each do |region|
144
174
  @logger.debug "Reviewing: #{region.name}"
@@ -150,17 +180,28 @@ module Beaker
150
180
  @logger.debug "Examining #{instance.id} (keyname: #{instance.key_name}, launch time: #{instance.launch_time}, status: #{instance.status})"
151
181
  if ((time_now - instance.launch_time) > max_age*60*60) and instance.status.to_s !~ /terminated/
152
182
  @logger.debug "Kill! #{instance.id}: #{instance.key_name} (Current status: #{instance.status})"
153
- instance.terminate()
154
- kill_count += 1
183
+ instance.terminate()
184
+ kill_count += 1
155
185
  end
156
186
  end
157
187
  rescue AWS::Core::Resource::NotFound, AWS::EC2::Errors => e
158
188
  @logger.debug "Failed to remove instance: #{instance.id}, #{e}"
159
189
  end
160
190
  end
161
- # Occasionaly, tearing down ec2 instances leaves orphaned EBS volumes behind -- these stack up quickly.
162
- # This simply looks for EBS volumes that are not in use
163
- # Note: don't use volumes.each here as that funtion doesn't allow proper rescue from error states
191
+ end
192
+
193
+ @logger.notify "#{key}: Killed #{kill_count} instance(s)"
194
+ end
195
+
196
+ # Destroy any volumes marked 'available', INCLUDING THOSE YOU DON'T OWN! Use with care.
197
+ def kill_zombie_volumes
198
+ # Occasionaly, tearing down ec2 instances leaves orphaned EBS volumes behind -- these stack up quickly.
199
+ # This simply looks for EBS volumes that are not in use
200
+ # Note: don't use volumes.each here as that funtion doesn't allow proper rescue from error states
201
+ @logger.notify("aws-sdk: Kill Zombie Volumes!")
202
+ volume_count = 0
203
+ @ec2.regions.each do |region|
204
+ @logger.debug "Reviewing: #{region.name}"
164
205
  volumes = @ec2.regions[region.name].volumes.map { |vol| vol.id }
165
206
  volumes.each do |vol|
166
207
  begin
@@ -175,7 +216,7 @@ module Beaker
175
216
  end
176
217
  end
177
218
  end
178
- @logger.notify "#{key}: Killed #{kill_count} instance(s), freed #{volume_count} volume(s)"
219
+ @logger.notify "Freed #{volume_count} volume(s)"
179
220
 
180
221
  end
181
222
 
@@ -43,12 +43,15 @@ module Beaker
43
43
  end
44
44
  port = container.json["NetworkSettings"]["Ports"]["22/tcp"][0]["HostPort"]
45
45
 
46
+ forward_ssh_agent = @options[:forward_ssh_agent] || false
47
+
46
48
  # Update host metadata
47
49
  host['ip'] = ip
48
50
  host['port'] = port
49
51
  host['ssh'] = {
50
52
  :password => root_password,
51
53
  :port => port,
54
+ :forward_agent => forward_ssh_agent,
52
55
  }
53
56
 
54
57
  @logger.debug("node available as ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@#{ip} -p #{port}")
@@ -22,6 +22,7 @@ module Beaker
22
22
  #HACK HACK HACK - add checks here to ensure that we have box + box_url
23
23
  #generate the VagrantFile
24
24
  v_file = "Vagrant.configure(\"2\") do |c|\n"
25
+ v_file << " c.ssh.forward_agent = true\n" if options[:forward_ssh_agent] == true
25
26
  hosts.each do |host|
26
27
  host['ip'] ||= randip #use the existing ip, otherwise default to a random ip
27
28
  v_file << " c.vm.define '#{host.name}' do |v|\n"
@@ -30,8 +31,7 @@ module Beaker
30
31
  v_file << " v.vm.box_url = '#{host['box_url']}'\n" unless host['box_url'].nil?
31
32
  v_file << " v.vm.box_version = '#{host['box_version']}'\n" unless host['box_version'].nil?
32
33
  v_file << " v.vm.box_check_update = '#{host['box_check_update'] ||= 'true'}'\n"
33
- v_file << " v.vm.base_mac = '#{randmac}'\n"
34
- v_file << " v.vm.network :private_network, ip: \"#{host['ip'].to_s}\", :netmask => \"#{host['netmask'] ||= "255.255.0.0"}\"\n"
34
+ v_file << " v.vm.network :private_network, ip: \"#{host['ip'].to_s}\", :netmask => \"#{host['netmask'] ||= "255.255.0.0"}\", :mac => \"#{randmac}\"\n"
35
35
 
36
36
  if /windows/i.match(host['platform'])
37
37
  v_file << " v.vm.network :forwarded_port, guest: 3389, host: 3389\n"
@@ -65,7 +65,7 @@ module Beaker
65
65
  stdout.read
66
66
  end
67
67
  #replace hostname with ip
68
- ssh_config = ssh_config.gsub(/#{host.name}/, host['ip']) unless not host['ip']
68
+ ssh_config = ssh_config.gsub(/Host #{host.name}/, "Host #{host['ip']}") unless not host['ip']
69
69
  if host['platform'] =~ /windows/
70
70
  ssh_config = ssh_config.gsub(/127\.0\.0\.1/, host['ip']) unless not host['ip']
71
71
  end
@@ -28,17 +28,19 @@ module Beaker
28
28
  raise "Couldn't find VM #{name} in vSphere!"
29
29
  end
30
30
 
31
- snapshot = vsphere_helper.find_snapshot(vm, snap) or
32
- raise "Could not find snapshot '#{snap}' for VM #{vm.name}!"
31
+ if snap
32
+ snapshot = vsphere_helper.find_snapshot(vm, snap) or
33
+ raise "Could not find snapshot '#{snap}' for VM #{vm.name}!"
33
34
 
34
- @logger.notify "Reverting #{vm.name} to snapshot '#{snap}'"
35
- start = Time.now
36
- # This will block for each snapshot...
37
- # The code to issue them all and then wait until they are all done sucks
38
- snapshot.RevertToSnapshot_Task.wait_for_completion
35
+ @logger.notify "Reverting #{vm.name} to snapshot '#{snap}'"
36
+ start = Time.now
37
+ # This will block for each snapshot...
38
+ # The code to issue them all and then wait until they are all done sucks
39
+ snapshot.RevertToSnapshot_Task.wait_for_completion
39
40
 
40
- time = Time.now - start
41
- @logger.notify "Spent %.2f seconds reverting" % time
41
+ time = Time.now - start
42
+ @logger.notify "Spent %.2f seconds reverting" % time
43
+ end
42
44
 
43
45
  unless vm.runtime.powerState == "poweredOn"
44
46
  @logger.notify "Booting #{vm.name}"
@@ -36,7 +36,11 @@ class VsphereHelper
36
36
  end
37
37
 
38
38
  def find_snapshot vm, snapname
39
- search_child_snaps vm.snapshot.rootSnapshotList, snapname
39
+ if vm.snapshot
40
+ search_child_snaps vm.snapshot.rootSnapshotList, snapname
41
+ else
42
+ raise "vm #{vm.name} has no snapshots to revert to"
43
+ end
40
44
  end
41
45
 
42
46
  def search_child_snaps tree, snapname
data/lib/beaker/logger.rb CHANGED
@@ -171,7 +171,7 @@ module Beaker
171
171
  else
172
172
  # Remove invalid and undefined UTF-8 character encodings
173
173
  string.to_s.force_encoding('UTF-8')
174
- return string.chars.select{|i| i.valid_encoding?}.join
174
+ return string.to_s.chars.select{|i| i.valid_encoding?}.join
175
175
  end
176
176
  end
177
177
 
@@ -66,6 +66,12 @@ module Beaker
66
66
  @cmd_options[:provision] = bool
67
67
  end
68
68
 
69
+ opts.on '--[no-]configure',
70
+ 'Do not configure vm images before testing',
71
+ '(default: true)' do |bool|
72
+ @cmd_options[:configure] = bool
73
+ end
74
+
69
75
  opts.on '--preserve-hosts [MODE]',
70
76
  'How should SUTs be treated post test',
71
77
  'Possible values:',
@@ -171,7 +177,7 @@ module Beaker
171
177
  end
172
178
 
173
179
  opts.on '--[no-]validate',
174
- 'Validate that SUTs are correctly configured before running tests',
180
+ 'Validate that SUTs are correctly provisioned before running tests',
175
181
  '(default: true)' do |bool|
176
182
  @cmd_options[:validate] = bool
177
183
  end
@@ -51,6 +51,28 @@ module Beaker
51
51
  self[:type] ? self[:type] =~ /pe/ : true
52
52
  end
53
53
 
54
+ # Determine the puppet type of the ObjectHash
55
+ #
56
+ # Default is FOSS
57
+ #
58
+ # @example Use this method to test if the :type setting is pe
59
+ # a['type'] = 'pe'
60
+ # a.get_type == :pe
61
+ #
62
+ # @return [Symbol] the type given in the options
63
+ def get_type
64
+ case self[:type]
65
+ when /pe/
66
+ :pe
67
+ when /foss/
68
+ :foss
69
+ when /aio/
70
+ :aio
71
+ else
72
+ :foss
73
+ end
74
+ end
75
+
54
76
  # Determine if key is stored in ObjectHash
55
77
  # @param [Object] k The key to find in ObjectHash, searches for
56
78
  # both k as String and k as Symbol
@@ -278,8 +278,8 @@ module Beaker
278
278
  end
279
279
 
280
280
  #check for valid type
281
- if @options[:type] !~ /(pe)|(git)|(foss)/
282
- parser_error "--type must be one of pe, git, or foss, not '#{@options[:type]}'"
281
+ if @options[:type] !~ /pe|git|foss|aio/
282
+ parser_error "--type must be one of pe, git, foss, or aio not '#{@options[:type]}'"
283
283
  end
284
284
 
285
285
  #check for valid fail mode
@@ -115,6 +115,7 @@ module Beaker
115
115
  :created_by => ENV['USER'] || ENV['USERNAME'] || 'unknown',
116
116
  :jenkins_build_url => nil,
117
117
  :validate => true,
118
+ :configure => true,
118
119
  :log_level => 'info',
119
120
  :trace_limit => 10,
120
121
  :"master-start-curl-retries" => 120,
data/lib/beaker/result.rb CHANGED
@@ -33,7 +33,7 @@ module Beaker
33
33
  def convert string
34
34
  # Remove invalid and undefined UTF-8 character encodings
35
35
  string.to_s.force_encoding('UTF-8')
36
- string.chars.select{|i| i.valid_encoding?}.join
36
+ string.to_s.chars.select{|i| i.valid_encoding?}.join
37
37
  end
38
38
 
39
39
  def log(logger)
@@ -1,5 +1,5 @@
1
1
  module Beaker
2
2
  module Version
3
- STRING = '2.1.0'
3
+ STRING = '2.2.0'
4
4
  end
5
5
  end