beaker 1.21.0 → 2.0.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 +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)
|