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,236 @@
1
+ #
2
+ # Author:: Salim Afiune (<salim@afiunemaya.com.mx>)
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2014, Salim Afiune
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
+ require_relative "../configurable"
20
+ require_relative "../errors"
21
+ require_relative "../lazy_hash"
22
+ require_relative "../logging"
23
+ require_relative "../login_command"
24
+ require_relative "../plugin_base"
25
+
26
+ module Kitchen
27
+ module Transport
28
+ # Wrapped exception for any internally raised Transport errors.
29
+ #
30
+ # @author Salim Afiune <salim@afiunemaya.com.mx>
31
+ class TransportFailed < TransientFailure
32
+ attr_reader :exit_code
33
+
34
+ def initialize(message, exit_code = nil)
35
+ @exit_code = exit_code
36
+ super(message)
37
+ end
38
+ end
39
+
40
+ # Base class for a transport.
41
+ #
42
+ # @author Salim Afiune <salim@afiunemaya.com.mx>
43
+ # @author Fletcher Nichol <fnichol@nichol.ca>
44
+ class Base < Kitchen::Plugin::Base
45
+ include Configurable
46
+ include Logging
47
+
48
+ # Create a new transport by providing a configuration hash.
49
+ #
50
+ # @param config [Hash] initial provided configuration
51
+ def initialize(config = {})
52
+ @connection = nil
53
+ init_config(config)
54
+ end
55
+
56
+ # Creates a new Connection, configured by a merging of configuration
57
+ # and state data. Depending on the implementation, the Connection could
58
+ # be saved or cached to speed up multiple calls, given the same state
59
+ # hash as input.
60
+ #
61
+ # @param state [Hash] mutable instance state
62
+ # @return [Connection] a connection for this transport
63
+ # @raise [TransportFailed] if a connection could not be returned
64
+ # rubocop:disable Lint/UnusedMethodArgument
65
+ def connection(state)
66
+ raise ClientError, "#{self.class}#connection must be implemented"
67
+ end
68
+
69
+ # Check system and configuration for common errors.
70
+ #
71
+ # @param state [Hash] mutable instance state
72
+ # @returns [Boolean] Return true if a problem is found.
73
+ def doctor(state)
74
+ false
75
+ end
76
+
77
+ # Closes the connection, if it is still active.
78
+ #
79
+ # @return [void]
80
+ def cleanup!
81
+ # This method may be left unimplemented if that is applicable
82
+ end
83
+
84
+ # A Connection instance can be generated and re-generated, given new
85
+ # connection details such as connection port, hostname, credentials, etc.
86
+ # This object is responsible for carrying out the actions on the remote
87
+ # host such as executing commands, transferring files, etc.
88
+ #
89
+ # @author Fletcher Nichol <fnichol@nichol.ca>
90
+ class Connection
91
+ include Logging
92
+
93
+ # Create a new Connection instance.
94
+ #
95
+ # @param options [Hash] connection options
96
+ # @yield [self] yields itself for block-style invocation
97
+ def initialize(options = {})
98
+ init_options(options)
99
+
100
+ yield self if block_given?
101
+ end
102
+
103
+ # Closes the session connection, if it is still active.
104
+ def close
105
+ # this method may be left unimplemented if that is applicable
106
+ end
107
+
108
+ # Execute a command on the remote host.
109
+ #
110
+ # @param command [String] command string to execute
111
+ # @raise [TransportFailed] if the command does not exit successfully,
112
+ # which may vary by implementation
113
+ def execute(command)
114
+ raise ClientError, "#{self.class}#execute must be implemented"
115
+ end
116
+
117
+ # Execute a command on the remote host and retry
118
+ #
119
+ # @param command [String] command string to execute
120
+ # @param retryable_exit_codes [Array] Array of exit codes to retry against
121
+ # @param max_retries [Fixnum] maximum number of retry attempts
122
+ # @param wait_time [Fixnum] number of seconds to wait before retrying command
123
+ # @raise [TransportFailed] if the command does not exit successfully,
124
+ # which may vary by implementation
125
+ def execute_with_retry(command, retryable_exit_codes = [], max_retries = 1, wait_time = 30)
126
+ tries = 0
127
+ begin
128
+ tries += 1
129
+ debug("Attempting to execute command - try #{tries} of #{max_retries}.")
130
+ execute(command)
131
+ rescue Kitchen::Transport::TransportFailed => e
132
+ if retry?(tries, max_retries, retryable_exit_codes, e.exit_code)
133
+ close
134
+ sleep wait_time
135
+ retry
136
+ else
137
+ raise e
138
+ end
139
+ end
140
+ end
141
+
142
+ def retry?(current_try, max_retries, retryable_exit_codes, exit_code)
143
+ current_try <= max_retries &&
144
+ !retryable_exit_codes.nil? &&
145
+ retryable_exit_codes.flatten.include?(exit_code)
146
+ end
147
+
148
+ # Builds a LoginCommand which can be used to open an interactive
149
+ # session on the remote host.
150
+ #
151
+ # @return [LoginCommand] an object containing the array of command line
152
+ # tokens and exec options to be used in a fork/exec
153
+ # @raise [ActionFailed] if the action could not be completed
154
+ def login_command
155
+ raise ActionFailed, "Remote login not supported in #{self.class}."
156
+ end
157
+
158
+ # Uploads local files or directories to remote host.
159
+ #
160
+ # @param locals [Array<String>] paths to local files or directories
161
+ # @param remote [String] path to remote destination
162
+ # @raise [TransportFailed] if the files could not all be uploaded
163
+ # successfully, which may vary by implementation
164
+ def upload(locals, remote) # rubocop:disable Lint/UnusedMethodArgument
165
+ raise ClientError, "#{self.class}#upload must be implemented"
166
+ end
167
+
168
+ # Download remote files or directories to local host.
169
+ #
170
+ # @param remotes [Array<String>] paths to remote files or directories
171
+ # @param local [String] path to local destination. If `local` is an
172
+ # existing directory, `remote` will be downloaded into the directory
173
+ # using its original name
174
+ # @raise [TransportFailed] if the files could not all be downloaded
175
+ # successfully, which may vary by implementation
176
+ def download(remotes, local) # rubocop:disable Lint/UnusedMethodArgument
177
+ raise ClientError, "#{self.class}#download must be implemented"
178
+ end
179
+
180
+ # Block and return only when the remote host is prepared and ready to
181
+ # execute command and upload files. The semantics and details will
182
+ # vary by implementation, but a round trip through the hosted
183
+ # service is preferred to simply waiting on a socket to become
184
+ # available.
185
+ def wait_until_ready
186
+ # this method may be left unimplemented if that is applicable
187
+ end
188
+
189
+ def rsyn_chef_repo(dirs_to_copy, root_path)
190
+ # this method may be left unimplemented if that is applicable
191
+ end
192
+
193
+ private
194
+
195
+ # @return [Kitchen::Logger] a logger
196
+ # @api private
197
+ attr_reader :logger
198
+
199
+ # @return [Hash] connection options
200
+ # @api private
201
+ attr_reader :options
202
+
203
+ # Initialize incoming options for use by the object.
204
+ #
205
+ # @param options [Hash] configuration options
206
+ def init_options(options)
207
+ @options = options.dup
208
+ @logger = @options.delete(:logger) || Kitchen.logger
209
+ end
210
+ end
211
+
212
+ # Sets the API version for this transport. If the transport does not set
213
+ # this value, then `nil` will be used and reported.
214
+ #
215
+ # Sets the API version for this transport
216
+ #
217
+ # @example setting an API version
218
+ #
219
+ # module Kitchen
220
+ # module Transport
221
+ # class NewTransport < Kitchen::Transport::Base
222
+ #
223
+ # kitchen_transport_api_version 2
224
+ #
225
+ # end
226
+ # end
227
+ # end
228
+ #
229
+ # @param version [Integer,String] a version number
230
+ #
231
+ def self.kitchen_transport_api_version(version)
232
+ @api_version = version
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,78 @@
1
+ #
2
+ # Author:: Salim Afiune (<salim@afiunemaya.com.mx>)
3
+ #
4
+ # Copyright (C) 2013, Salim Afiune
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 "../../kitchen"
19
+
20
+ module Kitchen
21
+ module Transport
22
+ # Dummy transport for Kitchen. This transport does nothing but report what would
23
+ # happen if this transport did anything of consequence. As a result it may
24
+ # be a useful transport to use when debugging or developing new features or
25
+ # plugins.
26
+ class Dummy < Kitchen::Transport::Base
27
+ kitchen_transport_api_version 1
28
+
29
+ plugin_version Kitchen::VERSION
30
+
31
+ default_config :sleep, 1
32
+ default_config :random_exit_code, 0
33
+
34
+ def connection(state, &block)
35
+ options = config.to_hash.merge(state)
36
+ Kitchen::Transport::Dummy::Connection.new(options, &block)
37
+ end
38
+
39
+ # TODO: comment
40
+ class Connection < Kitchen::Transport::Base::Connection
41
+ # (see Base#execute)
42
+ def execute(command)
43
+ report(:execute, command)
44
+ if options[:random_exit_code] != 0
45
+ info("Dummy exited (#{exit_code}) for command: [#{command}]")
46
+ end
47
+ end
48
+
49
+ def upload(locals, remote)
50
+ report(:upload, "#{locals.inspect} => #{remote}")
51
+ end
52
+
53
+ def download(remotes, local)
54
+ report(:download, "#{remotes.inspect} => #{local}")
55
+ end
56
+
57
+ private
58
+
59
+ # Report what action is taking place, sleeping if so configured, and
60
+ # possibly fail randomly.
61
+ #
62
+ # @param action [Symbol] the action currently taking place
63
+ # @param state [Hash] the state hash
64
+ # @api private
65
+ def report(action, msg = "")
66
+ what = action.capitalize
67
+ info("[Dummy] #{what} #{msg} on Transport=Dummy")
68
+ sleep_if_set
69
+ debug("[Dummy] #{what} #{msg} completed (#{options[:sleep]}s).")
70
+ end
71
+
72
+ def sleep_if_set
73
+ sleep(options[:sleep].to_f) if options[:sleep].to_f > 0.0
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,145 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ require "fileutils" unless defined?(FileUtils)
15
+
16
+ require_relative "../shell_out"
17
+ require_relative "base"
18
+ require_relative "../version"
19
+
20
+ module Kitchen
21
+ module Transport
22
+ # Exec transport for Kitchen. This transport runs all commands locally.
23
+ #
24
+ # @since 1.19
25
+ class Exec < Kitchen::Transport::Base
26
+ kitchen_transport_api_version 1
27
+
28
+ plugin_version Kitchen::VERSION
29
+
30
+ def connection(state, &block)
31
+ options = connection_options(config.to_hash.merge(state))
32
+ Kitchen::Transport::Exec::Connection.new(options, &block)
33
+ end
34
+
35
+ # Fake connection which just does local operations.
36
+ class Connection < Kitchen::Transport::Base::Connection
37
+ include ShellOut
38
+
39
+ # (see Base#execute)
40
+ def execute(command)
41
+ return if command.nil?
42
+
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
55
+ end
56
+
57
+ # "Upload" the files by copying them locally.
58
+ #
59
+ # @see Base#upload
60
+ def upload(locals, remote)
61
+ # evaluate $env:temp on Windows
62
+ real_remote = remote.to_s == "\$env:TEMP\\kitchen" ? kitchen_temp : remote
63
+ FileUtils.mkdir_p(real_remote)
64
+ Array(locals).each do |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
125
+ end
126
+ end
127
+ end
128
+
129
+ private
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
142
+ end
143
+ end
144
+ end
145
+ end