beaker 1.21.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/CONTRIBUTING.md +1 -0
- data/HISTORY.md +17288 -2
- data/Rakefile +6 -2
- data/beaker.gemspec +15 -19
- data/lib/beaker.rb +2 -5
- data/lib/beaker/answers.rb +2 -0
- data/lib/beaker/answers/version34.rb +37 -1
- data/lib/beaker/cli.rb +4 -0
- data/lib/beaker/command.rb +16 -84
- data/lib/beaker/command_factory.rb +13 -2
- data/lib/beaker/dsl/assertions.rb +25 -2
- data/lib/beaker/dsl/ezbake_utils.rb +2 -2
- data/lib/beaker/dsl/helpers.rb +66 -12
- data/lib/beaker/dsl/install_utils.rb +128 -66
- data/lib/beaker/dsl/wrappers.rb +41 -3
- data/lib/beaker/host.rb +42 -6
- data/lib/beaker/host/mac.rb +62 -0
- data/lib/beaker/host/mac/group.rb +96 -0
- data/lib/beaker/host/mac/user.rb +93 -0
- data/lib/beaker/host/unix/exec.rb +1 -1
- data/lib/beaker/host/unix/pkg.rb +11 -11
- data/lib/beaker/host/windows.rb +4 -4
- data/lib/beaker/host_prebuilt_steps.rb +194 -58
- data/lib/beaker/hypervisor.rb +16 -9
- data/lib/beaker/hypervisor/aws_sdk.rb +61 -17
- data/lib/beaker/hypervisor/docker.rb +14 -2
- data/lib/beaker/hypervisor/ec2_helper.rb +15 -3
- data/lib/beaker/hypervisor/vagrant.rb +22 -10
- data/lib/beaker/hypervisor/vagrant_libvirt.rb +11 -0
- data/lib/beaker/hypervisor/vagrant_virtualbox.rb +1 -1
- data/lib/beaker/hypervisor/vcloud_pooled.rb +8 -39
- data/lib/beaker/logger.rb +15 -9
- data/lib/beaker/network_manager.rb +2 -2
- data/lib/beaker/options/command_line_parser.rb +1 -1
- data/lib/beaker/options/parser.rb +1 -8
- data/lib/beaker/options/presets.rb +70 -45
- data/lib/beaker/perf.rb +3 -4
- data/lib/beaker/platform.rb +2 -1
- data/lib/beaker/result.rb +3 -9
- data/lib/beaker/ssh_connection.rb +2 -0
- data/lib/beaker/test_case.rb +2 -21
- data/lib/beaker/test_suite.rb +21 -25
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/answers_spec.rb +36 -0
- data/spec/beaker/cli_spec.rb +45 -45
- data/spec/beaker/command_spec.rb +25 -36
- data/spec/beaker/dsl/assertions_spec.rb +20 -27
- data/spec/beaker/dsl/ezbake_utils_spec.rb +5 -5
- data/spec/beaker/dsl/helpers_spec.rb +293 -208
- data/spec/beaker/dsl/install_utils_spec.rb +310 -189
- data/spec/beaker/dsl/outcomes_spec.rb +6 -6
- data/spec/beaker/dsl/roles_spec.rb +27 -18
- data/spec/beaker/dsl/structure_spec.rb +11 -11
- data/spec/beaker/dsl/wrappers_spec.rb +35 -11
- data/spec/beaker/host/mac/group_spec.rb +124 -0
- data/spec/beaker/host/mac/user_spec.rb +134 -0
- data/spec/beaker/host/unix/pkg_spec.rb +40 -24
- data/spec/beaker/host/windows/group_spec.rb +1 -1
- data/spec/beaker/host_prebuilt_steps_spec.rb +194 -68
- data/spec/beaker/host_spec.rb +145 -67
- data/spec/beaker/hypervisor/aixer_spec.rb +6 -6
- data/spec/beaker/hypervisor/aws_sdk_spec.rb +22 -7
- data/spec/beaker/hypervisor/docker_spec.rb +71 -50
- data/spec/beaker/hypervisor/ec2_helper_spec.rb +25 -4
- data/spec/beaker/hypervisor/fusion_spec.rb +2 -2
- data/spec/beaker/hypervisor/hypervisor_spec.rb +20 -27
- data/spec/beaker/hypervisor/hypervisor_spec.rb.orig +80 -0
- data/spec/beaker/hypervisor/solaris_spec.rb +8 -8
- data/spec/beaker/hypervisor/vagrant_fusion_spec.rb +6 -8
- data/spec/beaker/hypervisor/vagrant_libvirt_spec.rb +34 -0
- data/spec/beaker/hypervisor/vagrant_spec.rb +34 -33
- data/spec/beaker/hypervisor/vagrant_virtualbox_spec.rb +18 -8
- data/spec/beaker/hypervisor/vagrant_workstation_spec.rb +6 -8
- data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +8 -8
- data/spec/beaker/hypervisor/vcloud_spec.rb +10 -10
- data/spec/beaker/hypervisor/vsphere_helper_spec.rb +8 -8
- data/spec/beaker/hypervisor/vsphere_spec.rb +1 -1
- data/spec/beaker/logger_spec.rb +45 -31
- data/spec/beaker/options/command_line_parser_spec.rb +10 -2
- data/spec/beaker/options/hosts_file_parser_spec.rb +9 -2
- data/spec/beaker/options/options_hash_spec.rb +2 -2
- data/spec/beaker/options/parser_spec.rb +2 -2
- data/spec/beaker/options/pe_version_scaper_spec.rb +6 -1
- data/spec/beaker/options/presets_spec.rb +11 -1
- data/spec/beaker/shared/error_handler_spec.rb +5 -5
- data/spec/beaker/shared/host_manager_spec.rb +3 -2
- data/spec/beaker/shared/repetition_spec.rb +18 -18
- data/spec/beaker/ssh_connection_spec.rb +33 -4
- data/spec/beaker/test_case_spec.rb +9 -9
- data/spec/beaker/test_suite_spec.rb +14 -14
- data/spec/helpers.rb +4 -4
- data/spec/matchers.rb +4 -4
- data/spec/mocks.rb +5 -1
- data/spec/spec_helper.rb +2 -8
- metadata +114 -80
- data/lib/beaker/hypervisor/blimper.rb +0 -108
- data/spec/beaker/hypervisor/blimper_spec.rb +0 -42
- data/spec/beaker/options/data/LATEST +0 -1
- data/spec/beaker/puppet_command_spec.rb +0 -161
- data/spec/mock_blimpy.rb +0 -48
@@ -14,10 +14,11 @@ module Beaker
|
|
14
14
|
WINDOWS_PACKAGES = ['curl']
|
15
15
|
SLES_PACKAGES = ['curl', 'ntp']
|
16
16
|
DEBIAN_PACKAGES = ['curl', 'ntpdate', 'lsb-release']
|
17
|
+
CUMULUS_PACKAGES = ['addons', 'ntpdate', 'lsb-release']
|
17
18
|
ETC_HOSTS_PATH = "/etc/hosts"
|
18
19
|
ETC_HOSTS_PATH_SOLARIS = "/etc/inet/hosts"
|
19
20
|
ROOT_KEYS_SCRIPT = "https://raw.githubusercontent.com/puppetlabs/puppetlabs-sshkeys/master/templates/scripts/manage_root_authorized_keys"
|
20
|
-
ROOT_KEYS_SYNC_CMD = "curl -k -o - -L #{ROOT_KEYS_SCRIPT}
|
21
|
+
ROOT_KEYS_SYNC_CMD = "curl -k -o - -L #{ROOT_KEYS_SCRIPT} %s"
|
21
22
|
APT_CFG = %q{ Acquire::http::Proxy "http://proxy.puppetlabs.net:3128/"; }
|
22
23
|
IPS_PKG_REPO="http://solaris-11-internal-repo.delivery.puppetlabs.net"
|
23
24
|
|
@@ -66,11 +67,15 @@ module Beaker
|
|
66
67
|
report_and_raise(logger, e, "timesync (--ntp)")
|
67
68
|
end
|
68
69
|
|
69
|
-
#Validate that hosts are prepared to be used as SUTs, if packages are missing attempt to
|
70
|
-
#install them.
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
70
|
+
# Validate that hosts are prepared to be used as SUTs, if packages are missing attempt to
|
71
|
+
# install them.
|
72
|
+
#
|
73
|
+
# Verifies the presence of #{HostPrebuiltSteps::UNIX_PACKAGES} on unix platform hosts,
|
74
|
+
# {HostPrebuiltSteps::SLES_PACKAGES} on SUSE platform hosts,
|
75
|
+
# {HostPrebuiltSteps::DEBIAN_PACKAGES} on debian platform hosts,
|
76
|
+
# {HostPrebuiltSteps::CUMULUS_PACKAGES} on cumulus platform hosts,
|
77
|
+
# and {HostPrebuiltSteps::WINDOWS_PACKAGES} on windows platform hosts.
|
78
|
+
#
|
74
79
|
# @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
|
75
80
|
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
76
81
|
# @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
|
@@ -79,35 +84,33 @@ module Beaker
|
|
79
84
|
block_on host do |host|
|
80
85
|
case
|
81
86
|
when host['platform'] =~ /sles-/
|
82
|
-
SLES_PACKAGES
|
83
|
-
if not host.check_for_package pkg
|
84
|
-
host.install_package pkg
|
85
|
-
end
|
86
|
-
end
|
87
|
+
check_and_install_packages_if_needed(host, SLES_PACKAGES)
|
87
88
|
when host['platform'] =~ /debian/
|
88
|
-
DEBIAN_PACKAGES
|
89
|
-
|
90
|
-
|
91
|
-
end
|
92
|
-
end
|
89
|
+
check_and_install_packages_if_needed(host, DEBIAN_PACKAGES)
|
90
|
+
when host['platform'] =~ /cumulus/
|
91
|
+
check_and_install_packages_if_needed(host, CUMULUS_PACKAGES)
|
93
92
|
when host['platform'] =~ /windows/
|
94
|
-
WINDOWS_PACKAGES
|
95
|
-
|
96
|
-
|
97
|
-
end
|
98
|
-
end
|
99
|
-
when host['platform'] !~ /debian|aix|solaris|windows|sles-|osx-/
|
100
|
-
UNIX_PACKAGES.each do |pkg|
|
101
|
-
if not host.check_for_package pkg
|
102
|
-
host.install_package pkg
|
103
|
-
end
|
104
|
-
end
|
93
|
+
check_and_install_packages_if_needed(host, WINDOWS_PACKAGES)
|
94
|
+
when host['platform'] !~ /debian|aix|solaris|windows|sles-|osx-|cumulus/
|
95
|
+
check_and_install_packages_if_needed(host, UNIX_PACKAGES)
|
105
96
|
end
|
106
97
|
end
|
107
98
|
rescue => e
|
108
99
|
report_and_raise(logger, e, "validate")
|
109
100
|
end
|
110
101
|
|
102
|
+
# Installs the given packages if they aren't already on a host
|
103
|
+
#
|
104
|
+
# @param [Host] host Host to act on
|
105
|
+
# @param [Array<String>] package_list List of package names to install
|
106
|
+
def check_and_install_packages_if_needed host, package_list
|
107
|
+
package_list.each do |pkg|
|
108
|
+
if not host.check_for_package pkg
|
109
|
+
host.install_package pkg
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
111
114
|
#Install a set of authorized keys using {HostPrebuiltSteps::ROOT_KEYS_SCRIPT}. This is a
|
112
115
|
#convenience method to allow for easy login to hosts after they have been provisioned with
|
113
116
|
#Beaker.
|
@@ -124,9 +127,17 @@ module Beaker
|
|
124
127
|
logger.notify "Sync root authorized_keys from github on #{host.name}"
|
125
128
|
# Allow all exit code, as this operation is unlikely to cause problems if it fails.
|
126
129
|
if host['platform'].include? 'solaris'
|
127
|
-
host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "bash"), :acceptable_exit_codes => (0..255))
|
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))
|
128
139
|
else
|
129
|
-
host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "env PATH=/usr/gnu/bin:$PATH bash"), :acceptable_exit_codes => (0..255))
|
140
|
+
host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "| env PATH=/usr/gnu/bin:$PATH bash"), :acceptable_exit_codes => (0..255))
|
130
141
|
end
|
131
142
|
end
|
132
143
|
rescue => e
|
@@ -144,10 +155,11 @@ module Beaker
|
|
144
155
|
# @option opts [String] :epel_5_pkg Package to download from provided link for el-5
|
145
156
|
# @raise [Exception] Raises an error if the host provided's platform != /el-(5|6)/
|
146
157
|
def epel_info_for host, opts
|
147
|
-
|
148
|
-
|
149
|
-
raise "epel_info_for not available for #{host.name} on platform #{host['platform']}"
|
158
|
+
if !el_based?(host)
|
159
|
+
raise "epel_info_for! not available for #{host.name} on platform #{host['platform']}"
|
150
160
|
end
|
161
|
+
|
162
|
+
version = host['platform'].version
|
151
163
|
if version == '6'
|
152
164
|
url = "#{host[:epel_url] || opts[:epel_url]}/#{version}"
|
153
165
|
pkg = host[:epel_pkg] || opts[:epel_6_pkg]
|
@@ -160,12 +172,13 @@ module Beaker
|
|
160
172
|
return url, host[:epel_arch] || opts[:epel_arch] || 'i386', pkg
|
161
173
|
end
|
162
174
|
|
163
|
-
#Run 'apt-get update' on the provided host or hosts.
|
164
|
-
#ubuntu or
|
175
|
+
# Run 'apt-get update' on the provided host or hosts.
|
176
|
+
# If the platform of the provided host is not ubuntu, debian or cumulus: do nothing.
|
177
|
+
#
|
165
178
|
# @param [Host, Array<Host>] hosts One or more hosts to act upon
|
166
179
|
def apt_get_update hosts
|
167
180
|
block_on hosts do |host|
|
168
|
-
if host[:platform] =~ /
|
181
|
+
if host[:platform] =~ /ubuntu|debian|cumulus/
|
169
182
|
host.exec(Command.new("apt-get update"))
|
170
183
|
end
|
171
184
|
end
|
@@ -185,24 +198,21 @@ module Beaker
|
|
185
198
|
end
|
186
199
|
end
|
187
200
|
|
188
|
-
#
|
189
|
-
# proxy {HostPrebuiltSteps::APT_CFG} proxy
|
190
|
-
#
|
191
|
-
#
|
201
|
+
# On ubuntu, debian, or cumulus host or hosts: alter apt configuration to use
|
202
|
+
# the internal Puppet Labs proxy {HostPrebuiltSteps::APT_CFG} proxy.
|
203
|
+
# On solaris-11 host or hosts: alter pkg to point to
|
204
|
+
# the internal Puppet Labs proxy {HostPrebuiltSteps::IPS_PKG_REPO}.
|
205
|
+
#
|
206
|
+
# Do nothing for other platform host or hosts.
|
207
|
+
#
|
192
208
|
# @param [Host, Array<Host>] host One or more hosts to act upon
|
193
209
|
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
194
210
|
# @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
|
195
211
|
def proxy_config( host, opts )
|
196
|
-
# repo_proxy
|
197
|
-
# supports ubuntu, debian and solaris platforms
|
198
212
|
logger = opts[:logger]
|
199
213
|
block_on host do |host|
|
200
214
|
case
|
201
|
-
when host['platform'] =~ /ubuntu/
|
202
|
-
host.exec(Command.new("if test -f /etc/apt/apt.conf; then mv /etc/apt/apt.conf /etc/apt/apt.conf.bk; fi"))
|
203
|
-
copy_file_to_remote(host, '/etc/apt/apt.conf', APT_CFG)
|
204
|
-
apt_get_update(host)
|
205
|
-
when host['platform'] =~ /debian/
|
215
|
+
when host['platform'] =~ /ubuntu|debian|cumulus/
|
206
216
|
host.exec(Command.new("if test -f /etc/apt/apt.conf; then mv /etc/apt/apt.conf /etc/apt/apt.conf.bk; fi"))
|
207
217
|
copy_file_to_remote(host, '/etc/apt/apt.conf', APT_CFG)
|
208
218
|
apt_get_update(host)
|
@@ -234,7 +244,7 @@ module Beaker
|
|
234
244
|
debug_opt = opts[:debug] ? 'vh' : ''
|
235
245
|
block_on host do |host|
|
236
246
|
case
|
237
|
-
when host['platform']
|
247
|
+
when el_based?(host) && ['5','6'].include?(host['platform'].version)
|
238
248
|
result = host.exec(Command.new('rpm -qa | grep epel-release'), :acceptable_exit_codes => [0,1])
|
239
249
|
if result.exit_code == 1
|
240
250
|
url, arch, pkg = epel_info_for host, opts
|
@@ -316,7 +326,10 @@ module Beaker
|
|
316
326
|
end
|
317
327
|
end
|
318
328
|
|
319
|
-
#Update sshd_config on debian, ubuntu, centos, el, redhat and fedora boxes to allow for root login
|
329
|
+
# Update sshd_config on debian, ubuntu, centos, el, redhat, cumulus, and fedora boxes to allow for root login
|
330
|
+
#
|
331
|
+
# Does nothing on other platfoms.
|
332
|
+
#
|
320
333
|
# @param [Host, Array<Host>] host One or more hosts to act upon
|
321
334
|
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
322
335
|
# @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
|
@@ -324,13 +337,14 @@ module Beaker
|
|
324
337
|
logger = opts[:logger]
|
325
338
|
block_on host do |host|
|
326
339
|
logger.debug "Update /etc/ssh/sshd_config to allow root login"
|
327
|
-
|
328
|
-
|
340
|
+
# note: this sed command only works on gnu sed
|
341
|
+
host.exec(Command.new("sudo su -c \"sed -ri 's/^#?PermitRootLogin no|^#?PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config\""), {:pty => true}
|
342
|
+
)
|
329
343
|
#restart sshd
|
330
|
-
if host['platform'] =~ /debian|ubuntu/
|
344
|
+
if host['platform'] =~ /debian|ubuntu|cumulus/
|
331
345
|
host.exec(Command.new("sudo su -c \"service ssh restart\""), {:pty => true})
|
332
|
-
elsif host['platform'] =~ /centos|el-|redhat|fedora/
|
333
|
-
host.exec(Command.new("sudo
|
346
|
+
elsif host['platform'] =~ /centos|el-|redhat|fedora|eos/
|
347
|
+
host.exec(Command.new("sudo -E service sshd restart"))
|
334
348
|
else
|
335
349
|
@logger.warn("Attempting to update ssh on non-supported platform: #{host.name}: #{host['platform']}")
|
336
350
|
end
|
@@ -344,7 +358,7 @@ module Beaker
|
|
344
358
|
def disable_se_linux host, opts
|
345
359
|
logger = opts[:logger]
|
346
360
|
block_on host do |host|
|
347
|
-
if host['platform'] =~ /centos|el-|redhat|fedora/
|
361
|
+
if host['platform'] =~ /centos|el-|redhat|fedora|eos/
|
348
362
|
@logger.debug("Disabling se_linux on #{host.name}")
|
349
363
|
host.exec(Command.new("sudo su -c \"setenforce 0\""), {:pty => true})
|
350
364
|
else
|
@@ -360,7 +374,7 @@ module Beaker
|
|
360
374
|
def disable_iptables host, opts
|
361
375
|
logger = opts[:logger]
|
362
376
|
block_on host do |host|
|
363
|
-
if host['platform'] =~ /centos|el-|redhat|fedora/
|
377
|
+
if host['platform'] =~ /centos|el-|redhat|fedora|eos/
|
364
378
|
logger.debug("Disabling iptables on #{host.name}")
|
365
379
|
host.exec(Command.new("sudo su -c \"/etc/init.d/iptables stop\""), {:pty => true})
|
366
380
|
else
|
@@ -370,7 +384,7 @@ module Beaker
|
|
370
384
|
end
|
371
385
|
|
372
386
|
# Setup files for enabling requests to pass to a proxy server
|
373
|
-
# This works for the APT package manager on debian and
|
387
|
+
# This works for the APT package manager on debian, ubuntu, and cumulus
|
374
388
|
# and YUM package manager on el, centos, fedora and redhat.
|
375
389
|
# @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
|
376
390
|
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
@@ -381,9 +395,9 @@ module Beaker
|
|
381
395
|
block_on host do |host|
|
382
396
|
logger.debug("enabling proxy support on #{host.name}")
|
383
397
|
case host['platform']
|
384
|
-
when /ubuntu/, /debian/
|
398
|
+
when /ubuntu/, /debian/, /cumulus/
|
385
399
|
host.exec(Command.new("echo 'Acquire::http::Proxy \"#{opts[:package_proxy]}/\";' >> /etc/apt/apt.conf.d/10proxy"))
|
386
|
-
when /^el-/, /centos/, /fedora/, /redhat/
|
400
|
+
when /^el-/, /centos/, /fedora/, /redhat/, /eos/
|
387
401
|
host.exec(Command.new("echo 'proxy=#{opts[:package_proxy]}/' >> /etc/yum.conf"))
|
388
402
|
else
|
389
403
|
logger.debug("Attempting to enable package manager proxy support on non-supported platform: #{host.name}: #{host['platform']}")
|
@@ -391,6 +405,128 @@ module Beaker
|
|
391
405
|
end
|
392
406
|
end
|
393
407
|
|
408
|
+
|
409
|
+
# Merge the two provided hashes so that an array of values is created from collisions
|
410
|
+
# @param [Hash] h1 The first hash
|
411
|
+
# @param [Hash] h2 The second hash
|
412
|
+
# @return [Hash] A merged hash with arrays of values where collisions between the two hashes occured.
|
413
|
+
# @example
|
414
|
+
# > h1 = {:PATH=>"/1st/path"}
|
415
|
+
# > h2 = {:PATH=>"/2nd/path"}
|
416
|
+
# > additive_hash_merge(h1, h2)
|
417
|
+
# => {:PATH=>["/1st/path", "/2nd/path"]}
|
418
|
+
def additive_hash_merge h1, h2
|
419
|
+
merged_hash = {}
|
420
|
+
normalized_h2 = h2.inject({}) { |h, (k, v)| h[k.to_s.upcase] = v; h }
|
421
|
+
h1.each_pair do |key, val|
|
422
|
+
normalized_key = key.to_s.upcase
|
423
|
+
if normalized_h2.has_key?(normalized_key)
|
424
|
+
merged_hash[key] = [h1[key], normalized_h2[normalized_key]]
|
425
|
+
merged_hash[key] = merged_hash[key].uniq #remove dupes
|
426
|
+
end
|
427
|
+
end
|
428
|
+
merged_hash
|
429
|
+
end
|
430
|
+
|
431
|
+
# 'echo' the provided value on the given host
|
432
|
+
# @param [Host] host The host to execute the 'echo' on
|
433
|
+
# @param [String] val The string to 'echo' on the host
|
434
|
+
def echo_on_host host, val
|
435
|
+
#val = val.gsub(/"/, "\"").gsub(/\(/, "\(")
|
436
|
+
host.exec(Command.new("echo \"#{val}\"")).stdout.chomp
|
437
|
+
end
|
438
|
+
|
439
|
+
# Create the hash of default environment from host (:host_env), global options hash (:host_env) and default PE/Foss puppet variables
|
440
|
+
# @param [Host] host The host to construct the environment hash for, host specific environment should be in :host_env in a hash
|
441
|
+
# @param [Hash] opts Hash of options, including optional global host_env to be applied to each provided host
|
442
|
+
# @return [Hash] A hash of environment variables for provided host
|
443
|
+
def construct_env host, opts
|
444
|
+
env = additive_hash_merge(host[:host_env], opts[:host_env])
|
445
|
+
|
446
|
+
#Add PATH and RUBYLIB
|
447
|
+
|
448
|
+
#prepend any PATH already set for this host
|
449
|
+
|
450
|
+
env['PATH'] = (%w(puppetbindir facterbindir hierabindir) << env['PATH']).compact.reject(&:empty?)
|
451
|
+
#get the PATH defaults
|
452
|
+
env['PATH'].map! { |val| host[val] }
|
453
|
+
env['PATH'] = env['PATH'].compact.reject(&:empty?)
|
454
|
+
#run the paths through echo to see if they have any subcommands that need processing
|
455
|
+
env['PATH'].map! { |val| echo_on_host(host, val) }
|
456
|
+
|
457
|
+
#prepend any RUBYLIB already set for this host
|
458
|
+
env['RUBYLIB'] = (%w(hieralibdir hierapuppetlibdir pluginlibpath puppetlibdir facterlibdir) << env['RUBYLIB']).compact.reject(&:empty?)
|
459
|
+
#get the RUBYLIB defaults
|
460
|
+
env['RUBYLIB'].map! { |val| host[val] }
|
461
|
+
env['RUBYLIB'] = env['RUBYLIB'].compact.reject(&:empty?)
|
462
|
+
#run the paths through echo to see if they have any subcommands that need processing
|
463
|
+
env['RUBYLIB'].map! { |val| echo_on_host(host, val) }
|
464
|
+
|
465
|
+
env.each_key do |key|
|
466
|
+
env[key] = env[key].join(':')
|
467
|
+
end
|
468
|
+
env
|
469
|
+
end
|
470
|
+
|
471
|
+
# Add a host specific set of env vars to each provided host's ~/.ssh/environment
|
472
|
+
# @param [Host, Array<Host>] host One or more hosts to act upon
|
473
|
+
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
474
|
+
def set_env host, opts
|
475
|
+
logger = opts[:logger]
|
476
|
+
|
477
|
+
block_on host do |host|
|
478
|
+
env = construct_env(host, opts)
|
479
|
+
logger.debug("setting local environment on #{host.name}")
|
480
|
+
case host['platform']
|
481
|
+
when /windows/
|
482
|
+
host.exec(Command.new("echo 'PermitUserEnvironment yes' >> /etc/sshd_config"))
|
483
|
+
host.exec(Command.new("cygrunsrv -E sshd"))
|
484
|
+
host.exec(Command.new("cygrunsrv -S sshd"))
|
485
|
+
env['CYGWIN'] = 'nodosfilewarning'
|
486
|
+
when /osx/
|
487
|
+
host.exec(Command.new("echo 'PermitUserEnvironment yes' >> /etc/sshd_config"))
|
488
|
+
host.exec(Command.new("launchctl unload /System/Library/LaunchDaemons/ssh.plist"))
|
489
|
+
host.exec(Command.new("launchctl load /System/Library/LaunchDaemons/ssh.plist"))
|
490
|
+
when /debian|ubuntu|cumulus/
|
491
|
+
host.exec(Command.new("echo 'PermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
|
492
|
+
host.exec(Command.new("service ssh restart"))
|
493
|
+
when /el-|centos|fedora|redhat|oracle|scientific|eos/
|
494
|
+
host.exec(Command.new("echo 'PermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
|
495
|
+
host.exec(Command.new("service sshd restart"))
|
496
|
+
when /sles/
|
497
|
+
host.exec(Command.new("echo 'PermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
|
498
|
+
host.exec(Command.new("rcsshd restart"))
|
499
|
+
when /solaris/
|
500
|
+
host.exec(Command.new("echo 'PermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
|
501
|
+
host.exec(Command.new("svcadm restart svc:/network/ssh:default"))
|
502
|
+
when /aix/
|
503
|
+
host.exec(Command.new("echo 'PermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
|
504
|
+
host.exec(Command.new("stopsrc -g ssh"))
|
505
|
+
host.exec(Command.new("startsrc -g ssh"))
|
506
|
+
end
|
507
|
+
#ensure that ~/.ssh/environment exists
|
508
|
+
host.exec(Command.new("touch #{host[:ssh_env_file]}"))
|
509
|
+
#add the constructed env vars to this host
|
510
|
+
host.add_env_var('RUBYLIB', '$RUBYLIB')
|
511
|
+
host.add_env_var('PATH', '$PATH')
|
512
|
+
env.each_pair do |var, value|
|
513
|
+
host.add_env_var(var, value)
|
514
|
+
end
|
515
|
+
#close the host to re-establish the connection with the new sshd settings
|
516
|
+
host.close
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
private
|
521
|
+
|
522
|
+
# A helper to tell whether a host is el-based
|
523
|
+
# @param [Host] host the host to act upon
|
524
|
+
#
|
525
|
+
# @return [Boolean] if the host is el_based
|
526
|
+
def el_based? host
|
527
|
+
['centos','redhat','scientific','el','oracle'].include?(host['platform'].variant)
|
528
|
+
end
|
529
|
+
|
394
530
|
end
|
395
531
|
|
396
532
|
end
|
data/lib/beaker/hypervisor.rb
CHANGED
@@ -28,8 +28,6 @@ module Beaker
|
|
28
28
|
Beaker::Vsphere
|
29
29
|
when /^fusion$/
|
30
30
|
Beaker::Fusion
|
31
|
-
when /^blimpy$/
|
32
|
-
Beaker::Blimper
|
33
31
|
when /^ec2$/
|
34
32
|
Beaker::AwsSdk
|
35
33
|
when /^vcloud$/
|
@@ -40,6 +38,8 @@ module Beaker
|
|
40
38
|
end
|
41
39
|
when /^vagrant$/
|
42
40
|
Beaker::Vagrant
|
41
|
+
when /^vagrant_libvirt$/
|
42
|
+
Beaker::VagrantLibvirt
|
43
43
|
when /^vagrant_virtualbox$/
|
44
44
|
Beaker::VagrantVirtualbox
|
45
45
|
when /^vagrant_fusion$/
|
@@ -61,7 +61,7 @@ module Beaker
|
|
61
61
|
rescue LoadError
|
62
62
|
raise "Invalid hypervisor: #{type}"
|
63
63
|
end
|
64
|
-
const_get(
|
64
|
+
Beaker.const_get(type.capitalize)
|
65
65
|
end
|
66
66
|
|
67
67
|
hypervisor = hyper_class.new(hosts_to_provision, options)
|
@@ -85,7 +85,15 @@ module Beaker
|
|
85
85
|
nil
|
86
86
|
end
|
87
87
|
|
88
|
-
#
|
88
|
+
#Proxy package managers on tests hosts created by this hypervisor, runs before validation and configuration.
|
89
|
+
def proxy_package_manager
|
90
|
+
if @options[:package_proxy]
|
91
|
+
package_proxy(@hosts, @options)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
#Default configuration steps to be run for a given hypervisor. Any additional configuration to be done
|
96
|
+
#to the provided SUT for test execution to be successful.
|
89
97
|
def configure
|
90
98
|
if @options[:timesync]
|
91
99
|
timesync(@hosts, @options)
|
@@ -96,15 +104,14 @@ module Beaker
|
|
96
104
|
if @options[:add_el_extras]
|
97
105
|
add_el_extras(@hosts, @options)
|
98
106
|
end
|
99
|
-
if @options[:package_proxy]
|
100
|
-
package_proxy(@hosts, @options)
|
101
|
-
end
|
102
107
|
if @options[:disable_iptables]
|
103
108
|
disable_iptables @hosts, @options
|
104
109
|
end
|
110
|
+
set_env(@hosts, @options)
|
105
111
|
end
|
106
112
|
|
107
|
-
#Default validation steps to be run for a given hypervisor
|
113
|
+
#Default validation steps to be run for a given hypervisor. Ensures that SUTs meet requirements to be
|
114
|
+
#beaker test nodes.
|
108
115
|
def validate
|
109
116
|
if @options[:validate]
|
110
117
|
validate_host(@hosts, @options)
|
@@ -119,6 +126,6 @@ module Beaker
|
|
119
126
|
end
|
120
127
|
end
|
121
128
|
|
122
|
-
[ 'vsphere_helper', 'vagrant', 'vagrant_virtualbox', '
|
129
|
+
[ 'vsphere_helper', 'vagrant', 'vagrant_virtualbox', 'vagrant_libvirt', 'vagrant_fusion', 'vagrant_workstation', 'fusion', 'aws_sdk', 'vsphere', 'vcloud', 'vcloud_pooled', 'aixer', 'solaris', 'docker', 'google_compute', 'openstack' ].each do |lib|
|
123
130
|
require "beaker/hypervisor/#{lib}"
|
124
131
|
end
|
@@ -55,6 +55,9 @@ module Beaker
|
|
55
55
|
# Grab the ip addresses and dns from EC2 for each instance to use for ssh
|
56
56
|
populate_dns()
|
57
57
|
|
58
|
+
#enable root if user is not root
|
59
|
+
enable_root_on_hosts()
|
60
|
+
|
58
61
|
# Set the hostname for each box
|
59
62
|
set_hostnames()
|
60
63
|
|
@@ -88,10 +91,12 @@ module Beaker
|
|
88
91
|
nil #void
|
89
92
|
end
|
90
93
|
|
91
|
-
#Print instances to the logger.
|
92
|
-
#limited by regex compared to
|
93
|
-
|
94
|
-
|
94
|
+
# Print instances to the logger. Instances will be from all regions
|
95
|
+
# associated with provided key name and limited by regex compared to
|
96
|
+
# instance status. Defaults to running instances.
|
97
|
+
#
|
98
|
+
# @param [String] key The key_name to match for
|
99
|
+
# @param [Regex] status The regular expression to match against the instance's status
|
95
100
|
def log_instances(key = key_name, status = /running/)
|
96
101
|
instances = []
|
97
102
|
@ec2.regions.each do |region|
|
@@ -110,9 +115,11 @@ module Beaker
|
|
110
115
|
@logger.notify("#{output}")
|
111
116
|
end
|
112
117
|
|
113
|
-
#Shutdown and destroy ec2 instances idenfitied by key that have been alive
|
114
|
-
|
115
|
-
|
118
|
+
# Shutdown and destroy ec2 instances idenfitied by key that have been alive
|
119
|
+
# longer than ZOMBIE hours.
|
120
|
+
#
|
121
|
+
# @param [Integer] max_age The age in hours that a machine needs to be older than to be considered a zombie
|
122
|
+
# @param [String] key The key_name to match for
|
116
123
|
def kill_zombies(max_age = ZOMBIE, key = key_name)
|
117
124
|
@logger.notify("aws-sdk: Kill Zombies! (keyname: #{key}, age: #{max_age} hrs)")
|
118
125
|
#examine all available regions
|
@@ -176,6 +183,12 @@ module Beaker
|
|
176
183
|
@hosts.each do |host|
|
177
184
|
amitype = host['vmname'] || host['platform']
|
178
185
|
amisize = host['amisize'] || 'm1.small'
|
186
|
+
subnet_id = host['subnet_id'] || nil
|
187
|
+
vpc_id = host['vpc_id'] || nil
|
188
|
+
|
189
|
+
if vpc_id and !subnet_id
|
190
|
+
raise RuntimeError, "A subnet_id must be provided with a vpc_id"
|
191
|
+
end
|
179
192
|
|
180
193
|
# Use snapshot provided for this host
|
181
194
|
image_type = host['snapshot']
|
@@ -188,6 +201,9 @@ module Beaker
|
|
188
201
|
# Main region object for ec2 operations
|
189
202
|
region = @ec2.regions[ami_region]
|
190
203
|
|
204
|
+
# Obtain the VPC object if it exists
|
205
|
+
vpc = vpc_id ? region.vpcs[vpc_id] : nil
|
206
|
+
|
191
207
|
# Grab image object
|
192
208
|
image_id = ami[:image][image_type.to_sym]
|
193
209
|
@logger.notify("aws-sdk: Checking image #{image_id} exists and getting its root device")
|
@@ -220,11 +236,12 @@ module Beaker
|
|
220
236
|
:image_id => image_id,
|
221
237
|
:monitoring_enabled => true,
|
222
238
|
:key_pair => ensure_key_pair(region),
|
223
|
-
:security_groups => [ensure_group(region, Beaker::EC2Helper.amiports(host
|
239
|
+
:security_groups => [ensure_group(vpc || region, Beaker::EC2Helper.amiports(host))],
|
224
240
|
:instance_type => amisize,
|
225
241
|
:disable_api_termination => false,
|
226
242
|
:instance_initiated_shutdown_behavior => "terminate",
|
227
243
|
:block_device_mappings => block_device_mappings,
|
244
|
+
:subnet => subnet_id,
|
228
245
|
}
|
229
246
|
instance = region.instances.create(config)
|
230
247
|
|
@@ -273,7 +290,7 @@ module Beaker
|
|
273
290
|
end
|
274
291
|
end
|
275
292
|
|
276
|
-
#Add metadata tags to all instances
|
293
|
+
# Add metadata tags to all instances
|
277
294
|
#
|
278
295
|
# @return [void]
|
279
296
|
# @api private
|
@@ -334,6 +351,29 @@ module Beaker
|
|
334
351
|
end
|
335
352
|
end
|
336
353
|
|
354
|
+
# Enables root for instances with custom username like ubuntu-amis
|
355
|
+
#
|
356
|
+
# @return [void]
|
357
|
+
# @api private
|
358
|
+
def enable_root_on_hosts
|
359
|
+
@hosts.each do |host|
|
360
|
+
enable_root(host)
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# Enables root access for a host when username is not root
|
365
|
+
#
|
366
|
+
# @return [void]
|
367
|
+
# @api private
|
368
|
+
def enable_root(host)
|
369
|
+
if host['user'] != 'root'
|
370
|
+
copy_ssh_to_root(host, @options)
|
371
|
+
enable_root_login(host, @options)
|
372
|
+
host['user'] = 'root'
|
373
|
+
host.close
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
337
377
|
# Set the hostname of all instances to be the hostname defined in the
|
338
378
|
# beaker configuration.
|
339
379
|
#
|
@@ -431,18 +471,20 @@ module Beaker
|
|
431
471
|
|
432
472
|
# Return an existing group, or create new one
|
433
473
|
#
|
434
|
-
#
|
474
|
+
# Accepts a region or VPC as input for checking & creation.
|
475
|
+
#
|
476
|
+
# @param rv [AWS::EC2::Region, AWS::EC2::VPC] the AWS region or vpc control object
|
435
477
|
# @param ports [Array<Number>] an array of port numbers
|
436
478
|
# @return [AWS::EC2::SecurityGroup] created security group
|
437
479
|
# @api private
|
438
|
-
def ensure_group(
|
480
|
+
def ensure_group(rv, ports)
|
439
481
|
@logger.notify("aws-sdk: Ensure security group exists for ports #{ports.to_s}, create if not")
|
440
482
|
name = group_id(ports)
|
441
483
|
|
442
|
-
group =
|
484
|
+
group = rv.security_groups.filter('group-name', name).first
|
443
485
|
|
444
486
|
if group.nil?
|
445
|
-
group = create_group(
|
487
|
+
group = create_group(rv, ports)
|
446
488
|
end
|
447
489
|
|
448
490
|
group
|
@@ -450,15 +492,17 @@ module Beaker
|
|
450
492
|
|
451
493
|
# Create a new security group
|
452
494
|
#
|
453
|
-
#
|
495
|
+
# Accepts a region or VPC for group creation.
|
496
|
+
#
|
497
|
+
# @param rv [AWS::EC2::Region, AWS::EC2::VPC] the AWS region or vpc control object
|
454
498
|
# @param ports [Array<Number>] an array of port numbers
|
455
499
|
# @return [AWS::EC2::SecurityGroup] created security group
|
456
500
|
# @api private
|
457
|
-
def create_group(
|
501
|
+
def create_group(rv, ports)
|
458
502
|
name = group_id(ports)
|
459
503
|
@logger.notify("aws-sdk: Creating group #{name} for ports #{ports.to_s}")
|
460
|
-
group =
|
461
|
-
|
504
|
+
group = rv.security_groups.create(name,
|
505
|
+
:description => "Custom Beaker security group for #{ports.to_a}")
|
462
506
|
|
463
507
|
unless ports.is_a? Set
|
464
508
|
ports = Set.new(ports)
|