test-kitchen 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,3 +1,4 @@
1
+ # -*- encoding: utf-8 -*-
1
2
  #
2
3
  # Author:: Seth Chisamore <schisamo@opscode.com>
3
4
  #
@@ -17,13 +18,17 @@
17
18
  # limitations under the License.
18
19
  #
19
20
 
20
- require 'kitchen/driver/ssh_base'
21
+ require "kitchen"
21
22
 
22
23
  module Kitchen
23
24
 
24
25
  module Driver
25
26
 
26
- # Proxy driver for Test Kitchen.
27
+ # Simple driver that proxies commands through to a test instance whose
28
+ # lifecycle is not managed by Test Kitchen. This driver is useful for long-
29
+ # lived non-ephemeral test instances that are simply "reset" between test
30
+ # runs. Think executing against devices like network switches--this is why
31
+ # the driver was created.
27
32
  #
28
33
  # @author Seth Chisamore <schisamo@opscode.com>
29
34
  class Proxy < Kitchen::Driver::SSHBase
@@ -33,11 +38,13 @@ module Kitchen
33
38
 
34
39
  no_parallel_for :create, :destroy
35
40
 
41
+ # (see Base#create)
36
42
  def create(state)
37
43
  state[:hostname] = config[:host]
38
44
  reset_instance(state)
39
45
  end
40
46
 
47
+ # (see Base#destroy)
41
48
  def destroy(state)
42
49
  return if state[:hostname].nil?
43
50
  reset_instance(state)
@@ -46,13 +53,17 @@ module Kitchen
46
53
 
47
54
  private
48
55
 
56
+ # Resets the non-Kitchen managed instance using by issuing a command
57
+ # over SSH.
58
+ #
59
+ # @param state [Hash] the state hash
60
+ # @api private
49
61
  def reset_instance(state)
50
62
  if cmd = config[:reset_command]
51
63
  info("Resetting instance state with command: #{cmd}")
52
64
  ssh(build_ssh_args(state), cmd)
53
65
  end
54
66
  end
55
-
56
67
  end
57
68
  end
58
69
  end
@@ -31,10 +31,12 @@ module Kitchen
31
31
  default_config :sudo, true
32
32
  default_config :port, 22
33
33
 
34
- def create(state)
34
+ # (see Base#create)
35
+ def create(state) # rubocop:disable Lint/UnusedMethodArgument
35
36
  raise ClientError, "#{self.class}#create must be implemented"
36
37
  end
37
38
 
39
+ # (see Base#converge)
38
40
  def converge(state)
39
41
  provisioner = instance.provisioner
40
42
  provisioner.create_sandbox
@@ -51,35 +53,61 @@ module Kitchen
51
53
  provisioner && provisioner.cleanup_sandbox
52
54
  end
53
55
 
56
+ # (see Base#setup)
54
57
  def setup(state)
55
58
  Kitchen::SSH.new(*build_ssh_args(state)) do |conn|
56
- run_remote(busser_setup_cmd, conn)
59
+ run_remote(busser.setup_cmd, conn)
57
60
  end
58
61
  end
59
62
 
63
+ # (see Base#verify)
60
64
  def verify(state)
61
65
  Kitchen::SSH.new(*build_ssh_args(state)) do |conn|
62
- run_remote(busser_sync_cmd, conn)
63
- run_remote(busser_run_cmd, conn)
66
+ run_remote(busser.sync_cmd, conn)
67
+ run_remote(busser.run_cmd, conn)
64
68
  end
65
69
  end
66
70
 
67
- def destroy(state)
71
+ # (see Base#destroy)
72
+ def destroy(state) # rubocop:disable Lint/UnusedMethodArgument
68
73
  raise ClientError, "#{self.class}#destroy must be implemented"
69
74
  end
70
75
 
76
+ # (see Base#login_command)
71
77
  def login_command(state)
72
78
  SSH.new(*build_ssh_args(state)).login_command
73
79
  end
74
80
 
