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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 29d0736fe0c4a14aac48efa417d50780d2f48e216662733a3a4d526e6b6ea917
4
+ data.tar.gz: cd4485fb111391400af85845b9927a19a745b496411059d4f00eae9ab9ddcc1b
5
+ SHA512:
6
+ metadata.gz: 03c21555b0be1dd75b89d4cf1f7d63eea0dafefb29fd1bb9af8c7d6da575a449575adba2b067e654fb8e8d9d654503d4b930046f27456ed3fe92c8375a26ea02
7
+ data.tar.gz: a57aa49fcce002ef96be611b0ae70e4f284419d4c5da38609179f40a2fe207b2ee177dd104c3bf4dff2999fb01d8d638c62f99be08745e76169100bf0b3fc1ef
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem"s dependencies in test-kitchen.gemspec
4
+ gemspec
5
+
6
+ group :integration do
7
+ gem "berkshelf"
8
+ gem "kitchen-inspec"
9
+ gem "kitchen-dokken"
10
+ gem "kitchen-vagrant"
11
+ end
12
+
13
+ group :debug do
14
+ gem "pry", "~>0.12"
15
+ gem "pry-byebug"
16
+ gem "pry-stack_explorer"
17
+ end
18
+
19
+ group :chefstyle do
20
+ gem "chefstyle", "2.0.9"
21
+ end
data/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Author:: Fletcher Nichol (<fnichol@nichol.ca>)
2
+
3
+ Copyright 2012 Fletcher Nichol
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rake/testtask"
4
+ Rake::TestTask.new(:unit) do |t|
5
+ t.libs.push "lib"
6
+ t.test_files = FileList["spec/**/*_spec.rb"]
7
+ t.verbose = true
8
+ end
9
+
10
+ begin
11
+ require "cucumber"
12
+ require "cucumber/rake/task"
13
+ Cucumber::Rake::Task.new(:features) do |t|
14
+ t.cucumber_opts = ["features", "-x", "--format progress", "--no-color", "--tags 'not @ignore'"]
15
+ end
16
+ rescue LoadError
17
+ puts "cucumber is not available. (sudo) gem install cucumber to run tests."
18
+ end
19
+
20
+ desc "Run all test suites"
21
+ task test: %i{unit features}
22
+
23
+ desc "Display LOC stats"
24
+ task :stats do
25
+ puts "\n## Production Code Stats"
26
+ sh "countloc -r lib/kitchen lib/kitchen.rb"
27
+ puts "\n## Test Code Stats"
28
+ sh "countloc -r spec features"
29
+ end
30
+
31
+ begin
32
+ require "chefstyle"
33
+ require "rubocop/rake_task"
34
+ RuboCop::RakeTask.new(:style) do |task|
35
+ task.options += ["--display-cop-names", "--no-color"]
36
+ end
37
+ rescue LoadError
38
+ puts "chefstyle is not available. (sudo) gem install chefstyle to do style checking."
39
+ end
40
+
41
+ desc "Run all quality tasks"
42
+ task quality: %i{style stats}
43
+
44
+ task default: %i{test quality}
45
+
46
+ namespace :docs do
47
+ desc "Deploy docs"
48
+ task :deploy do
49
+ sh "cd docs && hugo"
50
+ sh "aws --profile chef-cd s3 sync docs/public s3://test-kitchen-legacy.cd.chef.co --delete --acl public-read"
51
+ sh "aws --profile chef-cd cloudfront create-invalidation --distribution-id EQD8MRW086SRT --paths '/*'"
52
+ end
53
+ end
data/bin/zl-kitchen ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # Trap interrupts to quit cleanly. See
3
+ # https://twitter.com/mitchellh/status/283014103189053442
4
+ Signal.trap("INT") { exit 1 }
5
+
6
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), %w{.. lib})
7
+ require "rubygems" unless defined?(Gem)
8
+ require "kitchen/cli"
9
+ require "kitchen/errors"
10
+
11
+ Kitchen.with_friendly_errors { Kitchen::CLI.start }
@@ -0,0 +1,48 @@
1
+ #
2
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
3
+ #
4
+ # Copyright (C) 2014, 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
+ module Kitchen
19
+ # Base64 encoder/decoder that operates on IO objects so as to minimize
20
+ # memory allocations on large payloads.
21
+ #
22
+ # @author Fletcher Nichol <fnichol@nichol.ca>
23
+ module Base64Stream
24
+ # Encodes an input stream into a Base64 output stream. The input and ouput
25
+ # objects must be opened IO resources. In other words, opening and closing
26
+ # the resources are not the responsibilty of this method.
27
+ #
28
+ # @param io_in [#read] input stream
29
+ # @param io_out [#write] output stream
30
+ def self.strict_encode(io_in, io_out)
31
+ buffer = ""
32
+ io_out.write([buffer].pack("m0")) while io_in.read(3 * 1000, buffer)
33
+ buffer = nil # rubocop:disable Lint/UselessAssignment
34
+ end
35
+
36
+ # Decodes a Base64 input stream into an output stream. The input and ouput
37
+ # objects must be opened IO resources. In other words, opening and closing
38
+ # the resources are not the responsibilty of this method.
39
+ #
40
+ # @param io_in [#read] input stream
41
+ # @param io_out [#write] output stream
42
+ def self.strict_decode(io_in, io_out)
43
+ buffer = ""
44
+ io_out.write(buffer.unpack("m0").first) while io_in.read(3 * 1000, buffer)
45
+ buffer = nil # rubocop:disable Lint/UselessAssignment
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright:: Copyright (c) Chef Software Inc.
4
+ # License:: Apache License, Version 2.0
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
+
19
+ module Kitchen
20
+ # Common Dependency Injection wiring for ChefUtils-related modules
21
+ module ChefUtilsWiring
22
+ private
23
+
24
+ def __config
25
+ # this would need to be some kind of Chef::Config looking thing, which probably requires
26
+ # a translation object from t-k config to Chef::Config layout if that ever becomes necessary.
27
+ # this ISNT the t-k config.
28
+ {}
29
+ end
30
+
31
+ def __log
32
+ @logger
33
+ end
34
+
35
+ def __transport_connection
36
+ # this could be wired up to train at some point, but need to be careful because about local vs. remote
37
+ # uses of helpers with test-kitchen, right now we're using it for local.
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,413 @@
1
+ #
2
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
3
+ #
4
+ # Copyright (C) 2012, 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
+ # CI tests fail without an explicit unconditional require of Thor
19
+ require "thor" # rubocop:disable Chef/Ruby/UnlessDefinedRequire
20
+
21
+ require_relative "../kitchen"
22
+ require_relative "generator/init"
23
+
24
+ module Kitchen
25
+ # The command line runner for Kitchen.
26
+ #
27
+ # @author Fletcher Nichol <fnichol@nichol.ca>
28
+ class CLI < Thor
29
+ # Common module to load and invoke a CLI-implementation agnostic command.
30
+ module PerformCommand
31
+ # Perform a CLI subcommand.
32
+ #
33
+ # @param task [String] action to take, usually corresponding to the
34
+ # subcommand name
35
+ # @param command [String] command class to create and invoke]
36
+ # @param args [Array] remainder arguments from processed ARGV
37
+ # (default: `nil`)
38
+ # @param additional_options [Hash] additional configuration needed to
39
+ # set up the command class (default: `{}`)
40
+ def perform(task, command, args = nil, additional_options = {})
41
+ require "kitchen/command/#{command}"
42
+
43
+ command_options = {
44
+ action: task,
45
+ help: -> { help(task) },
46
+ config: @config,
47
+ shell: shell,
48
+ }.merge(additional_options)
49
+
50
+ str_const = Thor::Util.camel_case(command)
51
+ klass = ::Kitchen::Command.const_get(str_const)
52
+ klass.new(args, options, command_options).call
53
+ end
54
+ end
55
+
56
+ include Logging
57
+ include PerformCommand
58
+
59
+ # The maximum number of concurrent instances that can run--which is a bit
60
+ # high
61
+ MAX_CONCURRENCY = 9999
62
+
63
+ attr_reader :config
64
+
65
+ # Constructs a new instance.
66
+ def initialize(*args)
67
+ super
68
+ $stdout.sync = true
69
+ @loader = Kitchen::Loader::YAML.new(
70
+ project_config: ENV["KITCHEN_YAML"] || ENV["KITCHEN_YML"],
71
+ local_config: ENV["KITCHEN_LOCAL_YAML"] || ENV["KITCHEN_LOCAL_YML"],
72
+ global_config: ENV["KITCHEN_GLOBAL_YAML"] || ENV["KITCHEN_GLOBAL_YML"]
73
+ )
74
+ @config = Kitchen::Config.new(
75
+ loader: @loader
76
+ )
77
+ @config.log_level = Kitchen.env_log unless Kitchen.env_log.nil?
78
+ @config.log_overwrite = Kitchen.env_log_overwrite unless Kitchen.env_log_overwrite.nil?
79
+ end
80
+
81
+ # Sets the logging method_options
82
+ # @api private
83
+ def self.log_options
84
+ method_option :log_level,
85
+ aliases: "-l",
86
+ desc: "Set the log level (debug, info, warn, error, fatal)"
87
+ method_option :log_overwrite,
88
+ desc: "Set to false to prevent log overwriting each time Test Kitchen runs",
89
+ type: :boolean
90
+ method_option :color,
91
+ type: :boolean,
92
+ lazy_default: $stdout.tty?,
93
+ desc: "Toggle color output for STDOUT logger"
94
+ end
95
+
96
+ # Sets the test_base_path method_options
97
+ # @api private
98
+ def self.test_base_path
99
+ method_option :test_base_path,
100
+ aliases: "-t",
101
+ desc: "Set the base path of the tests"
102
+ end
103
+
104
+ desc "list [INSTANCE|REGEXP|all]", "Lists one or more instances"
105
+ method_option :bare,
106
+ aliases: "-b",
107
+ type: :boolean,
108
+ desc: "List the name of each instance only, one per line"
109
+ method_option :json,
110
+ aliases: "-j",
111
+ type: :boolean,
112
+ desc: "Print data as JSON"
113
+ method_option :debug,
114
+ aliases: "-d",
115
+ type: :boolean,
116
+ desc: "[Deprecated] Please use `kitchen diagnose'"
117
+ log_options
118
+ def list(*args)
119
+ update_config!
120
+ perform("list", "list", args)
121
+ end
122
+ map status: :list
123
+
124
+ desc "diagnose [INSTANCE|REGEXP|all]", "Show computed diagnostic configuration"
125
+ method_option :loader,
126
+ type: :boolean,
127
+ desc: "Include data loader diagnostics"
128
+ method_option :plugins,
129
+ type: :boolean,
130
+ desc: "Include plugin diagnostics"
131
+ method_option :instances,
132
+ type: :boolean,
133
+ default: true,
134
+ desc: "Include instances diagnostics"
135
+ method_option :all,
136
+ type: :boolean,
137
+ desc: "Include all diagnostics"
138
+ log_options
139
+ test_base_path
140
+ def diagnose(*args)
141
+ update_config!
142
+ perform("diagnose", "diagnose", args, loader: @loader)
143
+ end
144
+
145
+ {
146
+ create: "Change instance state to create. " \
147
+ "Start one or more instances",
148
+ converge: "Change instance state to converge. " \
149
+ "Use a provisioner to configure one or more instances",
150
+ setup: "Change instance state to setup. " \
151
+ "Prepare to run automated tests. " \
152
+ "Install busser and related gems on one or more instances",
153
+ verify: "Change instance state to verify. " \
154
+ "Run automated tests on one or more instances",
155
+ destroy: "Change instance state to destroy. " \
156
+ "Delete all information for one or more instances",
157
+ }.each do |action, short_desc|
158
+ desc(
159
+ "#{action} [INSTANCE|REGEXP|all]",
160
+ short_desc
161
+ )
162
+ long_desc <<-DESC
163
+ The instance states are in order: destroy, create, converge, setup, verify, destroy.
164
+ Change one or more instances from the current state to the #{action} state. Actions for all
165
+ intermediate states will be executed. See https://kitchen.ci/ for further explanation.
166
+ DESC
167
+ method_option :concurrency,
168
+ aliases: "-c",
169
+ type: :numeric,
170
+ lazy_default: MAX_CONCURRENCY,
171
+ desc: <<-DESC.gsub(/^\s+/, "").tr("\n", " ")
172
+ Run a #{action} against all matching instances concurrently. Only N
173
+ instances will run at the same time if a number is given.
174
+ DESC
175
+ method_option :parallel,
176
+ aliases: "-p",
177
+ type: :boolean,
178
+ desc: <<-DESC.gsub(/^\s+/, "").tr("\n", " ")
179
+ [Future DEPRECATION, use --concurrency]
180
+ Run a #{action} against all matching instances concurrently.
181
+ DESC
182
+ if action == :converge || action == :verify
183
+ method_option :debug,
184
+ aliases: "-D",
185
+ type: :boolean,
186
+ default: false,
187
+ desc: "Run the #{action} with debugging enabled."
188
+ end
189
+ method_option :fail_fast,
190
+ aliases: "-f",
191
+ type: :boolean,
192
+ desc: "Fail immediately when errors occur in concurrency mode"
193
+
194
+ test_base_path
195
+ log_options
196
+ define_method(action) do |*args|
197
+ update_config!
198
+ perform(action, "action", args)
199
+ end
200
+ end
201
+
202
+ desc "test [INSTANCE|REGEXP|all]",
203
+ "Test (destroy, create, converge, setup, verify and destroy) one or more instances"
204
+ long_desc <<-DESC
205
+ The instance states are in order: destroy, create, converge, setup, verify, destroy.
206
+ Test changes the state of one or more instances to destroyed, then executes
207
+ the actions for each state up to destroy. At any sign of failure, executing the
208
+ actions stops and the instance is left in the last successful execution state.
209
+
210
+ There are 3 post-verify modes for instance cleanup, triggered with
211
+ the `--destroy' flag:
212
+
213
+ * passing: instances passing verify will be destroyed afterwards.\n
214
+ * always: instances will always be destroyed afterwards.\n
215
+ * never: instances will never be destroyed afterwards.
216
+ DESC
217
+ method_option :concurrency,
218
+ aliases: "-c",
219
+ type: :numeric,
220
+ lazy_default: MAX_CONCURRENCY,
221
+ desc: <<-DESC.gsub(/^\s+/, "").tr("\n", " ")
222
+ Run a test against all matching instances concurrently. Only N
223
+ instances will run at the same time if a number is given.
224
+ DESC
225
+ method_option :parallel,
226
+ aliases: "-p",
227
+ type: :boolean,
228
+ desc: <<-DESC.gsub(/^\s+/, "").tr("\n", " ")
229
+ [Future DEPRECATION, use --concurrency]
230
+ Run a test against all matching instances concurrently.
231
+ DESC
232
+ method_option :destroy,
233
+ aliases: "-d",
234
+ default: "passing",
235
+ desc: "Destroy strategy to use after testing (passing, always, never)."
236
+ method_option :auto_init,
237
+ type: :boolean,
238
+ default: false,
239
+ desc: "Invoke init command if .kitchen.yml is missing"
240
+ method_option :debug,
241
+ aliases: "-D",
242
+ type: :boolean,
243
+ default: false,
244
+ desc: "Run the converge and verify with debugging enabled."
245
+ test_base_path
246
+ log_options
247
+ def test(*args)
248
+ update_config!
249
+ ensure_initialized
250
+ perform("test", "test", args)
251
+ end
252
+
253
+ desc "login INSTANCE|REGEXP", "Log in to one instance"
254
+ log_options
255
+ def login(*args)
256
+ update_config!
257
+ perform("login", "login", args)
258
+ end
259
+
260
+ desc "package INSTANCE|REGEXP", "package an instance"
261
+ log_options
262
+ def package(*args)
263
+ update_config!
264
+ perform("package", "package", args)
265
+ end
266
+
267
+ desc "doctor INSTANCE|REGEXP", "Check for common system problems"
268
+ log_options
269
+ method_option :all,
270
+ aliases: "-a",
271
+ desc: "Check all instances"
272
+ def doctor(*args)
273
+ update_config!
274
+ perform("doctor", "doctor", args)
275
+ end
276
+
277
+ desc "exec INSTANCE|REGEXP -c REMOTE_COMMAND",
278
+ "Execute command on one or more instance"
279
+ method_option :command,
280
+ aliases: "-c",
281
+ desc: "execute via ssh"
282
+ log_options
283
+ def exec(*args)
284
+ update_config!
285
+ perform("exec", "exec", args)
286
+ end
287
+
288
+ desc "version", "Print Test Kitchen's version information"
289
+ def version
290
+ puts "Test Kitchen version #{Kitchen::VERSION}"
291
+ end
292
+ map %w{-v --version} => :version
293
+
294
+ desc "sink", "Show the Kitchen sink!", hide: true
295
+ def sink
296
+ perform("sink", "sink")
297
+ end
298
+
299
+ desc "console", "Test Kitchen Console!"
300
+ def console
301
+ perform("console", "console")
302
+ end
303
+
304
+ register Kitchen::Generator::Init, "init",
305
+ "init", "Adds some configuration to your cookbook so Kitchen can rock"
306
+ long_desc <<-D, for: "init"
307
+ Init will add Test Kitchen support to an existing project for
308
+ convergence integration testing. A default kitchen.yml file (which is
309
+ intended to be customized) is created in the project's root directory
310
+ and one or more gems will be added to the project's Gemfile.
311
+ D
312
+ tasks["init"].options = Kitchen::Generator::Init.class_options
313
+
314
+ class << self
315
+ private
316
+
317
+ # Ensure the any failing commands exit non-zero.
318
+ #
319
+ # @return [true] you die always on failure
320
+ # @api private
321
+ def exit_on_failure?
322
+ true
323
+ end
324
+ end
325
+
326
+ private
327
+
328
+ # @return [Logger] the common logger
329
+ # @api private
330
+ def logger
331
+ Kitchen.logger
332
+ end
333
+
334
+ # Update and finalize options for logging, concurrency, and other concerns.
335
+ #
336
+ # @api private
337
+ def update_config!
338
+ @config.log_level = log_level if log_level
339
+
340
+ unless options[:log_overwrite].nil?
341
+ @config.log_overwrite = options[:log_overwrite]
342
+ end
343
+ @config.colorize = options[:color] unless options[:color].nil?
344
+
345
+ if options[:test_base_path]
346
+ # ensure we have an absolute path
347
+ @config.test_base_path = File.absolute_path(options[:test_base_path])
348
+ end
349
+
350
+ @config.debug = options[:debug]
351
+
352
+ # Now that we have required configs, lets create our file logger
353
+ Kitchen.logger = Kitchen.default_file_logger(
354
+ log_level,
355
+ options[:log_overwrite]
356
+ )
357
+
358
+ update_parallel!
359
+ end
360
+
361
+ # Validate the log level from the config / CLI options, defaulting
362
+ # to :info if the supplied level is empty or invalid
363
+ #
364
+ # @api private
365
+ def log_level
366
+ return unless options[:log_level]
367
+ return @log_level if @log_level
368
+
369
+ level = options[:log_level].downcase.to_sym
370
+ unless valid_log_level?(level)
371
+ level = :info
372
+ banner "WARNING - invalid log level specified: " \
373
+ "\"#{options[:log_level]}\" - reverting to :info log level."
374
+ end
375
+
376
+ @log_level = level
377
+ end
378
+
379
+ # Check to whether a provided log level is valid
380
+ #
381
+ # @api private
382
+ def valid_log_level?(level)
383
+ !Util.to_logger_level(level).nil?
384
+ end
385
+
386
+ # Set parallel concurrency options for Thor
387
+ #
388
+ # @api private
389
+ def update_parallel!
390
+ if options[:parallel]
391
+ # warn here in a future release when option is used
392
+ @options = Thor::CoreExt::HashWithIndifferentAccess.new(options.to_hash)
393
+ if options[:parallel] && !options[:concurrency]
394
+ options[:concurrency] = MAX_CONCURRENCY
395
+ end
396
+ options.delete(:parallel)
397
+ options.freeze
398
+ end
399
+ end
400
+
401
+ # If auto_init option is active, invoke the init generator.
402
+ #
403
+ # @api private
404
+ def ensure_initialized
405
+ yaml = ENV["KITCHEN_YAML"] || ENV["KITCHEN_YML"] || ".kitchen.yml"
406
+
407
+ if options[:auto_init] && !File.exist?(yaml)
408
+ banner "Invoking init as '#{yaml}' file is missing"
409
+ invoke "init"
410
+ end
411
+ end
412
+ end
413
+ end
@@ -0,0 +1,52 @@
1
+ #
2
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
3
+ #
4
+ # Copyright (C) 2012, 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
+ # Delegate class which adds the ability to find single and multiple
22
+ # objects by their #name in an Array. Hey, it's better than monkey-patching
23
+ # Array, right?
24
+ #
25
+ # @author Fletcher Nichol <fnichol@nichol.ca>
26
+ class Collection < SimpleDelegator
27
+ # Returns a single object by its name, or nil if none are found.
28
+ #
29
+ # @param name [String] name of object
30
+ # @return [Object] first match by name, or nil if none are found
31
+ def get(name)
32
+ __getobj__.find { |i| i.name == name }
33
+ end
34
+
35
+ # Returns a Collection of all objects whose #name is matched by the
36
+ # regular expression.
37
+ #
38
+ # @param regexp [Regexp] a regular expression pattern
39
+ # @return [Kitchen::Config::Collection<Object>] a new collection of
40
+ # matched objects
41
+ def get_all(regexp)
42
+ Kitchen::Collection.new(__getobj__.select { |i| i.name =~ regexp })
43
+ end
44
+
45
+ # Returns an Array of names from the collection as strings.
46
+ #
47
+ # @return [Array<String>] array of name strings
48
+ def as_names
49
+ __getobj__.map(&:name)
50
+ end
51
+ end
52
+ end