test-kitchen 1.4.2 → 1.5.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 +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +29 -33
- data/CHANGELOG.md +86 -2
- data/CONTRIBUTING.md +17 -0
- data/Gemfile.proxy_tests +5 -0
- data/MAINTAINERS.md +24 -0
- data/features/kitchen_driver_discover_command.feature +6 -0
- data/features/kitchen_init_command.feature +55 -7
- data/features/step_definitions/gem_steps.rb +12 -4
- data/features/step_definitions/git_steps.rb +1 -1
- data/features/step_definitions/output_steps.rb +1 -1
- data/features/support/env.rb +13 -9
- data/lib/kitchen/cli.rb +46 -5
- data/lib/kitchen/command/driver_discover.rb +8 -0
- data/lib/kitchen/command.rb +1 -0
- data/lib/kitchen/config.rb +4 -0
- data/lib/kitchen/configurable.rb +32 -0
- data/lib/kitchen/driver/ssh_base.rb +18 -4
- data/lib/kitchen/generator/driver_create.rb +2 -2
- data/lib/kitchen/generator/init.rb +4 -4
- data/lib/kitchen/instance.rb +7 -0
- data/lib/kitchen/lazy_hash.rb +20 -0
- data/lib/kitchen/logger.rb +4 -7
- data/lib/kitchen/provisioner/base.rb +16 -1
- data/lib/kitchen/provisioner/chef_base.rb +43 -98
- data/lib/kitchen/provisioner/chef_solo.rb +7 -4
- data/lib/kitchen/provisioner/chef_zero.rb +12 -5
- data/lib/kitchen/ssh.rb +1 -1
- data/lib/kitchen/transport/base.rb +7 -0
- data/lib/kitchen/transport/ssh.rb +13 -6
- data/lib/kitchen/transport/winrm.rb +168 -50
- data/lib/kitchen/verifier/base.rb +18 -1
- data/lib/kitchen/verifier/busser.rb +12 -5
- data/lib/kitchen/verifier/shell.rb +101 -0
- data/lib/kitchen/version.rb +1 -2
- data/spec/kitchen/collection_spec.rb +1 -1
- data/spec/kitchen/configurable_spec.rb +211 -2
- data/spec/kitchen/driver/ssh_base_spec.rb +131 -8
- data/spec/kitchen/lazy_hash_spec.rb +27 -0
- data/spec/kitchen/logger_spec.rb +10 -0
- data/spec/kitchen/provisioner/base_spec.rb +25 -0
- data/spec/kitchen/provisioner/chef_base_spec.rb +133 -252
- data/spec/kitchen/provisioner/chef_solo_spec.rb +30 -0
- data/spec/kitchen/provisioner/chef_zero_spec.rb +27 -2
- data/spec/kitchen/provisioner/shell_spec.rb +60 -12
- data/spec/kitchen/ssh_spec.rb +1 -1
- data/spec/kitchen/transport/ssh_spec.rb +2 -1
- data/spec/kitchen/transport/winrm_spec.rb +228 -48
- data/spec/kitchen/verifier/base_spec.rb +26 -0
- data/spec/kitchen/verifier/busser_spec.rb +69 -3
- data/spec/kitchen/verifier/shell_spec.rb +157 -0
- data/support/busser_install_command.sh +1 -2
- data/support/chef_base_install_command.ps1 +19 -12
- data/templates/driver/README.md.erb +1 -1
- data/test-kitchen.gemspec +12 -3
- metadata +106 -10
|
@@ -24,9 +24,7 @@ require "uri"
|
|
|
24
24
|
require "kitchen"
|
|
25
25
|
|
|
26
26
|
module Kitchen
|
|
27
|
-
|
|
28
27
|
module Transport
|
|
29
|
-
|
|
30
28
|
# Wrapped exception for any internally raised WinRM-related errors.
|
|
31
29
|
#
|
|
32
30
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
@@ -38,19 +36,43 @@ module Kitchen
|
|
|
38
36
|
# @author Salim Afiune <salim@afiunemaya.com.mx>
|
|
39
37
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
40
38
|
class Winrm < Kitchen::Transport::Base
|
|
41
|
-
|
|
42
39
|
kitchen_transport_api_version 1
|
|
43
40
|
|
|
44
41
|
plugin_version Kitchen::VERSION
|
|
45
42
|
|
|
46
|
-
default_config :port, 5985
|
|
47
43
|
default_config :username, "administrator"
|
|
48
44
|
default_config :password, nil
|
|
49
|
-
default_config :endpoint_template, "http://%{hostname}:%{port}/wsman"
|
|
50
45
|
default_config :rdp_port, 3389
|
|
51
46
|
default_config :connection_retries, 5
|
|
52
47
|
default_config :connection_retry_sleep, 1
|
|
53
48
|
default_config :max_wait_until_ready, 600
|
|
49
|
+
default_config :winrm_transport, "plaintext"
|
|
50
|
+
default_config :port do |transport|
|
|
51
|
+
transport[:winrm_transport] == :ssl ? 5986 : 5985
|
|
52
|
+
end
|
|
53
|
+
default_config :endpoint_template do |transport|
|
|
54
|
+
scheme = transport[:winrm_transport] == :ssl ? "https" : "http"
|
|
55
|
+
"#{scheme}://%{hostname}:%{port}/wsman"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def finalize_config!(instance)
|
|
59
|
+
super
|
|
60
|
+
|
|
61
|
+
transport = config[:winrm_transport].to_sym
|
|
62
|
+
config[:winrm_transport] =
|
|
63
|
+
case transport
|
|
64
|
+
when :sspinegotiate
|
|
65
|
+
if host_os_windows?
|
|
66
|
+
transport
|
|
67
|
+
else
|
|
68
|
+
:plaintext
|
|
69
|
+
end
|
|
70
|
+
else
|
|
71
|
+
transport
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
self
|
|
75
|
+
end
|
|
54
76
|
|
|
55
77
|
# (see Base#connection)
|
|
56
78
|
def connection(state, &block)
|
|
@@ -70,7 +92,6 @@ module Kitchen
|
|
|
70
92
|
#
|
|
71
93
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
72
94
|
class Connection < Kitchen::Transport::Base::Connection
|
|
73
|
-
|
|
74
95
|
# (see Base::Connection#close)
|
|
75
96
|
def close
|
|
76
97
|
return if @session.nil?
|
|
@@ -87,6 +108,10 @@ module Kitchen
|
|
|
87
108
|
def execute(command)
|
|
88
109
|
return if command.nil?
|
|
89
110
|
logger.debug("[WinRM] #{self} (#{command})")
|
|
111
|
+
|
|
112
|
+
if command.length > MAX_COMMAND_SIZE
|
|
113
|
+
command = run_from_file_command(command)
|
|
114
|
+
end
|
|
90
115
|
exit_code, stderr = execute_with_exit_code(command)
|
|
91
116
|
|
|
92
117
|
if logger.debug? && exit_code == 0
|
|
@@ -108,7 +133,7 @@ module Kitchen
|
|
|
108
133
|
when /linux/
|
|
109
134
|
login_command_for_linux
|
|
110
135
|
else
|
|
111
|
-
|
|
136
|
+
fail ActionFailed, "Remote login not supported in #{self.class} " \
|
|
112
137
|
"from host OS '#{RbConfig::CONFIG["host_os"]}'."
|
|
113
138
|
end
|
|
114
139
|
end
|
|
@@ -122,9 +147,9 @@ module Kitchen
|
|
|
122
147
|
def wait_until_ready
|
|
123
148
|
delay = 3
|
|
124
149
|
session(
|
|
125
|
-
:retries
|
|
126
|
-
:delay
|
|
127
|
-
:message
|
|
150
|
+
:retries => max_wait_until_ready / delay,
|
|
151
|
+
:delay => delay,
|
|
152
|
+
:message => "Waiting for WinRM service on #{endpoint}, " \
|
|
128
153
|
"retrying in #{delay} seconds"
|
|
129
154
|
)
|
|
130
155
|
execute(PING_COMMAND.dup)
|
|
@@ -134,9 +159,14 @@ module Kitchen
|
|
|
134
159
|
|
|
135
160
|
PING_COMMAND = "Write-Host '[WinRM] Established\n'".freeze
|
|
136
161
|
|
|
162
|
+
# Maximum string to send to the transport to execute. WinRM has an 8000 character
|
|
163
|
+
# command line limit. The original command string is coverted to a base 64 encoded
|
|
164
|
+
# UTF-16 string which will double the string size.
|
|
165
|
+
MAX_COMMAND_SIZE = 3000
|
|
166
|
+
|
|
137
167
|
RESCUE_EXCEPTIONS_ON_ESTABLISH = lambda do
|
|
138
168
|
[
|
|
139
|
-
Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED,
|
|
169
|
+
Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
|
|
140
170
|
Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH,
|
|
141
171
|
::WinRM::WinRMHTTPTransportError, ::WinRM::WinRMAuthorizationError,
|
|
142
172
|
HTTPClient::KeepAliveDisconnected,
|
|
@@ -290,9 +320,9 @@ module Kitchen
|
|
|
290
320
|
# @return [LoginCommand] a login command
|
|
291
321
|
# @api private
|
|
292
322
|
def login_command_for_linux
|
|
293
|
-
args = %W[
|
|
294
|
-
args += %W[
|
|
295
|
-
args += %W[
|
|
323
|
+
args = %W[-u #{options[:user]}]
|
|
324
|
+
args += %W[-p #{options[:pass]}] if options.key?(:pass)
|
|
325
|
+
args += %W[#{URI.parse(endpoint).host}:#{rdp_port}]
|
|
296
326
|
|
|
297
327
|
LoginCommand.new("rdesktop", args)
|
|
298
328
|
end
|
|
@@ -364,7 +394,7 @@ module Kitchen
|
|
|
364
394
|
def session(retry_options = {})
|
|
365
395
|
@session ||= establish_shell({
|
|
366
396
|
:retries => connection_retries.to_i,
|
|
367
|
-
:delay
|
|
397
|
+
:delay => connection_retry_sleep.to_i
|
|
368
398
|
}.merge(retry_options))
|
|
369
399
|
end
|
|
370
400
|
|
|
@@ -375,11 +405,36 @@ module Kitchen
|
|
|
375
405
|
def to_s
|
|
376
406
|
"#{winrm_transport}::#{endpoint}<#{options.inspect}>"
|
|
377
407
|
end
|
|
408
|
+
|
|
409
|
+
# takes a long (greater than 3000 characters) command and saves it to a
|
|
410
|
+
# file and uploads it to the test instance.
|
|
411
|
+
#
|
|
412
|
+
# @param command [String] a long command to be saved and uploaded
|
|
413
|
+
# @return [String] a command that executes the uploaded script
|
|
414
|
+
# @api private
|
|
415
|
+
def run_from_file_command(command)
|
|
416
|
+
temp_dir = Dir.mktmpdir("kitchen-long-script")
|
|
417
|
+
begin
|
|
418
|
+
script_name = "#{instance_name}-long_script.ps1"
|
|
419
|
+
script_path = File.join(temp_dir, script_name)
|
|
420
|
+
|
|
421
|
+
File.open(script_path, "wb") do |file|
|
|
422
|
+
file.write(command)
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
target_path = File.join("$env:TEMP", "kitchen")
|
|
426
|
+
upload(script_path, target_path)
|
|
427
|
+
|
|
428
|
+
%{& "#{File.join(target_path, script_name)}"}
|
|
429
|
+
ensure
|
|
430
|
+
FileUtils.rmtree(temp_dir)
|
|
431
|
+
end
|
|
432
|
+
end
|
|
378
433
|
end
|
|
379
434
|
|
|
380
435
|
private
|
|
381
436
|
|
|
382
|
-
WINRM_TRANSPORT_SPEC_VERSION = "~> 1.0".freeze
|
|
437
|
+
WINRM_TRANSPORT_SPEC_VERSION = ["~> 1.0", ">= 1.0.3"].freeze
|
|
383
438
|
|
|
384
439
|
# Builds the hash of options needed by the Connection object on
|
|
385
440
|
# construction.
|
|
@@ -389,24 +444,38 @@ module Kitchen
|
|
|
389
444
|
# @api private
|
|
390
445
|
def connection_options(data)
|
|
391
446
|
opts = {
|
|
392
|
-
:instance_name
|
|
393
|
-
:kitchen_root
|
|
394
|
-
:logger
|
|
395
|
-
:
|
|
396
|
-
:
|
|
397
|
-
:
|
|
398
|
-
:
|
|
399
|
-
:
|
|
400
|
-
:pass => data[:password],
|
|
401
|
-
:rdp_port => data[:rdp_port],
|
|
402
|
-
:connection_retries => data[:connection_retries],
|
|
447
|
+
:instance_name => instance.name,
|
|
448
|
+
:kitchen_root => data[:kitchen_root],
|
|
449
|
+
:logger => logger,
|
|
450
|
+
:endpoint => data[:endpoint_template] % data,
|
|
451
|
+
:user => data[:username],
|
|
452
|
+
:pass => data[:password],
|
|
453
|
+
:rdp_port => data[:rdp_port],
|
|
454
|
+
:connection_retries => data[:connection_retries],
|
|
403
455
|
:connection_retry_sleep => data[:connection_retry_sleep],
|
|
404
|
-
:max_wait_until_ready
|
|
456
|
+
:max_wait_until_ready => data[:max_wait_until_ready],
|
|
457
|
+
:winrm_transport => data[:winrm_transport]
|
|
405
458
|
}
|
|
406
|
-
|
|
459
|
+
opts.merge!(additional_transport_args(opts[:winrm_transport]))
|
|
407
460
|
opts
|
|
408
461
|
end
|
|
409
462
|
|
|
463
|
+
def additional_transport_args(transport_type)
|
|
464
|
+
case transport_type
|
|
465
|
+
when :ssl, :sspinegotiate
|
|
466
|
+
{
|
|
467
|
+
:no_ssl_peer_verification => true,
|
|
468
|
+
:disable_sspi => false,
|
|
469
|
+
:basic_auth_only => false
|
|
470
|
+
}
|
|
471
|
+
when :plaintext
|
|
472
|
+
{
|
|
473
|
+
:disable_sspi => true,
|
|
474
|
+
:basic_auth_only => true
|
|
475
|
+
}
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
|
|
410
479
|
# Creates a new WinRM Connection instance and save it for potential
|
|
411
480
|
# future reuse.
|
|
412
481
|
#
|
|
@@ -424,41 +493,90 @@ module Kitchen
|
|
|
424
493
|
end
|
|
425
494
|
|
|
426
495
|
# (see Base#load_needed_dependencies!)
|
|
427
|
-
def load_needed_dependencies!
|
|
496
|
+
def load_needed_dependencies!
|
|
428
497
|
super
|
|
429
|
-
spec_version = WINRM_TRANSPORT_SPEC_VERSION.dup
|
|
430
|
-
logger.debug("Winrm Transport requested," \
|
|
431
|
-
" loading WinRM::Transport gem (#{spec_version})")
|
|
432
|
-
gem "winrm-transport", spec_version
|
|
433
|
-
first_load = require "winrm/transport/version"
|
|
434
498
|
load_winrm_transport!
|
|
435
|
-
|
|
436
|
-
version = ::WinRM::Transport::VERSION
|
|
437
|
-
if first_load
|
|
438
|
-
logger.debug("WinRM::Transport #{version} library loaded")
|
|
439
|
-
else
|
|
440
|
-
logger.debug("WinRM::Transport #{version} previously loaded")
|
|
441
|
-
end
|
|
442
|
-
rescue LoadError => e
|
|
443
|
-
logger.fatal("The `winrm-transport' gem is missing and must" \
|
|
444
|
-
" be installed or cannot be properly activated. Run" \
|
|
445
|
-
" `gem install winrm-transport --version '#{spec_version}'`" \
|
|
446
|
-
" or add the following to your Gemfile if you are using Bundler:" \
|
|
447
|
-
" `gem 'winrm-transport', '#{spec_version}'`.")
|
|
448
|
-
raise UserError,
|
|
449
|
-
"Could not load or activate WinRM::Transport (#{e.message})"
|
|
499
|
+
load_winrm_s! if host_os_windows?
|
|
450
500
|
end
|
|
451
501
|
|
|
452
502
|
# Load WinRM::Transport code.
|
|
453
503
|
#
|
|
454
504
|
# @api private
|
|
455
505
|
def load_winrm_transport!
|
|
506
|
+
spec_version = WINRM_TRANSPORT_SPEC_VERSION.dup
|
|
507
|
+
options = {
|
|
508
|
+
:load_msg => "Winrm Transport requested," \
|
|
509
|
+
" loading WinRM::Transport gem (#{spec_version})",
|
|
510
|
+
:success_msg => "WinRM::Transport library loaded",
|
|
511
|
+
:already_msg => "WinRM::Transport previously loaded",
|
|
512
|
+
:name => "winrm-transport",
|
|
513
|
+
:version => spec_version
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
load_with_rescue!(options) do
|
|
517
|
+
gem "winrm-transport", WINRM_TRANSPORT_SPEC_VERSION.dup
|
|
518
|
+
require "winrm/transport/version"
|
|
519
|
+
end
|
|
520
|
+
|
|
456
521
|
silence_warnings { require "winrm" }
|
|
457
522
|
require "winrm/transport/shell_closer"
|
|
458
523
|
require "winrm/transport/command_executor"
|
|
459
524
|
require "winrm/transport/file_transporter"
|
|
460
525
|
end
|
|
461
526
|
|
|
527
|
+
def load_winrm_s!
|
|
528
|
+
options = {
|
|
529
|
+
:load_msg => "The winrm-s gem is being loaded" \
|
|
530
|
+
" to enable sspiauthentication.",
|
|
531
|
+
:success_msg => "winrm-s is loaded." \
|
|
532
|
+
" sspinegotiate auth is now available.",
|
|
533
|
+
:already_msg => "winrm-s was already loaded.",
|
|
534
|
+
:name => "winrm-s"
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
load_with_rescue!(options) { require "winrm-s" }
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def load_with_rescue!(options = {}, &block)
|
|
541
|
+
logger.debug(options[:load_msg])
|
|
542
|
+
attempt_load = execute_block(&block)
|
|
543
|
+
if attempt_load
|
|
544
|
+
logger.debug(options[:success_msg])
|
|
545
|
+
else
|
|
546
|
+
logger.debug(options[:already_msg])
|
|
547
|
+
end
|
|
548
|
+
rescue LoadError => e
|
|
549
|
+
message = fail_to_load_gem_message(options[:name],
|
|
550
|
+
options[:version])
|
|
551
|
+
logger.fatal(message)
|
|
552
|
+
raise UserError,
|
|
553
|
+
"Could not load or activate #{options[:name]}. (#{e.message})"
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
def execute_block
|
|
557
|
+
yield if block_given?
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
def fail_to_load_gem_message(name, version = nil)
|
|
561
|
+
version_cmd = "--version '#{version}'" if version
|
|
562
|
+
version_file = "', '#{version}"
|
|
563
|
+
|
|
564
|
+
"The `#{name}` gem is missing and must" \
|
|
565
|
+
" be installed or cannot be properly activated. Run" \
|
|
566
|
+
" `gem install #{name} #{version_cmd}`" \
|
|
567
|
+
" or add the following to your Gemfile if you are using Bundler:" \
|
|
568
|
+
" `gem '#{name} #{version_file}'`."
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
def host_os_windows?
|
|
572
|
+
case RbConfig::CONFIG["host_os"]
|
|
573
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
|
574
|
+
true
|
|
575
|
+
else
|
|
576
|
+
false
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
|
|
462
580
|
# Return the last saved WinRM connection instance.
|
|
463
581
|
#
|
|
464
582
|
# @return [Winrm::Connection] a WinRM Connection instance
|
|
@@ -33,8 +33,8 @@ module Kitchen
|
|
|
33
33
|
include Logging
|
|
34
34
|
|
|
35
35
|
default_config :http_proxy, nil
|
|
36
|
-
|
|
37
36
|
default_config :https_proxy, nil
|
|
37
|
+
default_config :ftp_proxy, nil
|
|
38
38
|
|
|
39
39
|
default_config :root_path do |verifier|
|
|
40
40
|
verifier.windows_os? ? "$env:TEMP\\verifier" : "/tmp/verifier"
|
|
@@ -44,10 +44,14 @@ module Kitchen
|
|
|
44
44
|
verifier.windows_os? ? nil : true
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
default_config :chef_omnibus_root, "/opt/chef"
|
|
48
|
+
|
|
47
49
|
default_config :sudo_command do |verifier|
|
|
48
50
|
verifier.windows_os? ? nil : "sudo -E"
|
|
49
51
|
end
|
|
50
52
|
|
|
53
|
+
default_config :command_prefix, nil
|
|
54
|
+
|
|
51
55
|
default_config(:suite_name) { |busser| busser.instance.suite.name }
|
|
52
56
|
|
|
53
57
|
# Creates a new Verifier object using the provided configuration data
|
|
@@ -213,6 +217,19 @@ module Kitchen
|
|
|
213
217
|
def sudo(script)
|
|
214
218
|
config[:sudo] ? "#{config[:sudo_command]} #{script}" : script
|
|
215
219
|
end
|
|
220
|
+
|
|
221
|
+
# Conditionally prefixes a command with a command prefix.
|
|
222
|
+
# This should generally be done after a command has been
|
|
223
|
+
# conditionally prefixed by #sudo as certain platforms, such as
|
|
224
|
+
# Cisco Nexus, require all commands to be run with a prefix to
|
|
225
|
+
# obtain outbound network access.
|
|
226
|
+
#
|
|
227
|
+
# @param command [String] command to be prefixed
|
|
228
|
+
# @return [String] the command, conditionally prefixed with the configured prefix
|
|
229
|
+
# @api private
|
|
230
|
+
def prefix_command(script)
|
|
231
|
+
config[:command_prefix] ? "#{config[:command_prefix]} #{script}" : script
|
|
232
|
+
end
|
|
216
233
|
end
|
|
217
234
|
end
|
|
218
235
|
end
|
|
@@ -46,7 +46,7 @@ module Kitchen
|
|
|
46
46
|
if verifier.windows_os?
|
|
47
47
|
"$env:systemdrive\\opscode\\chef\\embedded\\bin"
|
|
48
48
|
else
|
|
49
|
-
|
|
49
|
+
verifier.remote_path_join(%W[#{verifier[:chef_omnibus_root]} embedded bin])
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -76,7 +76,7 @@ module Kitchen
|
|
|
76
76
|
cmd = sudo(config[:busser_bin]).dup.
|
|
77
77
|
tap { |str| str.insert(0, "& ") if powershell_shell? }
|
|
78
78
|
|
|
79
|
-
wrap_shell_code(Util.outdent!(<<-CMD))
|
|
79
|
+
prefix_command(wrap_shell_code(Util.outdent!(<<-CMD)))
|
|
80
80
|
#{busser_env}
|
|
81
81
|
|
|
82
82
|
#{cmd} suite cleanup
|
|
@@ -89,7 +89,7 @@ module Kitchen
|
|
|
89
89
|
|
|
90
90
|
vars = install_command_vars
|
|
91
91
|
|
|
92
|
-
shell_code_from_file(vars, "busser_install_command")
|
|
92
|
+
prefix_command(shell_code_from_file(vars, "busser_install_command"))
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
# (see Base#run_command)
|
|
@@ -99,7 +99,7 @@ module Kitchen
|
|
|
99
99
|
cmd = sudo(config[:busser_bin]).dup.
|
|
100
100
|
tap { |str| str.insert(0, "& ") if powershell_shell? }
|
|
101
101
|
|
|
102
|
-
wrap_shell_code(Util.outdent!(<<-CMD))
|
|
102
|
+
prefix_command(wrap_shell_code(Util.outdent!(<<-CMD)))
|
|
103
103
|
#{busser_env}
|
|
104
104
|
|
|
105
105
|
#{cmd} test
|
|
@@ -173,9 +173,16 @@ module Kitchen
|
|
|
173
173
|
gem, version = config[:version].split("@")
|
|
174
174
|
gem, version = "busser", gem if gem =~ /^\d+\.\d+\.\d+/
|
|
175
175
|
|
|
176
|
+
root = config[:root_path]
|
|
177
|
+
gem_bin = remote_path_join(root, "bin")
|
|
178
|
+
|
|
179
|
+
# We don't want the gems to be installed in the home directory,
|
|
180
|
+
# this will force the bindir and the gem install location both
|
|
181
|
+
# to be under /tmp/verifier
|
|
176
182
|
args = gem
|
|
177
183
|
args += " --version #{version}" if version
|
|
178
|
-
args += " --no-rdoc --no-ri"
|
|
184
|
+
args += " --no-rdoc --no-ri --no-format-executable -n #{gem_bin}"
|
|
185
|
+
args += " --no-user-install"
|
|
179
186
|
args
|
|
180
187
|
end
|
|
181
188
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Author:: SAWANOBORI Yukihiko (<sawanoboriyu@higanworks.com>)
|
|
4
|
+
#
|
|
5
|
+
# Copyright (C) 2015, HiganWorks LLC
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
|
|
19
|
+
require "kitchen/verifier/base"
|
|
20
|
+
|
|
21
|
+
module Kitchen
|
|
22
|
+
|
|
23
|
+
module Verifier
|
|
24
|
+
|
|
25
|
+
# Shell verifier for Kitchen. This verifier just execute shell command from local.
|
|
26
|
+
#
|
|
27
|
+
# @author SAWANOBORI Yukihiko (<sawanoboriyu@higanworks.com>)
|
|
28
|
+
class Shell < Kitchen::Verifier::Base
|
|
29
|
+
require "mixlib/shellout"
|
|
30
|
+
|
|
31
|
+
kitchen_verifier_api_version 1
|
|
32
|
+
|
|
33
|
+
plugin_version Kitchen::VERSION
|
|
34
|
+
|
|
35
|
+
default_config :sleep, 0
|
|
36
|
+
default_config :command, "true"
|
|
37
|
+
default_config :shellout_opts, {}
|
|
38
|
+
default_config :live_stream, $stdout
|
|
39
|
+
default_config :remote_exec, false
|
|
40
|
+
|
|
41
|
+
# (see Base#call)
|
|
42
|
+
def call(state)
|
|
43
|
+
info("[#{name}] Verify on instance=#{instance} with state=#{state}")
|
|
44
|
+
sleep_if_set
|
|
45
|
+
merge_state_to_env(state)
|
|
46
|
+
if config[:remote_exec]
|
|
47
|
+
instance.transport.connection(state) do |conn|
|
|
48
|
+
conn.execute(config[:command])
|
|
49
|
+
end
|
|
50
|
+
else
|
|
51
|
+
shellout
|
|
52
|
+
end
|
|
53
|
+
debug("[#{name}] Verify completed.")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# for legacy drivers.
|
|
57
|
+
def run_command
|
|
58
|
+
if config[:remote_exec]
|
|
59
|
+
config[:command]
|
|
60
|
+
else
|
|
61
|
+
shellout
|
|
62
|
+
nil
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
# Sleep for a period of time, if a value is set in the config.
|
|
69
|
+
#
|
|
70
|
+
# @api private
|
|
71
|
+
def sleep_if_set
|
|
72
|
+
config[:sleep].to_i.times do
|
|
73
|
+
info(".")
|
|
74
|
+
sleep 1
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def shellout
|
|
79
|
+
cmd = Mixlib::ShellOut.new(config[:command], config[:shellout_opts])
|
|
80
|
+
cmd.live_stream = config[:live_stream]
|
|
81
|
+
cmd.run_command
|
|
82
|
+
begin
|
|
83
|
+
cmd.error!
|
|
84
|
+
rescue Mixlib::ShellOut::ShellCommandFailed
|
|
85
|
+
raise ActionFailed, "Action #verify failed for #{instance.to_str}."
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def merge_state_to_env(state)
|
|
90
|
+
env_state = { :environment => {} }
|
|
91
|
+
env_state[:environment]["KITCHEN_INSTANCE"] = instance.name
|
|
92
|
+
env_state[:environment]["KITCHEN_PLATFORM"] = instance.platform.name
|
|
93
|
+
env_state[:environment]["KITCHEN_SUITE"] = instance.suite.name
|
|
94
|
+
state.each_pair do |key, value|
|
|
95
|
+
env_state[:environment]["KITCHEN_" + key.to_s.upcase] = value
|
|
96
|
+
end
|
|
97
|
+
config[:shellout_opts].merge!(env_state)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
data/lib/kitchen/version.rb
CHANGED
|
@@ -58,7 +58,7 @@ describe Kitchen::Collection do
|
|
|
58
58
|
result.get_all(/one/).size.must_equal 1
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
it "returns an empty Collection if
|
|
61
|
+
it "returns an empty Collection if no matches are found" do
|
|
62
62
|
result = collection.get_all(/noppa/)
|
|
63
63
|
result.must_equal []
|
|
64
64
|
result.get("nahuh").must_be_nil
|