test-kitchen-rsync 3.0.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
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