test-kitchen 1.6.0 → 1.7.0

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 (180) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +8 -7
  3. data/.github/ISSUE_TEMPLATE.md +56 -0
  4. data/.gitignore +28 -27
  5. data/.kitchen.ci.yml +23 -0
  6. data/.kitchen.proxy.yml +27 -0
  7. data/.rubocop.yml +3 -3
  8. data/.travis.yml +70 -53
  9. data/.yardopts +3 -3
  10. data/Berksfile +3 -0
  11. data/CHANGELOG.md +1083 -1051
  12. data/CONTRIBUTING.md +14 -14
  13. data/Gemfile +19 -14
  14. data/Gemfile.proxy_tests +4 -5
  15. data/Guardfile +42 -42
  16. data/LICENSE +15 -15
  17. data/MAINTAINERS.md +23 -24
  18. data/README.md +135 -135
  19. data/Rakefile +61 -76
  20. data/appveyor.yml +44 -34
  21. data/features/kitchen_action_commands.feature +164 -164
  22. data/features/kitchen_command.feature +16 -16
  23. data/features/kitchen_console_command.feature +34 -34
  24. data/features/kitchen_defaults.feature +38 -38
  25. data/features/kitchen_diagnose_command.feature +96 -96
  26. data/features/kitchen_driver_create_command.feature +64 -64
  27. data/features/kitchen_driver_discover_command.feature +25 -25
  28. data/features/kitchen_help_command.feature +16 -16
  29. data/features/kitchen_init_command.feature +274 -274
  30. data/features/kitchen_list_command.feature +104 -104
  31. data/features/kitchen_login_command.feature +62 -62
  32. data/features/kitchen_sink_command.feature +30 -30
  33. data/features/kitchen_test_command.feature +88 -88
  34. data/features/step_definitions/gem_steps.rb +36 -36
  35. data/features/step_definitions/git_steps.rb +5 -5
  36. data/features/step_definitions/output_steps.rb +5 -5
  37. data/features/support/env.rb +75 -75
  38. data/lib/kitchen.rb +150 -150
  39. data/lib/kitchen/base64_stream.rb +55 -55
  40. data/lib/kitchen/cli.rb +419 -419
  41. data/lib/kitchen/collection.rb +55 -55
  42. data/lib/kitchen/color.rb +65 -65
  43. data/lib/kitchen/command.rb +185 -185
  44. data/lib/kitchen/command/action.rb +45 -45
  45. data/lib/kitchen/command/console.rb +58 -58
  46. data/lib/kitchen/command/diagnose.rb +92 -92
  47. data/lib/kitchen/command/driver_discover.rb +105 -105
  48. data/lib/kitchen/command/exec.rb +41 -41
  49. data/lib/kitchen/command/list.rb +119 -119
  50. data/lib/kitchen/command/login.rb +43 -43
  51. data/lib/kitchen/command/sink.rb +54 -54
  52. data/lib/kitchen/command/test.rb +51 -51
  53. data/lib/kitchen/config.rb +322 -322
  54. data/lib/kitchen/configurable.rb +529 -529
  55. data/lib/kitchen/data_munger.rb +959 -960
  56. data/lib/kitchen/diagnostic.rb +141 -141
  57. data/lib/kitchen/driver.rb +56 -56
  58. data/lib/kitchen/driver/base.rb +134 -134
  59. data/lib/kitchen/driver/dummy.rb +108 -108
  60. data/lib/kitchen/driver/proxy.rb +72 -72
  61. data/lib/kitchen/driver/ssh_base.rb +357 -357
  62. data/lib/kitchen/errors.rb +229 -229
  63. data/lib/kitchen/generator/driver_create.rb +177 -177
  64. data/lib/kitchen/generator/init.rb +296 -296
  65. data/lib/kitchen/instance.rb +662 -662
  66. data/lib/kitchen/lazy_hash.rb +142 -142
  67. data/lib/kitchen/loader/yaml.rb +349 -349
  68. data/lib/kitchen/logger.rb +423 -423
  69. data/lib/kitchen/logging.rb +56 -56
  70. data/lib/kitchen/login_command.rb +52 -52
  71. data/lib/kitchen/metadata_chopper.rb +52 -52
  72. data/lib/kitchen/platform.rb +67 -67
  73. data/lib/kitchen/provisioner.rb +54 -54
  74. data/lib/kitchen/provisioner/base.rb +236 -236
  75. data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
  76. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
  77. data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
  78. data/lib/kitchen/provisioner/chef_apply.rb +124 -125
  79. data/lib/kitchen/provisioner/chef_base.rb +341 -294
  80. data/lib/kitchen/provisioner/chef_solo.rb +88 -89
  81. data/lib/kitchen/provisioner/chef_zero.rb +245 -245
  82. data/lib/kitchen/provisioner/dummy.rb +79 -79
  83. data/lib/kitchen/provisioner/shell.rb +138 -138
  84. data/lib/kitchen/rake_tasks.rb +63 -63
  85. data/lib/kitchen/shell_out.rb +93 -93
  86. data/lib/kitchen/ssh.rb +276 -276
  87. data/lib/kitchen/state_file.rb +120 -120
  88. data/lib/kitchen/suite.rb +51 -51
  89. data/lib/kitchen/thor_tasks.rb +66 -66
  90. data/lib/kitchen/transport.rb +54 -54
  91. data/lib/kitchen/transport/base.rb +176 -176
  92. data/lib/kitchen/transport/dummy.rb +79 -79
  93. data/lib/kitchen/transport/ssh.rb +364 -364
  94. data/lib/kitchen/transport/winrm.rb +486 -486
  95. data/lib/kitchen/util.rb +147 -147
  96. data/lib/kitchen/verifier.rb +55 -55
  97. data/lib/kitchen/verifier/base.rb +235 -235
  98. data/lib/kitchen/verifier/busser.rb +277 -277
  99. data/lib/kitchen/verifier/dummy.rb +79 -79
  100. data/lib/kitchen/verifier/shell.rb +101 -101
  101. data/lib/kitchen/version.rb +21 -21
  102. data/lib/vendor/hash_recursive_merge.rb +82 -82
  103. data/spec/kitchen/base64_stream_spec.rb +77 -77
  104. data/spec/kitchen/cli_spec.rb +56 -56
  105. data/spec/kitchen/collection_spec.rb +80 -80
  106. data/spec/kitchen/color_spec.rb +54 -54
  107. data/spec/kitchen/config_spec.rb +408 -408
  108. data/spec/kitchen/configurable_spec.rb +1095 -1062
  109. data/spec/kitchen/data_munger_spec.rb +2694 -2383
  110. data/spec/kitchen/diagnostic_spec.rb +129 -129
  111. data/spec/kitchen/driver/base_spec.rb +121 -121
  112. data/spec/kitchen/driver/dummy_spec.rb +199 -199
  113. data/spec/kitchen/driver/proxy_spec.rb +138 -138
  114. data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
  115. data/spec/kitchen/driver_spec.rb +112 -112
  116. data/spec/kitchen/errors_spec.rb +309 -309
  117. data/spec/kitchen/instance_spec.rb +1419 -1419
  118. data/spec/kitchen/lazy_hash_spec.rb +117 -117
  119. data/spec/kitchen/loader/yaml_spec.rb +774 -774
  120. data/spec/kitchen/logger_spec.rb +429 -429
  121. data/spec/kitchen/logging_spec.rb +59 -59
  122. data/spec/kitchen/login_command_spec.rb +68 -68
  123. data/spec/kitchen/metadata_chopper_spec.rb +82 -82
  124. data/spec/kitchen/platform_spec.rb +89 -89
  125. data/spec/kitchen/provisioner/base_spec.rb +386 -386
  126. data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
  127. data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1067
  128. data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
  129. data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
  130. data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
  131. data/spec/kitchen/provisioner/shell_spec.rb +566 -566
  132. data/spec/kitchen/provisioner_spec.rb +107 -107
  133. data/spec/kitchen/shell_out_spec.rb +150 -150
  134. data/spec/kitchen/ssh_spec.rb +693 -693
  135. data/spec/kitchen/state_file_spec.rb +129 -129
  136. data/spec/kitchen/suite_spec.rb +62 -62
  137. data/spec/kitchen/transport/base_spec.rb +89 -89
  138. data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
  139. data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
  140. data/spec/kitchen/transport_spec.rb +112 -112
  141. data/spec/kitchen/util_spec.rb +165 -165
  142. data/spec/kitchen/verifier/base_spec.rb +362 -362
  143. data/spec/kitchen/verifier/busser_spec.rb +610 -610
  144. data/spec/kitchen/verifier/dummy_spec.rb +99 -99
  145. data/spec/kitchen/verifier/shell_spec.rb +160 -158
  146. data/spec/kitchen/verifier_spec.rb +120 -120
  147. data/spec/kitchen_spec.rb +114 -114
  148. data/spec/spec_helper.rb +85 -85
  149. data/spec/support/powershell_max_size_spec.rb +40 -40
  150. data/support/busser_install_command.ps1 +14 -14
  151. data/support/busser_install_command.sh +14 -14
  152. data/support/chef-client-zero.rb +77 -77
  153. data/support/chef_base_init_command.ps1 +18 -18
  154. data/support/chef_base_init_command.sh +2 -2
  155. data/support/chef_base_install_command.ps1 +85 -85
  156. data/support/chef_base_install_command.sh +229 -229
  157. data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
  158. data/support/chef_zero_prepare_command_legacy.sh +10 -10
  159. data/support/download_helpers.sh +109 -109
  160. data/support/dummy-validation.pem +27 -27
  161. data/templates/driver/CHANGELOG.md.erb +3 -3
  162. data/templates/driver/Gemfile.erb +3 -3
  163. data/templates/driver/README.md.erb +64 -64
  164. data/templates/driver/Rakefile.erb +21 -21
  165. data/templates/driver/driver.rb.erb +23 -23
  166. data/templates/driver/gemspec.erb +29 -29
  167. data/templates/driver/gitignore.erb +17 -17
  168. data/templates/driver/license_apachev2.erb +15 -15
  169. data/templates/driver/license_lgplv3.erb +16 -16
  170. data/templates/driver/license_mit.erb +22 -22
  171. data/templates/driver/license_reserved.erb +5 -5
  172. data/templates/driver/tailor.erb +4 -4
  173. data/templates/driver/travis.yml.erb +11 -11
  174. data/templates/driver/version.rb.erb +12 -12
  175. data/templates/init/chefignore.erb +1 -1
  176. data/templates/init/kitchen.yml.erb +18 -18
  177. data/test-kitchen.gemspec +62 -62
  178. data/test/integration/default/default_spec.rb +3 -0
  179. data/testing_windows.md +37 -37
  180. metadata +23 -11
@@ -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