test-kitchen 1.7.0 → 1.7.1.dev

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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +8 -8
  3. data/.gitattributes +3 -0
  4. data/.github/ISSUE_TEMPLATE.md +55 -55
  5. data/.gitignore +28 -28
  6. data/.kitchen.ci.yml +23 -23
  7. data/.kitchen.proxy.yml +27 -27
  8. data/.rubocop.yml +3 -3
  9. data/.travis.yml +70 -70
  10. data/.yardopts +3 -3
  11. data/Berksfile +3 -3
  12. data/CHANGELOG.md +1090 -1083
  13. data/CONTRIBUTING.md +14 -14
  14. data/Gemfile +19 -19
  15. data/Gemfile.proxy_tests +4 -4
  16. data/Guardfile +42 -42
  17. data/LICENSE +15 -15
  18. data/MAINTAINERS.md +23 -23
  19. data/README.md +135 -135
  20. data/Rakefile +61 -61
  21. data/appveyor.yml +44 -44
  22. data/features/kitchen_action_commands.feature +164 -164
  23. data/features/kitchen_command.feature +16 -16
  24. data/features/kitchen_console_command.feature +34 -34
  25. data/features/kitchen_defaults.feature +38 -38
  26. data/features/kitchen_diagnose_command.feature +96 -96
  27. data/features/kitchen_driver_create_command.feature +64 -64
  28. data/features/kitchen_driver_discover_command.feature +25 -25
  29. data/features/kitchen_help_command.feature +16 -16
  30. data/features/kitchen_init_command.feature +274 -274
  31. data/features/kitchen_list_command.feature +104 -104
  32. data/features/kitchen_login_command.feature +62 -62
  33. data/features/kitchen_sink_command.feature +30 -30
  34. data/features/kitchen_test_command.feature +88 -88
  35. data/features/step_definitions/gem_steps.rb +36 -36
  36. data/features/step_definitions/git_steps.rb +5 -5
  37. data/features/step_definitions/output_steps.rb +5 -5
  38. data/features/support/env.rb +75 -75
  39. data/lib/kitchen.rb +150 -150
  40. data/lib/kitchen/base64_stream.rb +55 -55
  41. data/lib/kitchen/cli.rb +419 -419
  42. data/lib/kitchen/collection.rb +55 -55
  43. data/lib/kitchen/color.rb +65 -65
  44. data/lib/kitchen/command.rb +185 -185
  45. data/lib/kitchen/command/action.rb +45 -45
  46. data/lib/kitchen/command/console.rb +58 -58
  47. data/lib/kitchen/command/diagnose.rb +92 -92
  48. data/lib/kitchen/command/driver_discover.rb +105 -105
  49. data/lib/kitchen/command/exec.rb +41 -41
  50. data/lib/kitchen/command/list.rb +119 -119
  51. data/lib/kitchen/command/login.rb +43 -43
  52. data/lib/kitchen/command/sink.rb +54 -54
  53. data/lib/kitchen/command/test.rb +51 -51
  54. data/lib/kitchen/config.rb +322 -322
  55. data/lib/kitchen/configurable.rb +529 -529
  56. data/lib/kitchen/data_munger.rb +959 -959
  57. data/lib/kitchen/diagnostic.rb +141 -141
  58. data/lib/kitchen/driver.rb +56 -56
  59. data/lib/kitchen/driver/base.rb +134 -134
  60. data/lib/kitchen/driver/dummy.rb +108 -108
  61. data/lib/kitchen/driver/proxy.rb +72 -72
  62. data/lib/kitchen/driver/ssh_base.rb +357 -357
  63. data/lib/kitchen/errors.rb +229 -229
  64. data/lib/kitchen/generator/driver_create.rb +177 -177
  65. data/lib/kitchen/generator/init.rb +296 -296
  66. data/lib/kitchen/instance.rb +662 -662
  67. data/lib/kitchen/lazy_hash.rb +142 -142
  68. data/lib/kitchen/loader/yaml.rb +349 -349
  69. data/lib/kitchen/logger.rb +423 -423
  70. data/lib/kitchen/logging.rb +56 -56
  71. data/lib/kitchen/login_command.rb +52 -52
  72. data/lib/kitchen/metadata_chopper.rb +52 -52
  73. data/lib/kitchen/platform.rb +67 -67
  74. data/lib/kitchen/provisioner.rb +54 -54
  75. data/lib/kitchen/provisioner/base.rb +236 -236
  76. data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
  77. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
  78. data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
  79. data/lib/kitchen/provisioner/chef_apply.rb +124 -124
  80. data/lib/kitchen/provisioner/chef_base.rb +341 -341
  81. data/lib/kitchen/provisioner/chef_solo.rb +88 -88
  82. data/lib/kitchen/provisioner/chef_zero.rb +245 -245
  83. data/lib/kitchen/provisioner/dummy.rb +79 -79
  84. data/lib/kitchen/provisioner/shell.rb +138 -138
  85. data/lib/kitchen/rake_tasks.rb +63 -63
  86. data/lib/kitchen/shell_out.rb +93 -93
  87. data/lib/kitchen/ssh.rb +276 -276
  88. data/lib/kitchen/state_file.rb +120 -120
  89. data/lib/kitchen/suite.rb +51 -51
  90. data/lib/kitchen/thor_tasks.rb +66 -66
  91. data/lib/kitchen/transport.rb +54 -54
  92. data/lib/kitchen/transport/base.rb +176 -176
  93. data/lib/kitchen/transport/dummy.rb +79 -79
  94. data/lib/kitchen/transport/ssh.rb +364 -364
  95. data/lib/kitchen/transport/winrm.rb +486 -486
  96. data/lib/kitchen/util.rb +147 -147
  97. data/lib/kitchen/verifier.rb +55 -55
  98. data/lib/kitchen/verifier/base.rb +235 -235
  99. data/lib/kitchen/verifier/busser.rb +277 -277
  100. data/lib/kitchen/verifier/dummy.rb +79 -79
  101. data/lib/kitchen/verifier/shell.rb +101 -101
  102. data/lib/kitchen/version.rb +21 -21
  103. data/lib/vendor/hash_recursive_merge.rb +82 -82
  104. data/spec/kitchen/base64_stream_spec.rb +77 -77
  105. data/spec/kitchen/cli_spec.rb +56 -56
  106. data/spec/kitchen/collection_spec.rb +80 -80
  107. data/spec/kitchen/color_spec.rb +54 -54
  108. data/spec/kitchen/config_spec.rb +408 -408
  109. data/spec/kitchen/configurable_spec.rb +1095 -1095
  110. data/spec/kitchen/data_munger_spec.rb +2694 -2694
  111. data/spec/kitchen/diagnostic_spec.rb +129 -129
  112. data/spec/kitchen/driver/base_spec.rb +121 -121
  113. data/spec/kitchen/driver/dummy_spec.rb +199 -199
  114. data/spec/kitchen/driver/proxy_spec.rb +138 -138
  115. data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
  116. data/spec/kitchen/driver_spec.rb +112 -112
  117. data/spec/kitchen/errors_spec.rb +309 -309
  118. data/spec/kitchen/instance_spec.rb +1419 -1419
  119. data/spec/kitchen/lazy_hash_spec.rb +117 -117
  120. data/spec/kitchen/loader/yaml_spec.rb +774 -774
  121. data/spec/kitchen/logger_spec.rb +429 -429
  122. data/spec/kitchen/logging_spec.rb +59 -59
  123. data/spec/kitchen/login_command_spec.rb +68 -68
  124. data/spec/kitchen/metadata_chopper_spec.rb +82 -82
  125. data/spec/kitchen/platform_spec.rb +89 -89
  126. data/spec/kitchen/provisioner/base_spec.rb +386 -386
  127. data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
  128. data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1161
  129. data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
  130. data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
  131. data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
  132. data/spec/kitchen/provisioner/shell_spec.rb +566 -566
  133. data/spec/kitchen/provisioner_spec.rb +107 -107
  134. data/spec/kitchen/shell_out_spec.rb +150 -150
  135. data/spec/kitchen/ssh_spec.rb +693 -693
  136. data/spec/kitchen/state_file_spec.rb +129 -129
  137. data/spec/kitchen/suite_spec.rb +62 -62
  138. data/spec/kitchen/transport/base_spec.rb +89 -89
  139. data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
  140. data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
  141. data/spec/kitchen/transport_spec.rb +112 -112
  142. data/spec/kitchen/util_spec.rb +165 -165
  143. data/spec/kitchen/verifier/base_spec.rb +362 -362
  144. data/spec/kitchen/verifier/busser_spec.rb +610 -610
  145. data/spec/kitchen/verifier/dummy_spec.rb +99 -99
  146. data/spec/kitchen/verifier/shell_spec.rb +160 -160
  147. data/spec/kitchen/verifier_spec.rb +120 -120
  148. data/spec/kitchen_spec.rb +114 -114
  149. data/spec/spec_helper.rb +85 -85
  150. data/spec/support/powershell_max_size_spec.rb +40 -40
  151. data/support/busser_install_command.ps1 +14 -14
  152. data/support/busser_install_command.sh +14 -14
  153. data/support/chef-client-zero.rb +77 -77
  154. data/support/chef_base_init_command.ps1 +18 -18
  155. data/support/chef_base_init_command.sh +2 -2
  156. data/support/chef_base_install_command.ps1 +85 -85
  157. data/support/chef_base_install_command.sh +229 -229
  158. data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
  159. data/support/chef_zero_prepare_command_legacy.sh +10 -10
  160. data/support/download_helpers.sh +109 -109
  161. data/support/dummy-validation.pem +27 -27
  162. data/templates/driver/CHANGELOG.md.erb +3 -3
  163. data/templates/driver/Gemfile.erb +3 -3
  164. data/templates/driver/README.md.erb +64 -64
  165. data/templates/driver/Rakefile.erb +21 -21
  166. data/templates/driver/driver.rb.erb +23 -23
  167. data/templates/driver/gemspec.erb +29 -29
  168. data/templates/driver/gitignore.erb +17 -17
  169. data/templates/driver/license_apachev2.erb +15 -15
  170. data/templates/driver/license_lgplv3.erb +16 -16
  171. data/templates/driver/license_mit.erb +22 -22
  172. data/templates/driver/license_reserved.erb +5 -5
  173. data/templates/driver/tailor.erb +4 -4
  174. data/templates/driver/travis.yml.erb +11 -11
  175. data/templates/driver/version.rb.erb +12 -12
  176. data/templates/init/chefignore.erb +1 -1
  177. data/templates/init/kitchen.yml.erb +18 -18
  178. data/test-kitchen.gemspec +62 -62
  179. data/test/integration/default/default_spec.rb +3 -3
  180. data/testing_windows.md +37 -37
  181. metadata +5 -4
