beaker 0.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 +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.simplecov +14 -0
- data/DOCUMENTING.md +167 -0
- data/Gemfile +3 -0
- data/LICENSE +17 -0
- data/README.md +332 -0
- data/Rakefile +121 -0
- data/beaker.gemspec +42 -0
- data/beaker.rb +10 -0
- data/bin/beaker +9 -0
- data/lib/beaker.rb +36 -0
- data/lib/beaker/answers.rb +29 -0
- data/lib/beaker/answers/version28.rb +104 -0
- data/lib/beaker/answers/version30.rb +194 -0
- data/lib/beaker/cli.rb +113 -0
- data/lib/beaker/command.rb +241 -0
- data/lib/beaker/command_factory.rb +21 -0
- data/lib/beaker/dsl.rb +85 -0
- data/lib/beaker/dsl/assertions.rb +87 -0
- data/lib/beaker/dsl/helpers.rb +625 -0
- data/lib/beaker/dsl/install_utils.rb +299 -0
- data/lib/beaker/dsl/outcomes.rb +99 -0
- data/lib/beaker/dsl/roles.rb +97 -0
- data/lib/beaker/dsl/structure.rb +63 -0
- data/lib/beaker/dsl/wrappers.rb +100 -0
- data/lib/beaker/host.rb +193 -0
- data/lib/beaker/host/aix.rb +15 -0
- data/lib/beaker/host/aix/file.rb +16 -0
- data/lib/beaker/host/aix/group.rb +35 -0
- data/lib/beaker/host/aix/user.rb +32 -0
- data/lib/beaker/host/unix.rb +54 -0
- data/lib/beaker/host/unix/exec.rb +15 -0
- data/lib/beaker/host/unix/file.rb +16 -0
- data/lib/beaker/host/unix/group.rb +40 -0
- data/lib/beaker/host/unix/pkg.rb +22 -0
- data/lib/beaker/host/unix/user.rb +32 -0
- data/lib/beaker/host/windows.rb +44 -0
- data/lib/beaker/host/windows/exec.rb +18 -0
- data/lib/beaker/host/windows/file.rb +15 -0
- data/lib/beaker/host/windows/group.rb +36 -0
- data/lib/beaker/host/windows/pkg.rb +26 -0
- data/lib/beaker/host/windows/user.rb +32 -0
- data/lib/beaker/hypervisor.rb +37 -0
- data/lib/beaker/hypervisor/aixer.rb +52 -0
- data/lib/beaker/hypervisor/blimper.rb +123 -0
- data/lib/beaker/hypervisor/fusion.rb +56 -0
- data/lib/beaker/hypervisor/solaris.rb +65 -0
- data/lib/beaker/hypervisor/vagrant.rb +118 -0
- data/lib/beaker/hypervisor/vcloud.rb +175 -0
- data/lib/beaker/hypervisor/vsphere.rb +80 -0
- data/lib/beaker/hypervisor/vsphere_helper.rb +200 -0
- data/lib/beaker/logger.rb +167 -0
- data/lib/beaker/network_manager.rb +73 -0
- data/lib/beaker/options_parsing.rb +323 -0
- data/lib/beaker/result.rb +55 -0
- data/lib/beaker/shared.rb +15 -0
- data/lib/beaker/shared/error_handler.rb +17 -0
- data/lib/beaker/shared/host_handler.rb +46 -0
- data/lib/beaker/shared/repetition.rb +28 -0
- data/lib/beaker/ssh_connection.rb +198 -0
- data/lib/beaker/test_case.rb +225 -0
- data/lib/beaker/test_config.rb +148 -0
- data/lib/beaker/test_suite.rb +288 -0
- data/lib/beaker/utils.rb +7 -0
- data/lib/beaker/utils/ntp_control.rb +42 -0
- data/lib/beaker/utils/repo_control.rb +92 -0
- data/lib/beaker/utils/setup_helper.rb +77 -0
- data/lib/beaker/utils/validator.rb +27 -0
- data/spec/beaker/command_spec.rb +94 -0
- data/spec/beaker/dsl/assertions_spec.rb +104 -0
- data/spec/beaker/dsl/helpers_spec.rb +230 -0
- data/spec/beaker/dsl/install_utils_spec.rb +70 -0
- data/spec/beaker/dsl/outcomes_spec.rb +43 -0
- data/spec/beaker/dsl/roles_spec.rb +86 -0
- data/spec/beaker/dsl/structure_spec.rb +60 -0
- data/spec/beaker/dsl/wrappers_spec.rb +52 -0
- data/spec/beaker/host_spec.rb +95 -0
- data/spec/beaker/logger_spec.rb +117 -0
- data/spec/beaker/options_parsing_spec.rb +37 -0
- data/spec/beaker/puppet_command_spec.rb +128 -0
- data/spec/beaker/ssh_connection_spec.rb +39 -0
- data/spec/beaker/test_case_spec.rb +6 -0
- data/spec/beaker/test_suite_spec.rb +44 -0
- data/spec/mocks_and_helpers.rb +34 -0
- data/spec/spec_helper.rb +15 -0
- metadata +359 -0
@@ -0,0 +1,299 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Beaker
|
4
|
+
module DSL
|
5
|
+
#
|
6
|
+
# This module contains methods to help cloning, extracting git info,
|
7
|
+
# ordering of Puppet packages, and installing ruby projects that
|
8
|
+
# contain an `install.rb` script.
|
9
|
+
module InstallUtils
|
10
|
+
|
11
|
+
# The default install path
|
12
|
+
SourcePath = "/opt/puppet-git-repos"
|
13
|
+
|
14
|
+
# A regex to know if the uri passed is pointing to a git repo
|
15
|
+
GitURI = %r{^(git|https?|file)://|^git@}
|
16
|
+
|
17
|
+
# Github's ssh signature for cloning via ssh
|
18
|
+
GitHubSig = 'github.com,207.97.227.239 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=='
|
19
|
+
|
20
|
+
# @param [String] uri A uri in the format of <git uri>#<revision>
|
21
|
+
# the `git://`, `http://`, `https://`, and ssh
|
22
|
+
# (if cloning as the remote git user) protocols
|
23
|
+
# are valid for <git uri>
|
24
|
+
#
|
25
|
+
# @example Usage
|
26
|
+
# project = extract_repo_info_from 'git@github.com:puppetlabs/SuperSecretSauce#what_is_justin_doing'
|
27
|
+
#
|
28
|
+
# puts project[:name]
|
29
|
+
# #=> 'SuperSecretSauce'
|
30
|
+
#
|
31
|
+
# puts project[:rev]
|
32
|
+
# #=> 'what_is_justin_doing'
|
33
|
+
#
|
34
|
+
# @return [Hash{Symbol=>String}] Returns a hash containing the project
|
35
|
+
# name, repository path, and revision
|
36
|
+
# (defaults to HEAD)
|
37
|
+
#
|
38
|
+
# @api dsl
|
39
|
+
def extract_repo_info_from uri
|
40
|
+
project = {}
|
41
|
+
repo, rev = uri.split('#', 2)
|
42
|
+
project[:name] = Pathname.new(repo).basename('.git').to_s
|
43
|
+
project[:path] = repo
|
44
|
+
project[:rev] = rev || 'HEAD'
|
45
|
+
return project
|
46
|
+
end
|
47
|
+
|
48
|
+
# Takes an array of package info hashes (like that returned from
|
49
|
+
# {#extract_repo_info_from}) and sorts the `puppet`, `facter`, `hiera`
|
50
|
+
# packages so that puppet's dependencies will be installed first.
|
51
|
+
#
|
52
|
+
# @!visibility private
|
53
|
+
def order_packages packages_array
|
54
|
+
puppet = packages_array.select {|e| e[:name] == 'puppet' }
|
55
|
+
puppet_depends_on = packages_array.select do |e|
|
56
|
+
e[:name] == 'hiera' or e[:name] == 'facter'
|
57
|
+
end
|
58
|
+
depends_on_puppet = (packages_array - puppet) - puppet_depends_on
|
59
|
+
[puppet_depends_on, puppet, depends_on_puppet].flatten
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param [Host] host An object implementing {Beaker::Hosts}'s
|
63
|
+
# interface.
|
64
|
+
# @param [String] path The path on the remote [host] to the repository
|
65
|
+
# @param [Hash{Symbol=>String}] repository A hash representing repo
|
66
|
+
# info like that emitted by
|
67
|
+
# {#extract_repo_info_from}
|
68
|
+
#
|
69
|
+
# @example Getting multiple project versions
|
70
|
+
# versions = [puppet_repo, facter_repo, hiera_repo].inject({}) do |vers, repo_info|
|
71
|
+
# vers.merge(find_git_repo_versions(host, '/opt/git-puppet-repos', repo_info) )
|
72
|
+
# end
|
73
|
+
# @return [Hash] Executes git describe on [host] and returns a Hash
|
74
|
+
# with the key of [repository[:name]] and value of
|
75
|
+
# the output from git describe.
|
76
|
+
#
|
77
|
+
# @note This requires the helper methods:
|
78
|
+
# * {Beaker::DSL::Structure#step}
|
79
|
+
# * {Beaker::DSL::Helpers#on}
|
80
|
+
#
|
81
|
+
# @api dsl
|
82
|
+
def find_git_repo_versions host, path, repository
|
83
|
+
version = {}
|
84
|
+
step "Grab version for #{repository[:name]}" do
|
85
|
+
on host, "cd #{path}/#{repository[:name]} && " +
|
86
|
+
"git describe || true" do
|
87
|
+
version[repository[:name]] = stdout.chomp
|
88
|
+
end
|
89
|
+
end
|
90
|
+
version
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# @see #find_git_repo_versions
|
95
|
+
def install_from_git host, path, repository
|
96
|
+
name = repository[:name]
|
97
|
+
repo = repository[:path]
|
98
|
+
rev = repository[:rev]
|
99
|
+
target = "#{path}/#{name}"
|
100
|
+
|
101
|
+
step "Clone #{repo} if needed" do
|
102
|
+
on host, "test -d #{path} || mkdir -p #{path}"
|
103
|
+
on host, "test -d #{target} || git clone #{repo} #{target}"
|
104
|
+
end
|
105
|
+
|
106
|
+
step "Update #{name} and check out revision #{rev}" do
|
107
|
+
commands = ["cd #{target}",
|
108
|
+
"remote rm origin",
|
109
|
+
"remote add origin #{repo}",
|
110
|
+
"fetch origin",
|
111
|
+
"clean -fdx",
|
112
|
+
"checkout -f #{rev}"]
|
113
|
+
on host, commands.join(" && git ")
|
114
|
+
end
|
115
|
+
|
116
|
+
step "Install #{name} on the system" do
|
117
|
+
# The solaris ruby IPS package has bindir set to /usr/ruby/1.8/bin.
|
118
|
+
# However, this is not the path to which we want to deliver our
|
119
|
+
# binaries. So if we are using solaris, we have to pass the bin and
|
120
|
+
# sbin directories to the install.rb
|
121
|
+
install_opts = ''
|
122
|
+
install_opts = '--bindir=/usr/bin --sbindir=/usr/sbin' if
|
123
|
+
host['platform'].include? 'solaris'
|
124
|
+
|
125
|
+
on host, "cd #{target} && " +
|
126
|
+
"if [ -f install.rb ]; then " +
|
127
|
+
"ruby ./install.rb #{install_opts}; " +
|
128
|
+
"else true; fi"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def do_install hosts, version, path, pre_30, options = {}
|
133
|
+
#convenience methods for installation
|
134
|
+
########################################################
|
135
|
+
def installer_cmd(host, version, installer)
|
136
|
+
if host['platform'] =~ /windows/
|
137
|
+
"cd #{host['working_dir']} && msiexec.exe /qn /i puppet-enterprise-#{version}.msi"
|
138
|
+
else
|
139
|
+
"cd #{host['working_dir']}/#{host['dist']} && ./#{installer}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
def link_exists?(link)
|
143
|
+
require "net/http"
|
144
|
+
require "open-uri"
|
145
|
+
url = URI.parse(link)
|
146
|
+
Net::HTTP.start(url.host, url.port) do |http|
|
147
|
+
return http.head(url.request_uri).code == "200"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
def fetch_puppet(hosts, version, path)
|
151
|
+
local = File.directory?(path)
|
152
|
+
hosts.each do |host|
|
153
|
+
filename = ""
|
154
|
+
extension = ""
|
155
|
+
if host['platform'] =~ /windows/
|
156
|
+
filename = "puppet-enterprise-#{version}"
|
157
|
+
extension = ".msi"
|
158
|
+
else
|
159
|
+
filename = "#{host['dist']}"
|
160
|
+
extension = ""
|
161
|
+
if local
|
162
|
+
extension = File.exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
|
163
|
+
else
|
164
|
+
extension = link_exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
if local
|
168
|
+
if not File.exists?("#{path}/#{filename}#{extension}")
|
169
|
+
raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
|
170
|
+
end
|
171
|
+
scp_to host, "#{path}/#{filename}#{extension}", "#{host['working_dir']}/#{filename}#{extension}"
|
172
|
+
else
|
173
|
+
if not link_exists?("#{path}/#{filename}#{extension}")
|
174
|
+
raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
|
175
|
+
end
|
176
|
+
on host, "cd #{host['working_dir']}; curl #{path}/#{filename}#{extension} -o #{filename}#{extension}"
|
177
|
+
end
|
178
|
+
if extension =~ /gz/
|
179
|
+
on host, "cd #{host['working_dir']}; gunzip #{filename}#{extension}"
|
180
|
+
end
|
181
|
+
if extension =~ /tar/
|
182
|
+
on host, "cd #{host['working_dir']}; tar -xvf #{filename}.tar"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
########################################################
|
187
|
+
#start installation steps here
|
188
|
+
options[:installer] = 'puppet-enterprise-installer' unless options[:installer]
|
189
|
+
options[:type] = :install unless options[:type]
|
190
|
+
hostcert='uname | grep -i sunos > /dev/null && hostname || hostname -s'
|
191
|
+
master_certname = on(master, hostcert).stdout.strip
|
192
|
+
answers = Beaker::Answers.answers(version, hosts, master_certname, options)
|
193
|
+
special_nodes = [master, database, dashboard].uniq
|
194
|
+
real_agents = agents - special_nodes
|
195
|
+
|
196
|
+
# Set PE distribution for all the hosts, create working dir
|
197
|
+
use_all_tar = ENV['PE_USE_ALL_TAR'] == 'true'
|
198
|
+
hosts.each do |host|
|
199
|
+
platform = use_all_tar ? 'all' : host['platform']
|
200
|
+
host['dist'] = "puppet-enterprise-#{version}-#{platform}"
|
201
|
+
host['working_dir'] = "/tmp/" + Time.new.strftime("%Y-%m-%d_%H.%M.%S") #unique working dirs make me happy
|
202
|
+
on host, "mkdir #{host['working_dir']}"
|
203
|
+
end
|
204
|
+
|
205
|
+
fetch_puppet(hosts, version, path)
|
206
|
+
|
207
|
+
hosts.each do |host|
|
208
|
+
# Database host was added in 3.0. Skip it if installing an older version
|
209
|
+
next if host == database and host != master and host != dashboard and pre_30
|
210
|
+
if host['platform'] =~ /windows/
|
211
|
+
on host, "#{installer_cmd(host, version, options[:installer])} PUPPET_MASTER_SERVER=#{master} PUPPET_AGENT_CERTNAME=#{host}"
|
212
|
+
else
|
213
|
+
create_remote_file host, "#{host['working_dir']}/answers", Beaker::Answers.answer_string(host, answers)
|
214
|
+
|
215
|
+
on host, "#{installer_cmd(host, version, options[:installer])} -a #{host['working_dir']}/answers"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
# If we're installing a version less than 3.0, ignore the database host
|
221
|
+
install_hosts = hosts.dup
|
222
|
+
install_hosts.delete(database) if pre_30 and database != master and database != dashboard
|
223
|
+
|
224
|
+
# On each agent, we ensure the certificate is signed then shut down the agent
|
225
|
+
install_hosts.each do |host|
|
226
|
+
sign_certificate(host)
|
227
|
+
stop_agent(host)
|
228
|
+
end
|
229
|
+
|
230
|
+
# Wait for PuppetDB to be totally up and running
|
231
|
+
sleep_until_puppetdb_started(database) unless pre_30
|
232
|
+
|
233
|
+
# Run the agent once to ensure everything is in the dashboard
|
234
|
+
install_hosts.each do |host|
|
235
|
+
on host, puppet_agent('-t'), :acceptable_exit_codes => [0,2]
|
236
|
+
|
237
|
+
# Workaround for PE-1105 when deploying 3.0.0
|
238
|
+
# The installer did not respect our database host answers in 3.0.0,
|
239
|
+
# and would cause puppetdb to be bounced by the agent run. By sleeping
|
240
|
+
# again here, we ensure that if that bounce happens during an upgrade
|
241
|
+
# test we won't fail early in the install process.
|
242
|
+
if version == '3.0.0' and host == database
|
243
|
+
sleep_until_puppetdb_started(database)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
install_hosts.each do |host|
|
248
|
+
wait_for_host_in_dashboard(host)
|
249
|
+
end
|
250
|
+
|
251
|
+
if pre_30
|
252
|
+
task = 'nodegroup:add_all_nodes group=default'
|
253
|
+
else
|
254
|
+
task = 'defaultgroup:ensure_default_group'
|
255
|
+
end
|
256
|
+
on dashboard, "/opt/puppet/bin/rake -sf /opt/puppet/share/puppet-dashboard/Rakefile #{task} RAILS_ENV=production"
|
257
|
+
|
258
|
+
# Now that all hosts are in the dashbaord, run puppet one more
|
259
|
+
# time to configure mcollective
|
260
|
+
on install_hosts, puppet_agent('-t'), :acceptable_exit_codes => [0,2]
|
261
|
+
end
|
262
|
+
|
263
|
+
#is version a < version b
|
264
|
+
#3.0.0-160-gac44cfb is greater than 3.0.0, and 2.8.2
|
265
|
+
def version_is_less a, b
|
266
|
+
a = a.split('-')[0].split('.')
|
267
|
+
b = b.split('-')[0].split('.')
|
268
|
+
(0...a.length).each do |i|
|
269
|
+
if i < b.length
|
270
|
+
if a[i] < b[i]
|
271
|
+
return true
|
272
|
+
elsif a[i] > b[i]
|
273
|
+
return false
|
274
|
+
end
|
275
|
+
else
|
276
|
+
return false
|
277
|
+
end
|
278
|
+
end
|
279
|
+
return false
|
280
|
+
end
|
281
|
+
|
282
|
+
def install_pe version, path
|
283
|
+
pre_30 = version_is_less(version, '3.0')
|
284
|
+
step "Install #{version} PE on #{path}"
|
285
|
+
do_install hosts, version, path, pre_30
|
286
|
+
end
|
287
|
+
|
288
|
+
def upgrade_pe version, path, from
|
289
|
+
pre_30 = version_is_less(version, '3.0')
|
290
|
+
if pre_30
|
291
|
+
do_install(hosts, version, path, pre_30, :type => :upgrade, :installer => 'puppet-enterprise-upgrader', :from => from)
|
292
|
+
else
|
293
|
+
do_install(hosts, version, path, pre_30, :type => :upgrade, :from => from)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Beaker
|
2
|
+
module DSL
|
3
|
+
# This module includes dsl helpers for setting the state of a test case.
|
4
|
+
# They do not need inclusion if using third party test runner. The
|
5
|
+
# Exception classes that they raise however should be defined as other
|
6
|
+
# DSL helpers will raise them as needed. See individual DSL modules
|
7
|
+
# for their specific dependencies. A class that mixes in this module
|
8
|
+
# must have a method #logger which will yield an object that responds to
|
9
|
+
# #notify and #warn. NOTE: the interface to logger may change shortly and
|
10
|
+
# {Beaker::Logger} should be consulted for the appropriate
|
11
|
+
# interface.
|
12
|
+
#
|
13
|
+
# Simply these methods log a message and raise the appropriate Exception
|
14
|
+
# The exceptions are are caught by {Beaker::TestCase} and are
|
15
|
+
# designed to allow some degree of freedom from the individual third
|
16
|
+
# party test runners that could be used.
|
17
|
+
module Outcomes
|
18
|
+
|
19
|
+
# Raise this class if it is determined that a test case should not
|
20
|
+
# be executed because the feature in question is still a
|
21
|
+
# "Work in Progress"
|
22
|
+
class PendingTest < Exception; end
|
23
|
+
|
24
|
+
# Raise this class if execution should be stopped because the test
|
25
|
+
# is not applicable within a given environment.
|
26
|
+
class SkipTest < Exception; end
|
27
|
+
|
28
|
+
# Raise this class if some criteria has been met that proves a failure.
|
29
|
+
class FailTest < Exception; end
|
30
|
+
|
31
|
+
# Raise this class if execution should stop because enough criteria has
|
32
|
+
# shown itself to pass the test.
|
33
|
+
class PassTest < Exception; end
|
34
|
+
|
35
|
+
|
36
|
+
# Raises FailTest Exception and logs an error message
|
37
|
+
#
|
38
|
+
# @param [String] msg An optional message to log
|
39
|
+
# @raise [FailTest]
|
40
|
+
# @api dsl
|
41
|
+
def fail_test msg = nil
|
42
|
+
message = formatted_message( msg, 'Failed' )
|
43
|
+
logger.warn( [message, logger.pretty_backtrace].join("\n") )
|
44
|
+
|
45
|
+
raise( FailTest, message )
|
46
|
+
end
|
47
|
+
|
48
|
+
# Raises PassTest Exception and logs a message
|
49
|
+
#
|
50
|
+
# @param [String] msg An optional message to log
|
51
|
+
# @raise [PassTest]
|
52
|
+
# @api dsl
|
53
|
+
def pass_test msg = nil
|
54
|
+
message = formatted_message( msg, 'Passed' )
|
55
|
+
logger.notify( message )
|
56
|
+
|
57
|
+
raise( PassTest, message )
|
58
|
+
end
|
59
|
+
|
60
|
+
# Raises PendingTest Exception and logs an error message
|
61
|
+
#
|
62
|
+
# @param [String] msg An optional message to log
|
63
|
+
# @raise [PendingTest]
|
64
|
+
# @api dsl
|
65
|
+
def pending_test msg = nil
|
66
|
+
message = formatted_message( msg, 'is Pending' )
|
67
|
+
logger.warn( message )
|
68
|
+
|
69
|
+
raise( PendingTest, message )
|
70
|
+
end
|
71
|
+
|
72
|
+
# Raises SkipTest Exception and logs a message
|
73
|
+
#
|
74
|
+
# @param [String] msg An optional message to log
|
75
|
+
# @raise [SkipTest]
|
76
|
+
# @api dsl
|
77
|
+
def skip_test msg = nil
|
78
|
+
message = formatted_message( msg, 'was Skipped' )
|
79
|
+
logger.notify( message )
|
80
|
+
|
81
|
+
raise( SkipTest, message )
|
82
|
+
end
|
83
|
+
|
84
|
+
# Formats an optional message or self appended by a state, either
|
85
|
+
# bracketted in newlines
|
86
|
+
#
|
87
|
+
# @param [String, nil] message The message (or nil) to format
|
88
|
+
# @param [String] default_str The string to be appended to self if
|
89
|
+
# message is nil
|
90
|
+
#
|
91
|
+
# @return [String] A prettier string with helpful info
|
92
|
+
# @!visibility private
|
93
|
+
def formatted_message(message, default_str )
|
94
|
+
msg = message ? "\n#{message}\n" : "\n#{self} #{default_str}.\n"
|
95
|
+
return msg
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Beaker
|
2
|
+
module DSL
|
3
|
+
#
|
4
|
+
# Identifying hosts.
|
5
|
+
#
|
6
|
+
# This aids in reaching common subsets of hosts in a testing matrix.
|
7
|
+
#
|
8
|
+
# It requires the class it is mixed into to provide the attribute
|
9
|
+
# `hosts` which contain the hosts to search, these should implement
|
10
|
+
# {Beaker::Host}'s interface. They, at least, must have #[]
|
11
|
+
# and #to_s available and provide an array when #[]('roles') is called.
|
12
|
+
#
|
13
|
+
# Also the constant {FailTest} needs to be defined it will be raised
|
14
|
+
# in error conditions
|
15
|
+
#
|
16
|
+
# @api dsl
|
17
|
+
module Roles
|
18
|
+
|
19
|
+
# The hosts for which ['roles'] include 'agent'
|
20
|
+
#
|
21
|
+
# @return [Array<Host>] May be empty
|
22
|
+
#
|
23
|
+
# @example Basic usage
|
24
|
+
# agents.each do |agent|
|
25
|
+
# ...test each agent in turn...
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
def agents
|
29
|
+
hosts_as 'agent'
|
30
|
+
end
|
31
|
+
|
32
|
+
# The host for which ['roles'] include 'master'
|
33
|
+
#
|
34
|
+
# @return [Array<Host>]
|
35
|
+
# @raise [Beaker::DSL::Outcomes::FailTest] if there are less
|
36
|
+
# or more than 1 master is found.
|
37
|
+
#
|
38
|
+
# @example Basic usage
|
39
|
+
# on, master, 'cat /etc/puppet/puppet.conf'
|
40
|
+
#
|
41
|
+
def master
|
42
|
+
find_only_one :master
|
43
|
+
end
|
44
|
+
|
45
|
+
# The host for which ['roles'] include 'database'
|
46
|
+
#
|
47
|
+
# @return [Array<Host>]
|
48
|
+
# @raise [Beaker::DSL::Outcomes::FailTest] if there are less
|
49
|
+
# or more than 1 database is found.
|
50
|
+
#
|
51
|
+
# @example Basic usage
|
52
|
+
# on, agent, "curl -k http://#{database}:8080"
|
53
|
+
#
|
54
|
+
def database
|
55
|
+
find_only_one :database
|
56
|
+
end
|
57
|
+
|
58
|
+
# The host for which ['roles'] include 'dashboard'
|
59
|
+
#
|
60
|
+
# @return [Array<Host>]
|
61
|
+
# @raise [Beaker::DSL::Outcomes::FailTest] if there are less
|
62
|
+
# or more than 1 dashboard is found.
|
63
|
+
#
|
64
|
+
# @example Basic usage
|
65
|
+
# on, agent, "curl https://#{database}/nodes/#{agent}"
|
66
|
+
#
|
67
|
+
def dashboard
|
68
|
+
find_only_one :dashboard
|
69
|
+
end
|
70
|
+
|
71
|
+
# Select hosts that include a desired role from #hosts
|
72
|
+
#
|
73
|
+
# @param [String, Symbol] desired_role The role to select for
|
74
|
+
# @return [Array<Host>] The hosts that match
|
75
|
+
# desired_role, may be empty
|
76
|
+
#
|
77
|
+
# @example Basic usage
|
78
|
+
# hairy = hosts_as :yak
|
79
|
+
# hairy.each do |yak|
|
80
|
+
# on yak, 'shave'
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# @api public
|
84
|
+
def hosts_as(desired_role = nil)
|
85
|
+
hosts_with_role(hosts, desired_role)
|
86
|
+
end
|
87
|
+
|
88
|
+
# @param [Symbol, String] role The role to find a host for
|
89
|
+
# @return [Host] Returns the host, if one and only one is found
|
90
|
+
# @raise Raises a failure exception if one and only one host that matches
|
91
|
+
# the specified role is NOT found.
|
92
|
+
def find_only_one role
|
93
|
+
only_host_with_role(hosts, role)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|