81
+ # Executes an arbitrary command on an instance over an SSH connection.
82
+ #
83
+ # @param state [Hash] mutable instance and driver state
84
+ # @param command [String] the command to be executed
85
+ # @raise [ActionFailed] if the command could not be successfully completed
86
+ def remote_command(state, command)
87
+ Kitchen::SSH.new(*build_ssh_args(state)) do |conn|
88
+ run_remote(command, conn)
89
+ end
90
+ end
91
+
92
+ # **(Deprecated)** Executes a remote command over SSH.
93
+ #
94
+ # @param ssh_args [Array] ssh arguments
95
+ # @param command [String] remote command to invoke
96
+ # @deprecated This method should no longer be called directly and exists
97
+ # to support very old drivers. This will be removed in the future.
75
98
  def ssh(ssh_args, command)
76
99
  Kitchen::SSH.new(*ssh_args) do |conn|
77
100
  run_remote(command, conn)
78
101
  end
79
102
  end
80
103
 
81
- protected
104
+ private
82
105
 
106
+ # Builds arguments for constructing a `Kitchen::SSH` instance.
107
+ #
108
+ # @param state [Hash] state hash
109
+ # @return [Array] SSH constructor arguments
110
+ # @api private
83
111
  def build_ssh_args(state)
84
112
  combined = config.to_hash.merge(state)
85
113
 
@@ -96,6 +124,12 @@ module Kitchen
96
124
  [combined[:hostname], combined[:username], opts]
97
125
  end
98
126
 
127
+ # Adds http and https proxy environment variables to a command, if set
128
+ # in configuration data.
129
+ #
130
+ # @param cmd [String] command string
131
+ # @return [String] command string
132
+ # @api private
99
133
  def env_cmd(cmd)
100
134
  env = "env"
101
135
  env << " http_proxy=#{config[:http_proxy]}" if config[:http_proxy]
@@ -104,6 +138,12 @@ module Kitchen
104
138
  env == "env" ? cmd : "#{env} #{cmd}"
105
139
  end
106
140
 
141
+ # Executes a remote command over SSH.
142
+ #
143
+ # @param command [String] remove command to run
144
+ # @param connection [Kitchen::SSH] an SSH connection
145
+ # @raise [ActionFailed] if an exception occurs
146
+ # @api private
107
147
  def run_remote(command, connection)
108
148
  return if command.nil?
109
149
 
@@ -112,16 +152,30 @@ module Kitchen
112
152
  raise ActionFailed, ex.message
113
153
  end
114
154
 
155
+ # Transfers one or more local paths over SSH.
156
+ #
157
+ # @param locals [Array<String>] array of local paths
158
+ # @param remote [String] remote destination path
159
+ # @param connection [Kitchen::SSH] an SSH connection
160
+ # @raise [ActionFailed] if an exception occurs
161
+ # @api private
115
162
  def transfer_path(locals, remote, connection)
116
163
  return if locals.nil? || Array(locals).empty?
117
164
 
118
- info("Transfering files to #{instance.to_str}")
165
+ info("Transferring files to #{instance.to_str}")
119
166
  locals.each { |local| connection.upload_path!(local, remote) }
120
167
  debug("Transfer complete")
121
168
  rescue SSHFailed, Net::SSH::Exception => ex
122
169
  raise ActionFailed, ex.message
123
170
  end
124
171
 
172
+ # Blocks until a TCP socket is available where a remote SSH server
173
+ # should be listening.
174
+ #
175
+ # @param hostname [String] remote SSH server host
176
+ # @param username [String] SSH username (default: `nil`)
177
+ # @param options [Hash] configuration hash (default: `{}`)
178
+ # @api private
125
179
  def wait_for_sshd(hostname, username = nil, options = {})
126
180
  SSH.new(hostname, username, { :logger => logger }.merge(options)).wait
127
181
  end
@@ -16,6 +16,8 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
+ require "English"
20
+
19
21
  module Kitchen
20
22
 
21
23
  # All Kitchen errors and exceptions.
@@ -23,6 +25,24 @@ module Kitchen
23
25
  # @author Fletcher Nichol <fnichol@nichol.ca>
24
26
  module Error
25
27
 
