test-kitchen 2.6.0 → 2.9.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/Rakefile +1 -1
- data/bin/kitchen +1 -1
- data/lib/kitchen.rb +2 -4
- data/lib/kitchen/cli.rb +2 -1
- data/lib/kitchen/command.rb +0 -2
- data/lib/kitchen/command/action.rb +1 -1
- data/lib/kitchen/command/diagnose.rb +3 -3
- data/lib/kitchen/command/list.rb +1 -1
- data/lib/kitchen/command/test.rb +1 -1
- data/lib/kitchen/config.rb +1 -1
- data/lib/kitchen/driver/base.rb +2 -38
- data/lib/kitchen/driver/ssh_base.rb +3 -39
- data/lib/kitchen/instance.rb +41 -14
- data/lib/kitchen/loader/yaml.rb +2 -2
- data/lib/kitchen/logger.rb +1 -1
- data/lib/kitchen/plugin_base.rb +60 -0
- data/lib/kitchen/provisioner/base.rb +2 -1
- data/lib/kitchen/provisioner/chef/common_sandbox.rb +1 -1
- data/lib/kitchen/provisioner/chef/policyfile.rb +6 -6
- data/lib/kitchen/provisioner/chef_base.rb +10 -8
- data/lib/kitchen/provisioner/chef_solo.rb +4 -0
- data/lib/kitchen/provisioner/shell.rb +1 -1
- data/lib/kitchen/shell_out.rb +1 -1
- data/lib/kitchen/ssh.rb +6 -3
- data/lib/kitchen/state_file.rb +1 -1
- data/lib/kitchen/thor_tasks.rb +1 -1
- data/lib/kitchen/transport/base.rb +2 -1
- data/lib/kitchen/transport/exec.rb +91 -5
- data/lib/kitchen/transport/ssh.rb +4 -4
- data/lib/kitchen/transport/winrm.rb +13 -9
- data/lib/kitchen/util.rb +11 -1
- data/lib/kitchen/verifier/base.rb +2 -1
- data/lib/kitchen/verifier/busser.rb +3 -3
- data/lib/kitchen/verifier/shell.rb +1 -1
- data/lib/kitchen/version.rb +1 -1
- data/test-kitchen.gemspec +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58365d9f59d1210a1c8f56f7fe095f285fde61e6251c61b164569b783d75d6f8
|
4
|
+
data.tar.gz: ceef4069cb15be71c35992173d3d347717f8149dc3a7fe2f4863e5a8aaac98c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf9e9206b2b78a39fa9fdeca2104e3cf17fed69821644f0055e7638e23a15f50dc11c9923718e5cb997d9a2ef416bbe2e48649fc6d6e7c02fd8627fbbe86f6b1
|
7
|
+
data.tar.gz: 86102634d2ad1b336cd5e18fdfe005ea7ef18f77e185351f041567aeb32b224609e457ca6904ea865bb18f278e836fdca4ae9afedff1877dd71564ed17d54d1b
|
data/Rakefile
CHANGED
@@ -42,7 +42,7 @@ desc "Run all quality tasks"
|
|
42
42
|
task quality: %i{style stats}
|
43
43
|
|
44
44
|
begin
|
45
|
-
require "yard"
|
45
|
+
require "yard" unless defined?(YARD)
|
46
46
|
YARD::Rake::YardocTask.new
|
47
47
|
rescue LoadError
|
48
48
|
puts "yard is not available. (sudo) gem install yard to generate yard documentation."
|
data/bin/kitchen
CHANGED
data/lib/kitchen.rb
CHANGED
@@ -15,9 +15,7 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
-
require "pathname"
|
19
|
-
require "thread"
|
20
|
-
|
18
|
+
require "pathname" unless defined?(Pathname)
|
21
19
|
require_relative "kitchen/errors"
|
22
20
|
require_relative "kitchen/logger"
|
23
21
|
require_relative "kitchen/logging"
|
@@ -67,7 +65,7 @@ module Kitchen
|
|
67
65
|
#
|
68
66
|
# @return [Pathname] root path of gem
|
69
67
|
def source_root
|
70
|
-
@source_root ||= Pathname.new(File.expand_path("
|
68
|
+
@source_root ||= Pathname.new(File.expand_path("..", __dir__))
|
71
69
|
end
|
72
70
|
|
73
71
|
# Returns a default logger which emits on standard output.
|
data/lib/kitchen/cli.rb
CHANGED
@@ -15,7 +15,8 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
-
require
|
18
|
+
# CI tests fail without an explicit unconditional require of Thor
|
19
|
+
require "thor" # rubocop:disable Chef/Ruby/UnlessDefinedRequire
|
19
20
|
|
20
21
|
require_relative "../kitchen"
|
21
22
|
require_relative "generator/init"
|
data/lib/kitchen/command.rb
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
require_relative "../command"
|
19
19
|
require_relative "../diagnostic"
|
20
20
|
|
21
|
-
|
21
|
+
autoload :YAML, "yaml"
|
22
22
|
|
23
23
|
module Kitchen
|
24
24
|
module Command
|
@@ -32,9 +32,9 @@ module Kitchen
|
|
32
32
|
|
33
33
|
loader = record_failure { load_loader }
|
34
34
|
|
35
|
-
puts Kitchen::Diagnostic.new(
|
35
|
+
puts YAML.dump(Kitchen::Diagnostic.new(
|
36
36
|
loader: loader, instances: instances, plugins: plugins?
|
37
|
-
).read
|
37
|
+
).read)
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
data/lib/kitchen/command/list.rb
CHANGED
data/lib/kitchen/command/test.rb
CHANGED
data/lib/kitchen/config.rb
CHANGED
@@ -213,7 +213,7 @@ module Kitchen
|
|
213
213
|
provisioner: Provisioner::DEFAULT_PLUGIN,
|
214
214
|
verifier: Verifier::DEFAULT_PLUGIN,
|
215
215
|
transport: lambda do |_suite, platform|
|
216
|
-
|
216
|
+
/^win/i.match?(platform) ? "winrm" : Transport::DEFAULT_PLUGIN
|
217
217
|
end,
|
218
218
|
},
|
219
219
|
kitchen_root: kitchen_root,
|
data/lib/kitchen/driver/base.rb
CHANGED
@@ -19,6 +19,7 @@ require_relative "../configurable"
|
|
19
19
|
require_relative "../errors"
|
20
20
|
require_relative "../lazy_hash"
|
21
21
|
require_relative "../logging"
|
22
|
+
require_relative "../plugin_base"
|
22
23
|
require_relative "../shell_out"
|
23
24
|
|
24
25
|
module Kitchen
|
@@ -26,7 +27,7 @@ module Kitchen
|
|
26
27
|
# Base class for a driver.
|
27
28
|
#
|
28
29
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
29
|
-
class Base
|
30
|
+
class Base < Kitchen::Plugin::Base
|
30
31
|
include Configurable
|
31
32
|
include Logging
|
32
33
|
include ShellOut
|
@@ -69,43 +70,6 @@ module Kitchen
|
|
69
70
|
false
|
70
71
|
end
|
71
72
|
|
72
|
-
class << self
|
73
|
-
# @return [Array<Symbol>] an array of action method names that cannot
|
74
|
-
# be run concurrently and must be run in serial via a shared mutex
|
75
|
-
attr_reader :serial_actions
|
76
|
-
end
|
77
|
-
|
78
|
-
# Registers certain driver actions that cannot be safely run concurrently
|
79
|
-
# in threads across multiple instances. Typically this might be used
|
80
|
-
# for create or destroy actions that use an underlying resource that
|
81
|
-
# cannot be used at the same time.
|
82
|
-
#
|
83
|
-
# A shared mutex for this driver object will be used to synchronize all
|
84
|
-
# registered methods.
|
85
|
-
#
|
86
|
-
# @example a single action method that cannot be run concurrently
|
87
|
-
#
|
88
|
-
# no_parallel_for :create
|
89
|
-
#
|
90
|
-
# @example multiple action methods that cannot be run concurrently
|
91
|
-
#
|
92
|
-
# no_parallel_for :create, :destroy
|
93
|
-
#
|
94
|
-
# @param methods [Array<Symbol>] one or more actions as symbols
|
95
|
-
# @raise [ClientError] if any method is not a valid action method name
|
96
|
-
def self.no_parallel_for(*methods)
|
97
|
-
action_methods = %i{create setup converge verify destroy}
|
98
|
-
|
99
|
-
Array(methods).each do |meth|
|
100
|
-
next if action_methods.include?(meth)
|
101
|
-
|
102
|
-
raise ClientError, "##{meth} is not a valid no_parallel_for method"
|
103
|
-
end
|
104
|
-
|
105
|
-
@serial_actions ||= []
|
106
|
-
@serial_actions += methods
|
107
|
-
end
|
108
|
-
|
109
73
|
# Sets the API version for this driver. If the driver does not set this
|
110
74
|
# value, then `nil` will be used and reported.
|
111
75
|
#
|
@@ -18,7 +18,8 @@
|
|
18
18
|
require "thor/util"
|
19
19
|
|
20
20
|
require_relative "../lazy_hash"
|
21
|
-
|
21
|
+
require_relative "../plugin_base"
|
22
|
+
require "benchmark" unless defined?(Benchmark)
|
22
23
|
|
23
24
|
module Kitchen
|
24
25
|
module Driver
|
@@ -42,7 +43,7 @@ module Kitchen
|
|
42
43
|
# Transport, and Verifier subsystems may not be picked up in these
|
43
44
|
# Drivers. When legacy Driver::SSHBase support is removed, this class
|
44
45
|
# will no longer be available.
|
45
|
-
class SSHBase
|
46
|
+
class SSHBase < Kitchen::Plugin::Base
|
46
47
|
include ShellOut
|
47
48
|
include Configurable
|
48
49
|
include Logging
|
@@ -179,43 +180,6 @@ module Kitchen
|
|
179
180
|
# documented dependency is missing from the system
|
180
181
|
def verify_dependencies; end
|
181
182
|
|
182
|
-
class << self
|
183
|
-
# @return [Array<Symbol>] an array of action method names that cannot
|
184
|
-
# be run concurrently and must be run in serial via a shared mutex
|
185
|
-
attr_reader :serial_actions
|
186
|
-
end
|
187
|
-
|
188
|
-
# Registers certain driver actions that cannot be safely run concurrently
|
189
|
-
# in threads across multiple instances. Typically this might be used
|
190
|
-
# for create or destroy actions that use an underlying resource that
|
191
|
-
# cannot be used at the same time.
|
192
|
-
#
|
193
|
-
# A shared mutex for this driver object will be used to synchronize all
|
194
|
-
# registered methods.
|
195
|
-
#
|
196
|
-
# @example a single action method that cannot be run concurrently
|
197
|
-
#
|
198
|
-
# no_parallel_for :create
|
199
|
-
#
|
200
|
-
# @example multiple action methods that cannot be run concurrently
|
201
|
-
#
|
202
|
-
# no_parallel_for :create, :destroy
|
203
|
-
#
|
204
|
-
# @param methods [Array<Symbol>] one or more actions as symbols
|
205
|
-
# @raise [ClientError] if any method is not a valid action method name
|
206
|
-
def self.no_parallel_for(*methods)
|
207
|
-
action_methods = %i{create converge setup verify destroy}
|
208
|
-
|
209
|
-
Array(methods).each do |meth|
|
210
|
-
next if action_methods.include?(meth)
|
211
|
-
|
212
|
-
raise ClientError, "##{meth} is not a valid no_parallel_for method"
|
213
|
-
end
|
214
|
-
|
215
|
-
@serial_actions ||= []
|
216
|
-
@serial_actions += methods
|
217
|
-
end
|
218
|
-
|
219
183
|
# Cache directory that a driver could implement to inform the provisioner
|
220
184
|
# that it can leverage it internally
|
221
185
|
#
|
data/lib/kitchen/instance.rb
CHANGED
@@ -15,8 +15,8 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
-
require "benchmark"
|
19
|
-
require "fileutils"
|
18
|
+
require "benchmark" unless defined?(Benchmark)
|
19
|
+
require "fileutils" unless defined?(FileUtils)
|
20
20
|
|
21
21
|
module Kitchen
|
22
22
|
# An instance of a suite running on a platform. A created instance may be a
|
@@ -28,7 +28,7 @@ module Kitchen
|
|
28
28
|
include Logging
|
29
29
|
|
30
30
|
class << self
|
31
|
-
# @return [Hash] a hash of
|
31
|
+
# @return [Hash] a hash of mutexes, arranged by Plugin class names
|
32
32
|
# @api private
|
33
33
|
attr_accessor :mutexes
|
34
34
|
|
@@ -322,21 +322,29 @@ module Kitchen
|
|
322
322
|
end
|
323
323
|
end
|
324
324
|
|
325
|
-
#
|
326
|
-
#
|
325
|
+
# If a plugin has declared via .no_parallel_for that it is not
|
326
|
+
# thread-safe for certain actions, create a mutex to track it.
|
327
327
|
#
|
328
|
+
# @param plugin_class[Class] Kitchen::Plugin::Base
|
328
329
|
# @api private
|
329
|
-
def
|
330
|
-
|
331
|
-
|
332
|
-
if driver.class.serial_actions
|
330
|
+
def setup_plugin_mutexes(plugin_class)
|
331
|
+
if plugin_class.serial_actions
|
333
332
|
Kitchen.mutex.synchronize do
|
334
333
|
self.class.mutexes ||= {}
|
335
|
-
self.class.mutexes[
|
334
|
+
self.class.mutexes[plugin_class] = Mutex.new
|
336
335
|
end
|
337
336
|
end
|
338
337
|
end
|
339
338
|
|
339
|
+
# Perform any final configuration or preparation needed for the driver
|
340
|
+
# object carry out its duties.
|
341
|
+
#
|
342
|
+
# @api private
|
343
|
+
def setup_driver
|
344
|
+
@driver.finalize_config!(self)
|
345
|
+
setup_plugin_mutexes(driver.class)
|
346
|
+
end
|
347
|
+
|
340
348
|
# Perform any final configuration or preparation needed for the lifecycle hooks
|
341
349
|
# object carry out its duties.
|
342
350
|
#
|
@@ -351,6 +359,7 @@ module Kitchen
|
|
351
359
|
# @api private
|
352
360
|
def setup_provisioner
|
353
361
|
@provisioner.finalize_config!(self)
|
362
|
+
setup_plugin_mutexes(provisioner.class)
|
354
363
|
end
|
355
364
|
|
356
365
|
# Perform any final configuration or preparation needed for the transport
|
@@ -359,6 +368,7 @@ module Kitchen
|
|
359
368
|
# @api private
|
360
369
|
def setup_transport
|
361
370
|
transport.finalize_config!(self)
|
371
|
+
setup_plugin_mutexes(transport.class)
|
362
372
|
end
|
363
373
|
|
364
374
|
# Perform any final configuration or preparation needed for the verifier
|
@@ -367,6 +377,7 @@ module Kitchen
|
|
367
377
|
# @api private
|
368
378
|
def setup_verifier
|
369
379
|
verifier.finalize_config!(self)
|
380
|
+
setup_plugin_mutexes(verifier.class)
|
370
381
|
end
|
371
382
|
|
372
383
|
# Perform all actions in order from last state to desired state.
|
@@ -541,10 +552,11 @@ module Kitchen
|
|
541
552
|
# @param block [Proc] a block to be called
|
542
553
|
# @api private
|
543
554
|
def synchronize_or_call(what, state)
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
555
|
+
plugin_class = plugin_class_for_action(what)
|
556
|
+
if Array(plugin_class.serial_actions).include?(what)
|
557
|
+
debug("#{to_str} is synchronizing on #{plugin_class}##{what}")
|
558
|
+
self.class.mutexes[plugin_class].synchronize do
|
559
|
+
debug("#{to_str} is messaging #{plugin_class}##{what}")
|
548
560
|
yield(state)
|
549
561
|
end
|
550
562
|
else
|
@@ -552,6 +564,21 @@ module Kitchen
|
|
552
564
|
end
|
553
565
|
end
|
554
566
|
|
567
|
+
# Maps the given action to the plugin class associated with the action
|
568
|
+
#
|
569
|
+
# @param what[Symbol] action
|
570
|
+
# @return [Class] Kitchen::Plugin::Base
|
571
|
+
# @api private
|
572
|
+
def plugin_class_for_action(what)
|
573
|
+
{
|
574
|
+
create: driver,
|
575
|
+
setup: transport,
|
576
|
+
converge: provisioner,
|
577
|
+
verify: verifier,
|
578
|
+
destroy: driver,
|
579
|
+
}[what].class
|
580
|
+
end
|
581
|
+
|
555
582
|
# Writes a high level message for logging and/or output.
|
556
583
|
#
|
557
584
|
# In this case, all instance banner messages will be written to the common
|
data/lib/kitchen/loader/yaml.rb
CHANGED
@@ -15,9 +15,9 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
-
require "erb"
|
18
|
+
require "erb" unless defined?(Erb)
|
19
19
|
require_relative "../../vendor/hash_recursive_merge"
|
20
|
-
require "yaml"
|
20
|
+
require "yaml" unless defined?(YAML)
|
21
21
|
|
22
22
|
module Kitchen
|
23
23
|
module Loader
|
data/lib/kitchen/logger.rb
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
3
|
+
#
|
4
|
+
# Copyright (C) 2014, Fletcher Nichol
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
module Kitchen
|
19
|
+
module Plugin
|
20
|
+
class Base
|
21
|
+
class << self
|
22
|
+
# @return [Array<Symbol>] an array of action method names that cannot
|
23
|
+
# be run concurrently and must be run in serial via a shared mutex
|
24
|
+
attr_reader :serial_actions
|
25
|
+
end
|
26
|
+
|
27
|
+
# Registers certain driver actions that cannot be safely run concurrently
|
28
|
+
# in threads across multiple instances. Typically this might be used
|
29
|
+
# for create or destroy actions that use an underlying resource that
|
30
|
+
# cannot be used at the same time.
|
31
|
+
#
|
32
|
+
# A shared mutex for this driver object will be used to synchronize all
|
33
|
+
# registered methods.
|
34
|
+
#
|
35
|
+
# @example a single action method that cannot be run concurrently
|
36
|
+
#
|
37
|
+
# no_parallel_for :create
|
38
|
+
#
|
39
|
+
# @example multiple action methods that cannot be run concurrently
|
40
|
+
#
|
41
|
+
# no_parallel_for :create, :destroy
|
42
|
+
#
|
43
|
+
# @param methods [Array<Symbol>] one or more actions as symbols
|
44
|
+
# @raise [ClientError] if any method is not a valid action method name
|
45
|
+
def self.no_parallel_for(*methods)
|
46
|
+
action_methods = %i{create setup converge verify destroy}
|
47
|
+
|
48
|
+
Array(methods).each do |meth|
|
49
|
+
next if action_methods.include?(meth)
|
50
|
+
|
51
|
+
raise ClientError, "##{meth} is not a valid no_parallel_for method"
|
52
|
+
end
|
53
|
+
|
54
|
+
@serial_actions ||= []
|
55
|
+
@serial_actions += methods
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -18,13 +18,14 @@
|
|
18
18
|
require_relative "../configurable"
|
19
19
|
require_relative "../errors"
|
20
20
|
require_relative "../logging"
|
21
|
+
require_relative "../plugin_base"
|
21
22
|
|
22
23
|
module Kitchen
|
23
24
|
module Provisioner
|
24
25
|
# Base class for a provisioner.
|
25
26
|
#
|
26
27
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
27
|
-
class Base
|
28
|
+
class Base < Kitchen::Plugin::Base
|
28
29
|
include Configurable
|
29
30
|
include Logging
|
30
31
|
|
@@ -15,8 +15,8 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
-
require "shellwords"
|
19
|
-
require "rbconfig"
|
18
|
+
require "shellwords" unless defined?(Shellwords)
|
19
|
+
require "rbconfig" unless defined?(RbConfig)
|
20
20
|
|
21
21
|
require_relative "../../errors"
|
22
22
|
require_relative "../../logging"
|
@@ -110,13 +110,13 @@ module Kitchen
|
|
110
110
|
# @return [String]
|
111
111
|
# @api private
|
112
112
|
def escape_path(path)
|
113
|
-
if RbConfig::CONFIG["host_os"]
|
113
|
+
if /mswin|mingw/.match?(RbConfig::CONFIG["host_os"])
|
114
114
|
# I know what you're thinking: "just use Shellwords.escape". That
|
115
115
|
# method produces incorrect results on Windows with certain input
|
116
116
|
# which would be a metacharacter in Sh but is not for one or more of
|
117
117
|
# Windows command line parsing libraries. This covers the 99% case of
|
118
118
|
# spaces in the path without breaking other stuff.
|
119
|
-
if
|
119
|
+
if /[ \t\n\v"]/.match?(path)
|
120
120
|
"\"#{path.gsub(/[ \t\n\v\"\\]/) { |m| '\\' + m[0] }}\""
|
121
121
|
else
|
122
122
|
path
|
@@ -136,7 +136,7 @@ module Kitchen
|
|
136
136
|
# @api private
|
137
137
|
def detect_chef_command!(logger)
|
138
138
|
unless ENV["PATH"].split(File::PATH_SEPARATOR).any? do |path|
|
139
|
-
if RbConfig::CONFIG["host_os"]
|
139
|
+
if /mswin|mingw/.match?(RbConfig::CONFIG["host_os"])
|
140
140
|
# Windows could have different extentions: BAT, EXE or NONE
|
141
141
|
%w{chef chef.exe chef.bat}.each do |bin|
|
142
142
|
File.exist?(File.join(path, bin))
|
@@ -146,7 +146,7 @@ module Kitchen
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
logger.fatal("The `chef` executable cannot be found in your " \
|
149
|
-
"PATH. Ensure you have installed
|
149
|
+
"PATH. Ensure you have installed Chef Workstation " \
|
150
150
|
"from https://downloads.chef.io and that your PATH " \
|
151
151
|
"setting includes the path to the `chef` command.")
|
152
152
|
raise UserError,
|
@@ -15,18 +15,18 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
-
require "fileutils"
|
19
|
-
require "pathname"
|
20
|
-
require "json"
|
21
|
-
require "cgi"
|
18
|
+
require "fileutils" unless defined?(FileUtils)
|
19
|
+
require "pathname" unless defined?(Pathname)
|
20
|
+
require "json" unless defined?(JSON)
|
21
|
+
require "cgi" unless defined?(CGI)
|
22
22
|
|
23
23
|
require_relative "chef/policyfile"
|
24
24
|
require_relative "chef/berkshelf"
|
25
25
|
require_relative "chef/common_sandbox"
|
26
26
|
require_relative "../util"
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
module LicenseAcceptance
|
28
|
+
autoload :Acceptor, "license_acceptance/acceptor"
|
29
|
+
end
|
30
30
|
|
31
31
|
begin
|
32
32
|
require "chef-config/config"
|
@@ -156,7 +156,7 @@ module Kitchen
|
|
156
156
|
product_name: <chef or chef-workstation>
|
157
157
|
install_strategy: skip
|
158
158
|
MSG
|
159
|
-
when provisioner[:require_chef_omnibus].to_s.match(/\d/)
|
159
|
+
when provisioner[:require_chef_omnibus].to_s.match?(/\d/)
|
160
160
|
Util.outdent!(<<-MSG)
|
161
161
|
The 'require_chef_omnibus' attribute with version values will change
|
162
162
|
to use the new 'product_version' attribute.
|
@@ -503,6 +503,7 @@ module Kitchen
|
|
503
503
|
# @return [String] contents of product based install script
|
504
504
|
# @api private
|
505
505
|
def script_for_product
|
506
|
+
require "mixlib/install"
|
506
507
|
installer = Mixlib::Install.new({
|
507
508
|
product_name: config[:product_name],
|
508
509
|
product_version: config[:product_version],
|
@@ -576,6 +577,7 @@ module Kitchen
|
|
576
577
|
# @return [String] contents of version based install script
|
577
578
|
# @api private
|
578
579
|
def script_for_omnibus_version
|
580
|
+
require "mixlib/install/script_generator"
|
579
581
|
installer = Mixlib::Install::ScriptGenerator.new(
|
580
582
|
config[:require_chef_omnibus], powershell_shell?, install_options
|
581
583
|
)
|
@@ -27,6 +27,10 @@ module Kitchen
|
|
27
27
|
|
28
28
|
plugin_version Kitchen::VERSION
|
29
29
|
|
30
|
+
# ChefSolo is dependent on Berkshelf, which is not thread-safe.
|
31
|
+
# See discussion on https://github.com/test-kitchen/test-kitchen/issues/1307
|
32
|
+
no_parallel_for :converge
|
33
|
+
|
30
34
|
default_config :solo_rb, {}
|
31
35
|
|
32
36
|
default_config :chef_solo_path do |provisioner|
|
data/lib/kitchen/shell_out.rb
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
-
require "mixlib/shellout"
|
18
|
+
require "mixlib/shellout" unless defined?(Mixlib::ShellOut)
|
19
19
|
|
20
20
|
module Kitchen
|
21
21
|
# Mixin that wraps a command shell out invocation, providing a #run_command
|
data/lib/kitchen/ssh.rb
CHANGED
@@ -16,9 +16,10 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
18
|
require "logger"
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
module Net
|
20
|
+
autoload :SSH, "net/ssh"
|
21
|
+
end
|
22
|
+
require "socket" unless defined?(Socket)
|
22
23
|
|
23
24
|
require_relative "errors"
|
24
25
|
require_relative "login_command"
|
@@ -90,6 +91,7 @@ module Kitchen
|
|
90
91
|
# `Net::SCP.upload`
|
91
92
|
# @see http://net-ssh.github.io/net-scp/classes/Net/SCP.html#method-i-upload
|
92
93
|
def upload!(local, remote, options = {}, &progress)
|
94
|
+
require "net/scp" unless defined?(Net::SCP)
|
93
95
|
if progress.nil?
|
94
96
|
progress = lambda do |_ch, name, sent, total|
|
95
97
|
logger.debug("Uploaded #{name} (#{total} bytes)") if sent == total
|
@@ -100,6 +102,7 @@ module Kitchen
|
|
100
102
|
end
|
101
103
|
|
102
104
|
def upload(local, remote, options = {}, &progress)
|
105
|
+
require "net/scp" unless defined?(Net::SCP)
|
103
106
|
if progress.nil?
|
104
107
|
progress = lambda do |_ch, name, sent, total|
|
105
108
|
if sent == total
|
data/lib/kitchen/state_file.rb
CHANGED
data/lib/kitchen/thor_tasks.rb
CHANGED
@@ -21,6 +21,7 @@ require_relative "../errors"
|
|
21
21
|
require_relative "../lazy_hash"
|
22
22
|
require_relative "../logging"
|
23
23
|
require_relative "../login_command"
|
24
|
+
require_relative "../plugin_base"
|
24
25
|
|
25
26
|
module Kitchen
|
26
27
|
module Transport
|
@@ -40,7 +41,7 @@ module Kitchen
|
|
40
41
|
#
|
41
42
|
# @author Salim Afiune <salim@afiunemaya.com.mx>
|
42
43
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
43
|
-
class Base
|
44
|
+
class Base < Kitchen::Plugin::Base
|
44
45
|
include Configurable
|
45
46
|
include Logging
|
46
47
|
|
@@ -11,7 +11,7 @@
|
|
11
11
|
# See the License for the specific language governing permissions and
|
12
12
|
# limitations under the License.
|
13
13
|
|
14
|
-
require "fileutils"
|
14
|
+
require "fileutils" unless defined?(FileUtils)
|
15
15
|
|
16
16
|
require_relative "../shell_out"
|
17
17
|
require_relative "base"
|
@@ -28,7 +28,7 @@ module Kitchen
|
|
28
28
|
plugin_version Kitchen::VERSION
|
29
29
|
|
30
30
|
def connection(state, &block)
|
31
|
-
options = config.to_hash.merge(state)
|
31
|
+
options = connection_options(config.to_hash.merge(state))
|
32
32
|
Kitchen::Transport::Exec::Connection.new(options, &block)
|
33
33
|
end
|
34
34
|
|
@@ -40,19 +40,105 @@ module Kitchen
|
|
40
40
|
def execute(command)
|
41
41
|
return if command.nil?
|
42
42
|
|
43
|
-
|
43
|
+
if host_os_windows?
|
44
|
+
run_command(run_from_file_command(command))
|
45
|
+
close
|
46
|
+
else
|
47
|
+
run_command(command)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def close
|
52
|
+
if host_os_windows?
|
53
|
+
FileUtils.remove(exec_script_file)
|
54
|
+
end
|
44
55
|
end
|
45
56
|
|
46
57
|
# "Upload" the files by copying them locally.
|
47
58
|
#
|
48
59
|
# @see Base#upload
|
49
60
|
def upload(locals, remote)
|
50
|
-
|
61
|
+
# evaluate $env:temp on Windows
|
62
|
+
real_remote = remote.to_s == "\$env:TEMP\\kitchen" ? kitchen_temp : remote
|
63
|
+
FileUtils.mkdir_p(real_remote)
|
51
64
|
Array(locals).each do |local|
|
52
|
-
FileUtils.cp_r(local,
|
65
|
+
FileUtils.cp_r(local, real_remote)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# (see Base#init_options)
|
70
|
+
def init_options(options)
|
71
|
+
super
|
72
|
+
@instance_name = @options.delete(:instance_name)
|
73
|
+
@kitchen_root = @options.delete(:kitchen_root)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
# @return [String] display name for the associated instance
|
79
|
+
# @api private
|
80
|
+
attr_reader :instance_name
|
81
|
+
|
82
|
+
# @return [String] local path to the root of the project
|
83
|
+
# @api private
|
84
|
+
attr_reader :kitchen_root
|
85
|
+
|
86
|
+
# Takes a long command and saves it to a file and uploads it to
|
87
|
+
# the test instance. Windows has cli character limits.
|
88
|
+
#
|
89
|
+
# @param command [String] a long command to be saved and uploaded
|
90
|
+
# @return [String] a command that executes the uploaded script
|
91
|
+
# @api private
|
92
|
+
def run_from_file_command(command)
|
93
|
+
if logger.debug?
|
94
|
+
debug("Creating exec script for #{instance_name} (#{exec_script_file})")
|
95
|
+
debug("Executing #{exec_script_file}")
|
96
|
+
end
|
97
|
+
File.open(exec_script_file, "wb") { |file| file.write(command) }
|
98
|
+
%{powershell -file "#{exec_script_file}"}
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [String] evaluated $env:temp variable
|
102
|
+
# @api private
|
103
|
+
def kitchen_temp
|
104
|
+
"#{ENV["temp"]}/kitchen"
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [String] name of script using instance name
|
108
|
+
# @api private
|
109
|
+
def exec_script_name
|
110
|
+
"#{instance_name}-exec-script.ps1"
|
111
|
+
end
|
112
|
+
|
113
|
+
# @return [String] file path for exec script to be run
|
114
|
+
# @api private
|
115
|
+
def exec_script_file
|
116
|
+
File.join(kitchen_root, ".kitchen", exec_script_name)
|
117
|
+
end
|
118
|
+
|
119
|
+
def host_os_windows?
|
120
|
+
case RbConfig::CONFIG["host_os"]
|
121
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
122
|
+
true
|
123
|
+
else
|
124
|
+
false
|
53
125
|
end
|
54
126
|
end
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
55
130
|
|
131
|
+
# Builds the hash of options needed by the Connection object on construction.
|
132
|
+
#
|
133
|
+
# @param data [Hash] merged configuration and mutable state data
|
134
|
+
# @return [Hash] hash of connection options
|
135
|
+
# @api private
|
136
|
+
def connection_options(data)
|
137
|
+
opts = {
|
138
|
+
instance_name: instance.name,
|
139
|
+
kitchen_root: Dir.pwd,
|
140
|
+
}
|
141
|
+
opts
|
56
142
|
end
|
57
143
|
end
|
58
144
|
end
|
@@ -17,13 +17,13 @@
|
|
17
17
|
|
18
18
|
require_relative "../../kitchen"
|
19
19
|
|
20
|
-
require "fileutils"
|
21
|
-
require "net/ssh"
|
20
|
+
require "fileutils" unless defined?(FileUtils)
|
21
|
+
require "net/ssh" unless defined?(Net::SSH)
|
22
22
|
require "net/ssh/gateway"
|
23
23
|
require "net/ssh/proxy/http"
|
24
24
|
require "net/scp"
|
25
|
-
require "timeout"
|
26
|
-
require "benchmark"
|
25
|
+
require "timeout" unless defined?(Timeout)
|
26
|
+
require "benchmark" unless defined?(Benchmark)
|
27
27
|
|
28
28
|
module Kitchen
|
29
29
|
module Transport
|
@@ -17,10 +17,10 @@
|
|
17
17
|
# See the License for the specific language governing permissions and
|
18
18
|
# limitations under the License.
|
19
19
|
|
20
|
-
require "rbconfig"
|
21
|
-
require "uri"
|
20
|
+
require "rbconfig" unless defined?(RbConfig)
|
21
|
+
require "uri" unless defined?(URI)
|
22
22
|
require_relative "../../kitchen"
|
23
|
-
require "winrm"
|
23
|
+
require "winrm" unless defined?(WinRM::Connection)
|
24
24
|
|
25
25
|
module Kitchen
|
26
26
|
module Transport
|
@@ -308,16 +308,20 @@ module Kitchen
|
|
308
308
|
|
309
309
|
# Builds a `LoginCommand` for use by Linux-based platforms.
|
310
310
|
#
|
311
|
-
# TODO: determine whether or not `desktop` exists
|
312
|
-
#
|
313
311
|
# @return [LoginCommand] a login command
|
314
312
|
# @api private
|
315
313
|
def login_command_for_linux
|
316
|
-
|
317
|
-
|
318
|
-
|
314
|
+
xfreerdp = Util.command_exists? "xfreerdp"
|
315
|
+
unless xfreerdp
|
316
|
+
raise WinrmFailed, "xfreerdp binary not found. Please install freerdp2-x11 on Debian-based systems or freerdp on Redhat-based systems."
|
317
|
+
end
|
318
|
+
|
319
|
+
args = %W{/u:#{options[:user]}}
|
320
|
+
args += %W{/p:#{options[:password]}} if options.key?(:password)
|
321
|
+
args += %W{/v:#{URI.parse(options[:endpoint]).host}:#{rdp_port}}
|
322
|
+
args += %W{/cert-tofu} # always accept certificate
|
319
323
|
|
320
|
-
LoginCommand.new(
|
324
|
+
LoginCommand.new(xfreerdp, args)
|
321
325
|
end
|
322
326
|
|
323
327
|
# Builds a `LoginCommand` for use by Mac-based platforms.
|
data/lib/kitchen/util.rb
CHANGED
@@ -110,7 +110,7 @@ module Kitchen
|
|
110
110
|
def self.wrap_command(cmd)
|
111
111
|
cmd = "false" if cmd.nil?
|
112
112
|
cmd = "true" if cmd.to_s.empty?
|
113
|
-
cmd = cmd.sub(/\n\Z/, "") if
|
113
|
+
cmd = cmd.sub(/\n\Z/, "") if /\n\Z/.match?(cmd)
|
114
114
|
|
115
115
|
"sh -c '\n#{cmd}\n'"
|
116
116
|
end
|
@@ -215,5 +215,15 @@ module Kitchen
|
|
215
215
|
def self.snake_case(a_string)
|
216
216
|
Thor::Util.snake_case(a_string)
|
217
217
|
end
|
218
|
+
|
219
|
+
# Check if a cmd exists on the PATH
|
220
|
+
def self.command_exists?(cmd)
|
221
|
+
paths = ENV["PATH"].split(File::PATH_SEPARATOR) + [ "/bin", "/usr/bin", "/sbin", "/usr/sbin" ]
|
222
|
+
paths.each do |path|
|
223
|
+
filename = File.join(path, cmd)
|
224
|
+
return filename if File.executable?(filename)
|
225
|
+
end
|
226
|
+
false
|
227
|
+
end
|
218
228
|
end
|
219
229
|
end
|
@@ -18,13 +18,14 @@
|
|
18
18
|
require_relative "../errors"
|
19
19
|
require_relative "../configurable"
|
20
20
|
require_relative "../logging"
|
21
|
+
require_relative "../plugin_base"
|
21
22
|
|
22
23
|
module Kitchen
|
23
24
|
module Verifier
|
24
25
|
# Base class for a verifier.
|
25
26
|
#
|
26
27
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
27
|
-
class Base
|
28
|
+
class Base < Kitchen::Plugin::Base
|
28
29
|
include Configurable
|
29
30
|
include Logging
|
30
31
|
|
@@ -15,8 +15,8 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
-
require "base64"
|
19
|
-
require "digest"
|
18
|
+
require "base64" unless defined?(Base64)
|
19
|
+
require "digest" unless defined?(Digest)
|
20
20
|
|
21
21
|
require_relative "base"
|
22
22
|
|
@@ -168,7 +168,7 @@ module Kitchen
|
|
168
168
|
# @api private
|
169
169
|
def gem_install_args
|
170
170
|
gem, version = config[:version].split("@")
|
171
|
-
if
|
171
|
+
if /^\d+\.\d+\.\d+/.match?(gem)
|
172
172
|
version = gem
|
173
173
|
gem = "busser"
|
174
174
|
end
|
data/lib/kitchen/version.rb
CHANGED
data/test-kitchen.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test-kitchen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fletcher Nichol
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mixlib-shellout
|
@@ -423,6 +423,7 @@ files:
|
|
423
423
|
- lib/kitchen/metadata_chopper.rb
|
424
424
|
- lib/kitchen/platform.rb
|
425
425
|
- lib/kitchen/plugin.rb
|
426
|
+
- lib/kitchen/plugin_base.rb
|
426
427
|
- lib/kitchen/provisioner.rb
|
427
428
|
- lib/kitchen/provisioner/base.rb
|
428
429
|
- lib/kitchen/provisioner/chef/berkshelf.rb
|
@@ -499,7 +500,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
499
500
|
- !ruby/object:Gem::Version
|
500
501
|
version: '0'
|
501
502
|
requirements: []
|
502
|
-
rubygems_version: 3.1.
|
503
|
+
rubygems_version: 3.1.4
|
503
504
|
signing_key:
|
504
505
|
specification_version: 4
|
505
506
|
summary: Test Kitchen is an integration tool for developing and testing infrastructure
|