test-kitchen 1.2.1 → 1.3.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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +1 -1
  3. data/.rubocop.yml +3 -0
  4. data/.travis.yml +20 -9
  5. data/CHANGELOG.md +219 -108
  6. data/Gemfile +10 -6
  7. data/Guardfile +38 -9
  8. data/README.md +11 -1
  9. data/Rakefile +21 -37
  10. data/bin/kitchen +4 -4
  11. data/features/kitchen_action_commands.feature +161 -0
  12. data/features/kitchen_console_command.feature +34 -0
  13. data/features/kitchen_diagnose_command.feature +64 -0
  14. data/features/kitchen_init_command.feature +29 -17
  15. data/features/kitchen_list_command.feature +2 -2
  16. data/features/kitchen_login_command.feature +56 -0
  17. data/features/{sink_command.feature → kitchen_sink_command.feature} +0 -0
  18. data/features/kitchen_test_command.feature +88 -0
  19. data/features/step_definitions/gem_steps.rb +8 -6
  20. data/features/step_definitions/git_steps.rb +4 -2
  21. data/features/step_definitions/output_steps.rb +5 -0
  22. data/features/support/env.rb +12 -9
  23. data/lib/kitchen.rb +60 -38
  24. data/lib/kitchen/base64_stream.rb +55 -0
  25. data/lib/kitchen/busser.rb +124 -58
  26. data/lib/kitchen/cli.rb +121 -38
  27. data/lib/kitchen/collection.rb +3 -3
  28. data/lib/kitchen/color.rb +4 -4
  29. data/lib/kitchen/command.rb +78 -11
  30. data/lib/kitchen/command/action.rb +3 -2
  31. data/lib/kitchen/command/console.rb +12 -5
  32. data/lib/kitchen/command/diagnose.rb +17 -3
  33. data/lib/kitchen/command/driver_discover.rb +26 -7
  34. data/lib/kitchen/command/exec.rb +41 -0
  35. data/lib/kitchen/command/list.rb +44 -14
  36. data/lib/kitchen/command/login.rb +2 -1
  37. data/lib/kitchen/command/sink.rb +2 -1
  38. data/lib/kitchen/command/test.rb +5 -4
  39. data/lib/kitchen/config.rb +146 -14
  40. data/lib/kitchen/configurable.rb +314 -0
  41. data/lib/kitchen/data_munger.rb +522 -18
  42. data/lib/kitchen/diagnostic.rb +43 -4
  43. data/lib/kitchen/driver.rb +4 -4
  44. data/lib/kitchen/driver/base.rb +80 -115
  45. data/lib/kitchen/driver/dummy.rb +34 -6
  46. data/lib/kitchen/driver/proxy.rb +14 -3
  47. data/lib/kitchen/driver/ssh_base.rb +61 -7
  48. data/lib/kitchen/errors.rb +109 -9
  49. data/lib/kitchen/generator/driver_create.rb +39 -5
  50. data/lib/kitchen/generator/init.rb +130 -45
  51. data/lib/kitchen/instance.rb +162 -28
  52. data/lib/kitchen/lazy_hash.rb +79 -7
  53. data/lib/kitchen/loader/yaml.rb +159 -27
  54. data/lib/kitchen/logger.rb +267 -21
  55. data/lib/kitchen/logging.rb +30 -3
  56. data/lib/kitchen/login_command.rb +11 -2
  57. data/lib/kitchen/metadata_chopper.rb +2 -2
  58. data/lib/kitchen/provisioner.rb +4 -4
  59. data/lib/kitchen/provisioner/base.rb +107 -103
  60. data/lib/kitchen/provisioner/chef/berkshelf.rb +36 -8
  61. data/lib/kitchen/provisioner/chef/librarian.rb +40 -11
  62. data/lib/kitchen/provisioner/chef_base.rb +206 -167
  63. data/lib/kitchen/provisioner/chef_solo.rb +25 -7
  64. data/lib/kitchen/provisioner/chef_zero.rb +105 -29
  65. data/lib/kitchen/provisioner/dummy.rb +1 -1
  66. data/lib/kitchen/provisioner/shell.rb +21 -6
  67. data/lib/kitchen/rake_tasks.rb +8 -3
  68. data/lib/kitchen/shell_out.rb +15 -18
  69. data/lib/kitchen/ssh.rb +122 -27
  70. data/lib/kitchen/state_file.rb +24 -7
  71. data/lib/kitchen/thor_tasks.rb +9 -4
  72. data/lib/kitchen/util.rb +43 -118
  73. data/lib/kitchen/version.rb +1 -1
  74. data/lib/vendor/hash_recursive_merge.rb +10 -2
  75. data/spec/kitchen/base64_stream_spec.rb +77 -0
  76. data/spec/kitchen/busser_spec.rb +490 -0
  77. data/spec/kitchen/collection_spec.rb +10 -10
  78. data/spec/kitchen/color_spec.rb +2 -2
  79. data/spec/kitchen/config_spec.rb +234 -62
  80. data/spec/kitchen/configurable_spec.rb +490 -0
  81. data/spec/kitchen/data_munger_spec.rb +1070 -862
  82. data/spec/kitchen/diagnostic_spec.rb +79 -0
  83. data/spec/kitchen/driver/base_spec.rb +80 -85
  84. data/spec/kitchen/driver/dummy_spec.rb +43 -14
  85. data/spec/kitchen/driver/proxy_spec.rb +134 -0
  86. data/spec/kitchen/driver/ssh_base_spec.rb +644 -0
  87. data/spec/kitchen/driver_spec.rb +15 -15
  88. data/spec/kitchen/errors_spec.rb +309 -0
  89. data/spec/kitchen/instance_spec.rb +143 -46
  90. data/spec/kitchen/lazy_hash_spec.rb +36 -9
  91. data/spec/kitchen/loader/yaml_spec.rb +237 -226
  92. data/spec/kitchen/logger_spec.rb +419 -0
  93. data/spec/kitchen/logging_spec.rb +59 -0
  94. data/spec/kitchen/login_command_spec.rb +49 -0
  95. data/spec/kitchen/metadata_chopper_spec.rb +82 -0
  96. data/spec/kitchen/platform_spec.rb +4 -4
  97. data/spec/kitchen/provisioner/base_spec.rb +65 -125
  98. data/spec/kitchen/provisioner/chef_base_spec.rb +798 -0
  99. data/spec/kitchen/provisioner/chef_solo_spec.rb +316 -0
  100. data/spec/kitchen/provisioner/chef_zero_spec.rb +624 -0
  101. data/spec/kitchen/provisioner/shell_spec.rb +269 -0
  102. data/spec/kitchen/provisioner_spec.rb +6 -6
  103. data/spec/kitchen/shell_out_spec.rb +143 -0
  104. data/spec/kitchen/ssh_spec.rb +683 -0
  105. data/spec/kitchen/state_file_spec.rb +28 -21
  106. data/spec/kitchen/suite_spec.rb +7 -7
  107. data/spec/kitchen/util_spec.rb +68 -10
  108. data/spec/kitchen_spec.rb +107 -0
  109. data/spec/spec_helper.rb +18 -13
  110. data/support/chef-client-zero.rb +10 -9
  111. data/support/chef_helpers.sh +16 -0
  112. data/support/download_helpers.sh +109 -0
  113. data/test-kitchen.gemspec +42 -33
  114. metadata +107 -33
