beaker 2.9.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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