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
@@ -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