@@ -16,7 +16,7 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'delegate'
19
+ require "delegate"
20
20
 
21
21
  module Kitchen
22
22
 
@@ -42,14 +42,14 @@ module Kitchen
42
42
  # @return [Kitchen::Config::Collection<Object>] a new collection of
43
43
  # matched objects
44
44
  def get_all(regexp)
45
- Kitchen::Collection.new(__getobj__.find_all { |i| i.name =~ regexp })
45
+ Kitchen::Collection.new(__getobj__.select { |i| i.name =~ regexp })
46
46
  end
47
47
 
48
48
  # Returns an Array of names from the collection as strings.
49
49
  #
50
50
  # @return [Array<String>] array of name strings
51
51
  def as_names
52
- __getobj__.map { |i| i.name }
52
+ __getobj__.map(&:name)
53
53
  end
54
54
  end
55
55
  end
@@ -33,10 +33,10 @@ module Kitchen
33
33
  :bright_cyan => 96, :bright_white => 97
34
34
  }.freeze
35
35
 
36
- COLORS = %w(
36
+ COLORS = %w[
37
37
  cyan yellow green magenta blue bright_cyan bright_yellow
38
38
  bright_green bright_magenta bright_blue
39
- ).freeze
39
+ ].freeze
40
40
 
41
41
  # Returns an ansi escaped string representing a color control sequence.
