test-kitchen 2.9.0 → 2.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58365d9f59d1210a1c8f56f7fe095f285fde61e6251c61b164569b783d75d6f8
4
- data.tar.gz: ceef4069cb15be71c35992173d3d347717f8149dc3a7fe2f4863e5a8aaac98c5
3
+ metadata.gz: 51ed51940914e0c4ffb30d1e11be2e3554289833261e0b418eaa2ebdb674cab9
4
+ data.tar.gz: c3c9be7593e1c0c333102168228c84e217244c5071da0bfb2ba543edca7581ba
5
5
  SHA512:
6
- metadata.gz: bf9e9206b2b78a39fa9fdeca2104e3cf17fed69821644f0055e7638e23a15f50dc11c9923718e5cb997d9a2ef416bbe2e48649fc6d6e7c02fd8627fbbe86f6b1
7
- data.tar.gz: 86102634d2ad1b336cd5e18fdfe005ea7ef18f77e185351f041567aeb32b224609e457ca6904ea865bb18f278e836fdca4ae9afedff1877dd71564ed17d54d1b
6
+ metadata.gz: 59633a6df2c274542ee3d4c649c55f8632077a98476ee655a1f59c0b39d42fad9077294b0e615d8e7f697feef4cbb027a9df7be81708832760d45eee72fbf159
7
+ data.tar.gz: 34164cc7046bb2aa507fa33373c928d94be84284a99ba629562c585614c1818d032a42a1b2b83ab0b95382e984841be63a2dc32a05412dbf8d60a15839325146
@@ -162,7 +162,7 @@ module Kitchen
162
162
  long_desc <<-DESC
163
163
  The instance states are in order: destroy, create, converge, setup, verify, destroy.
164
164
  Change one or more instances from the current state to the #{action} state. Actions for all
165
- intermediate states will be executed. See http://kitchen.ci for further explanation.
165
+ intermediate states will be executed. See https://kitchen.ci/ for further explanation.
166
166
  DESC
167
167
  method_option :concurrency,
168
168
  aliases: "-c",
@@ -244,16 +244,18 @@ module Kitchen
244
244
  # @return [Instance] a new Instance object
245
245
  # @api private
246
246
  def new_instance(suite, platform, index)
247
+ sf = new_state_file(suite, platform)
248
+
247
249
  Instance.new(
248
250
  driver: new_driver(suite, platform),
249
- lifecycle_hooks: new_lifecycle_hooks(suite, platform),
251
+ lifecycle_hooks: new_lifecycle_hooks(suite, platform, sf),
250
252
  logger: new_instance_logger(suite, platform, index),
251
253
  suite: suite,
252
254
  platform: platform,
253
255
  provisioner: new_provisioner(suite, platform),
254
256
  transport: new_transport(suite, platform),
255
257
  verifier: new_verifier(suite, platform),
256
- state_file: new_state_file(suite, platform)
258
+ state_file: sf
257
259
  )
258
260
  end
259
261
 
@@ -284,11 +286,12 @@ module Kitchen
284
286
  #
285
287
  # @param suite [Suite,#name] a Suite
286
288
  # @param platform [Platform,#name] a Platform
289
+ # @param state_file [Kitchen::StateFile] a SateFile
287
290
  # @return [LifecycleHooks] a new LifecycleHooks object
288
291
  # @api private
289
- def new_lifecycle_hooks(suite, platform)
292
+ def new_lifecycle_hooks(suite, platform, state_file)
290
293
  lhdata = data.lifecycle_hooks_data_for(suite.name, platform.name)
291
- LifecycleHooks.new(lhdata)
294
+ LifecycleHooks.new(lhdata, state_file)
292
295
  end
293
296
 
294
297
  # Builds a newly configured Provisioner object, for a given Suite and
