beaker 1.3.2 → 1.4.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/lib/beaker/dsl/helpers.rb +12 -2
- data/lib/beaker/dsl/install_utils.rb +43 -5
- data/lib/beaker/host.rb +16 -7
- data/lib/beaker/options/command_line_parser.rb +1 -1
- data/lib/beaker/options/parser.rb +2 -2
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/dsl/helpers_spec.rb +19 -0
- data/spec/beaker/dsl/install_utils_spec.rb +64 -1
- data/spec/beaker/host_spec.rb +8 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZmRmOTdmNmVlZDNkMjFiMGIyNTAzZTRjYjRiMDRmYWU5Mjk3NDZmMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NjY1MWEyOGQyMzdjNDZjM2Q0YWNmMzY0N2U3ZTE4ZGQ4NThmMWExNw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTk5MWY3N2NjNWI5ZDMwNjZiMzM4YWRlNmUwMDczYTY3ZTFhNDc1MzViYzEz
|
10
|
+
NjZkZDBkZjczMWEwZWNjOTEyN2E1ZTk1N2YxNDFlMzhlOWVjMzE4ZjhmOTVj
|
11
|
+
OTlkODM2Y2Y0NWViYjA4ZWE3YzA0M2RhYzExZGRiOTI0MDZjMzQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NWRlNmUxNzM0Y2E3MDYwNmNjODZhYzk1YzQ1NDdjMTA2NWQ5ZTdjMjAzODVj
|
14
|
+
ZjdlYzg4NjI5MDFjMTU2MjRjYTNkZWNhZDVkZWIzNDc1MmRhZGQwMDVlZmIx
|
15
|
+
OGY1OTdkZDdhZTk2OWJlOGNiZTM0MGIyMzViZTVhMzg4NTFhZTM=
|
data/lib/beaker/dsl/helpers.rb
CHANGED
@@ -659,6 +659,11 @@ module Beaker
|
|
659
659
|
# if `puppet --apply` indicates that there were
|
660
660
|
# changes or failures during its execution.
|
661
661
|
#
|
662
|
+
# @option opts [Boolean] :expect_changes (false) This option enables
|
663
|
+
# detailed exit codes and causes a test failure
|
664
|
+
# if `puppet --apply` indicates that there were
|
665
|
+
# no resource changes during its execution.
|
666
|
+
#
|
662
667
|
# @option opts [Boolean] :expect_failures (false) This option enables
|
663
668
|
# detailed exit codes and causes a test failure
|
664
669
|
# if `puppet --apply` indicates there were no
|
@@ -679,8 +684,8 @@ module Beaker
|
|
679
684
|
# "... an exit code of '2' means there were changes, an exit code of
|
680
685
|
# '4' means there were failures during the transaction, and an exit
|
681
686
|
# code of '6' means there were both changes and failures."
|
682
|
-
if [opts[:catch_changes],opts[:catch_failures],opts[:expect_failures]].select{|x|x}.length > 1
|
683
|
-
raise(ArgumentError, "Cannot specify more than one of `catch_failures`, `catch_changes`, or `
|
687
|
+
if [opts[:catch_changes],opts[:catch_failures],opts[:expect_failures],opts[:expect_changes]].select{|x|x}.length > 1
|
688
|
+
raise(ArgumentError, "Cannot specify more than one of `catch_failures`, `catch_changes`, `expect_failures`, or `expect_changes` for a single manifest")
|
684
689
|
end
|
685
690
|
if opts[:catch_changes]
|
686
691
|
args << '--detailed-exitcodes'
|
@@ -697,6 +702,11 @@ module Beaker
|
|
697
702
|
|
698
703
|
# We're after failures specifically so allow exit codes 1, 4, and 6 only.
|
699
704
|
on_options[:acceptable_exit_codes] |= [1, 4, 6]
|
705
|
+
elsif opts[:expect_changes]
|
706
|
+
args << '--detailed-exitcodes'
|
707
|
+
|
708
|
+
# We're after changes specifically so allow exit code 2 only.
|
709
|
+
on_options[:acceptable_exit_codes] |= [2]
|
700
710
|
else
|
701
711
|
# Either use the provided acceptable_exit_codes or default to [0]
|
702
712
|
on_options[:acceptable_exit_codes] |= [0]
|
@@ -141,12 +141,14 @@ module Beaker
|
|
141
141
|
# on host, "#{installer_cmd(host, options)} -a #{host['working_dir']}/answers"
|
142
142
|
# @api private
|
143
143
|
def installer_cmd(host, options)
|
144
|
+
version = options[:pe_ver] || host['pe_ver']
|
144
145
|
if host['platform'] =~ /windows/
|
145
146
|
version = options[:pe_ver_win] || host['pe_ver']
|
146
147
|
"cd #{host['working_dir']} && msiexec.exe /qn /i puppet-enterprise-#{version}.msi"
|
147
|
-
|
148
|
-
|
149
|
-
|
148
|
+
# Frictionless install didn't exist pre-3.2.0, so in that case we fall
|
149
|
+
# through and do a regular install.
|
150
|
+
elsif host['roles'].include? 'frictionless' and ! version_is_less(version, '3.2.0')
|
151
|
+
"cd #{host['working_dir']} && curl -kO https://#{master}:8140/packages/#{version}/install.bash && bash install.bash"
|
150
152
|
else
|
151
153
|
"cd #{host['working_dir']}/#{host['dist']} && ./#{options[:installer]} -a #{host['working_dir']}/answers"
|
152
154
|
end
|
@@ -184,7 +186,7 @@ module Beaker
|
|
184
186
|
def fetch_puppet(hosts, options)
|
185
187
|
hosts.each do |host|
|
186
188
|
# We install Puppet from the master for frictionless installs, so we don't need to *fetch* anything
|
187
|
-
next if host['roles'].include? 'frictionless'
|
189
|
+
next if host['roles'].include? 'frictionless' and ! version_is_less(options[:pe_ver] || host['pe_ver'], '3.2.0')
|
188
190
|
|
189
191
|
windows = host['platform'] =~ /windows/
|
190
192
|
path = options[:pe_dir] || host['pe_dir']
|
@@ -279,7 +281,8 @@ module Beaker
|
|
279
281
|
on host, "#{installer_cmd(host, options)} PUPPET_MASTER_SERVER=#{master} PUPPET_AGENT_CERTNAME=#{host}"
|
280
282
|
else
|
281
283
|
# We only need answers if we're using the classic installer
|
282
|
-
|
284
|
+
version = options[:pe_ver] || host['pe_ver']
|
285
|
+
if (! host['roles'].include? 'frictionless') || version_is_less(version, '3.2.0')
|
283
286
|
answers = Beaker::Answers.answers(options[:pe_ver] || host['pe_ver'], hosts, master_certname, options)
|
284
287
|
create_remote_file host, "#{host['working_dir']}/answers", Beaker::Answers.answer_string(host, answers)
|
285
288
|
end
|
@@ -383,6 +386,41 @@ module Beaker
|
|
383
386
|
special_nodes + real_agents
|
384
387
|
end
|
385
388
|
|
389
|
+
#Install POSS based upon host configuration and options
|
390
|
+
# @example
|
391
|
+
# install_puppet
|
392
|
+
#
|
393
|
+
# @note This will attempt to add a repository for apt.puppetlabs.com on
|
394
|
+
# Debian or Ubuntu machines, or yum.puppetlabs.com on EL or Fedora
|
395
|
+
# machines, then install the package 'puppet'
|
396
|
+
#
|
397
|
+
# @api dsl
|
398
|
+
# @return nil
|
399
|
+
def install_puppet
|
400
|
+
hosts.each do |host|
|
401
|
+
if host['platform'] =~ /el-(5|6)/
|
402
|
+
relver = $1
|
403
|
+
on host, "rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-el-#{relver}.noarch.rpm"
|
404
|
+
on host, 'yum install -y puppet'
|
405
|
+
elsif host['platform'] =~ /fedora-(\d+)/
|
406
|
+
relver = $1
|
407
|
+
on host, "rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-fedora-#{relver}.noarch.rpm"
|
408
|
+
on host, 'yum install -y puppet'
|
409
|
+
elsif host['platform'] =~ /(ubuntu|debian)/
|
410
|
+
if ! host.check_for_package 'curl'
|
411
|
+
on host, 'apt-get install -y curl'
|
412
|
+
end
|
413
|
+
on host, 'curl -O http://apt.puppetlabs.com/puppetlabs-release-$(lsb_release -c -s).deb'
|
414
|
+
on host, 'dpkg -i puppetlabs-release-$(lsb_release -c -s).deb'
|
415
|
+
on host, 'apt-get -y -f -m update'
|
416
|
+
on host, 'apt-get install -y puppet'
|
417
|
+
else
|
418
|
+
raise "install_puppet() called for unsupported platform '#{host['platform']}' on '#{host.name}'"
|
419
|
+
end
|
420
|
+
end
|
421
|
+
nil
|
422
|
+
end
|
423
|
+
|
386
424
|
#Install PE based upon host configuration and options
|
387
425
|
# @example
|
388
426
|
# install_pe
|
data/lib/beaker/host.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'socket'
|
2
2
|
require 'timeout'
|
3
|
+
require 'benchmark'
|
3
4
|
|
4
5
|
%w(command ssh_connection).each do |lib|
|
5
6
|
begin
|
@@ -131,6 +132,14 @@ module Beaker
|
|
131
132
|
@options.is_pe?
|
132
133
|
end
|
133
134
|
|
135
|
+
def log_prefix
|
136
|
+
if @defaults['vmhostname']
|
137
|
+
"#{self} (#{@name})"
|
138
|
+
else
|
139
|
+
self.to_s
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
134
143
|
def connection
|
135
144
|
@connection ||= SshConnection.connect( reachable_name,
|
136
145
|
self['user'],
|
@@ -149,11 +158,7 @@ module Beaker
|
|
149
158
|
if options[:silent]
|
150
159
|
output_callback = nil
|
151
160
|
else
|
152
|
-
|
153
|
-
@logger.debug "\n#{self} (#{@name}) $ #{cmdline}"
|
154
|
-
else
|
155
|
-
@logger.debug "\n#{self} $ #{cmdline}"
|
156
|
-
end
|
161
|
+
@logger.debug "\n#{log_prefix} $ #{cmdline}"
|
157
162
|
output_callback = logger.method(:host_output)
|
158
163
|
end
|
159
164
|
|
@@ -161,7 +166,12 @@ module Beaker
|
|
161
166
|
# is this returning a result object?
|
162
167
|
# the options should come at the end of the method signature (rubyism)
|
163
168
|
# and they shouldn't be ssh specific
|
164
|
-
result =
|
169
|
+
result = nil
|
170
|
+
|
171
|
+
seconds = Benchmark.realtime {
|
172
|
+
result = connection.execute(cmdline, options, output_callback)
|
173
|
+
}
|
174
|
+
@logger.debug "\n#{log_prefix} executed in %0.2f seconds" % seconds
|
165
175
|
|
166
176
|
unless options[:silent]
|
167
177
|
# What?
|
@@ -180,7 +190,6 @@ module Beaker
|
|
180
190
|
end
|
181
191
|
|
182
192
|
def do_scp_to source, target, options
|
183
|
-
|
184
193
|
@logger.debug "localhost $ scp #{source} #{@name}:#{target} #{options.to_s}"
|
185
194
|
result = connection.scp_to(source, target, options, $dry_run)
|
186
195
|
return result
|
@@ -234,8 +234,8 @@ module Beaker
|
|
234
234
|
end
|
235
235
|
|
236
236
|
#check for valid type
|
237
|
-
if @options[:type] !~ /(pe)|(git)/
|
238
|
-
parser_error "--type must be one of pe or
|
237
|
+
if @options[:type] !~ /(pe)|(git)|(foss)/
|
238
|
+
parser_error "--type must be one of pe, git, or foss, not '#{@options[:type]}'"
|
239
239
|
end
|
240
240
|
|
241
241
|
#check for valid fail mode
|
data/lib/beaker/version.rb
CHANGED
@@ -359,6 +359,25 @@ describe ClassMixedWithDSLHelpers do
|
|
359
359
|
:catch_changes => true
|
360
360
|
)
|
361
361
|
end
|
362
|
+
it 'enforces a 2 exit code through :expect_changes' do
|
363
|
+
subject.should_receive( :create_remote_file ).and_return( true )
|
364
|
+
subject.should_receive( :puppet ).
|
365
|
+
with( 'apply', '--verbose', '--trace', '--detailed-exitcodes', /apply_manifest.\d+.pp/ ).
|
366
|
+
and_return( 'puppet_command' )
|
367
|
+
|
368
|
+
subject.should_receive( :on ).with(
|
369
|
+
'my_host',
|
370
|
+
'puppet_command',
|
371
|
+
:acceptable_exit_codes => [2]
|
372
|
+
)
|
373
|
+
|
374
|
+
subject.apply_manifest_on(
|
375
|
+
'my_host',
|
376
|
+
'class { "boo": }',
|
377
|
+
:trace => true,
|
378
|
+
:expect_changes => true
|
379
|
+
)
|
380
|
+
end
|
362
381
|
it 'enforces exit codes through :expect_failures' do
|
363
382
|
subject.should_receive( :create_remote_file ).and_return( true )
|
364
383
|
subject.should_receive( :puppet ).
|
@@ -197,8 +197,9 @@ describe ClassMixedWithDSLInstallUtils do
|
|
197
197
|
|
198
198
|
end
|
199
199
|
|
200
|
-
it "does nothing for a frictionless agent" do
|
200
|
+
it "does nothing for a frictionless agent for PE >= 3.2.0" do
|
201
201
|
unixhost['roles'] << 'frictionless'
|
202
|
+
unixhost['pe_ver'] = '3.2.0'
|
202
203
|
|
203
204
|
subject.should_not_receive(:scp_to)
|
204
205
|
subject.should_not_receive(:on)
|
@@ -257,6 +258,68 @@ describe ClassMixedWithDSLInstallUtils do
|
|
257
258
|
end
|
258
259
|
end
|
259
260
|
|
261
|
+
describe '#install_puppet' do
|
262
|
+
let(:hosts) do
|
263
|
+
make_hosts({:platform => platform })
|
264
|
+
end
|
265
|
+
|
266
|
+
before do
|
267
|
+
subject.stub(:hosts).and_return(hosts)
|
268
|
+
subject.stub(:on).and_return(Beaker::Result.new({},''))
|
269
|
+
end
|
270
|
+
context 'on el-6' do
|
271
|
+
let(:platform) { "el-6-i386" }
|
272
|
+
it 'installs' do
|
273
|
+
expect(subject).to receive(:on).with(hosts[0], /puppetlabs-release-el-6\.noarch\.rpm/)
|
274
|
+
expect(subject).to receive(:on).with(hosts[0], 'yum install -y puppet')
|
275
|
+
subject.install_puppet
|
276
|
+
end
|
277
|
+
end
|
278
|
+
context 'on el-5' do
|
279
|
+
let(:platform) { "el-5-i386" }
|
280
|
+
it 'installs' do
|
281
|
+
expect(subject).to receive(:on).with(hosts[0], /puppetlabs-release-el-5\.noarch\.rpm/)
|
282
|
+
expect(subject).to receive(:on).with(hosts[0], 'yum install -y puppet')
|
283
|
+
subject.install_puppet
|
284
|
+
end
|
285
|
+
end
|
286
|
+
context 'on fedora' do
|
287
|
+
let(:platform) { "fedora-18-x86_84" }
|
288
|
+
it 'installs' do
|
289
|
+
expect(subject).to receive(:on).with(hosts[0], /puppetlabs-release-fedora-18\.noarch\.rpm/)
|
290
|
+
expect(subject).to receive(:on).with(hosts[0], 'yum install -y puppet')
|
291
|
+
subject.install_puppet
|
292
|
+
end
|
293
|
+
end
|
294
|
+
context 'on debian' do
|
295
|
+
let(:platform) { "debian-7-amd64" }
|
296
|
+
it 'installs' do
|
297
|
+
expect(subject).to receive(:on).with(hosts[0], /puppetlabs-release-\$\(lsb_release -c -s\)\.deb/)
|
298
|
+
expect(subject).to receive(:on).with(hosts[0], 'dpkg -i puppetlabs-release-$(lsb_release -c -s).deb')
|
299
|
+
expect(subject).to receive(:on).with(hosts[0], 'apt-get -y -f -m update')
|
300
|
+
expect(subject).to receive(:on).with(hosts[0], 'apt-get install -y puppet')
|
301
|
+
subject.install_puppet
|
302
|
+
end
|
303
|
+
end
|
304
|
+
context 'on ubuntu' do
|
305
|
+
let(:platform) { "ubuntu-12.04-amd64" }
|
306
|
+
it 'installs' do
|
307
|
+
expect(subject).to receive(:on).with(hosts[0], /puppetlabs-release-\$\(lsb_release -c -s\)\.deb/)
|
308
|
+
expect(subject).to receive(:on).with(hosts[0], 'dpkg -i puppetlabs-release-$(lsb_release -c -s).deb')
|
309
|
+
expect(subject).to receive(:on).with(hosts[0], 'apt-get -y -f -m update')
|
310
|
+
expect(subject).to receive(:on).with(hosts[0], 'apt-get install -y puppet')
|
311
|
+
subject.install_puppet
|
312
|
+
end
|
313
|
+
end
|
314
|
+
context 'on solaris' do
|
315
|
+
let(:platform) { 'solaris-11-x86_64' }
|
316
|
+
it 'raises an error' do
|
317
|
+
expect(subject).to_not receive(:on)
|
318
|
+
expect { subject.install_puppet }.to raise_error(/unsupported platform/)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
260
323
|
describe 'install_pe' do
|
261
324
|
|
262
325
|
it 'calls do_install with sorted hosts' do
|
data/spec/beaker/host_spec.rb
CHANGED
@@ -112,6 +112,14 @@ module Beaker
|
|
112
112
|
it 'receives a result object from the connection#execute'
|
113
113
|
it "returns the result object"
|
114
114
|
|
115
|
+
it 'logs the amount of time spent executing the command' do
|
116
|
+
result.exit_code = 0
|
117
|
+
|
118
|
+
expect(host.logger).to receive(:debug).with(/host executed in \d\.\d{2} seconds/)
|
119
|
+
|
120
|
+
host.exec(command,{})
|
121
|
+
end
|
122
|
+
|
115
123
|
context "controls the result objects logging" do
|
116
124
|
it "and passes a test if the exit_code doesn't match the default :acceptable_exit_codes of 0" do
|
117
125
|
result.exit_code = 0
|