beaker 2.9.0 → 2.10.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.
@@ -403,7 +403,8 @@ module Beaker
403
403
  end
404
404
  if options[:expect_connection_failure] && result.exit_code
405
405
  # should have had a connection failure, but didn't
406
- raise CommandFailure, "Host '#{self}' should have resulted in a connection failure running:\n #{cmdline}\nLast #{@options[:trace_limit]} lines of output were:\n#{result.formatted_output(@options[:trace_limit])}"
406
+ # this can happen because of timing issues, so just raise a warning for now
407
+ @logger.warn "Host '#{self}' should have resulted in a connection failure running:\n #{cmdline}\nLast #{@options[:trace_limit]} lines of output were:\n#{result.formatted_output(@options[:trace_limit])}"
407
408
  end
408
409
  # No, TestCase has the knowledge about whether its failed, checking acceptable
409
410
  # exit codes at the host level and then raising...
@@ -1,6 +1,10 @@
1
1
  module Aix::Exec
2
2
  include Beaker::CommandFactory
3
3
 
4
+ def reboot
5
+ exec(Beaker::Command.new("shutdown -Fr"), :expect_connection_failure => true)
6
+ end
7
+
4
8
  def get_ip
5
9
  execute("ifconfig -a inet| awk '/broadcast/ {print $2}' | cut -d/ -f1 | head -1").strip
6
10
  end
@@ -5,6 +5,14 @@ end
5
5
  module FreeBSD
6
6
  class Host < Unix::Host
7
7
 
8
+ [
9
+ 'exec',
10
+ ].each do |lib|
11
+ require "beaker/host/freebsd/#{lib}"
12
+ end
13
+
14
+ include FreeBSD::Exec
15
+
8
16
  def self.foss_defaults
9
17
  h = Beaker::Options::OptionsHash.new