@@ -0,0 +1,78 @@
1
+ module Kitchen
2
+ class LifecycleHook
3
+ class Base
4
+ # @return [Kitchen::LifecycleHooks]
5
+ attr_reader :lifecycle_hooks
6
+
7
+ # return [String]
8
+ attr_reader :phase
9
+
10
+ # return [Hash]
11
+ attr_reader :hook
12
+
13
+ # @param lifecycle_hooks [Kitchen::LifecycleHooks]
14
+ # @param phase [String]
15
+ # @param hook [Hash]
16
+ def initialize(lifecycle_hooks, phase, hook)
17
+ @lifecycle_hooks = lifecycle_hooks
18
+ @phase = phase
19
+ @hook = hook
20
+ end
21
+
22
+ # return [void]
23
+ def run
24
+ raise NotImplementedError
25
+ end
26
+
27
+ # @return [TrueClass, FalseClass]
28
+ def should_run?
29
+ if !includes.empty?
30
+ includes.include?(platform_name)
31
+ elsif !excludes.empty?
32
+ !excludes.include?(platform_name)
33
+ else
34
+ true
35
+ end
36
+ end
37
+
38
+ # @return [Logger] the lifecycle hooks's logger
39
+ # otherwise
40
+ # @api private
41
+ def logger
42
+ lifecycle_hooks.send(:logger)
43
+ end
44
+
45
+ private
46
+
47
+ # @return [Kitchen::Instance]
48
+ def instance
49
+ lifecycle_hooks.instance
50
+ end
51
+
52
+ # @return [Hash]
53
+ def config
54
+ lifecycle_hooks.send(:config)
55
+ end
56
+
57
+ # @return [Kitchen::StateFile]
58
+ def state_file
59
+ lifecycle_hooks.state_file
60
+ end
61
+
62
+ # @return [Array<String>] names of excluded platforms
63
+ def excludes
64
+ @excludes ||= hook.fetch(:excludes, [])
65
+ end
66
+
67
+ # @return [Array<String>] names of only included platforms
68
+ def includes
69
+ @includes ||= hook.fetch(:includes, [])
70
+ end
71
+
72
+ # @return [String]
73
+ def platform_name
74
+ instance.platform.name
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,53 @@
1
+ require_relative "base"
2
+ require_relative "../shell_out"
3
+ require_relative "../logging"
4
+
5
+ module Kitchen
6
+ class LifecycleHook
7
+ class Local < Base
8
+ include ShellOut
9
+ include Logging
10
+
11
+ # Execute a specific local command hook.
12
+ #
13
+ # @return [void]
14
+ def run
15
+ state = state_file.read
16
+ # set up empty user variable
17
+ user = {}
18
+ # Set up some environment variables with instance info.
19
+ environment = {
20
+ "KITCHEN_INSTANCE_NAME" => instance.name,
21
+ "KITCHEN_SUITE_NAME" => instance.suite.name,
22
+ "KITCHEN_PLATFORM_NAME" => instance.platform.name,
23
+ "KITCHEN_INSTANCE_HOSTNAME" => state[:hostname].to_s,
24
+ }
25
+ # If the user specified env vars too, fix them up because symbol keys
26
+ # make mixlib-shellout sad.
27
+ hook[:environment]&.each do |k, v|
28
+ environment[k.to_s] = v.to_s
29
+ end
30
+
31
+ # add user to user hash for later merging
32
+ user[:user] = hook[:user] if hook[:user]
33
+
34
+ # Default the cwd to the kitchen root and resolve a relative input cwd against that.
35
+ cwd = if hook[:cwd]
36
+ File.expand_path(hook[:cwd], config[:kitchen_root])
37
+ else
38
+ config[:kitchen_root]
39
+ end
40
+ # Build the options for mixlib-shellout.
41
+ opts = {}.merge(user).merge(cwd: cwd, environment: environment)
42
+ run_command(command, opts)
43
+ end
44
+
45
+ private
46
+
47
+ # @return [String]
48
+ def command
49
+ hook.fetch(:local)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,33 @@
1
+ require_relative "base"
2
+ require_relative "../errors"
3
+
4
+ module Kitchen
5
+ class LifecycleHook
6
+ class Remote < Base
7
+ # Execute a specific remote command hook.
8
+ #
9
+ # @return [void]
10
+ def run
11
+ # Check if we're in a state that makes sense to even try.
12
+ unless instance.last_action
13
+ if hook[:skippable]
14
+ # Just not even trying.
15
+ return
16
+ else
17
+ raise UserError, "Cannot use remote lifecycle hooks during phases when the instance is not available"
18
+ end
19
+ end
20
+
21
+ conn = instance.transport.connection(state_file.read)
22
+ conn.execute(command)
23
+ end
24
+
25
+ private
26
+
27
+ # return [String]
28
+ def command
29
+ hook.fetch(:remote)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -15,8 +15,11 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
+ require_relative "configurable"
18
19
  require_relative "errors"