28
+ # Creates an array of strings, representing a formatted exception,
29
+ # containing backtrace and nested exception info as necessary, that can
30
+ # be viewed by a human.
31
+ #
32
+ # For example:
33
+ #
34
+ # ------Exception-------
35
+ # Class: Kitchen::StandardError
36
+ # Message: Failure starting the party
37
+ # ---Nested Exception---
38
+ # Class: IOError
39
+ # Message: not enough directories for a party
40
+ # ------Backtrace-------
41
+ # nil
42
+ # ----------------------
43
+ #
44
+ # @param exception [::StandardError] an exception
45
+ # @return [Array<String>] a formatted message
26
46
  def self.formatted_trace(exception)
27
47
  arr = formatted_exception(exception).dup
28
48
  last = arr.pop
@@ -34,12 +54,27 @@ module Kitchen
34
54
  arr
35
55
  end
36
56
 
57
+ # Creates an array of strings, representing a formatted exception that
58
+ # can be viewed by a human. Thanks to MiniTest for the inspiration
59
+ # upon which this output has been designed.
60
+ #
61
+ # For example:
62
+ #
63
+ # ------Exception-------
64
+ # Class: Kitchen::StandardError
65
+ # Message: I have failed you
66
+ # ----------------------
67
+ #
68
+ # @param exception [::StandardError] an exception
69
+ # @param title [String] a custom title for the message
70
+ # (default: `"Exception"`)
71
+ # @return [Array<String>] a formatted message
37
72
  def self.formatted_exception(exception, title = "Exception")
38
73
  [
39
74
  title.center(22, "-"),
40
75
  "Class: #{exception.class}",
41
76
  "Message: #{exception.message}",
42
- "".center(22, "-"),
77
+ "".center(22, "-")
43
78
  ]
44
79
  end
45
80
  end
@@ -50,9 +85,16 @@ module Kitchen
50
85
 
51
86
  include Error
52
87
 
88
+ # @return [::StandardError] the original (wrapped) exception
53
89
  attr_reader :original
54
90
 
55
- def initialize(msg, original = $!)
91
+ # Creates a new StandardError exception which optionally wraps an original
92
+ # exception if given or detected by checking the `$!` global variable.
93
+ #
94
+ # @param msg [String] exception message
95
+ # @param original [::StandardError] an original exception which will be
96
+ # wrapped (default: `$ERROR_INFO`)
97
+ def initialize(msg, original = $ERROR_INFO)
56
98
  super(msg)
57
99
  @original = original
58
100
  end
@@ -60,23 +102,54 @@ module Kitchen
60
102
 
61
103
  # Base exception class for all exceptions that are caused by user input
62
104
  # errors.
63
- class UserError < StandardError ; end
105
+ class UserError < StandardError; end
64
106
 
65
107
  # Base exception class for all exceptions that are caused by incorrect use
66
108
  # of an API.
67
- class ClientError < StandardError ; end
109
+ class ClientError < StandardError; end
68
110
 
69
111
  # Base exception class for exceptions that are caused by external library
70
112
  # failures which may be temporary.
71
- class TransientFailure < StandardError ; end
113
+ class TransientFailure < StandardError; end
72
114
 
73
115
  # Exception class for any exceptions raised when performing an instance
74
116
  # action.
75
- class ActionFailed < TransientFailure ; end
117
+ class ActionFailed < TransientFailure; end
76
118
 
77
119
  # Exception class capturing what caused an instance to die.
78
- class InstanceFailure < TransientFailure ; end
120
+ class InstanceFailure < TransientFailure; end
79
121
 
