beaker 0.0.0 → 1.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/.travis.yml +8 -0
- data/README.md +6 -6
- data/beaker.gemspec +6 -2
- data/lib/beaker.rb +1 -1
- data/lib/beaker/answers.rb +34 -7
- data/lib/beaker/answers/version20.rb +124 -0
- data/lib/beaker/answers/version28.rb +21 -0
- data/lib/beaker/answers/version30.rb +24 -5
- data/lib/beaker/cli.rb +55 -41
- data/lib/beaker/command.rb +2 -2
- data/lib/beaker/dsl/helpers.rb +320 -106
- data/lib/beaker/dsl/install_utils.rb +202 -81
- data/lib/beaker/dsl/roles.rb +40 -0
- data/lib/beaker/host.rb +28 -20
- data/lib/beaker/host/unix.rb +7 -4
- data/lib/beaker/host/unix/pkg.rb +42 -12
- data/lib/beaker/host/windows.rb +9 -5
- data/lib/beaker/host/windows/group.rb +1 -1
- data/lib/beaker/host/windows/pkg.rb +41 -8
- data/lib/beaker/hypervisor.rb +23 -10
- data/lib/beaker/hypervisor/aixer.rb +15 -19
- data/lib/beaker/hypervisor/blimper.rb +71 -72
- data/lib/beaker/hypervisor/fusion.rb +11 -10
- data/lib/beaker/hypervisor/solaris.rb +17 -23
- data/lib/beaker/hypervisor/vagrant.rb +27 -12
- data/lib/beaker/hypervisor/vcloud.rb +154 -138
- data/lib/beaker/hypervisor/vcloud_pooled.rb +97 -0
- data/lib/beaker/hypervisor/vsphere.rb +8 -5
- data/lib/beaker/hypervisor/vsphere_helper.rb +43 -33
- data/lib/beaker/network_manager.rb +16 -12
- data/lib/beaker/options/command_line_parser.rb +199 -0
- data/lib/beaker/options/hosts_file_parser.rb +39 -0
- data/lib/beaker/options/options_file_parser.rb +45 -0
- data/lib/beaker/options/options_hash.rb +294 -0
- data/lib/beaker/options/parser.rb +288 -0
- data/lib/beaker/options/pe_version_scraper.rb +35 -0
- data/lib/beaker/options/presets.rb +70 -0
- data/lib/beaker/shared.rb +2 -1
- data/lib/beaker/shared/host_handler.rb +7 -2
- data/lib/beaker/shared/repetition.rb +1 -0
- data/lib/beaker/shared/timed.rb +14 -0
- data/lib/beaker/test_case.rb +2 -38
- data/lib/beaker/test_suite.rb +11 -25
- data/lib/beaker/utils/repo_control.rb +6 -8
- data/lib/beaker/utils/setup_helper.rb +9 -20
- data/spec/beaker/answers_spec.rb +109 -0
- data/spec/beaker/command_spec.rb +2 -2
- data/spec/beaker/dsl/assertions_spec.rb +1 -3
- data/spec/beaker/dsl/helpers_spec.rb +519 -84
- data/spec/beaker/dsl/install_utils_spec.rb +265 -16
- data/spec/beaker/dsl/roles_spec.rb +31 -10
- data/spec/beaker/host/windows/group_spec.rb +55 -0
- data/spec/beaker/host_spec.rb +130 -40
- data/spec/beaker/hypervisor/aixer_spec.rb +34 -0
- data/spec/beaker/hypervisor/blimper_spec.rb +77 -0
- data/spec/beaker/hypervisor/fusion_spec.rb +26 -0
- data/spec/beaker/hypervisor/hypervisor_spec.rb +66 -0
- data/spec/beaker/hypervisor/solaris_spec.rb +39 -0
- data/spec/beaker/hypervisor/vagrant_spec.rb +105 -0
- data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +60 -0
- data/spec/beaker/hypervisor/vcloud_spec.rb +70 -0
- data/spec/beaker/hypervisor/vsphere_helper_spec.rb +162 -0
- data/spec/beaker/hypervisor/vsphere_spec.rb +76 -0
- data/spec/beaker/options/command_line_parser_spec.rb +25 -0
- data/spec/beaker/options/data/LATEST +1 -0
- data/spec/beaker/options/data/badyaml.cfg +21 -0
- data/spec/beaker/options/data/hosts.cfg +21 -0
- data/spec/beaker/options/data/opts.txt +6 -0
- data/spec/beaker/options/hosts_file_parser_spec.rb +30 -0
- data/spec/beaker/options/options_file_parser_spec.rb +23 -0
- data/spec/beaker/options/options_hash_spec.rb +111 -0
- data/spec/beaker/options/parser_spec.rb +172 -0
- data/spec/beaker/options/pe_version_scaper_spec.rb +15 -0
- data/spec/beaker/options/presets_spec.rb +24 -0
- data/spec/beaker/puppet_command_spec.rb +54 -21
- data/spec/beaker/shared/error_handler_spec.rb +40 -0
- data/spec/beaker/shared/host_handler_spec.rb +104 -0
- data/spec/beaker/shared/repetition_spec.rb +72 -0
- data/spec/beaker/test_suite_spec.rb +3 -16
- data/spec/beaker/utils/ntp_control_spec.rb +42 -0
- data/spec/beaker/utils/repo_control_spec.rb +168 -0
- data/spec/beaker/utils/setup_helper_spec.rb +82 -0
- data/spec/beaker/utils/validator_spec.rb +58 -0
- data/spec/helpers.rb +97 -0
- data/spec/matchers.rb +39 -0
- data/spec/mock_blimpy.rb +48 -0
- data/spec/mock_fission.rb +60 -0
- data/spec/mock_vsphere.rb +310 -0
- data/spec/mock_vsphere_helper.rb +183 -0
- data/spec/mocks.rb +83 -0
- data/spec/spec_helper.rb +8 -1
- metadata +106 -13
- data/beaker.rb +0 -10
- data/lib/beaker/options_parsing.rb +0 -323
- data/lib/beaker/test_config.rb +0 -148
- data/spec/beaker/options_parsing_spec.rb +0 -37
- data/spec/mocks_and_helpers.rb +0 -34
data/lib/beaker/command.rb
CHANGED
|
@@ -91,7 +91,7 @@ module Beaker
|
|
|
91
91
|
"#{env_string} #{cmd} #{options_string} #{args_string}"
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
# @param [Hash]
|
|
94
|
+
# @param [Hash] opts These are the options that the command takes
|
|
95
95
|
#
|
|
96
96
|
# @return [String] String of the options and flags for command.
|
|
97
97
|
#
|
|
@@ -150,7 +150,7 @@ module Beaker
|
|
|
150
150
|
# knowledge contained here. Really the relationship should be
|
|
151
151
|
# reversed where a host is asked for an appropriate Command when
|
|
152
152
|
# given a generic Command.
|
|
153
|
-
def environment_string_for host, env
|
|
153
|
+
def environment_string_for host, env
|
|
154
154
|
return '' if env.empty?
|
|
155
155
|
|
|
156
156
|
env_array = parse_env_hash_for( host, env ).compact
|
data/lib/beaker/dsl/helpers.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
require 'resolv'
|
|
2
|
+
require 'inifile'
|
|
3
|
+
require 'timeout'
|
|
2
4
|
require 'beaker/dsl/outcomes'
|
|
3
5
|
|
|
4
6
|
module Beaker
|
|
@@ -13,6 +15,9 @@ module Beaker
|
|
|
13
15
|
# {Beaker::Host}'s interface to act upon.
|
|
14
16
|
# * a method *logger* that yields a logger implementing
|
|
15
17
|
# {Beaker::Logger}'s interface.
|
|
18
|
+
# * the module {Beaker::DSL::Roles} that provides access to the various hosts implementing
|
|
19
|
+
# {Beaker::Host}'s interface to act upon
|
|
20
|
+
# * the module {Beaker::DSL::Wrappers} the provides convenience methods for {Beaker::DSL::Command} creation
|
|
16
21
|
#
|
|
17
22
|
#
|
|
18
23
|
# @api dsl
|
|
@@ -31,7 +36,8 @@ module Beaker
|
|
|
31
36
|
|
|
32
37
|
# The primary method for executing commands *on* some set of hosts.
|
|
33
38
|
#
|
|
34
|
-
# @param [Host, Array<Host
|
|
39
|
+
# @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon,
|
|
40
|
+
# or a role (String or Symbol) that identifies one or more hosts.
|
|
35
41
|
# @param [String, Command] command The command to execute on *host*.
|
|
36
42
|
# @param [Proc] block Additional actions or assertions.
|
|
37
43
|
# @!macro common_opts
|
|
@@ -54,6 +60,12 @@ module Beaker
|
|
|
54
60
|
# end
|
|
55
61
|
# end
|
|
56
62
|
#
|
|
63
|
+
# @example Using a role (defined in a String) to identify the host
|
|
64
|
+
# on "master", "echo hello"
|
|
65
|
+
#
|
|
66
|
+
# @example Using a role (defined in a Symbol) to identify the host
|
|
67
|
+
# on :dashboard, "echo hello"
|
|
68
|
+
#
|
|
57
69
|
# @return [Result] An object representing the outcome of *command*.
|
|
58
70
|
# @raise [FailTest] Raises an exception if *command* obviously fails.
|
|
59
71
|
def on(host, command, opts = {}, &block)
|
|
@@ -61,6 +73,9 @@ module Beaker
|
|
|
61
73
|
cmd_opts = opts[:environment] ? { 'ENV' => opts.delete(:environment) } : Hash.new
|
|
62
74
|
command = Command.new(command.to_s, [], cmd_opts)
|
|
63
75
|
end
|
|
76
|
+
if host.is_a? String or host.is_a? Symbol
|
|
77
|
+
host = hosts_as(host) #check by role
|
|
78
|
+
end
|
|
64
79
|
if host.is_a? Array
|
|
65
80
|
host.map { |h| on h, command, opts, &block }
|
|
66
81
|
else
|
|
@@ -73,6 +88,66 @@ module Beaker
|
|
|
73
88
|
end
|
|
74
89
|
end
|
|
75
90
|
|
|
91
|
+
# The method for executing commands on the default host
|
|
92
|
+
#
|
|
93
|
+
# @param [String, Command] command The command to execute on *host*.
|
|
94
|
+
# @param [Proc] block Additional actions or assertions.
|
|
95
|
+
# @!macro common_opts
|
|
96
|
+
#
|
|
97
|
+
# @example Most basic usage
|
|
98
|
+
# shell 'ls /tmp'
|
|
99
|
+
#
|
|
100
|
+
# @example Allowing additional exit codes to pass
|
|
101
|
+
# shell 'puppet agent -t', :acceptable_exit_codes => [0,2]
|
|
102
|
+
#
|
|
103
|
+
# @example Using the returned result for any kind of checking
|
|
104
|
+
# if shell('ls -la ~').stdout =~ /\.bin/
|
|
105
|
+
# ...do some action...
|
|
106
|
+
# end
|
|
107
|
+
#
|
|
108
|
+
# @example Using TestCase helpers from within a test.
|
|
109
|
+
# agents.each do |agent|
|
|
110
|
+
# shell('cat /etc/puppet/puppet.conf') do |result|
|
|
111
|
+
# assert_match result.stdout, /server = #{master}/, 'WTF Mate'
|
|
112
|
+
# end
|
|
113
|
+
# end
|
|
114
|
+
#
|
|
115
|
+
# @return [Result] An object representing the outcome of *command*.
|
|
116
|
+
# @raise [FailTest] Raises an exception if *command* obviously fails.
|
|
117
|
+
def shell(command, opts = {}, &block)
|
|
118
|
+
on(default, command, opts, &block)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @deprecated
|
|
122
|
+
# An proxy for the last {Beaker::Result#stdout} returned by
|
|
123
|
+
# a method that makes remote calls. Use the {Beaker::Result}
|
|
124
|
+
# object returned by the method directly instead. For Usage see
|
|
125
|
+
# {Beaker::Result}.
|
|
126
|
+
def stdout
|
|
127
|
+
return nil if @result.nil?
|
|
128
|
+
@result.stdout
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# @deprecated
|
|
132
|
+
# An proxy for the last {Beaker::Result#stderr} returned by
|
|
133
|
+
# a method that makes remote calls. Use the {Beaker::Result}
|
|
134
|
+
# object returned by the method directly instead. For Usage see
|
|
135
|
+
# {Beaker::Result}.
|
|
136
|
+
def stderr
|
|
137
|
+
return nil if @result.nil?
|
|
138
|
+
@result.stderr
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# @deprecated
|
|
142
|
+
# An proxy for the last {Beaker::Result#exit_code} returned by
|
|
143
|
+
# a method that makes remote calls. Use the {Beaker::Result}
|
|
144
|
+
# object returned by the method directly instead. For Usage see
|
|
145
|
+
# {Beaker::Result}.
|
|
146
|
+
def exit_code
|
|
147
|
+
return nil if @result.nil?
|
|
148
|
+
@result.exit_code
|
|
149
|
+
end
|
|
150
|
+
|
|
76
151
|
# Move a file from a remote to a local path
|
|
77
152
|
# @note If using {Beaker::Host} for the hosts *scp* is not
|
|
78
153
|
# required on the system as it uses Ruby's net/scp library. The
|
|
@@ -119,17 +194,17 @@ module Beaker
|
|
|
119
194
|
|
|
120
195
|
# Check to see if a package is installed on a remote host
|
|
121
196
|
#
|
|
122
|
-
# @param [Host] host A host object
|
|
197
|
+
# @param [Host] host A host object
|
|
123
198
|
# @param [String] package_name Name of the package to check for.
|
|
124
199
|
#
|
|
125
|
-
# @return [Boolean] true/false if the package is found
|
|
200
|
+
# @return [Boolean] true/false if the package is found
|
|
126
201
|
def check_for_package host, package_name
|
|
127
202
|
host.check_for_package package_name
|
|
128
203
|
end
|
|
129
204
|
|
|
130
205
|
# Install a package on a host
|
|
131
206
|
#
|
|
132
|
-
# @param [Host] host A host object
|
|
207
|
+
# @param [Host] host A host object
|
|
133
208
|
# @param [String] package_name Name of the package to install
|
|
134
209
|
#
|
|
135
210
|
# @return [Result] An object representing the outcome of *install command*.
|
|
@@ -180,6 +255,12 @@ module Beaker
|
|
|
180
255
|
on host, remote_path, opts, &block
|
|
181
256
|
end
|
|
182
257
|
|
|
258
|
+
# Move a local script to default host and execute it
|
|
259
|
+
# @see #run_script_on
|
|
260
|
+
def run_script(script, opts = {}, &block)
|
|
261
|
+
run_script_on(default, script, opts, &block)
|
|
262
|
+
end
|
|
263
|
+
|
|
183
264
|
# Limit the hosts a test case is run against
|
|
184
265
|
# @note This will modify the {Beaker::TestCase#hosts} member
|
|
185
266
|
# in place unless an array of hosts is passed into it and
|
|
@@ -198,7 +279,7 @@ module Beaker
|
|
|
198
279
|
# considered for inclusion or exclusion. The key is any attribute
|
|
199
280
|
# of the host that will be yielded by {Beaker::Host#[]}.
|
|
200
281
|
# The value can be any string/regex or array of strings/regexp.
|
|
201
|
-
# The values are compared using
|
|
282
|
+
# The values are compared using [Enumerable#any?] so that if one
|
|
202
283
|
# value of an array matches the host is considered a match for that
|
|
203
284
|
# criteria.
|
|
204
285
|
# @param [Array<Host>] host_array This creatively named parameter is
|
|
@@ -259,6 +340,23 @@ module Beaker
|
|
|
259
340
|
hosts_to_modify
|
|
260
341
|
end
|
|
261
342
|
|
|
343
|
+
# Ensures that host restrictions as specifid by type, criteria and
|
|
344
|
+
# host_array are confined to activity within the passed block.
|
|
345
|
+
# TestCase#hosts is reset after block has executed.
|
|
346
|
+
#
|
|
347
|
+
# @see #confine
|
|
348
|
+
def confine_block(type, criteria, host_array = nil, &block)
|
|
349
|
+
begin
|
|
350
|
+
original_hosts = self.hosts.dup
|
|
351
|
+
confine(type, criteria, host_array)
|
|
352
|
+
|
|
353
|
+
yield
|
|
354
|
+
|
|
355
|
+
ensure
|
|
356
|
+
self.hosts = original_hosts
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
262
360
|
# @!visibility private
|
|
263
361
|
def inspect_host(host, property, one_or_more_values)
|
|
264
362
|
values = Array(one_or_more_values)
|
|
@@ -285,14 +383,25 @@ module Beaker
|
|
|
285
383
|
# 6. Revert Puppet to the pre-test state
|
|
286
384
|
# 7. Testing artifacts are saved in a folder named for the test
|
|
287
385
|
#
|
|
288
|
-
# @param [Host]
|
|
386
|
+
# @param [Host] host One object that act like Host
|
|
289
387
|
#
|
|
290
|
-
# @param [Hash{Symbol=>String}]
|
|
291
|
-
# config_opts Represent puppet settings.
|
|
388
|
+
# @param [Hash{Symbol=>String}] conf_opts Represents puppet settings.
|
|
292
389
|
# Sections of the puppet.conf may be
|
|
293
390
|
# specified, if no section is specified the
|
|
294
391
|
# a puppet.conf file will be written with the
|
|
295
|
-
# options put in a section named after [mode]
|
|
392
|
+
# options put in a section named after [mode]
|
|
393
|
+
#
|
|
394
|
+
# There is a special setting for command_line
|
|
395
|
+
# arguments such as --debug or --logdest, which
|
|
396
|
+
# cannot be set in puppet.conf. For example:
|
|
397
|
+
#
|
|
398
|
+
# :__commandline_args__ => '--logdest /tmp/a.log'
|
|
399
|
+
#
|
|
400
|
+
# These will only be applied when starting a FOSS
|
|
401
|
+
# master, as a pe master is just bounced.
|
|
402
|
+
#
|
|
403
|
+
# @param [File] testdir The temporary directory which will hold backup
|
|
404
|
+
# configuration, and other test artifacts.
|
|
296
405
|
#
|
|
297
406
|
# @param [Block] block The point of this method, yields so
|
|
298
407
|
# tests may be ran. After the block is finished
|
|
@@ -314,71 +423,127 @@ module Beaker
|
|
|
314
423
|
#
|
|
315
424
|
# @api dsl
|
|
316
425
|
def with_puppet_running_on host, conf_opts, testdir = host.tmpdir(File.basename(@path)), &block
|
|
426
|
+
raise(ArgumentError, "with_puppet_running_on's conf_opts must be a Hash. You provided a #{conf_opts.class}: '#{conf_opts}'") if !conf_opts.kind_of?(Hash)
|
|
427
|
+
cmdline_args = conf_opts.delete(:__commandline_args__)
|
|
428
|
+
|
|
317
429
|
begin
|
|
318
|
-
backup_file host, host['puppetpath'], testdir, 'puppet.conf'
|
|
430
|
+
backup_file = backup_the_file(host, host['puppetpath'], testdir, 'puppet.conf')
|
|
319
431
|
lay_down_new_puppet_conf host, conf_opts, testdir
|
|
320
432
|
|
|
321
433
|
if host.is_pe?
|
|
322
|
-
bounce_service( 'pe-httpd' )
|
|
323
|
-
|
|
434
|
+
bounce_service( host, 'pe-httpd' )
|
|
324
435
|
else
|
|
325
|
-
start_puppet_from_source_on!( host )
|
|
436
|
+
puppet_master_started = start_puppet_from_source_on!( host, cmdline_args )
|
|
326
437
|
end
|
|
327
438
|
|
|
328
439
|
yield self if block_given?
|
|
440
|
+
|
|
441
|
+
rescue Exception => early_exception
|
|
442
|
+
original_exception = RuntimeError.new("PuppetAcceptance::DSL::Helpers.with_puppet_running_on failed (check backtrace for location) because: #{early_exception}\n#{early_exception.backtrace.join("\n")}\n")
|
|
443
|
+
raise(original_exception)
|
|
444
|
+
|
|
329
445
|
ensure
|
|
330
|
-
|
|
446
|
+
begin
|
|
447
|
+
restore_puppet_conf_from_backup( host, backup_file )
|
|
331
448
|
|
|
332
|
-
|
|
333
|
-
|
|
449
|
+
if host.is_pe?
|
|
450
|
+
bounce_service( host, 'pe-httpd' )
|
|
451
|
+
else
|
|
452
|
+
stop_puppet_from_source_on( host ) if puppet_master_started
|
|
453
|
+
end
|
|
334
454
|
|
|
335
|
-
|
|
336
|
-
|
|
455
|
+
rescue Exception => teardown_exception
|
|
456
|
+
if original_exception
|
|
457
|
+
logger.error("Raised during attempt to teardown with_puppet_running_on: #{teardown_exception}\n---\n")
|
|
458
|
+
raise original_exception
|
|
459
|
+
else
|
|
460
|
+
raise teardown_exception
|
|
461
|
+
end
|
|
337
462
|
end
|
|
338
463
|
end
|
|
339
464
|
end
|
|
340
465
|
|
|
466
|
+
# Test Puppet running in a certain run mode with specific options,
|
|
467
|
+
# on the default host
|
|
468
|
+
# @api dsl
|
|
469
|
+
# @see #with_puppet_running_on
|
|
470
|
+
def with_puppet_running conf_opts, testdir = host.tmpdir(File.basename(@path)), &block
|
|
471
|
+
with_puppet_running_on(default, conf_opts, testdir, &block)
|
|
472
|
+
end
|
|
473
|
+
|
|
341
474
|
# @!visibility private
|
|
342
|
-
def restore_puppet_conf_from_backup( host )
|
|
475
|
+
def restore_puppet_conf_from_backup( host, backup_file )
|
|
343
476
|
puppetpath = host['puppetpath']
|
|
344
477
|
|
|
345
|
-
host.exec( Command.new( "if [ -f #{
|
|
346
|
-
"cat #{
|
|
347
|
-
"#{puppetpath}/puppet.conf; " +
|
|
348
|
-
"rm -
|
|
478
|
+
host.exec( Command.new( "if [ -f '#{backup_file}' ]; then " +
|
|
479
|
+
"cat '#{backup_file}' > " +
|
|
480
|
+
"'#{puppetpath}/puppet.conf'; " +
|
|
481
|
+
"rm -f '#{backup_file}'; " +
|
|
349
482
|
"fi" ) )
|
|
350
483
|
end
|
|
351
484
|
|
|
352
485
|
# @!visibility private
|
|
353
|
-
def
|
|
486
|
+
def backup_the_file host, current_dir, new_dir, filename = 'puppet.conf'
|
|
354
487
|
old_location = current_dir + '/' + filename
|
|
355
|
-
new_location = new_dir + '/' + filename
|
|
488
|
+
new_location = new_dir + '/' + filename + '.bak'
|
|
356
489
|
|
|
357
490
|
host.exec( Command.new( "cp #{old_location} #{new_location}" ) )
|
|
491
|
+
|
|
492
|
+
return new_location
|
|
358
493
|
end
|
|
359
494
|
|
|
360
495
|
# @!visibility private
|
|
361
|
-
def start_puppet_from_source_on! host
|
|
362
|
-
host.exec(
|
|
496
|
+
def start_puppet_from_source_on! host, args = ''
|
|
497
|
+
host.exec( puppet( 'master', args ) )
|
|
363
498
|
|
|
364
499
|
logger.debug 'Waiting for the puppet master to start'
|
|
365
500
|
unless port_open_within?( host, 8140, 10 )
|
|
501
|
+
dump_puppet_log(host)
|
|
366
502
|
raise Beaker::DSL::FailTest, 'Puppet master did not start in a timely fashion'
|
|
367
503
|
end
|
|
368
504
|
logger.debug 'The puppet master has started'
|
|
505
|
+
return true
|
|
369
506
|
end
|
|
370
507
|
|
|
371
508
|
# @!visibility private
|
|
372
509
|
def stop_puppet_from_source_on( host )
|
|
373
|
-
host.exec( Command.new(
|
|
510
|
+
pid = host.exec( Command.new('cat `puppet master --configprint pidfile`') ).stdout.chomp
|
|
511
|
+
host.exec( Command.new( "kill #{pid}" ) )
|
|
512
|
+
Timeout.timeout(10) do
|
|
513
|
+
while host.exec( Command.new( "kill -0 #{pid}"), :acceptable_exit_codes => [0,1] ).exit_code == 0 do
|
|
514
|
+
# until kill -0 finds no process and we know that puppet has finished cleaning up
|
|
515
|
+
sleep 1
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
rescue RuntimeError => e
|
|
519
|
+
dump_puppet_log host
|
|
520
|
+
raise e
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
# @!visibility private
|
|
524
|
+
def dump_puppet_log(host)
|
|
525
|
+
syslogfile = case host['platform']
|
|
526
|
+
when /fedora|centos|el/ then '/var/log/messages'
|
|
527
|
+
when /ubuntu|debian/ then '/var/log/syslog'
|
|
528
|
+
else return
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
logger.notify "\n*************************"
|
|
532
|
+
logger.notify "* Dumping master log *"
|
|
533
|
+
logger.notify "*************************"
|
|
534
|
+
host.exec( Command.new( "tail -n 100 #{syslogfile}" ), :acceptable_exit_codes => [0,1])
|
|
535
|
+
logger.notify "*************************\n"
|
|
374
536
|
end
|
|
375
537
|
|
|
376
538
|
# @!visibility private
|
|
377
539
|
def lay_down_new_puppet_conf( host, configuration_options, testdir )
|
|
378
|
-
new_conf = puppet_conf_for( host )
|
|
540
|
+
new_conf = puppet_conf_for( host, configuration_options )
|
|
379
541
|
create_remote_file host, "#{testdir}/puppet.conf", new_conf.to_s
|
|
380
542
|
|
|
381
|
-
host.exec(
|
|
543
|
+
host.exec(
|
|
544
|
+
Command.new( "cat #{testdir}/puppet.conf > #{host['puppetpath']}/puppet.conf" ),
|
|
545
|
+
:silent => true
|
|
546
|
+
)
|
|
382
547
|
host.exec( Command.new( "cat #{host['puppetpath']}/puppet.conf" ) )
|
|
383
548
|
end
|
|
384
549
|
|
|
@@ -467,6 +632,12 @@ module Beaker
|
|
|
467
632
|
on host, puppet( 'apply', *args), on_options, &block
|
|
468
633
|
end
|
|
469
634
|
|
|
635
|
+
# Runs 'puppet apply' on default host, piping manifest through stdin
|
|
636
|
+
# @see #apply_manifest_on
|
|
637
|
+
def apply_manifest(manifest, opts = {}, &block)
|
|
638
|
+
apply_manifest_on(default, manifest, opts, &block)
|
|
639
|
+
end
|
|
640
|
+
|
|
470
641
|
# @deprecated
|
|
471
642
|
def run_agent_on(host, arg='--no-daemonize --verbose --onetime --test',
|
|
472
643
|
options={}, &block)
|
|
@@ -517,7 +688,7 @@ module Beaker
|
|
|
517
688
|
# removed always.
|
|
518
689
|
#
|
|
519
690
|
# @param machine [String] the host to execute this stub
|
|
520
|
-
# @param
|
|
691
|
+
# @param ip_spec [Hash{String=>String}] a hash containing the host to ip
|
|
521
692
|
# mappings
|
|
522
693
|
# @example Stub puppetlabs.com on the master to 127.0.0.1
|
|
523
694
|
# stub_hosts_on(master, 'puppetlabs.com' => '127.0.0.1')
|
|
@@ -537,6 +708,16 @@ module Beaker
|
|
|
537
708
|
end
|
|
538
709
|
end
|
|
539
710
|
|
|
711
|
+
# This method accepts a block and using the puppet resource 'host' will
|
|
712
|
+
# setup host aliases before and after that block on the default host
|
|
713
|
+
#
|
|
714
|
+
# @example Stub puppetlabs.com on the default host to 127.0.0.1
|
|
715
|
+
# stub_hosts('puppetlabs.com' => '127.0.0.1')
|
|
716
|
+
# @see #stub_hosts_on
|
|
717
|
+
def stub_hosts(ip_spec)
|
|
718
|
+
stub_hosts_on(default, ip_spec)
|
|
719
|
+
end
|
|
720
|
+
|
|
540
721
|
# This wraps the method `stub_hosts_on` and makes the stub specific to
|
|
541
722
|
# the forge alias.
|
|
542
723
|
#
|
|
@@ -545,81 +726,114 @@ module Beaker
|
|
|
545
726
|
@forge_ip ||= Resolv.getaddress(forge)
|
|
546
727
|
stub_hosts_on(machine, 'forge.puppetlabs.com' => @forge_ip)
|
|
547
728
|
end
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
729
|
+
|
|
730
|
+
# This wraps the method `stub_hosts` and makes the stub specific to
|
|
731
|
+
# the forge alias.
|
|
732
|
+
#
|
|
733
|
+
# @see #stub_forge_on
|
|
734
|
+
def stub_forge
|
|
735
|
+
stub_forge_on(default)
|
|
736
|
+
end
|
|
737
|
+
|
|
738
|
+
def sleep_until_puppetdb_started(host)
|
|
739
|
+
curl_with_retries("start puppetdb", host, "http://localhost:8080", 0, 120)
|
|
740
|
+
curl_with_retries("start puppetdb (ssl)",
|
|
741
|
+
host, "https://#{host.node_name}:8081", [35, 60])
|
|
742
|
+
end
|
|
743
|
+
|
|
744
|
+
def curl_with_retries(desc, host, url, desired_exit_codes, max_retries = 60, retry_interval = 1)
|
|
745
|
+
retry_command(desc, host, "curl #{url}", desired_exit_codes, max_retries, retry_interval)
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
def retry_command(desc, host, command, desired_exit_codes = 0, max_retries = 60, retry_interval = 1)
|
|
749
|
+
desired_exit_codes = [desired_exit_codes].flatten
|
|
750
|
+
result = on host, command, :acceptable_exit_codes => (0...127)
|
|
751
|
+
num_retries = 0
|
|
752
|
+
until desired_exit_codes.include?(result.exit_code)
|
|
753
|
+
sleep retry_interval
|
|
754
|
+
result = on host, command, :acceptable_exit_codes => (0...127)
|
|
755
|
+
num_retries += 1
|
|
756
|
+
if (num_retries > max_retries)
|
|
757
|
+
fail("Unable to #{desc}")
|
|
758
|
+
end
|
|
759
|
+
end
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
#stops the puppet agent running on the host
|
|
763
|
+
def stop_agent_on(agent)
|
|
764
|
+
vardir = agent.puppet['vardir']
|
|
765
|
+
agent_running = true
|
|
766
|
+
while agent_running
|
|
767
|
+
result = on agent, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1]
|
|
768
|
+
agent_running = (result.exit_code == 0)
|
|
769
|
+
sleep 2 unless agent_running
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
if agent['platform'].include?('solaris')
|
|
773
|
+
on(agent, '/usr/sbin/svcadm disable -s svc:/network/pe-puppet:default')
|
|
774
|
+
elsif agent['platform'].include?('aix')
|
|
775
|
+
on(agent, '/usr/bin/stopsrc -s pe-puppet')
|
|
776
|
+
elsif agent['platform'].include?('windows')
|
|
777
|
+
on(agent, 'net stop pe-puppet', :acceptable_exit_codes => [0,2])
|
|
778
|
+
else
|
|
779
|
+
# For the sake of not passing the PE version into this method,
|
|
780
|
+
# we just query the system to find out which service we want to
|
|
781
|
+
# stop
|
|
782
|
+
result = on agent, "[ -e /etc/init.d/pe-puppet-agent ]", :acceptable_exit_codes => [0,1]
|
|
783
|
+
service = (result.exit_code == 0) ? 'pe-puppet-agent' : 'pe-puppet'
|
|
784
|
+
on(agent, "/etc/init.d/#{service} stop")
|
|
785
|
+
end
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
#stops the puppet agent running on the default host
|
|
789
|
+
# @see #stop_agent_on
|
|
790
|
+
def stop_agent
|
|
791
|
+
stop_agent_on(default)
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
#wait for a given host to appear in the dashboard
|
|
796
|
+
def wait_for_host_in_dashboard(host)
|
|
797
|
+
hostname = host.node_name
|
|
798
|
+
retry_command("Wait for #{hostname} to be in the console", dashboard, "! curl --sslv3 -k -I https://#{dashboard}/nodes/#{hostname} | grep '404 Not Found'")
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
# Ensure the host has requested a cert, then sign it
|
|
802
|
+
#
|
|
803
|
+
# @param [Host] host The host to sign for
|
|
804
|
+
#
|
|
805
|
+
# @returns nil
|
|
806
|
+
# @raise [FailTest] if process times out
|
|
807
|
+
def sign_certificate_for(host)
|
|
808
|
+
if [master, dashboard, database].include? host
|
|
809
|
+
|
|
810
|
+
on host, puppet( 'agent -t' ), :acceptable_exit_codes => [0,1,2]
|
|
811
|
+
on master, puppet( "cert --allow-dns-alt-names sign #{host}" ), :acceptable_exit_codes => [0,24]
|
|
812
|
+
|
|
813
|
+
else
|
|
814
|
+
|
|
815
|
+
hostname = Regexp.escape host.node_name
|
|
816
|
+
|
|
817
|
+
last_sleep = 0
|
|
818
|
+
next_sleep = 1
|
|
819
|
+
(0..10).each do |i|
|
|
820
|
+
fail_test("Failed to sign cert for #{hostname}") if i == 10
|
|
821
|
+
|
|
822
|
+
on master, puppet("cert --sign --all"), :acceptable_exit_codes => [0,24]
|
|
823
|
+
break if on(master, puppet("cert --list --all")).stdout =~ /\+ "?#{hostname}"?/
|
|
824
|
+
sleep next_sleep
|
|
825
|
+
(last_sleep, next_sleep) = next_sleep, last_sleep+next_sleep
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
end
|
|
829
|
+
end
|
|
830
|
+
|
|
831
|
+
#prompt the master to sign certs then check to confirm the cert for the default host is signed
|
|
832
|
+
#@see #sign_certificate_for
|
|
833
|
+
def sign_certificate
|
|
834
|
+
sign_certificate_for(default)
|
|
835
|
+
end
|
|
836
|
+
|
|
623
837
|
end
|
|
624
838
|
end
|
|
625
839
|
end
|