10
18
  h.merge({
@@ -0,0 +1,10 @@
1
+ module FreeBSD::Exec
2
+ include Beaker::CommandFactory
3
+
4
+ def echo_to_file(str, filename)
5
+ # FreeBSD gets weird about special characters, we have to go a little OTT here
6
+ escaped_str = str.gsub(/\t/,'\\t').gsub(/\n/,'\\n')
7
+
8
+ exec(Beaker::Command.new("printf #{escaped_str} > #{filename}"))
9
+ end
10
+ end
@@ -1,6 +1,10 @@
1
1
  module PSWindows::Exec
2
2
  include Beaker::CommandFactory
3
3
 
4
+ def reboot
5
+ exec(Beaker::Command.new("shutdown /r /t 0"), :expect_connection_failure => true)
6
+ end
7
+
4
8
  ABS_CMD = 'c:\\\\windows\\\\system32\\\\cmd.exe'
5
9
  CMD = 'cmd.exe'
6
10
 
@@ -1,6 +1,14 @@
1
1
  module Unix::Exec
2
2
  include Beaker::CommandFactory
3
3
 
4
+ def reboot
5
+ if self['platform'] =~ /solaris/
6
+ exec(Beaker::Command.new("reboot"), :expect_connection_failure => true)
7
+ else
8
+ exec(Beaker::Command.new("/sbin/shutdown -r now"), :expect_connection_failure => true)
9
+ end
10
+ end
11
+
4
12
  def echo(msg, abs=true)
5
13
  (abs ? '/bin/echo' : 'echo') + " #{msg}"
6
14
  end
@@ -19,6 +19,9 @@ module Unix::Pkg
19
19
 
20
20
  def check_for_package(name)
21
21
  case self['platform']
22
+ when /sles-10/
23
+ result = exec(Beaker::Command.new("zypper se -i --match-exact #{name}"), :acceptable_exit_codes => (0...127))
24
+ result.stdout =~ /No packages found/ ? (return false) : (return result.exit_code == 0)
22
25
  when /sles-/
23
26
  result = exec(Beaker::Command.new("zypper se -i --match-exact #{name}"), :acceptable_exit_codes => (0...127))
24
27
  when /el-4/
@@ -208,4 +211,4 @@ module Unix::Pkg
208
211
  raise "Package repo cannot be deployed on #{self}; the platform is not supported"
209
212
  end
210
213
  end
211
- end
214
+ end
@@ -1,6 +1,10 @@
1
1
  module Windows::Exec
2
2
  include Beaker::CommandFactory
3
3
 
4
+ def reboot
5
+ exec(Beaker::Command.new("shutdown /r /t 0"), :expect_connection_failure => true)
6
+ end
7
+
4
8
  ABS_CMD = 'c:\\\\windows\\\\system32\\\\cmd.exe'
5
9
  CMD = 'cmd.exe'
6
10
 
@@ -13,8 +13,10 @@ module Beaker
13
13
  SLEEPWAIT = 5
14
14
  TRIES = 5
15
15
  UNIX_PACKAGES = ['curl', 'ntpdate']
16
+ FREEBSD_PACKAGES = ['curl']
16
17
  WINDOWS_PACKAGES = ['curl']
17
18
  PSWINDOWS_PACKAGES = []
19
+ SLES10_PACKAGES = ['curl']
18
20
  SLES_PACKAGES = ['curl', 'ntp']
19
21
  DEBIAN_PACKAGES = ['curl', 'ntpdate', 'lsb-release']
20
22
  CUMULUS_PACKAGES = ['addons', 'ntpdate', 'lsb-release']
@@ -87,6 +89,8 @@ module Beaker
87
89
  logger = opts[:logger]
88
90
  block_on host do |host|
89
91
  case
92
+ when host['platform'] =~ /sles-10/
93
+ check_and_install_packages_if_needed(host, SLES10_PACKAGES)
90
94
  when host['platform'] =~ /sles-/
91
95
  check_and_install_packages_if_needed(host, SLES_PACKAGES)
92
96
  when host['platform'] =~ /debian/
@@ -97,6 +101,8 @@ module Beaker
97
101
  check_and_install_packages_if_needed(host, WINDOWS_PACKAGES)
98
102
  when (host['platform'] =~ /windows/ and not host.is_cygwin?)
99
103
  check_and_install_packages_if_needed(host, PSWINDOWS_PACKAGES)
104
+ when host['platform'] =~ /freebsd/
105
+ check_and_install_packages_if_needed(host, FREEBSD_PACKAGES)
100
106
  when host['platform'] !~ /debian|aix|solaris|windows|sles-|osx-|cumulus/
101
107
  check_and_install_packages_if_needed(host, UNIX_PACKAGES)
102
108
  end
@@ -289,7 +295,11 @@ module Beaker
289
295
  # @param [Host] host the host to act upon
290
296
  # @param [String] etc_hosts The string to append to the /etc/hosts file
291
297
  def set_etc_hosts(host, etc_hosts)
292
- host.exec(Command.new("echo '#{etc_hosts}' > /etc/hosts"))
298
+ if host['platform'] =~ /freebsd/
299
+ host.echo_to_file(etc_hosts, '/etc/hosts')
300
+ else
301
+ host.exec(Command.new("echo '#{etc_hosts}' > /etc/hosts"))
302
+ end
293
303
  end
294
304
 
295
305
  #Make it possible to log in as root by copying the current users ssh keys to the root account
@@ -307,6 +317,8 @@ module Beaker
307
317
  host.exec(Command.new("if exist .ssh (xcopy .ssh C:\\Users\\Administrator\\.ssh /s /e)"))
308
318
  elsif host['platform'] =~ /osx/
309
319
  host.exec(Command.new('sudo cp -r .ssh /var/root/.'), {:pty => true})
320
+ elsif host['platform'] =~ /freebsd/
321
+ host.exec(Command.new('sudo cp -r .ssh /root/.'), {:pty => true})
310
322
  else
311
323
  host.exec(Command.new('sudo su -c "cp -r .ssh /root/."'), {:pty => true})
312
324
  end
@@ -345,6 +357,8 @@ module Beaker
345
357
  if host['platform'] =~ /osx/
346
358
  host.exec(Command.new("sudo sed -i '' 's/#PermitRootLogin no/PermitRootLogin Yes/g' /etc/sshd_config"))
347
359
  host.exec(Command.new("sudo sed -i '' 's/#PermitRootLogin yes/PermitRootLogin Yes/g' /etc/sshd_config"))
360
+ elsif host['platform'] =~ /freebsd/
361
+ host.exec(Command.new("sudo sed -i -e 's/#PermitRootLogin no/PermitRootLogin yes/g' /etc/ssh/sshd_config"), {:pty => true} )
348
362
  elsif host.is_cygwin?
349
363
  host.exec(Command.new("sudo su -c \"sed -ri 's/^#?PermitRootLogin no|^#?PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config\""), {:pty => true})
350
364
  else
@@ -353,8 +367,12 @@ module Beaker
353
367
  #restart sshd
354
368
  if host['platform'] =~ /debian|ubuntu|cumulus/
355
369
  host.exec(Command.new("sudo su -c \"service ssh restart\""), {:pty => true})
370
+ elsif host['platform'] =~ /centos-7|el-7|redhat-7/
371
+ host.exec(Command.new("sudo -E systemctl restart sshd.service"), {:ptry => true})
356
372
  elsif host['platform'] =~ /centos|el-|redhat|fedora|eos/
357
373
  host.exec(Command.new("sudo -E /sbin/service sshd reload"), {:pty => true})
374
+ elsif host['platform'] =~ /freebsd/
375
+ host.exec(Command.new("sudo /etc/rc.d/sshd restart"))
358
376
  else
359
377
  logger.warn("Attempting to update ssh on non-supported platform: #{host.name}: #{host['platform']}")
360
378
  end
@@ -509,6 +527,9 @@ module Beaker
509
527
  when /debian|ubuntu|cumulus/
510
528
  host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
511
529
  host.exec(Command.new("service ssh restart"))
530
+ when /el-7|centos-7|redhat-7|oracle-7|scientific-7|eos-7/
531
+ host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
532
+ host.exec(Command.new("systemctl restart sshd.service"))
512
533
  when /el-|centos|fedora|redhat|oracle|scientific|eos/
513
534
  host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
514
535
  host.exec(Command.new("/sbin/service sshd restart"))
@@ -522,6 +543,9 @@ module Beaker
522
543
  host.exec(Command.new("echo '\nPermitUserEnvironment yes' >> /etc/ssh/sshd_config"))
523
544
  host.exec(Command.new("stopsrc -g ssh"))
524
545
  host.exec(Command.new("startsrc -g ssh"))
546
+ when /freebsd/
547
+ host.echo_to_file('\nPermitUserEnvironment yes', '/etc/ssh/sshd_config')
548
+ host.exec(Command.new("sudo /etc/rc.d/sshd restart"))
525
549
  end
526
550
 
527
551
  if host['platform'] !~ /windows/ or (host['platform'] =~ /windows/ and host.is_cygwin?)
@@ -115,13 +115,28 @@ module Beaker
115
115
  # Associate a public IP to the server
116
116
  # Create if there are no floating ips available
117
117
  #
118
- ip = @compute_client.addresses.find { |ip| ip.instance_id.nil? }
119
- if ip.nil?
120
- @logger.debug "Creating IP for #{host.name} (#{host[:vmhostname]})"
121
- ip = @compute_client.addresses.create
118
+ # Do we already have an address?
119
+ @logger.debug vm.addresses
120
+
121
+ begin
122
+ if vm.addresses[@options[:openstack_network]]
123
+ address = vm.addresses[@options[:openstack_network]].map{ |network| network['addr'] }.first
124
+ end
125
+ rescue NoMethodError
126
+ @logger.debug "No current address retrievable from OpenStack data"
122
127
  end
123
- ip.server = vm
124
- host[:ip] = ip.ip
128
+ unless address
129
+ ip = @compute_client.addresses.find { |ip| ip.instance_id.nil? }
130
+
131
+ if ip.nil?
132
+ @logger.debug "Creating IP for #{host.name} (#{host[:vmhostname]})"
133
+ ip = @compute_client.addresses.create
134
+ end
135
+ ip.server = vm
136
+ address = ip.ip
137
+ end
138
+ host[:ip] = address
139
+
125
140
  @logger.debug "OpenStack host #{host.name} (#{host[:vmhostname]}) assigned ip: #{host[:ip]}"
126
141
 
127
142
  #set metadata
@@ -131,7 +146,7 @@ module Beaker
131
146
  @vms << vm
132
147
 
133
148
  #enable root if user is not root
134
- enable_root_on_hosts()
149
+ enable_root(host)
135
150
  end
136
151
  end
137
152
 
@@ -154,8 +169,10 @@ module Beaker
154
169
  end
155
170
  end
156
171
 
157
- # Enables root for instances with custom username like ubuntu-amis
158
- #
172
+ # Enables root access for a host when username is not root
173
+ # This method ripped from the aws_sdk implementation and is probably wrong
174
+ # because it iterates on a collection when there's no guarantee the collection
175
+ # has all been brought up in openstack yet and will thus explode
159
176
  # @return [void]
160
177
  # @api private
161
178
  def enable_root_on_hosts
@@ -164,10 +181,8 @@ module Beaker
164
181
  end
165
182
  end
166
183
 
167
- # Enables root access for a host when username is not root
168
- #
169
- # @return [void]
170
- # @api private
184
+ # enable root on a single host (the current one presumably) but only
185
+ # if the username isn't 'root'
171
186
  def enable_root(host)
172
187
  if host['user'] != 'root'
173
188
  copy_ssh_to_root(host, @options)
@@ -46,6 +46,25 @@ module Beaker
46
46
  v_file << " v.vm.synced_folder '.', '/vagrant', :nfs => true\n"
47
47
  end
48
48
 
49
+ if /freebsd/i.match(host['platform'])
50
+ v_file << " v.ssh.shell = 'sh'\n"
51
+ v_file << " v.vm.guest = :freebsd\n"
52
+
53
+ # FreeBSD NFS has a character restriction of 88 characters
54
+ # So you can enable it but if your module has a long name it probably won't work...
55
+ # So to keep things simple let's rsync by default!
56
+ #
57
+ # Further reading if interested:
58
+ # http://www.secnetix.de/olli/FreeBSD/mnamelen.hawk
59
+ # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=167105
60
+ #
61
+ if host['vagrant_freebsd_nfs'].nil?
62
+ v_file << " v.vm.synced_folder '.', '/vagrant', type: 'rsync'\n"
63
+ else
64
+ v_file << " v.vm.synced_folder '.', '/vagrant', :nfs => true\n"
65
+ end
66
+ end
67
+
49
68
  v_file << self.class.provider_vfile_section(host, options)
50
69
 
51
70
  v_file << " end\n"
@@ -129,7 +129,7 @@ module Beaker
129
129
  time = Time.new
130
130
  stamp = time.strftime('%Y-%m-%d %H:%M:%S')
131
131
  verb = create ? '+' : '-'
132
- line = "#{stamp}\t[#{verb}]\t#{host['hypervisor']}\t#{host['platform']}\t#{host}"
132
+ line = "#{stamp}\t[#{verb}]\t#{host['hypervisor']}\t#{host['platform']}\t#{host.log_prefix}"
133
133
  sut_logger.notify line
134
134
  line
135
135
  end
@@ -196,6 +196,7 @@ module Beaker
196
196
  :q_install_update_server => 'y',
197
197
  :q_exit_for_nc_migrate => 'n',
198
198
  :q_enable_future_parser => 'n',
199
+ :q_pe_check_for_updates => 'n',
199
200
  },
200
201
  :dot_fog => File.join(ENV['HOME'], '.fog'),
201
202
  :ec2_yaml => 'config/image_templates/ec2.yaml',
@@ -1,5 +1,5 @@
1
1
  module Beaker
2
2
  module Version
3
- STRING = '2.9.0'
3
+ STRING = '2.10.0'
4
4
  end
5
5
  end
@@ -184,6 +184,14 @@ module Beaker
184
184
  @answers = answers.answers
185
185
  end
186
186
 
187
+ it 'should add q_pe_check_for_updates to master' do
188
+ expect( @answers['vm1'][:q_pe_check_for_updates] ).to be === 'n'
189
+ end
190
+
191
+ it 'should add q_pe_check_for_updates to dashboard' do
192
+ expect( @answers['vm2'][:q_pe_check_for_updates] ).to be === 'n'
193
+ end
194
+
187
195
  it 'adds :q_enable_future_parser to all hosts, default to "n"' do
188
196
  hosts.each do |host|
189
197
  expect( basic_hosts[0][:answers][:q_enable_future_parser] ).to be == 'n'
@@ -224,6 +232,18 @@ module Beaker
224
232
  end
225
233
  end
226
234
 
235
+ it 'should add q_pe_check_for_updates to master' do
236
+ expect( @answers['vm1'][:q_pe_check_for_updates] ).to be === 'n'
237
+ end
238
+
239
+ it 'should add q_pe_check_for_updates to dashboard' do
240
+ expect( @answers['vm2'][:q_pe_check_for_updates] ).to be === 'n'
241
+ end
242
+
243
+ it 'should not add q_pe_check_for_updates to agent/database' do
244
+ expect( @answers['vm3']).to_not include :q_pe_check_for_updates
245
+ end
246
+
227
247
  # re-enable these tests once these keys are eliminated
228
248
  #
229
249
  # it 'should not have q_puppet_enterpriseconsole_database_name key' do
@@ -282,6 +302,18 @@ module Beaker
282
302
  @answers = answers.answers
283
303
  end
284
304
 
305
+ it 'should add q_pe_check_for_updates to master' do
306
+ expect( @answers['vm1'][:q_pe_check_for_updates] ).to be === 'n'
307
+ end
308
+
309
+ it 'should add q_pe_check_for_updates to dashboard' do
310
+ expect( @answers['vm2'][:q_pe_check_for_updates] ).to be === 'n'
311
+ end
312
+
313
+ it 'should not add q_pe_check_for_updates to agent/database' do
314
+ expect( @answers['vm3']).to_not include :q_pe_check_for_updates
315
+ end
316
+
285
317
  # The only difference between 3.2 and 3.0 is the addition of the
286
318
  # master certname to the dashboard answers
287
319
  it 'should add q_puppetmaster_certname to the dashboard answers' do
@@ -91,6 +91,9 @@ module Beaker
91
91
  options = cli.instance_variable_get(:@options)
92
92
  options[:fail_mode] = 'fast'
93
93
  options[:preserve_hosts] = 'always'
94
+ options[:log_dated_dir] = '.'
95
+ options[:hosts_file] = 'sample.cfg'
96
+ cli.instance_variable_set(:@hosts, {})
94
97
  cli.instance_variable_set(:@options, options)
95
98
 
96
99
  netmanager = double(:netmanager)
@@ -175,6 +178,9 @@ module Beaker
175
178
  options = cli.instance_variable_get(:@options)
176
179
  options[:fail_mode] = 'fast'
177
180
  options[:preserve_hosts] = 'onpass'
181
+ options[:log_dated_dir] = '.'
182
+ options[:hosts_file] = 'sample.cfg'
183
+ cli.instance_variable_set(:@hosts, {})
178
184
  cli.instance_variable_set(:@options, options)
179
185
 
180
186
  netmanager = double(:netmanager)
@@ -184,6 +190,207 @@ module Beaker
184
190
  expect{ cli.execute! }.to_not raise_error
185
191
  end
186
192
  end
193
+
194
+ describe 'hosts file saving when preserve_hosts should happen' do
195
+
196
+ before :each do
197
+ allow( cli ).to receive(:run_suite).with(:pre_suite, :fast).and_return(true)
198
+ allow( cli ).to receive(:run_suite).with(:tests).and_return(true)
199
+ allow( cli ).to receive(:run_suite).with(:post_suite).and_return(true)
200
+ options = cli.instance_variable_get(:@options)
201
+ options[:fail_mode] = 'fast'
202
+ options[:preserve_hosts] = 'onpass'
203
+ options[:hosts_file] = 'sample.cfg'
204
+
205
+ hosts = [
206
+ { :hypervisor => 'peterPan' },
207
+ { :hypervisor => 'theMadHatter' },
208
+ ]
209
+ cli.instance_variable_set(:@hosts, hosts)
210
+
211
+ netmanager = double(:netmanager)
212
+ cli.instance_variable_set(:@network_manager, netmanager)
213
+ expect( netmanager ).to receive(:cleanup).never
214
+
215
+
216
+ allow( cli ).to receive( :print_env_vars_affecting_beaker )
217
+ logger = cli.instance_variable_get(:@logger)
218
+ expect( logger ).to receive( :send ).with( anything, anything ).ordered
219
+ expect( logger ).to receive( :send ).with( anything, anything ).ordered
220
+ end
221
+
222
+ it 'executes without error' do
223
+ options = cli.instance_variable_get(:@options)
224
+ Dir.mktmpdir do |dir|
225
+ options[:log_dated_dir] = File.absolute_path(dir)
226
+
227
+ expect{ cli.execute! }.to_not raise_error
228
+ end
229
+ end
230
+
231
+ it 'copies a file into the correct location' do
232
+ options = cli.instance_variable_get(:@options)
233
+ Dir.mktmpdir do |dir|
234
+ options[:log_dated_dir] = File.absolute_path(dir)
235
+
236
+ cli.execute!
237
+
238
+ copied_hosts_file = File.join(File.absolute_path(dir), options[:hosts_file])
239
+ expect( File.exists?(copied_hosts_file) ).to be_truthy
240
+ end
241
+ end
242
+
243
+ it 'generates a valid YAML file when it copies' do
244
+ options = cli.instance_variable_get(:@options)
245
+ Dir.mktmpdir do |dir|
246
+ options[:log_dated_dir] = File.absolute_path(dir)
247
+
248
+ cli.execute!
249
+
250
+ copied_hosts_file = File.join(File.absolute_path(dir), options[:hosts_file])
251
+ expect{ YAML.load_file(copied_hosts_file) }.to_not raise_error
252
+ end
253
+ end
254
+
255
+ it 'sets the @options :hosts_preserved_yaml_file to the copied file' do
256
+ options = cli.instance_variable_get(:@options)
257
+ Dir.mktmpdir do |dir|
258
+ options[:log_dated_dir] = File.absolute_path(dir)
259
+
260
+ expect( options.has_key?(:hosts_preserved_yaml_file) ).to be_falsy
261
+ cli.execute!
262
+ expect( options.has_key?(:hosts_preserved_yaml_file) ).to be_truthy
263
+
264
+ copied_hosts_file = File.join(File.absolute_path(dir), options[:hosts_file])
265
+ expect( options[:hosts_preserved_yaml_file] ).to be === copied_hosts_file
266
+ end
267
+ end
268
+
269
+ describe 'output text informing the user that re-use is possible' do
270
+
271
+ it 'if unsupported, does not output extra text' do
272
+ options = cli.instance_variable_get(:@options)
273
+ Dir.mktmpdir do |dir|
274
+ options[:log_dated_dir] = File.absolute_path(dir)
275
+ copied_hosts_file = File.join(File.absolute_path(dir), options[:hosts_file])
276
+
277
+ logger = cli.instance_variable_get(:@logger)
278
+ expect( logger ).to receive( :send ).with( anything, "\nYou can re-run commands against the already provisioned SUT(s) by following these steps:\n").never
279
+ expect( logger ).to receive( :send ).with( anything, "- change the hosts file to #{copied_hosts_file}").never
280
+ expect( logger ).to receive( :send ).with( anything, '- use the --no-provision flag').never
281
+
282
+ cli.execute!
283
+ end
284
+ end
285
+
286
+ it 'if supported, outputs the text letting the user know they can re-use these hosts' do
287
+ options = cli.instance_variable_get(:@options)
288
+ Dir.mktmpdir do |dir|
289
+ options[:log_dated_dir] = File.absolute_path(dir)
290
+ copied_hosts_file = File.join(File.absolute_path(dir), options[:hosts_file])
291
+
292
+ hosts = cli.instance_variable_get(:@hosts)
293
+ hosts << { :hypervisor => 'fusion' }
294
+
295
+ reproducing_cmd = "the faith of the people"
296
+ allow( cli ).to receive( :build_hosts_preserved_reproducing_command ).and_return( reproducing_cmd )
297
+
298
+ logger = cli.instance_variable_get(:@logger)
299
+ expect( logger ).to receive( :send ).with( anything, "\nYou can re-run commands against the already provisioned SUT(s) with:\n").ordered
300
+ expect( logger ).to receive( :send ).with( anything, reproducing_cmd).ordered
301
+
302
+ cli.execute!
303
+ end
304
+ end
305
+
306
+ it 'if supported && docker is a hypervisor, outputs text + the untested warning' do
307
+ options = cli.instance_variable_get(:@options)
308
+ Dir.mktmpdir do |dir|
309
+ options[:log_dated_dir] = File.absolute_path(dir)
310
+ copied_hosts_file = File.join(File.absolute_path(dir), options[:hosts_file])
311
+
312
+ hosts = cli.instance_variable_get(:@hosts)
313
+ hosts << { :hypervisor => 'fusion' }
314
+ hosts << { :hypervisor => 'docker' }
315
+
316
+ reproducing_cmd = "the crow flies true says the shoe to you"
317
+ allow( cli ).to receive( :build_hosts_preserved_reproducing_command ).and_return( reproducing_cmd )
318
+
319
+ logger = cli.instance_variable_get(:@logger)
320
+ expect( logger ).to receive( :send ).with( anything, "\nYou can re-run commands against the already provisioned SUT(s) with:\n").ordered
321
+ expect( logger ).to receive( :send ).with( anything, '(docker support is untested for this feature. please reference the docs for more info)').ordered
322
+ expect( logger ).to receive( :send ).with( anything, reproducing_cmd).ordered
323
+
324
+ cli.execute!
325
+ end
326
+ end
327
+
328
+ it 'if unsupported && docker is a hypervisor, no extra text output' do
329
+ options = cli.instance_variable_get(:@options)
330
+ Dir.mktmpdir do |dir|
331
+ options[:log_dated_dir] = File.absolute_path(dir)
332
+ copied_hosts_file = File.join(File.absolute_path(dir), options[:hosts_file])
333
+
334
+ hosts = cli.instance_variable_get(:@hosts)
335
+ hosts << { :hypervisor => 'docker' }
336
+
337
+ logger = cli.instance_variable_get(:@logger)
338
+ expect( logger ).to receive( :send ).with( anything, "\nYou can re-run commands against the already provisioned SUT(s) with:\n").never
339
+ expect( logger ).to receive( :send ).with( anything, '(docker support is untested for this feature. please reference the docs for more info)').never
340
+ expect( logger ).to receive( :send ).with( anything, "- change the hosts file to #{copied_hosts_file}").never
341
+ expect( logger ).to receive( :send ).with( anything, '- use the --no-provision flag').never
342
+
343
+ cli.execute!
344
+ end
345
+ end
346
+
347
+
348
+ end
349
+ end
350
+ describe '#build_hosts_preserved_reproducing_command' do
351
+
352
+ it 'replaces the hosts file' do
353
+ new_hosts_file = 'john/deer/was/here.txt'
354
+ command_to_sub = 'p --log-level debug --hosts pants/of/plan.poo jam --jankies --flag-business'
355
+ command_correct = "p --log-level debug --hosts #{new_hosts_file} jam --jankies --flag-business"
356
+
357
+ answer = cli.build_hosts_preserved_reproducing_command(command_to_sub, new_hosts_file)
358
+ expect( answer.start_with?(command_correct) ).to be_truthy
359
+ end
360
+
361
+ it 'doesn\'t replace an entry if no --hosts key is found' do
362
+ command_to_sub = 'p --log-level debug johnnypantaloons7 --jankies --flag-business'
363
+ command_correct = 'p --log-level debug johnnypantaloons7 --jankies --flag-business'
364
+
365
+ answer = cli.build_hosts_preserved_reproducing_command(command_to_sub, 'john/deer/plans.txt')
366
+ expect( answer.start_with?(command_correct) ).to be_truthy
367
+ end
368
+
369
+ it 'removes any old --provision flags' do
370
+ command_to_sub = '--provision jam --provision --jankies --flag-business'
371
+ command_correct = 'jam --jankies --flag-business'
372
+
373
+ answer = cli.build_hosts_preserved_reproducing_command(command_to_sub, 'can/talk/to/pigs.yml')
374
+ expect( answer.start_with?(command_correct) ).to be_truthy
375
+ end
376
+
377
+ it 'removes any old --no-provision flags' do
378
+ command_to_sub = 'jam --no-provision --jankoos --no-provision --flag-businesses'
379
+ command_correct = 'jam --jankoos --flag-businesses'
380
+
381
+ answer = cli.build_hosts_preserved_reproducing_command(command_to_sub, 'can/talk/to/bears.yml')
382
+ expect( answer.start_with?(command_correct) ).to be_truthy
383
+ end
384
+
385
+ it 'adds a --no-provision flag to the end of the command' do
386
+ new_hosts_file = 'john/deer/was/here.txt'
387
+ command_to_sub = 'p --log-level debug johnnypantaloons7 --jankies --flag-business'
388
+ command_correct = command_to_sub + ' --no-provision'
389
+
390
+ answer = cli.build_hosts_preserved_reproducing_command(command_to_sub, new_hosts_file)
391
+ expect( answer ).to be === command_correct
392
+ end
393
+ end
187
394
  end
188
395
  end
189
396
  end