122
+ # Yields to a code block in order to consistently emit a useful crash/error
123
+ # message and exit appropriately. There are two primary failure conditions:
124
+ # an expected instance failure, and any other unexpected failures.
125
+ #
126
+ # **Note** This method may call `Kernel.exit` so may not return if the
127
+ # yielded code block raises an exception.
128
+ #
129
+ # ## Instance Failure
130
+ #
131
+ # This is an expected failure scenario which could happen if an instance
132
+ # couldn't be created, a Chef run didn't successfully converge, a
133
+ # post-convergence test suite failed, etc. In other words, you can count on
134
+ # encountering these failures all the time--this is Kitchen's worldview:
135
+ # crash early and often. In this case a cleanly formatted exception is
136
+ # written to `STDERR` and the exception message is written to
137
+ # the common Kitchen file logger.
138
+ #
139
+ # ## Unexpected Failure
140
+ #
141
+ # All other forms of `Kitchen::Error` exceptions are considered unexpected
142
+ # or unplanned exceptions, typically from user configuration errors, driver
143
+ # or provisioner coding issues or bugs, or internal code issues. Given
144
+ # a stable release of Kitchen and a solid set of drivers and provisioners,
145
+ # the most likely cause of this is user configuration error originating in
146
+ # the `.kitchen.yml` setup. For this reason, the exception is written to
147
+ # `STDERR`, a full formatted exception trace is written to the common
148
+ # Kitchen file logger, and a message is displayed on `STDERR` to the user
149
+ # informing them to check the log files and check their configuration with
150
+ # the `kitchen diagnose` subcommand.
151
+ #
152
+ # @raise [SystemExit] if an exception is raised in the yielded block
80
153
  def self.with_friendly_errors
81
154
  yield
82
155
  rescue Kitchen::InstanceFailure => e
@@ -93,6 +166,13 @@ module Kitchen
93
166
 
94
167
  private
95
168
 
169
+ # Writes an array of lines to the common Kitchen logger's file device at the
170
+ # given severity level. If the Kitchen logger is set to debug severity, then
171
+ # the array of lines will also be written to the console output.
172
+ #
173
+ # @param level [Symbol,String] the desired log level
174
+ # @param lines [Array<String>] an array of strings to log
175
+ # @api private
96
176
  def self.file_log(level, lines)
97
177
  Array(lines).each do |line|
98
178
  if Kitchen.logger.debug?
@@ -103,16 +183,31 @@ module Kitchen
103
183
  end
104
184
  end
105
185
 
186
+ # Writes an array of lines to the `STDERR` device.
187
+ #
188
+ # @param lines [Array<String>] an array of strings to log
189
+ # @api private
106
190
  def self.stderr_log(lines)
107
- Array(lines).each do |line|
108
- $stderr.puts(Color.colorize(">>>>>> #{line}", :red))
191
+ Array(lines).map { |line| ">>>>>> #{line}" }.each do |line|
192
+ line = Color.colorize(line, :red) if Kitchen.tty?
193
+ $stderr.puts(line)
109
194
  end
110
195
  end
111
196
 
197
+ # Writes an array of lines to the common Kitchen debugger with debug
198
+ # severity.
199
+ #
200
+ # @param lines [Array<String>] an array of strings to log
201
+ # @api private
112
202
  def self.debug_log(lines)
113
203
  Array(lines).each { |line| Kitchen.logger.debug(line) }
114
204
  end
115
205
 
206
+ # Handles an instance failure exception.
207
+ #
208
+ # @param e [StandardError] an exception to handle
209
+ # @see Kitchen.with_friendly_errors
210
+ # @api private
116
211
  def self.handle_instance_failure(e)
117
212
  stderr_log(e.message.split(/\s{2,}/))
118
213
  stderr_log(Error.formatted_exception(e.original))
@@ -120,6 +215,11 @@ module Kitchen
120
215
  debug_log(Error.formatted_trace(e))
121
216
  end
122
217
 
218
+ # Handles an unexpected failure exception.
219
+ #
220
+ # @param e [StandardError] an exception to handle
221
+ # @see Kitchen.with_friendly_errors
222
+ # @api private
123
223
  def self.handle_error(e)
124
224
  stderr_log(Error.formatted_exception(e))
125
225
  stderr_log("Please see .kitchen/logs/kitchen.log for more details")
@@ -16,8 +16,8 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'thor/group'
20
- require 'thor/util'
19
+ require "thor/group"
20
+ require "thor/util"
21
21
 
22
22
  module Kitchen
23
23
 
@@ -32,9 +32,12 @@ module Kitchen
32
32
 