42
42
  #
@@ -46,8 +46,8 @@ module Kitchen
46
46
  # empty string otherwise
47
47
  def self.escape(name)
48
48
  return "" if name.nil?
49
- return "" unless ansi = ANSI[name]
50
- "\e[#{ansi}m"
49
+ return "" unless ANSI[name]
50
+ "\e[#{ANSI[name]}m"
51
51
  end
52
52
 
53
53
  # Returns a colorized ansi escaped string with the given color.
@@ -16,7 +16,7 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'thread'
19
+ require "thread"
20
20
 
21
21
  module Kitchen
22
22
 
@@ -29,27 +29,71 @@ module Kitchen
29
29
 
30
30
  include Logging
31
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
32
44
  def initialize(cmd_args, cmd_options, options = {})
33
45
  @args = cmd_args
34
46
  @options = cmd_options
35
47
  @action = options.fetch(:action, nil)
36
- @help = options.fetch(:help, lambda { "No help provided" })
48
+ @help = options.fetch(:help, -> { "No help provided" })
37
49
  @config = options.fetch(:config, nil)
38
50
  @loader = options.fetch(:loader, nil)
39
51
  @shell = options.fetch(:shell)
40
52
  end
41
53
 
42
- protected
54
+ private
43
55
 
44
- attr_reader :args, :options, :help, :config, :shell, :action
56
+ # @return [Array] remainder of the arguments from processed ARGV
57
+ # @api private
58
+ attr_reader :args
45
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
46
87
  def die(msg)
47
88
  error "\n#{msg}\n\n"
48
89
  help.call
49
90
  exit 1
50
91
  end
51
92
 
52
- def get_all_instances
93
+ # @return [Array<Instance>] an array of instances
94
+ # @raise [SystemExit] if no instances are returned
95
+ # @api private
96
+ def all_instances
53
97
  result = @config.instances
54
98
 
55
99
  if result.empty?
@@ -59,13 +103,20 @@ module Kitchen
59
103
  end
60
104
  end
61
105
 
62
- def get_filtered_instances(regexp)
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)
63
114
  result = begin
64
115
  @config.instances.get(regexp) ||
