test-kitchen-rsync 3.0.0.pre.1

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.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +21 -0
  3. data/LICENSE +15 -0
  4. data/Rakefile +53 -0
  5. data/bin/zl-kitchen +11 -0
  6. data/lib/kitchen/base64_stream.rb +48 -0
  7. data/lib/kitchen/chef_utils_wiring.rb +40 -0
  8. data/lib/kitchen/cli.rb +413 -0
  9. data/lib/kitchen/collection.rb +52 -0
  10. data/lib/kitchen/color.rb +63 -0
  11. data/lib/kitchen/command/action.rb +41 -0
  12. data/lib/kitchen/command/console.rb +54 -0
  13. data/lib/kitchen/command/diagnose.rb +84 -0
  14. data/lib/kitchen/command/doctor.rb +39 -0
  15. data/lib/kitchen/command/exec.rb +37 -0
  16. data/lib/kitchen/command/list.rb +148 -0
  17. data/lib/kitchen/command/login.rb +39 -0
  18. data/lib/kitchen/command/package.rb +32 -0
  19. data/lib/kitchen/command/sink.rb +50 -0
  20. data/lib/kitchen/command/test.rb +47 -0
  21. data/lib/kitchen/command.rb +207 -0
  22. data/lib/kitchen/config.rb +344 -0
  23. data/lib/kitchen/configurable.rb +616 -0
  24. data/lib/kitchen/data_munger.rb +1024 -0
  25. data/lib/kitchen/diagnostic.rb +138 -0
  26. data/lib/kitchen/driver/base.rb +133 -0
  27. data/lib/kitchen/driver/dummy.rb +105 -0
  28. data/lib/kitchen/driver/exec.rb +70 -0
  29. data/lib/kitchen/driver/proxy.rb +70 -0
  30. data/lib/kitchen/driver/ssh_base.rb +351 -0
  31. data/lib/kitchen/driver.rb +40 -0
  32. data/lib/kitchen/errors.rb +243 -0
  33. data/lib/kitchen/generator/init.rb +254 -0
  34. data/lib/kitchen/instance.rb +726 -0
  35. data/lib/kitchen/lazy_hash.rb +148 -0
  36. data/lib/kitchen/lifecycle_hook/base.rb +78 -0
  37. data/lib/kitchen/lifecycle_hook/local.rb +53 -0
  38. data/lib/kitchen/lifecycle_hook/remote.rb +39 -0
  39. data/lib/kitchen/lifecycle_hooks.rb +92 -0
  40. data/lib/kitchen/loader/yaml.rb +377 -0
  41. data/lib/kitchen/logger.rb +422 -0
  42. data/lib/kitchen/logging.rb +52 -0
  43. data/lib/kitchen/login_command.rb +49 -0
  44. data/lib/kitchen/metadata_chopper.rb +49 -0
  45. data/lib/kitchen/platform.rb +64 -0
  46. data/lib/kitchen/plugin.rb +76 -0
  47. data/lib/kitchen/plugin_base.rb +60 -0
  48. data/lib/kitchen/provisioner/base.rb +269 -0
  49. data/lib/kitchen/provisioner/chef/berkshelf.rb +116 -0
  50. data/lib/kitchen/provisioner/chef/common_sandbox.rb +350 -0
  51. data/lib/kitchen/provisioner/chef/policyfile.rb +163 -0
  52. data/lib/kitchen/provisioner/chef_apply.rb +121 -0
  53. data/lib/kitchen/provisioner/chef_base.rb +705 -0
  54. data/lib/kitchen/provisioner/chef_infra.rb +167 -0
  55. data/lib/kitchen/provisioner/chef_solo.rb +82 -0
  56. data/lib/kitchen/provisioner/chef_zero.rb +12 -0
  57. data/lib/kitchen/provisioner/dummy.rb +75 -0
  58. data/lib/kitchen/provisioner/shell.rb +157 -0
  59. data/lib/kitchen/provisioner.rb +42 -0
  60. data/lib/kitchen/rake_tasks.rb +80 -0
  61. data/lib/kitchen/shell_out.rb +90 -0
  62. data/lib/kitchen/ssh.rb +289 -0
  63. data/lib/kitchen/state_file.rb +112 -0
  64. data/lib/kitchen/suite.rb +48 -0
  65. data/lib/kitchen/thor_tasks.rb +63 -0
  66. data/lib/kitchen/transport/base.rb +236 -0
  67. data/lib/kitchen/transport/dummy.rb +78 -0
  68. data/lib/kitchen/transport/exec.rb +145 -0
  69. data/lib/kitchen/transport/ssh.rb +579 -0
  70. data/lib/kitchen/transport/winrm.rb +546 -0
  71. data/lib/kitchen/transport.rb +40 -0
  72. data/lib/kitchen/util.rb +229 -0
  73. data/lib/kitchen/verifier/base.rb +243 -0
  74. data/lib/kitchen/verifier/busser.rb +275 -0
  75. data/lib/kitchen/verifier/dummy.rb +75 -0
  76. data/lib/kitchen/verifier/shell.rb +99 -0
  77. data/lib/kitchen/verifier.rb +39 -0
  78. data/lib/kitchen/version.rb +20 -0
  79. data/lib/kitchen/which.rb +26 -0
  80. data/lib/kitchen.rb +152 -0
  81. data/lib/vendor/hash_recursive_merge.rb +79 -0
  82. data/support/busser_install_command.ps1 +14 -0
  83. data/support/busser_install_command.sh +21 -0
  84. data/support/chef-client-fail-if-update-handler.rb +15 -0
  85. data/support/chef_base_init_command.ps1 +18 -0
  86. data/support/chef_base_init_command.sh +1 -0
  87. data/support/chef_base_install_command.ps1 +85 -0
  88. data/support/chef_base_install_command.sh +229 -0
  89. data/support/download_helpers.sh +109 -0
  90. data/support/dummy-validation.pem +27 -0
  91. data/templates/driver/CHANGELOG.md.erb +3 -0
  92. data/templates/driver/Gemfile.erb +3 -0
  93. data/templates/driver/README.md.erb +64 -0
  94. data/templates/driver/Rakefile.erb +21 -0
  95. data/templates/driver/driver.rb.erb +23 -0
  96. data/templates/driver/gemspec.erb +29 -0
  97. data/templates/driver/gitignore.erb +17 -0
  98. data/templates/driver/license_apachev2.erb +15 -0
  99. data/templates/driver/license_lgplv3.erb +16 -0
  100. data/templates/driver/license_mit.erb +22 -0
  101. data/templates/driver/license_reserved.erb +5 -0
  102. data/templates/driver/tailor.erb +4 -0
  103. data/templates/driver/travis.yml.erb +11 -0
  104. data/templates/driver/version.rb.erb +12 -0
  105. data/templates/init/chefignore.erb +2 -0
  106. data/templates/init/kitchen.yml.erb +18 -0
  107. data/test-kitchen.gemspec +52 -0
  108. metadata +528 -0
