test-kitchen 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|