65
116
  @config.instances.get_all(/#{regexp}/)
66
117
  rescue RegexpError => e
67
- die "Invalid Ruby regular expression, " +
68
- "you may need to single quote the argument. " +
118
+ die "Invalid Ruby regular expression, " \
119
+ "you may need to single quote the argument. " \
69
120
  "Please try again or consult http://rubular.com/ (#{e.message})"
70
121
  end
71
122
  result = Array(result)
@@ -77,12 +128,21 @@ module Kitchen
77
128
  end
78
129
  end
79
130
 
131
+ # @return [Logger] the common logger
132
+ # @api private
80
133
  def logger
81
134
  Kitchen.logger
82
135
  end
83
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
84
144
  def parse_subcommand(arg = nil)
85
- arg == "all" ? get_all_instances : get_filtered_instances(arg)
145
+ arg == "all" ? all_instances : filtered_instances(arg)
86
146
  end
87
147
  end
88
148
 
@@ -91,6 +151,13 @@ module Kitchen
91
151
  # @author Fletcher Nichol <fnichol@nichol.ca>
92
152
  module RunAction
93
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
94
161
  def run_action(action, instances, *args)
95
162
  concurrency = 1
96
163
  if options[:concurrency]
@@ -99,7 +166,7 @@ module Kitchen
99
166
  end
100
167
 
101
168
  queue = Queue.new
102
- instances.each {|i| queue << i }
169
+ instances.each { |i| queue << i }
103
170
  concurrency.times { queue << nil }
104
171
 
105
172
  threads = []
@@ -110,7 +177,7 @@ module Kitchen
110
177
  end
111
178
  end
112
179
  end
113
- threads.map { |i| i.join }
180
+ threads.map(&:join)
114
181
  end
115
182
  end
116
183
  end
@@ -16,9 +16,9 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'kitchen/command'
19
+ require "kitchen/command"
20
20
 
21
- require 'benchmark'
21
+ require "benchmark"
22
22
 
23
23
  module Kitchen
24
24
 
@@ -31,6 +31,7 @@ module Kitchen
31
31
 
32
32
  include RunAction
33
33
 
34
+ # Invoke the command.
34
35
  def call
35
36
  banner "Starting Kitchen (v#{Kitchen::VERSION})"
36
37
  elapsed = Benchmark.measure do
@@ -16,7 +16,7 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'kitchen/command'
19
+ require "kitchen/command"
20
20
 
21
21
  module Kitchen
22
22
 
@@ -27,20 +27,27 @@ module Kitchen
27
27
  # @author Fletcher Nichol <fnichol@nichol.ca>
28
28
  class Console < Kitchen::Command::Base
29
29
 
30
+ # Invoke the command.
30
31
  def call
31
- require 'pry'
32
+ require "pry"
32
33
  Pry.start(@config, :prompt => [prompt(">"), prompt("*")])
33
- rescue LoadError => e
34
+ rescue LoadError
34
35
  warn %{Make sure you have the pry gem installed. You can install it with:}
35
36
  warn %{`gem install pry` or including 'gem "pry"' in your Gemfile.}
36
37
  exit 1
37
38
  end
38
39
 
39
- protected
40
+ private
40
41
 
42
+ # Construct a custom Pry prompt proc.
43
+ #
44
+ # @param char [String] prompt character
45
+ # @return [proc] a prompt proc
46
+ # @api private
41
47
  def prompt(char)
42
48
  proc { |target_self, nest_level, pry|
43
- ["[#{pry.input_array.size}] ",
49
+ [
50
+ "[#{pry.input_array.size}] ",
44
51
  "kc(#{Pry.view_clip(target_self.class)})",
45
52
  "#{":#{nest_level}" unless nest_level.zero?}#{char} "
46
53
  ].join
@@ -16,10 +16,10 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'kitchen/command'
20
- require 'kitchen/diagnostic'
19
+ require "kitchen/command"
20
+ require "kitchen/diagnostic"
21
21
 
22
- require 'yaml'
22
+ require "yaml"
23
23
 
24
24
  module Kitchen
25
25
 
@@ -30,6 +30,7 @@ module Kitchen
30
30
  # @author Fletcher Nichol <fnichol@nichol.ca>
31
31
  class Diagnose < Kitchen::Command::Base
32
32
 
33
+ # Invoke the command.
33
34
  def call
34
35
  instances = record_failure { load_instances }
35
36
 
@@ -41,6 +42,10 @@ module Kitchen
41
42
 
42
43
  private
43
44
 
45
+ # Loads and returns instances if they are requested.
46
+ #
47
+ # @return [Array<Instance>] an array of instances or an empty array
48
+ # @api private
44
49
  def load_instances
45
50
  if options[:all] || options[:instances]
46
51
  parse_subcommand(args.first)
@@ -49,6 +54,10 @@ module Kitchen
49
54
  end
50
55
  end
51
56
 
57
+ # Loads and returns loader configuration if it is requested.
58
+ #
59
+ # @return [Hash,nil] a hash or nil
60
+ # @api private
52
61
  def load_loader
53
62
  if options[:all] || options[:loader]
54
63
  @loader
@@ -57,6 +66,11 @@ module Kitchen
57
66
  end
58
67
  end
59
68
 
69
+ # Returns a hash with exception detail if an exception is raised in the
70
+ # yielded block.
71
+ #
72
+ # @return [yield,Hash] the result of the yielded block or an error hash
73
+ # @api private
60
74
  def record_failure
61
75
  yield
62
76
  rescue => e
@@ -16,10 +16,9 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'kitchen/command'
19
+ require "kitchen/command"
20
20
 
21
- require 'rubygems/spec_fetcher'
22
- require 'safe_yaml'
21
+ require "rubygems/spec_fetcher"
23
22
 
24
23
  module Kitchen
25
24
 
@@ -30,6 +29,7 @@ module Kitchen
30
29
  # @author Fletcher Nichol <fnichol@nichol.ca>
31
30
  class DriverDiscover < Kitchen::Command::Base
32
31
 
32
+ # Invoke the command.
33
33
  def call
34
34
  specs = fetch_gem_specs.sort { |x, y| x[0] <=> y[0] }
35
35
  specs = specs[0, 49].push(["...", "..."]) if specs.size > 49
@@ -37,33 +37,52 @@ module Kitchen
37
37
  print_table(specs, :indent => 4)
38
38
  end
39
39
 
40
- protected
40
+ private
41
41
 
42
+ # Fetches Kitchen-related RubyGems and returns an array of name/version
43
+ # tuples.
44
+ #
45
+ # @return [Array<Array>] an array of name/version tuples
46
+ # @api private
42
47
  def fetch_gem_specs
43
- SafeYAML::OPTIONS[:suppress_warnings] = true
44
48
  req = Gem::Requirement.default
45
49
  dep = Gem::Deprecate.skip_during do
46
50
  Gem::Dependency.new(/kitchen-/i, req)
47
51
  end
48
52
  fetcher = Gem::SpecFetcher.fetcher
49
53
 
50
- specs = if fetcher.respond_to?(:find_matching)
54
+ if fetcher.respond_to?(:find_matching)
51
55
  fetch_gem_specs_pre_rubygems_2(fetcher, dep)
52
56
  else
53
57
  fetch_gem_specs_post_rubygems_2(fetcher, dep)
54
58
  end
55
59
  end
56
60
 
61
+ # Fetches gem specs for RubyGems 2 and later.
62
+ #
63
+ # @param fetcher [Gem::SpecFetcher] a gemspec fetcher
64
+ # @param dep [Gem::Dependency] a gem dependency object
65
+ # @return [Array<Array>] an array of name/version tuples
66
+ # @api private
57
67
  def fetch_gem_specs_post_rubygems_2(fetcher, dep)
58
68
  specs = fetcher.spec_for_dependency(dep, false)
59
69
  specs.first.map { |t| [t.first.name, t.first.version] }
60
70
  end
61
71
 
72
+ # Fetches gem specs for pre-RubyGems 2.
73
+ #
74
+ # @param fetcher [Gem::SpecFetcher] a gemspec fetcher
75
+ # @param dep [Gem::Dependency] a gem dependency object
76
+ # @return [Array<Array>] an array of name/version tuples
77
+ # @api private
62
78
  def fetch_gem_specs_pre_rubygems_2(fetcher, dep)
63
79
  specs = fetcher.find_matching(dep, false, false, false)
64
- specs.map { |t| t.first }.map { |t| t[0, 2] }
80
+ specs.map(&:first).map { |t| t[0, 2] }
65
81
  end
66
82
 
83
+ # Print out a display table.
84
+ #
85
+ # @api private
67
86
  def print_table(*args)
68
87
  shell.print_table(*args)
69
88
  end
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: SAWANOBORI Yukihiko (<sawanoboriyu@higanworks.com>)
4
+ #
5
+ # Copyright (C) 2014, HiganWorks LLC
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 "kitchen/command"
20
+
21
+ module Kitchen
22
+
23
+ module Command
24
+
25
+ # Execute command on remote instance.
26
+ #
27
+ # @author SAWANOBORI Yukihiko (<sawanoboriyu@higanworks.com>)
28
+ class Exec < Kitchen::Command::Base
29
+
30
+ # Invoke the command.
31
+ def call
32
+ results = parse_subcommand(args.first)
33
+
34
+ results.each do |instance|
35
+ banner "Execute command on #{instance.name}."
36
+ instance.remote_exec(options[:command])
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -16,7 +16,7 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'kitchen/command'
19
+ require "kitchen/command"
20
20
 
21
21
  module Kitchen
22
22
 
@@ -27,24 +27,36 @@ module Kitchen
27
27
  # @author Fletcher Nichol <fnichol@nichol.ca>
28
28
  class List < Kitchen::Command::Base
29
29
 
30
+ # Invoke the command.
30
31
  def call
31
32
  result = parse_subcommand(args.first)
32
33
  if options[:debug]
33
- die "The --debug flag on the list subcommand is deprecated, " +
34
+ die "The --debug flag on the list subcommand is deprecated, " \
34
35
  "please use `kitchen diagnose'."
35
36
  elsif options[:bare]
36
- puts Array(result).map { |i| i.name }.join("\n")
37
+ puts Array(result).map(&:name).join("\n")
37
38
  else
38
39
  list_table(result)
39
40
  end
40
41
  end
41
42
 
42
- protected
43
+ private
43
44
 
45
+ # Add a trailing ansi color escape code to line up columns of colored
46
+ # output.
47
+ #
48
+ # @param string [String] a string
49
+ # @return [String]
50
+ # @api private
44
51
  def color_pad(string)
45
- string + set_color("", :white)
52
+ string + colorize("", :white)
46
53
  end
47
54
 
55
+ # Generate the display rows for an instance.
56
+ #
57
+ # @param instance [Instance] an instance
58
+ # @return [Array<String>]
59
+ # @api private
48
60
  def display_instance(instance)
49
61
  [
50
62
  color_pad(instance.name),
@@ -54,31 +66,49 @@ module Kitchen
54
66
  ]
55
67
  end
56
68
 
69
+ # Format and color the given last action.
70
+ #
71
+ # @param [String] the last action
72
+ # @return [String] formated last action
73
+ # @api private
57
74
  def format_last_action(last_action)
58
75
  case last_action
59
- when 'create' then set_color("Created", :cyan)
60
- when 'converge' then set_color("Converged", :magenta)
61
- when 'setup' then set_color("Set Up", :blue)
62
- when 'verify' then set_color("Verified", :yellow)
63
- when nil then set_color("<Not Created>", :red)
64
- else set_color("<Unknown>", :white)
76
+ when "create" then colorize("Created", :cyan)
77
+ when "converge" then colorize("Converged", :magenta)
78
+ when "setup" then colorize("Set Up", :blue)
79
+ when "verify" then colorize("Verified", :yellow)
80
+ when nil then colorize("<Not Created>", :red)
81
+ else colorize("<Unknown>", :white)
65
82
  end
66
83
  end
67
84
 
85
+ # Constructs a list display table and output it to the screen.
86
+ #
87
+ # @param result [Array<Instance>] an array of instances
88
+ # @api private
68
89
  def list_table(result)
69
90
  table = [
70
- [set_color("Instance", :green), set_color("Driver", :green),
71
- set_color("Provisioner", :green), set_color("Last Action", :green)]
91
+ [
92
+ colorize("Instance", :green), colorize("Driver", :green),
93
+ colorize("Provisioner", :green), colorize("Last Action", :green)
94
+ ]
72
95
  ]
73
96
  table += Array(result).map { |i| display_instance(i) }
74
97
  print_table(table)
75
98
  end
76
99
 
100
+ # Outputs a formatted display table.
101
+ #
102
+ # @api private
77
103
  def print_table(*args)
78
104
  shell.print_table(*args)
79
105
  end
80
106
 
81
- def set_color(*args)
107
+ # Colorize a string.
108
+ #
109
+ # @return [String] a colorized string
110
+ # @api private
111
+ def colorize(*args)
82
112
  shell.set_color(*args)
83
113
  end
84
114
  end