19
- require_relative "shell_out"
20
+ require_relative "lifecycle_hook/local"
21
+ require_relative "lifecycle_hook/remote"
22
+ require_relative "logging"
20
23
 
21
24
  module Kitchen
22
25
  # A helper object used by {Instance} to coordinate lifecycle hook calls from
@@ -27,10 +30,10 @@ module Kitchen
27
30
  class LifecycleHooks
28
31
  include Configurable
29
32
  include Logging
30
- include ShellOut
31
33
 
32
- def initialize(config)
34
+ def initialize(config, state_file)
33
35
  init_config(config)
36
+ @state_file = state_file
34
37
  end
35
38
 
36
39
  # Run a lifecycle phase with the pre and post hooks.
@@ -40,21 +43,22 @@ module Kitchen
40
43
  # @param block [Proc] Block of code implementing the lifecycle phase.
41
44
  # @return [void]
42
45
  def run_with_hooks(phase, state_file, &block)
43
- run(instance, phase, state_file, :pre)
46
+ run(phase, :pre)
44
47
  yield
45
- run(instance, phase, state_file, :post)
48
+ run(phase, :post)
46
49
  end
47
50
 
51
+ # @return [Kitchen::StateFile]
52
+ attr_reader :state_file
53
+
48
54
  private
49
55
 
50
56
  # Execute a specific lifecycle hook.
51
57
  #
52
- # @param instance [Instance] The instance object to run against.
53
58
  # @param phase [String] Lifecycle phase which is being executed.
54
- # @param state_file [StateFile] Instance state file object.
55
59
  # @param hook_timing [Symbol] `:pre` or `:post` to indicate which hook to run.
56
60
  # @return [void]
57
- def run(instance, phase, state_file, hook_timing)
61
+ def run(phase, hook_timing)
58
62
  # Yes this has to be a symbol because of how data munger works.
59
63
  hook_key = :"#{hook_timing}_#{phase}"
60
64
  # No hooks? We're outta here.
@@ -65,80 +69,24 @@ module Kitchen
65
69
  # Coerce the common case of a bare string to be a local command. This
66
70
  # is to match the behavior of the old `pre_create_command` semi-hook.
67
71
  hook = { local: hook } if hook.is_a?(String)
68
- if hook.include?(:local)
69
- # Local command execution on the workstation.
70
- run_local_hook(instance, state_file, hook)
71
- elsif hook.include?(:remote)
72
- # Remote command execution on the test instance.
73
- run_remote_hook(instance, state_file, hook)
74
- else
75
- raise UserError, "Unknown lifecycle hook target #{hook.inspect}"
76
- end
72
+ hook = generate_hook(phase, hook)
73
+ hook.run if hook.should_run?
77
74
  end
78
75
  end
79
76
 
80
- # Execute a specific local command hook.
81
- #
82
- # @param instance [Instance] The instance object to run against.
83
- # @param state_file [StateFile] Instance state file object.
84
- # @param hook [Hash] Hook configration to use.
85
- # @return [void]
86
- def run_local_hook(instance, state_file, hook)
87
- cmd = hook.fetch(:local)
88
- state = state_file.read
89
- # set up empty user variable
90
- user = {}
91
- # Set up some environment variables with instance info.
92
- environment = {
93
- "KITCHEN_INSTANCE_NAME" => instance.name,
94
- "KITCHEN_SUITE_NAME" => instance.suite.name,
95
- "KITCHEN_PLATFORM_NAME" => instance.platform.name,
96
- "KITCHEN_INSTANCE_HOSTNAME" => state[:hostname].to_s,
97
- }
98
- # If the user specified env vars too, fix them up because symbol keys
99
- # make mixlib-shellout sad.
100
- if hook[:environment]
101
- hook[:environment].each do |k, v|
102
- environment[k.to_s] = v.to_s
103
- end
104
- end
105
-
106
- # add user to user hash for later merging
107
- if hook[:user]
108
- user[:user] = hook[:user]
77
+ # @param phase [String]
78
+ # @param hook [Hash]
79
+ # @return [Kitchen::LifecycleHook::Local, Kitchen::LifecycleHook::Remote]
80
+ def generate_hook(phase, hook)
81
+ if hook.include?(:local)
82
+ # Local command execution on the workstation.
83
+ Kitchen::LifecycleHook::Local.new(self, phase, hook)
84
+ elsif hook.include?(:remote)
85
+ # Remote command execution on the test instance.
86
+ Kitchen::LifecycleHook::Remote.new(self, phase, hook)
87
+ else
88
+ raise UserError, "Unknown lifecycle hook target #{hook.inspect}"
109
89
  end
