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,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