33
33
  argument :name, :type => :string
34
34
 
35
- class_option :license, :aliases => "-l", :default => "apachev2",
35
+ class_option :license,
36
+ :aliases => "-l",
37
+ :default => "apachev2",
36
38
  :desc => "License type for gem (apachev2, mit, lgplv3, reserved)"
37
39
 
40
+ # Invoke the command.
38
41
  def create
39
42
  self.class.source_root(Kitchen.source_root.join("templates", "driver"))
40
43
 
@@ -45,6 +48,9 @@ module Kitchen
45
48
 
46
49
  private
47
50
 
51
+ # Creates top-level project files.
52
+ #
53
+ # @api private
48
54
  def create_core_files
49
55
  empty_directory(target_dir)
50
56
 
@@ -60,6 +66,9 @@ module Kitchen
60
66
  create_file(File.join(target_dir, ".cane"))
61
67
  end
62
68
 
69
+ # Creates source code files.
70
+ #
71
+ # @api private
63
72
  def create_source_files
64
73
  empty_directory(File.join(target_dir, "lib/kitchen/driver"))
65
74
 
@@ -73,6 +82,9 @@ module Kitchen
73
82
  )
74
83
  end
75
84
 
85
+ # Initialize a git repository.
86
+ #
87
+ # @api private
76
88
  def initialize_git
77
89
  inside(target_dir) do
78
90
  run("git init")
@@ -80,14 +92,24 @@ module Kitchen
80
92
  end
81
93
  end
82
94
 
95
+ # Render an ERb template to a destination file.
96
+ #
97
+ # @param erb [String] path to an ERb file
98
+ # @param dest [String] destination path for the rendered template
99
+ # @api private
83
100
  def create_template(erb, dest)
84
101
  template(erb, File.join(target_dir, dest), config)
85
102
  end
86
103
 
104
+ # @return [String] the path to the gem skeleton project
105
+ # @api private
87
106
  def target_dir
88
107
  File.join(Dir.pwd, "kitchen-#{name}")
89
108
  end
90
109
 
110
+ # @return [Hash] a configuration hash which can be used by templates as
111
+ # context
112
+ # @api private
91
113
  def config
92
114
  @config ||= {
93
115
  :name => name,
@@ -99,20 +121,28 @@ module Kitchen
99
121
  :email => email,
100
122
  :license => options[:license],
101
123
  :license_string => license_string,
102
- :year => Time.now.year,
124
+ :year => Time.now.year
103
125
  }
104
126
  end
105
127
 
128
+ # @return [String] a default author name taken from git configuration if
129
+ # found
130
+ # @api private
106
131
  def author
107
132
  git_user_name = %x{git config user.name}.chomp
108
133
  git_user_name.empty? ? "TODO: Write your name" : git_user_name
109
134
  end
110
135
 
136
+ # @return [String] a default email address taken from git configuration
137
+ # if found
138
+ # @api private
111
139
  def email
112
140
  git_user_email = %x{git config user.email}.chomp
113
141
  git_user_email.empty? ? "TODO: Write your email" : git_user_email
114
142
  end
115
143
 
144
+ # @return [String] a rendered license string for a given license
145
+ # @api private
116
146
  def license_string
117
147
  case options[:license]
118
148
  when "mit" then "MIT"
@@ -124,6 +154,8 @@ module Kitchen
124
154
  end
125
155
  end
126
156
 
157
+ # @return [String] the filename to use for the license file
158
+ # @api private
127
159
  def license_filename
128
160
  case options[:license]
129
161
  when "mit" then "LICENSE.txt"
@@ -134,9 +166,11 @@ module Kitchen
134
166
  end
135
167
  end
136
168
 
169
+ # @return [String] the license comment/preamble
170
+ # @api private
137
171
  def license_comment
138
172
  @license_comment ||= IO.read(File.join(target_dir, license_filename)).
139
- gsub(/^/, '# ').gsub(/\s+$/, '')
173
+ gsub(/^/, "# ").gsub(/\s+$/, "")
140
174
  end
141
175
  end
142
176
  end