test-kitchen 1.5.0 → 1.6.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 +2 -0
- data/CHANGELOG.md +977 -863
- data/CONTRIBUTING.md +3 -6
- data/Rakefile +9 -0
- data/lib/kitchen/command/driver_discover.rb +10 -4
- data/lib/kitchen/driver/ssh_base.rb +4 -0
- data/lib/kitchen/instance.rb +19 -1
- data/lib/kitchen/platform.rb +8 -2
- data/lib/kitchen/provisioner/base.rb +10 -2
- data/lib/kitchen/provisioner/chef_apply.rb +125 -0
- data/lib/kitchen/provisioner/chef_base.rb +12 -5
- data/lib/kitchen/transport/winrm.rb +36 -148
- data/lib/kitchen/version.rb +1 -1
- data/spec/kitchen/provisioner/base_spec.rb +33 -0
- data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -0
- data/spec/kitchen/provisioner/chef_base_spec.rb +11 -5
- data/spec/kitchen/ssh_spec.rb +6 -3
- data/spec/kitchen/transport/ssh_spec.rb +6 -4
- data/spec/kitchen/transport/winrm_spec.rb +70 -254
- data/spec/kitchen/verifier/shell_spec.rb +1 -0
- data/test-kitchen.gemspec +3 -3
- data/testing_windows.md +37 -0
- metadata +25 -27
data/CONTRIBUTING.md
CHANGED
@@ -6,12 +6,9 @@ This release process applies to all Test Kitchen projects, but each project may
|
|
6
6
|
2. Check out the master branch of the project being prepared for release.
|
7
7
|
3. Branch into a release-branch of the form `150_release_prep`.
|
8
8
|
4. Modify the `version.rb` file to specify the version for releasing.
|
9
|
-
5.
|
10
|
-
1. For these projects we use [PimpMyChangelog](https://github.com/pcreux/pimpmychangelog). All this does is make the CHANGELOG look pretty - for now we manually import the PRs / Issues and categorize them.
|
11
|
-
2. Start a [diff](https://github.com/test-kitchen/test-kitchen/compare/v1.4.2...master) in Github between master and the last release
|
12
|
-
3. Look for all the merged PRs and add them to the CHANGELOG.md under the appropriate category. They should have the form `* PR #999: PR Description (@author)`.
|
13
|
-
4. Install and run `pimpmychangelog`. This should change all the PR numbers and @ mentions into links.
|
9
|
+
5. Run `rake changelog` to regenerate the changelog.
|
14
10
|
6. `git commit` the `version.rb` and `CHANGELOG.md` changes to the branch and setup a PR for them. Allow the PR to run any automated tests and review the CHANGELOG for accuracy.
|
15
11
|
7. Merge the PR to master after review.
|
16
|
-
8. Switch your local copy to the master branch and `git pull` to pull in the release
|
12
|
+
8. Switch your local copy to the master branch and `git pull` to pull in the release preparation changes.
|
17
13
|
9. Run `rake release` on the master branch.
|
14
|
+
10. Modify the `version.rb` file and bump the patch or minor version, and commit/push.
|
data/Rakefile
CHANGED
@@ -65,3 +65,12 @@ task :deploy_over_dk do
|
|
65
65
|
end
|
66
66
|
|
67
67
|
task :dk_install => [:deploy_over_dk, :install]
|
68
|
+
|
69
|
+
require "github_changelog_generator/task"
|
70
|
+
|
71
|
+
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
72
|
+
config.future_release = Kitchen::VERSION
|
73
|
+
config.enhancement_labels = "enhancement,Enhancement,New Feature,Feature".split(",")
|
74
|
+
config.bug_labels = "bug,Bug,Improvement".split(",")
|
75
|
+
config.exclude_labels = %w[Duplicate Question Discussion]
|
76
|
+
end
|
@@ -19,8 +19,12 @@
|
|
19
19
|
require "kitchen/command"
|
20
20
|
|
21
21
|
require "rubygems/spec_fetcher"
|
22
|
-
|
23
|
-
require "chef-config/
|
22
|
+
begin
|
23
|
+
require "chef-config/config"
|
24
|
+
require "chef-config/workstation_config_loader"
|
25
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
26
|
+
# This space left intentionally blank.
|
27
|
+
end
|
24
28
|
|
25
29
|
module Kitchen
|
26
30
|
|
@@ -36,8 +40,10 @@ module Kitchen
|
|
36
40
|
# We are introducing the idea of using the Chef configuration as a
|
37
41
|
# unified config for all the ChefDK tools. The first practical
|
38
42
|
# implementation of this is 1 location to setup proxy configurations.
|
39
|
-
ChefConfig::WorkstationConfigLoader
|
40
|
-
|
43
|
+
if defined?(ChefConfig::WorkstationConfigLoader)
|
44
|
+
ChefConfig::WorkstationConfigLoader.new(options[:chef_config_path]).load
|
45
|
+
end
|
46
|
+
ChefConfig::Config.export_proxies if defined?(ChefConfig::Config.export_proxies)
|
41
47
|
|
42
48
|
specs = fetch_gem_specs.sort { |x, y| x[0] <=> y[0] }
|
43
49
|
specs = specs[0, 49].push(["...", "..."]) if specs.size > 49
|
@@ -123,6 +123,10 @@ module Kitchen
|
|
123
123
|
raise ClientError, "#{self.class}#destroy must be implemented"
|
124
124
|
end
|
125
125
|
|
126
|
+
def legacy_state(state)
|
127
|
+
backcompat_merged_state(state)
|
128
|
+
end
|
129
|
+
|
126
130
|
# (see Base#login_command)
|
127
131
|
def login_command(state)
|
128
132
|
instance.transport.connection(backcompat_merged_state(state)).
|
data/lib/kitchen/instance.rb
CHANGED
@@ -391,6 +391,20 @@ module Kitchen
|
|
391
391
|
self
|
392
392
|
end
|
393
393
|
|
394
|
+
# returns true, if the verifier is busser
|
395
|
+
def verifier_busser?(verifier)
|
396
|
+
!defined?(Kitchen::Verifier::Busser).nil? && verifier.is_a?(Kitchen::Verifier::Busser)
|
397
|
+
end
|
398
|
+
|
399
|
+
# returns true, if the verifier is dummy
|
400
|
+
def verifier_dummy?(verifier)
|
401
|
+
!defined?(Kitchen::Verifier::Dummy).nil? && verifier.is_a?(Kitchen::Verifier::Dummy)
|
402
|
+
end
|
403
|
+
|
404
|
+
def use_legacy_ssh_verifier?(verifier)
|
405
|
+
verifier_busser?(verifier) || verifier_dummy?(verifier)
|
406
|
+
end
|
407
|
+
|
394
408
|
# Perform the verify action.
|
395
409
|
#
|
396
410
|
# @see Driver::Base#verify
|
@@ -399,8 +413,12 @@ module Kitchen
|
|
399
413
|
def verify_action
|
400
414
|
banner "Verifying #{to_str}..."
|
401
415
|
elapsed = action(:verify) do |state|
|
402
|
-
|
416
|
+
# use special handling for legacy driver
|
417
|
+
if legacy_ssh_base_driver? && use_legacy_ssh_verifier?(verifier)
|
403
418
|
legacy_ssh_base_verify(state)
|
419
|
+
elsif legacy_ssh_base_driver?
|
420
|
+
# read ssh options from legacy driver
|
421
|
+
verifier.call(driver.legacy_state(state))
|
404
422
|
else
|
405
423
|
verifier.call(state)
|
406
424
|
end
|
data/lib/kitchen/platform.rb
CHANGED
@@ -44,13 +44,19 @@ module Kitchen
|
|
44
44
|
raise ClientError, "Platform#new requires option :name"
|
45
45
|
end
|
46
46
|
@os_type = options.fetch(:os_type) do
|
47
|
-
|
47
|
+
windows?(options) ? "windows" : "unix"
|
48
48
|
end
|
49
49
|
@shell_type = options.fetch(:shell_type) do
|
50
|
-
|
50
|
+
windows?(options) ? "powershell" : "bourne"
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
def windows?(options)
|
55
|
+
@name.downcase =~ /^win/ || (
|
56
|
+
!options[:transport].nil? && options[:transport][:name] == "winrm"
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
54
60
|
# Returns a Hash of configuration and other useful diagnostic information.
|
55
61
|
#
|
56
62
|
# @return [Hash] a diagnostic hash
|
@@ -205,10 +205,18 @@ module Kitchen
|
|
205
205
|
# Conditionally prefixes a command with a sudo command.
|
206
206
|
#
|
207
207
|
# @param command [String] command to be prefixed
|
208
|
-
# @return [String] the command,
|
208
|
+
# @return [String] the command, conditionally prefixed with sudo
|
209
209
|
# @api private
|
210
210
|
def sudo(script)
|
211
|
-
|
211
|
+
"#{sudo_command} #{script}".lstrip
|
212
|
+
end
|
213
|
+
|
214
|
+
# Returns the sudo command to use or empty string if sudo is not configured
|
215
|
+
#
|
216
|
+
# @return [String] the sudo command if sudo config is true
|
217
|
+
# @api private
|
218
|
+
def sudo_command
|
219
|
+
config[:sudo] ? config[:sudo_command].to_s : ""
|
212
220
|
end
|
213
221
|
|
214
222
|
# Conditionally prefixes a command with a command prefix.
|
@@ -0,0 +1,125 @@
|
|
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
|
+
# Usage:
|
20
|
+
#
|
21
|
+
# puts your recipes to` apply/` directory.
|
22
|
+
#
|
23
|
+
# An example of .kitchen.yml.
|
24
|
+
#
|
25
|
+
# ---
|
26
|
+
# driver:
|
27
|
+
# name: vagrant
|
28
|
+
#
|
29
|
+
# provisioner:
|
30
|
+
# name: chef_apply
|
31
|
+
#
|
32
|
+
# platforms:
|
33
|
+
# - name: ubuntu-12.04
|
34
|
+
# - name: centos-6.4
|
35
|
+
#
|
36
|
+
# suites:
|
37
|
+
# - name: default
|
38
|
+
# run_list:
|
39
|
+
# - recipe1
|
40
|
+
# - recipe2
|
41
|
+
#
|
42
|
+
#
|
43
|
+
# The chef-apply runs twice below.
|
44
|
+
#
|
45
|
+
# chef-apply apply/recipe1.rb
|
46
|
+
# chef-apply apply/recipe2.rb
|
47
|
+
|
48
|
+
require "kitchen/provisioner/chef_base"
|
49
|
+
|
50
|
+
module Kitchen
|
51
|
+
|
52
|
+
module Provisioner
|
53
|
+
|
54
|
+
# Chef Apply provisioner.
|
55
|
+
#
|
56
|
+
# @author SAWANOBORI Yukihiko <sawanoboriyu@higanworks.com>)
|
57
|
+
class ChefApply < ChefBase
|
58
|
+
|
59
|
+
kitchen_provisioner_api_version 2
|
60
|
+
|
61
|
+
plugin_version Kitchen::VERSION
|
62
|
+
|
63
|
+
default_config :chef_apply_path do |provisioner|
|
64
|
+
provisioner.
|
65
|
+
remote_path_join(%W[#{provisioner[:chef_omnibus_root]} bin chef-apply]).
|
66
|
+
tap { |path| path.concat(".bat") if provisioner.windows_os? }
|
67
|
+
end
|
68
|
+
|
69
|
+
default_config :apply_path do |provisioner|
|
70
|
+
provisioner.calculate_path("apply")
|
71
|
+
end
|
72
|
+
expand_path_for :apply_path
|
73
|
+
|
74
|
+
# (see ChefBase#create_sandbox)
|
75
|
+
def create_sandbox
|
76
|
+
@sandbox_path = Dir.mktmpdir("#{instance.name}-sandbox-")
|
77
|
+
File.chmod(0755, sandbox_path)
|
78
|
+
info("Preparing files for transfer")
|
79
|
+
debug("Creating local sandbox in #{sandbox_path}")
|
80
|
+
|
81
|
+
prepare_json
|
82
|
+
prepare(:apply)
|
83
|
+
end
|
84
|
+
|
85
|
+
# (see ChefBase#init_command)
|
86
|
+
def init_command
|
87
|
+
dirs = %w[
|
88
|
+
apply
|
89
|
+
].sort.map { |dir| remote_path_join(config[:root_path], dir) }
|
90
|
+
|
91
|
+
vars = if powershell_shell?
|
92
|
+
init_command_vars_for_powershell(dirs)
|
93
|
+
else
|
94
|
+
init_command_vars_for_bourne(dirs)
|
95
|
+
end
|
96
|
+
|
97
|
+
prefix_command(shell_code_from_file(vars, "chef_base_init_command"))
|
98
|
+
end
|
99
|
+
|
100
|
+
# (see ChefSolo#run_command)
|
101
|
+
def run_command
|
102
|
+
level = config[:log_level] == :info ? :auto : config[:log_level]
|
103
|
+
|
104
|
+
lines = []
|
105
|
+
config[:run_list].map do |recipe|
|
106
|
+
cmd = sudo(config[:chef_apply_path]).dup.
|
107
|
+
tap { |str| str.insert(0, "& ") if powershell_shell? }
|
108
|
+
args = [
|
109
|
+
"apply/#{recipe}.rb",
|
110
|
+
"--log_level #{level}",
|
111
|
+
"--no-color"
|
112
|
+
]
|
113
|
+
args << "--logfile #{config[:log_file]}" if config[:log_file]
|
114
|
+
|
115
|
+
lines << wrap_shell_code(
|
116
|
+
[cmd, *args].join(" ").
|
117
|
+
tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
prefix_command(lines.join("\n"))
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -26,8 +26,12 @@ require "kitchen/provisioner/chef/common_sandbox"
|
|
26
26
|
require "kitchen/provisioner/chef/librarian"
|
27
27
|
require "kitchen/util"
|
28
28
|
require "mixlib/install"
|
29
|
-
|
30
|
-
require "chef-config/
|
29
|
+
begin
|
30
|
+
require "chef-config/config"
|
31
|
+
require "chef-config/workstation_config_loader"
|
32
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
33
|
+
# This space left intentionally blank.
|
34
|
+
end
|
31
35
|
|
32
36
|
module Kitchen
|
33
37
|
|
@@ -96,10 +100,12 @@ module Kitchen
|
|
96
100
|
def initialize(config = {})
|
97
101
|
super(config)
|
98
102
|
|
99
|
-
ChefConfig::WorkstationConfigLoader
|
103
|
+
if defined?(ChefConfig::WorkstationConfigLoader)
|
104
|
+
ChefConfig::WorkstationConfigLoader.new(config[:config_path]).load
|
105
|
+
end
|
100
106
|
# This exports any proxy config present in the Chef config to
|
101
107
|
# appropriate environment variables, which Test Kitchen respects
|
102
|
-
ChefConfig::Config.export_proxies
|
108
|
+
ChefConfig::Config.export_proxies if defined?(ChefConfig::Config.export_proxies)
|
103
109
|
end
|
104
110
|
|
105
111
|
# (see Base#create_sandbox)
|
@@ -149,7 +155,8 @@ module Kitchen
|
|
149
155
|
{
|
150
156
|
:omnibus_url => config[:chef_omnibus_url],
|
151
157
|
:project => project.nil? ? nil : project[1],
|
152
|
-
:install_flags => config[:chef_omnibus_install_options]
|
158
|
+
:install_flags => config[:chef_omnibus_install_options],
|
159
|
+
:sudo_command => sudo_command
|
153
160
|
}.tap do |opts|
|
154
161
|
opts[:root] = config[:chef_omnibus_root] if config.key? :chef_omnibus_root
|
155
162
|
opts[:http_proxy] = config[:http_proxy] if config.key? :http_proxy
|
@@ -46,7 +46,7 @@ module Kitchen
|
|
46
46
|
default_config :connection_retries, 5
|
47
47
|
default_config :connection_retry_sleep, 1
|
48
48
|
default_config :max_wait_until_ready, 600
|
49
|
-
default_config :winrm_transport,
|
49
|
+
default_config :winrm_transport, :negotiate
|
50
50
|
default_config :port do |transport|
|
51
51
|
transport[:winrm_transport] == :ssl ? 5986 : 5985
|
52
52
|
end
|
@@ -58,18 +58,7 @@ module Kitchen
|
|
58
58
|
def finalize_config!(instance)
|
59
59
|
super
|
60
60
|
|
61
|
-
|
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
|
61
|
+
config[:winrm_transport] = config[:winrm_transport].to_sym
|
73
62
|
|
74
63
|
self
|
75
64
|
end
|
@@ -96,10 +85,7 @@ module Kitchen
|
|
96
85
|
def close
|
97
86
|
return if @session.nil?
|
98
87
|
|
99
|
-
shell_id = session.shell
|
100
|
-
logger.debug("[WinRM] closing remote shell #{shell_id} on #{self}")
|
101
88
|
session.close
|
102
|
-
logger.debug("[WinRM] remote shell #{shell_id} closed")
|
103
89
|
ensure
|
104
90
|
@session = nil
|
105
91
|
end
|
@@ -147,10 +133,8 @@ module Kitchen
|
|
147
133
|
def wait_until_ready
|
148
134
|
delay = 3
|
149
135
|
session(
|
150
|
-
:
|
151
|
-
:
|
152
|
-
:message => "Waiting for WinRM service on #{endpoint}, " \
|
153
|
-
"retrying in #{delay} seconds"
|
136
|
+
:retry_limit => max_wait_until_ready / delay,
|
137
|
+
:retry_delay => delay
|
154
138
|
)
|
155
139
|
execute(PING_COMMAND.dup)
|
156
140
|
end
|
@@ -164,16 +148,6 @@ module Kitchen
|
|
164
148
|
# UTF-16 string which will double the string size.
|
165
149
|
MAX_COMMAND_SIZE = 3000
|
166
150
|
|
167
|
-
RESCUE_EXCEPTIONS_ON_ESTABLISH = lambda do
|
168
|
-
[
|
169
|
-
Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
|
170
|
-
Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH,
|
171
|
-
::WinRM::WinRMHTTPTransportError, ::WinRM::WinRMAuthorizationError,
|
172
|
-
HTTPClient::KeepAliveDisconnected,
|
173
|
-
HTTPClient::ConnectTimeoutError
|
174
|
-
].freeze
|
175
|
-
end
|
176
|
-
|
177
151
|
# @return [Integer] how many times to retry when failing to execute
|
178
152
|
# a command or transfer files
|
179
153
|
# @api private
|
@@ -235,31 +209,6 @@ module Kitchen
|
|
235
209
|
end
|
236
210
|
end
|
237
211
|
|
238
|
-
# Establish a remote shell session on the remote host.
|
239
|
-
#
|
240
|
-
# @param opts [Hash] retry options
|
241
|
-
# @option opts [Integer] :retries the number of times to retry before
|
242
|
-
# failing
|
243
|
-
# @option opts [Float] :delay the number of seconds to wait until
|
244
|
-
# attempting a retry
|
245
|
-
# @option opts [String] :message an optional message to be logged on
|
246
|
-
# debug (overriding the default) when a rescuable exception is raised
|
247
|
-
# @return [Winrm::CommandExecutor] the command executor session
|
248
|
-
# @api private
|
249
|
-
def establish_shell(opts)
|
250
|
-
service_args = [endpoint, winrm_transport, options]
|
251
|
-
@service = ::WinRM::WinRMWebService.new(*service_args)
|
252
|
-
closer = WinRM::Transport::ShellCloser.new("#{self}", logger.debug?, service_args)
|
253
|
-
|
254
|
-
executor = WinRM::Transport::CommandExecutor.new(@service, logger, closer)
|
255
|
-
retryable(opts) do
|
256
|
-
logger.debug("[WinRM] opening remote shell on #{self}")
|
257
|
-
shell_id = executor.open
|
258
|
-
logger.debug("[WinRM] remote shell #{shell_id} is open on #{self}")
|
259
|
-
end
|
260
|
-
executor
|
261
|
-
end
|
262
|
-
|
263
212
|
# Execute a Powershell script over WinRM and return the command's
|
264
213
|
# exit code and standard error.
|
265
214
|
#
|
@@ -278,7 +227,7 @@ module Kitchen
|
|
278
227
|
# @return [Winrm::FileTransporter] a file transporter
|
279
228
|
# @api private
|
280
229
|
def file_transporter
|
281
|
-
@file_transporter ||= WinRM::
|
230
|
+
@file_transporter ||= WinRM::FS::Core::FileTransporter.new(session)
|
282
231
|
end
|
283
232
|
|
284
233
|
# (see Base#init_options)
|
@@ -353,38 +302,6 @@ module Kitchen
|
|
353
302
|
File.join(kitchen_root, ".kitchen", "#{instance_name}.rdp")
|
354
303
|
end
|
355
304
|
|
356
|
-
# Yields to a block and reties the block if certain rescuable
|
357
|
-
# exceptions are raised.
|
358
|
-
#
|
359
|
-
# @param opts [Hash] retry options
|
360
|
-
# @option opts [Integer] :retries the number of times to retry before
|
361
|
-
# failing
|
362
|
-
# @option opts [Float] :delay the number of seconds to wait until
|
363
|
-
# attempting a retry
|
364
|
-
# @option opts [String] :message an optional message to be logged on
|
365
|
-
# debug (overriding the default) when a rescuable exception is raised
|
366
|
-
# @return [Winrm::CommandExecutor] the command executor session
|
367
|
-
# @api private
|
368
|
-
def retryable(opts)
|
369
|
-
yield
|
370
|
-
rescue *RESCUE_EXCEPTIONS_ON_ESTABLISH.call => e
|
371
|
-
if (opts[:retries] -= 1) > 0
|
372
|
-
message = if opts[:message]
|
373
|
-
logger.debug("[WinRM] connection failed (#{e.inspect})")
|
374
|
-
opts[:message]
|
375
|
-
else
|
376
|
-
"[WinRM] connection failed, " \
|
377
|
-
"retrying in #{opts[:delay]} seconds (#{e.inspect})"
|
378
|
-
end
|
379
|
-
logger.info(message)
|
380
|
-
sleep(opts[:delay])
|
381
|
-
retry
|
382
|
-
else
|
383
|
-
logger.warn("[WinRM] connection failed, terminating (#{e.inspect})")
|
384
|
-
raise
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
305
|
# Establishes a remote shell session, or establishes one when invoked
|
389
306
|
# the first time.
|
390
307
|
#
|
@@ -392,10 +309,17 @@ module Kitchen
|
|
392
309
|
# @return [Winrm::CommandExecutor] the command executor session
|
393
310
|
# @api private
|
394
311
|
def session(retry_options = {})
|
395
|
-
@session ||=
|
396
|
-
|
397
|
-
|
398
|
-
|
312
|
+
@session ||= begin
|
313
|
+
opts = {
|
314
|
+
:retry_limit => connection_retries.to_i,
|
315
|
+
:retry_delay => connection_retry_sleep.to_i
|
316
|
+
}.merge(retry_options)
|
317
|
+
|
318
|
+
service_args = [endpoint, winrm_transport, options.merge(opts)]
|
319
|
+
@service = ::WinRM::WinRMWebService.new(*service_args)
|
320
|
+
@service.logger = logger
|
321
|
+
@service.create_executor
|
322
|
+
end
|
399
323
|
end
|
400
324
|
|
401
325
|
# String representation of object, reporting its connection details and
|
@@ -425,7 +349,7 @@ module Kitchen
|
|
425
349
|
target_path = File.join("$env:TEMP", "kitchen")
|
426
350
|
upload(script_path, target_path)
|
427
351
|
|
428
|
-
%{
|
352
|
+
%{powershell -ExecutionPolicy Bypass -File "#{File.join(target_path, script_name)}"}
|
429
353
|
ensure
|
430
354
|
FileUtils.rmtree(temp_dir)
|
431
355
|
end
|
@@ -434,7 +358,8 @@ module Kitchen
|
|
434
358
|
|
435
359
|
private
|
436
360
|
|
437
|
-
|
361
|
+
WINRM_SPEC_VERSION = ["~> 1.6"].freeze
|
362
|
+
WINRM_FS_SPEC_VERSION = ["~> 0.3"].freeze
|
438
363
|
|
439
364
|
# Builds the hash of options needed by the Connection object on
|
440
365
|
# construction.
|
@@ -461,8 +386,8 @@ module Kitchen
|
|
461
386
|
end
|
462
387
|
|
463
388
|
def additional_transport_args(transport_type)
|
464
|
-
case transport_type
|
465
|
-
when :ssl, :
|
389
|
+
case transport_type.to_sym
|
390
|
+
when :ssl, :negotiate
|
466
391
|
{
|
467
392
|
:no_ssl_peer_verification => true,
|
468
393
|
:disable_sspi => false,
|
@@ -473,6 +398,8 @@ module Kitchen
|
|
473
398
|
:disable_sspi => true,
|
474
399
|
:basic_auth_only => true
|
475
400
|
}
|
401
|
+
else
|
402
|
+
{}
|
476
403
|
end
|
477
404
|
end
|
478
405
|
|
@@ -495,66 +422,27 @@ module Kitchen
|
|
495
422
|
# (see Base#load_needed_dependencies!)
|
496
423
|
def load_needed_dependencies!
|
497
424
|
super
|
498
|
-
|
499
|
-
|
500
|
-
end
|
501
|
-
|
502
|
-
# Load WinRM::Transport code.
|
503
|
-
#
|
504
|
-
# @api private
|
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
|
-
|
521
|
-
silence_warnings { require "winrm" }
|
522
|
-
require "winrm/transport/shell_closer"
|
523
|
-
require "winrm/transport/command_executor"
|
524
|
-
require "winrm/transport/file_transporter"
|
525
|
-
end
|
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" }
|
425
|
+
load_with_rescue!("winrm", WINRM_SPEC_VERSION.dup)
|
426
|
+
load_with_rescue!("winrm-fs", WINRM_FS_SPEC_VERSION.dup)
|
538
427
|
end
|
539
428
|
|
540
|
-
def load_with_rescue!(
|
541
|
-
logger.debug(
|
542
|
-
|
429
|
+
def load_with_rescue!(gem_name, spec_version)
|
430
|
+
logger.debug("#{gem_name} requested," \
|
431
|
+
" loading #{gem_name} gem (#{spec_version})")
|
432
|
+
attempt_load = false
|
433
|
+
gem gem_name, spec_version
|
434
|
+
silence_warnings { attempt_load = require gem_name }
|
543
435
|
if attempt_load
|
544
|
-
logger.debug(
|
436
|
+
logger.debug("#{gem_name} is loaded.")
|
545
437
|
else
|
546
|
-
logger.debug(
|
438
|
+
logger.debug("#{gem_name} was already loaded.")
|
547
439
|
end
|
548
440
|
rescue LoadError => e
|
549
|
-
message = fail_to_load_gem_message(
|
550
|
-
|
441
|
+
message = fail_to_load_gem_message(gem_name,
|
442
|
+
spec_version)
|
551
443
|
logger.fatal(message)
|
552
444
|
raise UserError,
|
553
|
-
"Could not load or activate #{
|
554
|
-
end
|
555
|
-
|
556
|
-
def execute_block
|
557
|
-
yield if block_given?
|
445
|
+
"Could not load or activate #{gem_name}. (#{e.message})"
|
558
446
|
end
|
559
447
|
|
560
448
|
def fail_to_load_gem_message(name, version = nil)
|