@@ -0,0 +1,148 @@
1
+ #
2
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
3
+ #
4
+ # Copyright (C) 2013, 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
+ require "delegate"
19
+
20
+ module Kitchen
21
+ # A modifed Hash object that may contain callables as a value which must be
22
+ # executed in the context of another object. This allows for delayed
23
+ # evaluation of a hash value while still looking and largely feeling like a
24
+ # normal Ruby Hash.
25
+ #
26
+ # @example normal hash accessing with regular values
27
+ #
28
+ # data = {
29
+ # :symbol => true,
30
+ # "string" => "stuff"
31
+ # }
32
+ # context = "any object"
33
+ # lazy = Kitchen::Hash.new(data, context)
34
+ #
35
+ # lazy[:symbol] # => true
36
+ # lazy.fetch("string") # => "stuff"
37
+ #
38
+ # @example hash with callable blocks as values
39
+ #
40
+ # data = {
41
+ # :lambda => ->(c) { c.length },
42
+ # :proc => Proc.new { |c| c.reverse },
43
+ # :simple => "value"
44
+ # }
45
+ # context = "any object"
46
+ # lazy = Kitchen::Hash.new(data, context)
47
+ #
48
+ # lazy[:lambda] # => 10
49
+ # lazy.fetch(:proc) # => "tcejbo yna"
50
+ # lazy[:simple] # => "value"
51
+ #
52
+ # @author Fletcher Nichol <fnichol@nichol.ca>
53
+ class LazyHash < SimpleDelegator
54
+ include Enumerable
55
+
56
+ # Creates a new LazyHash using a Hash-like object to populate itself and
57
+ # an object that can be used as context in value-callable blocks. The
58
+ # context object can be used to compute values for keys at the time of
59
+ # fetching the value.
60
+ #
61
+ # @param obj [Hash, Object] a hash-like object
62
+ # @param context [Object] an object that can be used to compute values
63
+ def initialize(obj, context)
64
+ @context = context
65
+ super(obj)
66
+ end
67
+
68
+ # Retrieves the rendered value object corresponding to the key object. If
69
+ # not found, returns the default value.
70
+ #
71
+ # @param key [Object] hash key
72
+ # @return [Object, nil] the value for key or the default value if key is
73
+ # not found
74
+ def [](key)
75
+ proc_or_val(__getobj__[key])
76
+ end
77
+
78
+ # Returns a rendered value from the hash for the given key. If the key
79
+ # can't be found, there are several options: With no other arguments, it
80
+ # will raise an KeyError exception; if default is given, then that will be
81
+ # returned; if the optional code block is specified, then that will be run
82
+ # and its result returned.
83
+ #
84
+ # @param key [Object] hash key
85
+ # @param default [Object] default value if key is not set (optional)
86
+ # @return [Object, nil] the value for the key or the default value if key
87
+ # is not found
88
+ # @raise [KeyError] if the key is not found
89
+ def fetch(key, default = :__undefined__, &block)
90
+ case default
91
+ when :__undefined__
92
+ proc_or_val(__getobj__.fetch(key, &block))
93
+ else
94
+ proc_or_val(__getobj__.fetch(key, default, &block))
95
+ end
96
+ end
97
+
98
+ # Returns a new Hash with all keys and rendered values of the LazyHash.
99
+ #
100
+ # @return [Hash] a new hash
101
+ def to_hash
102
+ hash = {}
103
+ __getobj__.each_key { |key| hash[key] = self[key] }
104
+ hash
105
+ end
106
+
107
+ # Yields each key/value pair to the provided block. Returns a new
108
+ # Hash with only the keys and rendered values for which the block
109
+ # returns true.
110
+ #
111
+ # @return [Hash] a new hash
112
+ def select(&block)
113
+ to_hash.select(&block)
114
+ end
115
+
116
+ # If no block provided, returns an enumerator over the keys and
117
+ # rendered values in the underlying object. If a block is
118
+ # provided, calls the block once for each [key, rendered_value]
119
+ # pair in the underlying object.
120
+ #
121
+ # @return [Enumerator, Array]
122
+ def each(&block)
123
+ to_hash.each(&block)
124
+ end
125
+
126
+ # Returns a new Hash after deleting the key-value pairs for which the block
127
+ # returns true.
128
+ #
129
+ # @return [Hash] a new hash
130
+ def delete_if(&block)
131
+ to_hash.delete_if(&block)
132
+ end
133
+
134
+ private
135
+
136
+ # Returns an object or invokes call with context if object is callable.
137
+ #
138
+ # @return [Object] an object
139
+ # @api private
140
+ def proc_or_val(thing)
141
+ if thing.respond_to?(:call)
142
+ thing.call(@context)
143
+ else
144
+ thing
145
+ end
146
+ end
147
+ end
148
+ end
@@ -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,39 @@
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
+ begin
22
+ conn = instance.transport.connection(state_file.read)
23
+ conn.execute(command)
24
+ rescue Kitchen::Transport::SshFailed => e
25
+ return if hook[:skippable] && e.message.match(/^SSH exited \(\d{1,3}\) for command: \[.+\]$/)
26
+
27
+ raise
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # return [String]
34
+ def command
35
+ hook.fetch(:remote)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,92 @@
1
+ #
2
+ # Author:: Noah Kantrowitz <noah@coderanger.net>
3
+ #
4
+ # Copyright (C) 2018, Noah Kantrowitz
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
+ require_relative "configurable"
19
+ require_relative "errors"
20
+ require_relative "lifecycle_hook/local"
21
+ require_relative "lifecycle_hook/remote"
22
+ require_relative "logging"
23
+
24
+ module Kitchen
25
+ # A helper object used by {Instance} to coordinate lifecycle hook calls from
26
+ # the `lifecycle:` configuration section.
27
+ #
28
+ # @api internal
29
+ # @since 1.22
30
+ class LifecycleHooks
31
+ include Configurable
32
+ include Logging
33
+
34
+ def initialize(config, state_file)
35
+ init_config(config)
36
+ @state_file = state_file
37
+ end
38
+
39
+ # Run a lifecycle phase with the pre and post hooks.
40
+ #
41
+ # @param phase [String] Lifecycle phase which is being executed.
42
+ # @param state_file [StateFile] Instance state file object.
43
+ # @param block [Proc] Block of code implementing the lifecycle phase.
44
+ # @return [void]
45
+ def run_with_hooks(phase, state_file, &block)
46
+ run(phase, :pre)
47
+ yield
48
+ run(phase, :post)
49
+ end
50
+
51
+ # @return [Kitchen::StateFile]
52
+ attr_reader :state_file
53
+
54
+ private
55
+
56
+ # Execute a specific lifecycle hook.
57
+ #
58
+ # @param phase [String] Lifecycle phase which is being executed.
59
+ # @param hook_timing [Symbol] `:pre` or `:post` to indicate which hook to run.
60
+ # @return [void]
61
+ def run(phase, hook_timing)
62
+ # Yes this has to be a symbol because of how data munger works.
63
+ hook_key = :"#{hook_timing}_#{phase}"
64
+ # No hooks? We're outta here.
65
+ hook_data = Array(config[hook_key])
66
+ return if hook_data.empty?
67
+
68
+ hook_data.each do |hook|
69
+ # Coerce the common case of a bare string to be a local command. This
70
+ # is to match the behavior of the old `pre_create_command` semi-hook.
71
+ hook = { local: hook } if hook.is_a?(String)
72
+ hook = generate_hook(phase, hook)
73
+ hook.run if hook.should_run?
74
+ end
75
+ end
76
+
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}"
89
+ end
90
+ end
91
+ end
92
+ end