@@ -1,55 +1,55 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2012, Fletcher Nichol
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 "delegate"
20
-
21
- module Kitchen
22
-
23
- # Delegate class which adds the ability to find single and multiple
24
- # objects by their #name in an Array. Hey, it's better than monkey-patching
25
- # Array, right?
26
- #
27
- # @author Fletcher Nichol <fnichol@nichol.ca>
28
- class Collection < SimpleDelegator
29
-
30
- # Returns a single object by its name, or nil if none are found.
31
- #
32
- # @param name [String] name of object
33
- # @return [Object] first match by name, or nil if none are found
34
- def get(name)
35
- __getobj__.find { |i| i.name == name }
36
- end
37
-
38
- # Returns a Collection of all objects whose #name is matched by the
39
- # regular expression.
40
- #
41
- # @param regexp [Regexp] a regular expression pattern
42
- # @return [Kitchen::Config::Collection<Object>] a new collection of
43
- # matched objects
44
- def get_all(regexp)
45
- Kitchen::Collection.new(__getobj__.select { |i| i.name =~ regexp })
46
- end
47
-
48
- # Returns an Array of names from the collection as strings.
49
- #
50
- # @return [Array<String>] array of name strings
51
- def as_names
52
- __getobj__.map(&:name)
53
- end
54
- end
55
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, Fletcher Nichol
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 "delegate"
20
+
21
+ module Kitchen
22
+
23
+ # Delegate class which adds the ability to find single and multiple
24
+ # objects by their #name in an Array. Hey, it's better than monkey-patching
25
+ # Array, right?
26
+ #
27
+ # @author Fletcher Nichol <fnichol@nichol.ca>
28
+ class Collection < SimpleDelegator
29
+
30
+ # Returns a single object by its name, or nil if none are found.
31
+ #
32
+ # @param name [String] name of object
33
+ # @return [Object] first match by name, or nil if none are found
34
+ def get(name)
35
+ __getobj__.find { |i| i.name == name }
36
+ end
37
+
38
+ # Returns a Collection of all objects whose #name is matched by the
39
+ # regular expression.
40
+ #
41
+ # @param regexp [Regexp] a regular expression pattern
42
+ # @return [Kitchen::Config::Collection<Object>] a new collection of
43
+ # matched objects
44
+ def get_all(regexp)
45
+ Kitchen::Collection.new(__getobj__.select { |i| i.name =~ regexp })
46
+ end
47
+
48
+ # Returns an Array of names from the collection as strings.
49
+ #
50
+ # @return [Array<String>] array of name strings
51
+ def as_names
52
+ __getobj__.map(&:name)
53
+ end
54
+ end
55
+ end
data/lib/kitchen/color.rb CHANGED
@@ -1,65 +1,65 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2013, Fletcher Nichol
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
- module Kitchen
20
-
21
- # Utility methods to help ouput colorized text in a terminal. The
22
- # implementation is a compressed mashup of code from the Thor and Foreman
23
- # projects.
24
- #
25
- # @author Fletcher Nichol <fnichol@nichol.ca>
26
- module Color
27
-
28
- ANSI = {
29
- :reset => 0, :black => 30, :red => 31, :green => 32, :yellow => 33,
30
- :blue => 34, :magenta => 35, :cyan => 36, :white => 37,
31
- :bright_black => 90, :bright_red => 91, :bright_green => 92,
32
- :bright_yellow => 93, :bright_blue => 94, :bright_magenta => 95,
33
- :bright_cyan => 96, :bright_white => 97
34
- }.freeze
35
-
36
- COLORS = %w[
37
- cyan yellow green magenta blue bright_cyan bright_yellow
38
- bright_green bright_magenta bright_blue
39
- ].freeze
40
-
41
- # Returns an ansi escaped string representing a color control sequence.
42
- #
43
- # @param name [Symbol] a valid color representation, taken from
44
- # Kitchen::Color::ANSI
45
- # @return [String] an ansi escaped string if the color is valid and an
46
- # empty string otherwise
47
- def self.escape(name)
48
- return "" if name.nil?
49
- return "" unless ANSI[name]
50
- "\e[#{ANSI[name]}m"
51
- end
52
-
53
- # Returns a colorized ansi escaped string with the given color.
54
- #
55
- # @param str [String] a string to colorize
56
- # @param name [Symbol] a valid color representation, taken from
57
- # Kitchen::Color::ANSI
58
- # @return [String] an ansi escaped string if the color is valid and an
59
- # unescaped string otherwise
60
- def self.colorize(str, name)
61
- color = escape(name)
62
- color.empty? ? str : "#{color}#{str}#{escape(:reset)}"
63
- end
64
- end
65
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2013, Fletcher Nichol
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
+ module Kitchen
20
+
21
+ # Utility methods to help ouput colorized text in a terminal. The
22
+ # implementation is a compressed mashup of code from the Thor and Foreman
23
+ # projects.
24
+ #
25
+ # @author Fletcher Nichol <fnichol@nichol.ca>
26
+ module Color
27
+
28
+ ANSI = {
29
+ :reset => 0, :black => 30, :red => 31, :green => 32, :yellow => 33,
30
+ :blue => 34, :magenta => 35, :cyan => 36, :white => 37,
31
+ :bright_black => 90, :bright_red => 91, :bright_green => 92,
32
+ :bright_yellow => 93, :bright_blue => 94, :bright_magenta => 95,
33
+ :bright_cyan => 96, :bright_white => 97
34
+ }.freeze
35
+
36
+ COLORS = %w[
37
+ cyan yellow green magenta blue bright_cyan bright_yellow
38
+ bright_green bright_magenta bright_blue
39
+ ].freeze
40
+
41
+ # Returns an ansi escaped string representing a color control sequence.
42
+ #
43
+ # @param name [Symbol] a valid color representation, taken from
44
+ # Kitchen::Color::ANSI
45
+ # @return [String] an ansi escaped string if the color is valid and an
46
+ # empty string otherwise
47
+ def self.escape(name)
48
+ return "" if name.nil?
49
+ return "" unless ANSI[name]
50
+ "\e[#{ANSI[name]}m"
51
+ end
52
+
53
+ # Returns a colorized ansi escaped string with the given color.
54
+ #
55
+ # @param str [String] a string to colorize
56
+ # @param name [Symbol] a valid color representation, taken from
57
+ # Kitchen::Color::ANSI
58
+ # @return [String] an ansi escaped string if the color is valid and an
59
+ # unescaped string otherwise
60
+ def self.colorize(str, name)
61
+ color = escape(name)
62
+ color.empty? ? str : "#{color}#{str}#{escape(:reset)}"
63
+ end
64
+ end
65
+ end
@@ -1,185 +1,185 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2013, Fletcher Nichol
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 "thread"
20
-
21
- module Kitchen
22
-
23
- module Command
24
-
25
- # Base class for CLI commands.
26
- #
27
- # @author Fletcher Nichol <fnichol@nichol.ca>
28
- class Base
29
-
30
- include Logging
31
-
32
- # Contstructs a new Command object.
33
- #
34
- # @param cmd_args [Array] remainder of the arguments from processed ARGV
35
- # @param cmd_options [Hash] hash of Thor options
36
- # @param options [Hash] configuration options
37
- # @option options [String] :action action to take, usually corresponding
38
- # to the subcommand name (default: `nil`)
39
- # @option options [proc] :help a callable that displays help for the
40
- # command
41
- # @option options [Config] :config a Config object (default: `nil`)
42
- # @option options [Loader] :loader a Loader object (default: `nil`)
43
- # @option options [String] :shell a Thor shell object
44
- def initialize(cmd_args, cmd_options, options = {})
45
- @args = cmd_args
46
- @options = cmd_options
47
- @action = options.fetch(:action, nil)
48
- @help = options.fetch(:help, -> { "No help provided" })
49
- @config = options.fetch(:config, nil)
50
- @loader = options.fetch(:loader, nil)
51
- @shell = options.fetch(:shell)
52
- end
53
-
54
- private
55
-
56
- # @return [Array] remainder of the arguments from processed ARGV
57
- # @api private
58
- attr_reader :args
59
-
60
- # @return [Hash] hash of Thor options
61
- # @api private
62
- attr_reader :options
63
-
64
- # @return [proc] a callable that displays help for the command
65
- # @api private
66
- attr_reader :help
67
-
68
- # @return [Config] a Config object
69
- # @api private
70
- attr_reader :config
71
-
72
- # @return [Thor::Shell] a Thor shell object
73
- # @api private
74
- attr_reader :shell
75
-
76
- # @return [String] the action to perform
77
- # @api private
78
- attr_reader :action
79
-
80
- # Emit an error message, display contextual help and then exit with a
81
- # non-zero exit code.
82
- #
83
- # **Note** This method calls exit and will not return.
84
- #
85
- # @param msg [String] error message
86
- # @api private
87
- def die(msg)
88
- error "\n#{msg}\n\n"
89
- help.call
90
- exit 1
91
- end
92
-
93
- # @return [Array<Instance>] an array of instances
94
- # @raise [SystemExit] if no instances are returned
95
- # @api private
96
- def all_instances
97
- result = @config.instances
98
-
99
- if result.empty?
100
- die "No instances defined"
101
- else
102
- result
103
- end
104
- end
105
-
106
- # Return an array on instances whos name matches the regular expression.
107
- #
108
- # @param regexp [Regexp] a regular expression matching on instance names
109
- # @return [Array<Instance>] an array of instances
110
- # @raise [SystemExit] if no instances are returned or the regular
111
- # expression is invalid
112
- # @api private
113
- def filtered_instances(regexp)
114
- result = begin
115
- @config.instances.get(regexp) ||
116
- @config.instances.get_all(/#{regexp}/)
117
- rescue RegexpError => e
118
- die "Invalid Ruby regular expression, " \
119
- "you may need to single quote the argument. " \
120
- "Please try again or consult http://rubular.com/ (#{e.message})"
121
- end
122
- result = Array(result)
123
-
124
- if result.empty?
125
- die "No instances for regex `#{regexp}', try running `kitchen list'"
126
- else
127
- result
128
- end
129
- end
130
-
131
- # @return [Logger] the common logger
132
- # @api private
133
- def logger
134
- Kitchen.logger
135
- end
136
-
137
- # Return an array on instances whos name matches the regular expression,
138
- # the full instance name, or the `"all"` literal.
139
- #
140
- # @param arg [String] an instance name, a regular expression, the literal
141
- # `"all"`, or `nil`
142
- # @return [Array<Instance>] an array of instances
143
- # @api private
144
- def parse_subcommand(arg = nil)
145
- arg == "all" ? all_instances : filtered_instances(arg)
146
- end
147
- end
148
-
149
- # Common module to execute a Kitchen action such as create, converge, etc.
150
- #
151
- # @author Fletcher Nichol <fnichol@nichol.ca>
152
- module RunAction
153
-
154
- # Run an instance action (create, converge, setup, verify, destroy) on
155
- # a collection of instances. The instance actions will take place in a
156
- # seperate thread of execution which may or may not be running
157
- # concurrently.
158
- #
159
- # @param action [String] action to perform
160
- # @param instances [Array<Instance>] an array of instances
161
- def run_action(action, instances, *args)
162
- concurrency = 1
163
- if options[:concurrency]
164
- concurrency = options[:concurrency] || instances.size
165
- concurrency = instances.size if concurrency > instances.size
166
- end
167
-
168
- queue = Queue.new
169
- instances.each { |i| queue << i }
170
- concurrency.times { queue << nil }
171
-
172
- threads = []
173
- concurrency.times do
174
- threads << Thread.new do
175
- while instance = queue.pop
176
- instance.public_send(action, *args)
177
- instance.cleanup!
178
- end
179
- end
180
- end
181
- threads.map(&:join)
182
- end
183
- end
184
- end
185
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2013, Fletcher Nichol
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 "thread"
20
+
21
+ module Kitchen
22
+
23
+ module Command
24
+
25
+ # Base class for CLI commands.
26
+ #
27
+ # @author Fletcher Nichol <fnichol@nichol.ca>
28
+ class Base
29
+
30
+ include Logging
31
+
32
+ # Contstructs a new Command object.
33
+ #
34
+ # @param cmd_args [Array] remainder of the arguments from processed ARGV
35
+ # @param cmd_options [Hash] hash of Thor options
36
+ # @param options [Hash] configuration options
37
+ # @option options [String] :action action to take, usually corresponding
38
+ # to the subcommand name (default: `nil`)
39
+ # @option options [proc] :help a callable that displays help for the
40
+ # command
41
+ # @option options [Config] :config a Config object (default: `nil`)
42
+ # @option options [Loader] :loader a Loader object (default: `nil`)
43
+ # @option options [String] :shell a Thor shell object
44
+ def initialize(cmd_args, cmd_options, options = {})
45
+ @args = cmd_args
46
+ @options = cmd_options
47
+ @action = options.fetch(:action, nil)
48
+ @help = options.fetch(:help, -> { "No help provided" })
49
+ @config = options.fetch(:config, nil)
50
+ @loader = options.fetch(:loader, nil)
51
+ @shell = options.fetch(:shell)
52
+ end
53
+
54
+ private
55
+
56
+ # @return [Array] remainder of the arguments from processed ARGV
57
+ # @api private
58
+ attr_reader :args
59
+
60
+ # @return [Hash] hash of Thor options
61
+ # @api private
62
+ attr_reader :options
63
+
64
+ # @return [proc] a callable that displays help for the command
65
+ # @api private
66
+ attr_reader :help
67
+
68
+ # @return [Config] a Config object
69
+ # @api private
70
+ attr_reader :config
71
+
72
+ # @return [Thor::Shell] a Thor shell object
73
+ # @api private
74
+ attr_reader :shell
75
+
76
+ # @return [String] the action to perform
77
+ # @api private
78
+ attr_reader :action
79
+
80
+ # Emit an error message, display contextual help and then exit with a
81
+ # non-zero exit code.
82
+ #
83
+ # **Note** This method calls exit and will not return.
84
+ #
85
+ # @param msg [String] error message
86
+ # @api private
87
+ def die(msg)
88
+ error "\n#{msg}\n\n"
89
+ help.call
90
+ exit 1
91
+ end
92
+
93
+ # @return [Array<Instance>] an array of instances
94
+ # @raise [SystemExit] if no instances are returned
95
+ # @api private
96
+ def all_instances
97
+ result = @config.instances
98
+
99
+ if result.empty?
100
+ die "No instances defined"
101
+ else
102
+ result
103
+ end
104
+ end
105
+
106
+ # Return an array on instances whos name matches the regular expression.
107
+ #
108
+ # @param regexp [Regexp] a regular expression matching on instance names
109
+ # @return [Array<Instance>] an array of instances
110
+ # @raise [SystemExit] if no instances are returned or the regular
111
+ # expression is invalid
112
+ # @api private
113
+ def filtered_instances(regexp)
114
+ result = begin
115
+ @config.instances.get(regexp) ||
116
+ @config.instances.get_all(/#{regexp}/)
117
+ rescue RegexpError => e
118
+ die "Invalid Ruby regular expression, " \
119
+ "you may need to single quote the argument. " \
120
+ "Please try again or consult http://rubular.com/ (#{e.message})"
121
+ end
122
+ result = Array(result)
123
+
124
+ if result.empty?
125
+ die "No instances for regex `#{regexp}', try running `kitchen list'"
126
+ else
127
+ result
128
+ end
129
+ end
130
+
131
+ # @return [Logger] the common logger
132
+ # @api private
133
+ def logger
134
+ Kitchen.logger
135
+ end
136
+
137
+ # Return an array on instances whos name matches the regular expression,
138
+ # the full instance name, or the `"all"` literal.
139
+ #
140
+ # @param arg [String] an instance name, a regular expression, the literal
141
+ # `"all"`, or `nil`
142
+ # @return [Array<Instance>] an array of instances
143
+ # @api private
144
+ def parse_subcommand(arg = nil)
145
+ arg == "all" ? all_instances : filtered_instances(arg)
146
+ end
147
+ end
148
+
149
+ # Common module to execute a Kitchen action such as create, converge, etc.
150
+ #
151
+ # @author Fletcher Nichol <fnichol@nichol.ca>
152
+ module RunAction
153
+
154
+ # Run an instance action (create, converge, setup, verify, destroy) on
155
+ # a collection of instances. The instance actions will take place in a
156
+ # seperate thread of execution which may or may not be running
157
+ # concurrently.
158
+ #
159
+ # @param action [String] action to perform
160
+ # @param instances [Array<Instance>] an array of instances
161
+ def run_action(action, instances, *args)
162
+ concurrency = 1
163
+ if options[:concurrency]
164
+ concurrency = options[:concurrency] || instances.size
165
+ concurrency = instances.size if concurrency > instances.size
166
+ end
167
+
168
+ queue = Queue.new
169
+ instances.each { |i| queue << i }
170
+ concurrency.times { queue << nil }
171
+
172
+ threads = []
173
+ concurrency.times do
174
+ threads << Thread.new do
175
+ while instance = queue.pop
176
+ instance.public_send(action, *args)
177
+ instance.cleanup!
178
+ end
179
+ end
180
+ end
181
+ threads.map(&:join)
182
+ end
183
+ end
184
+ end
185
+ end