110
-
111
- # Default the cwd to the kitchen root and resolve a relative input cwd against that.
112
- cwd = if hook[:cwd]
113
- File.expand_path(hook[:cwd], config[:kitchen_root])
114
- else
115
- config[:kitchen_root]
116
- end
117
- # Build the options for mixlib-shellout.
118
- opts = {}.merge(user).merge(cwd: cwd, environment: environment)
119
- run_command(cmd, opts)
120
- end
121
-
122
- # Execute a specific remote command hook.
123
- #
124
- # @param instance [Instance] The instance object to run against.
125
- # @param state_file [StateFile] Instance state file object.
126
- # @param hook [Hash] Hook configration to use.
127
- # @return [void]
128
- def run_remote_hook(instance, state_file, hook)
129
- # Check if we're in a state that makes sense to even try.
130
- unless instance.last_action
131
- if hook[:skippable]
132
- # Just not even trying.
133
- return
134
- else
135
- raise UserError, "Cannot use remote lifecycle hooks during phases when the instance is not available"
136
- end
137
- end
138
-
139
- cmd = hook.fetch(:remote)
140
- conn = instance.transport.connection(state_file.read)
141
- conn.execute(cmd)
142
90
  end
143
91
  end
144
92
  end
@@ -17,6 +17,7 @@
17
17
 
18
18
  require "erb" unless defined?(Erb)
19
19
  require_relative "../../vendor/hash_recursive_merge"
20
+ require "psych" unless defined?(Psych)
20
21
  require "yaml" unless defined?(YAML)
21
22
 
22
23
  module Kitchen
@@ -51,6 +51,7 @@ module Kitchen
51
51
 
52
52
  default_config :command_prefix, nil
53
53
 
54
+ default_config :uploads, {}
54
55
  default_config :downloads, {}
55
56
 
56
57
  expand_path_for :test_base_path
@@ -72,6 +73,10 @@ module Kitchen
72
73
  sandbox_dirs = Util.list_directory(sandbox_path)
73
74
 
74
75
  instance.transport.connection(state) do |conn|
76
+ config[:uploads].to_h.each do |locals, remote|
77
+ debug("Uploading #{Array(locals).join(', ')} to #{remote}")
78
+ conn.upload(locals.to_s, remote)
79
+ end
75
80
  conn.execute(install_command)
76
81
  conn.execute(init_command)
77
82
  info("Transferring files to #{instance.to_str}")
@@ -16,5 +16,5 @@
16
16
  # limitations under the License.
17
17
 
18
18
  module Kitchen
19
- VERSION = "2.9.0".freeze
19
+ VERSION = "2.10.0".freeze
20
20
  end
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.9.0
4
+ version: 2.10.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-12-23 00:00:00.000000000 Z
11
+ date: 2021-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-shellout
@@ -415,6 +415,9 @@ files:
415
415
  - lib/kitchen/generator/init.rb
416
416
  - lib/kitchen/instance.rb
417
417
  - lib/kitchen/lazy_hash.rb
418
+ - lib/kitchen/lifecycle_hook/base.rb
419
+ - lib/kitchen/lifecycle_hook/local.rb
420
+ - lib/kitchen/lifecycle_hook/remote.rb
418
421
  - lib/kitchen/lifecycle_hooks.rb
419
422
  - lib/kitchen/loader/yaml.rb
420
423
  - lib/kitchen/logger.rb