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,177 +1,177 @@
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 "thor/group"
20
- require "thor/util"
21
-
22
- module Kitchen
23
-
24
- module Generator
25
-
26
- # A generator to create a new Kitchen Driver gem project.
27
- #
28
- # @author Fletcher Nichol <fnichol@nichol.ca>
29
- class DriverCreate < Thor::Group
30
-
31
- include Thor::Actions
32
-
33
- argument :name, :type => :string
34
-
35
- class_option :license,
36
- :aliases => "-l",
37
- :default => "apachev2",
38
- :desc => "License type for gem (apachev2, mit, lgplv3, reserved)"
39
-
40
- # Invoke the command.
41
- def create
42
- self.class.source_root(Kitchen.source_root.join("templates", "driver"))
43
-
44
- create_core_files
45
- create_source_files
46
- initialize_git
47
- end
48
-
49
- private
50
-
51
- # Creates top-level project files.
52
- #
53
- # @api private
54
- def create_core_files
55
- empty_directory(target_dir)
56
-
57
- create_template("CHANGELOG.md.erb", "CHANGELOG.md")
58
- create_template("Gemfile.erb", "Gemfile")
59
- create_template("Rakefile.erb", "Rakefile")
60
- create_template("README.md.erb", "README.md")
61
- create_template("gemspec.erb", "#{config[:gem_name]}.gemspec")
62
- create_template("license_#{config[:license]}.erb", license_filename)
63
- create_template("gitignore.erb", ".gitignore")
64
- create_template("tailor.erb", ".tailor")
65
- create_template("travis.yml.erb", ".travis.yml")
66
- create_file(File.join(target_dir, ".cane"))
67
- end
68
-
69
- # Creates source code files.
70
- #
71
- # @api private
72
- def create_source_files
73
- empty_directory(File.join(target_dir, "lib/kitchen/driver"))
74
-
75
- create_template(
76
- "version.rb.erb",
77
- "lib/kitchen/driver/#{name}_version.rb"
78
- )
79
- create_template(
80
- "driver.rb.erb",
81
- "lib/kitchen/driver/#{name}.rb"
82
- )
83
- end
84
-
85
- # Initialize a git repository.
86
- #
87
- # @api private
88
- def initialize_git
89
- inside(target_dir) do
90
- run("git init", :capture => true)
91
- run("git add .", :capture => true)
92
- end
93
- end
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
100
- def create_template(erb, dest)
101
- template(erb, File.join(target_dir, dest), config)
102
- end
103
-
104
- # @return [String] the path to the gem skeleton project
105
- # @api private
106
- def target_dir
107
- File.join(Dir.pwd, "kitchen-#{name}")
108
- end
109
-
110
- # @return [Hash] a configuration hash which can be used by templates as
111
- # context
112
- # @api private
113
- def config
114
- @config ||= {
115
- :name => name,
116
- :gem_name => "kitchen-#{name}",
117
- :gemspec => "kitchen-#{name}.gemspec",
118
- :klass_name => ::Thor::Util.camel_case(name),
119
- :constant_name => ::Thor::Util.snake_case(name).upcase,
120
- :author => author,
121
- :email => email,
122
- :license => options[:license],
123
- :license_string => license_string,
124
- :year => Time.now.year
125
- }
126
- end
127
-
128
- # @return [String] a default author name taken from git configuration if
129
- # found
130
- # @api private
131
- def author
132
- git_user_name = `git config user.name`.chomp
133
- git_user_name.empty? ? "TODO: Write your name" : git_user_name
134
- end
135
-
136
- # @return [String] a default email address taken from git configuration
137
- # if found
138
- # @api private
139
- def email
140
- git_user_email = `git config user.email`.chomp
141
- git_user_email.empty? ? "TODO: Write your email" : git_user_email
142
- end
143
-
144
- # @return [String] a rendered license string for a given license
145
- # @api private
146
- def license_string
147
- case options[:license]
148
- when "mit" then "MIT"
149
- when "apachev2" then "Apache 2.0"
150
- when "lgplv3" then "LGPL 3.0"
151
- when "reserved" then "All rights reserved"
152
- else
153
- raise ArgumentError, "No such license #{options[:license]}"
154
- end
155
- end
156
-
157
- # @return [String] the filename to use for the license file
158
- # @api private
159
- def license_filename
160
- case options[:license]
161
- when "mit" then "LICENSE.txt"
162
- when "apachev2", "reserved" then "LICENSE"
163
- when "lgplv3" then "COPYING"
164
- else
165
- raise ArgumentError, "No such license #{options[:license]}"
166
- end
167
- end
168
-
169
- # @return [String] the license comment/preamble
170
- # @api private
171
- def license_comment
172
- @license_comment ||= IO.read(File.join(target_dir, license_filename)).
173
- gsub(/^/, "# ").gsub(/\s+$/, "")
174
- end
175
- end
176
- end
177
- 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 "thor/group"
20
+ require "thor/util"
21
+
22
+ module Kitchen
23
+
24
+ module Generator
25
+
26
+ # A generator to create a new Kitchen Driver gem project.
27
+ #
28
+ # @author Fletcher Nichol <fnichol@nichol.ca>
29
+ class DriverCreate < Thor::Group
30
+
31
+ include Thor::Actions
32
+
33
+ argument :name, :type => :string
34
+
35
+ class_option :license,
36
+ :aliases => "-l",
37
+ :default => "apachev2",
38
+ :desc => "License type for gem (apachev2, mit, lgplv3, reserved)"
39
+
40
+ # Invoke the command.
41
+ def create
42
+ self.class.source_root(Kitchen.source_root.join("templates", "driver"))
43
+
44
+ create_core_files
45
+ create_source_files
46
+ initialize_git
47
+ end
48
+
49
+ private
50
+
51
+ # Creates top-level project files.
52
+ #
53
+ # @api private
54
+ def create_core_files
55
+ empty_directory(target_dir)
56
+
57
+ create_template("CHANGELOG.md.erb", "CHANGELOG.md")
58
+ create_template("Gemfile.erb", "Gemfile")
59
+ create_template("Rakefile.erb", "Rakefile")
60
+ create_template("README.md.erb", "README.md")
61
+ create_template("gemspec.erb", "#{config[:gem_name]}.gemspec")
62
+ create_template("license_#{config[:license]}.erb", license_filename)
63
+ create_template("gitignore.erb", ".gitignore")
64
+ create_template("tailor.erb", ".tailor")
65
+ create_template("travis.yml.erb", ".travis.yml")
66
+ create_file(File.join(target_dir, ".cane"))
67
+ end
68
+
69
+ # Creates source code files.
70
+ #
71
+ # @api private
72
+ def create_source_files
73
+ empty_directory(File.join(target_dir, "lib/kitchen/driver"))
74
+
75
+ create_template(
76
+ "version.rb.erb",
77
+ "lib/kitchen/driver/#{name}_version.rb"
78
+ )
79
+ create_template(
80
+ "driver.rb.erb",
81
+ "lib/kitchen/driver/#{name}.rb"
82
+ )
83
+ end
84
+
85
+ # Initialize a git repository.
86
+ #
87
+ # @api private
88
+ def initialize_git
89
+ inside(target_dir) do
90
+ run("git init", :capture => true)
91
+ run("git add .", :capture => true)
92
+ end
93
+ end
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
100
+ def create_template(erb, dest)
101
+ template(erb, File.join(target_dir, dest), config)
102
+ end
103
+
104
+ # @return [String] the path to the gem skeleton project
105
+ # @api private
106
+ def target_dir
107
+ File.join(Dir.pwd, "kitchen-#{name}")
108
+ end
109
+
110
+ # @return [Hash] a configuration hash which can be used by templates as
111
+ # context
112
+ # @api private
113
+ def config
114
+ @config ||= {
115
+ :name => name,
116
+ :gem_name => "kitchen-#{name}",
117
+ :gemspec => "kitchen-#{name}.gemspec",
118
+ :klass_name => ::Thor::Util.camel_case(name),
119
+ :constant_name => ::Thor::Util.snake_case(name).upcase,
120
+ :author => author,
121
+ :email => email,
122
+ :license => options[:license],
123
+ :license_string => license_string,
124
+ :year => Time.now.year
125
+ }
126
+ end
127
+
128
+ # @return [String] a default author name taken from git configuration if
129
+ # found
130
+ # @api private
131
+ def author
132
+ git_user_name = `git config user.name`.chomp
133
+ git_user_name.empty? ? "TODO: Write your name" : git_user_name
134
+ end
135
+
136
+ # @return [String] a default email address taken from git configuration
137
+ # if found
138
+ # @api private
139
+ def email
140
+ git_user_email = `git config user.email`.chomp
141
+ git_user_email.empty? ? "TODO: Write your email" : git_user_email
142
+ end
143
+
144
+ # @return [String] a rendered license string for a given license
145
+ # @api private
146
+ def license_string
147
+ case options[:license]
148
+ when "mit" then "MIT"
149
+ when "apachev2" then "Apache 2.0"
150
+ when "lgplv3" then "LGPL 3.0"
151
+ when "reserved" then "All rights reserved"
152
+ else
153
+ raise ArgumentError, "No such license #{options[:license]}"
154
+ end
155
+ end
156
+
157
+ # @return [String] the filename to use for the license file
158
+ # @api private
159
+ def license_filename
160
+ case options[:license]
161
+ when "mit" then "LICENSE.txt"
162
+ when "apachev2", "reserved" then "LICENSE"
163
+ when "lgplv3" then "COPYING"
164
+ else
165
+ raise ArgumentError, "No such license #{options[:license]}"
166
+ end
167
+ end
168
+
169
+ # @return [String] the license comment/preamble
170
+ # @api private
171
+ def license_comment
172
+ @license_comment ||= IO.read(File.join(target_dir, license_filename)).
173
+ gsub(/^/, "# ").gsub(/\s+$/, "")
174
+ end
175
+ end
176
+ end
177
+ end
@@ -1,296 +1,296 @@
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 "rubygems/gem_runner"
20
- require "thor/group"
21
-
22
- module Kitchen
23
-
24
- module Generator
25
-
26
- # A project initialization generator, to help prepare a cookbook project
27
- # for testing with Kitchen.
28
- #
29
- # @author Fletcher Nichol <fnichol@nichol.ca>
30
- class Init < Thor::Group
31
-
32
- include Thor::Actions
33
-
34
- class_option :driver,
35
- :type => :array,
36
- :aliases => "-D",
37
- :default => "kitchen-vagrant",
38
- :desc => <<-D.gsub(/^\s+/, "").gsub(/\n/, " ")
39
- One or more Kitchen Driver gems to be installed or added to a
40
- Gemfile
41
- D
42
-
43
- class_option :provisioner,
44
- :type => :string,
45
- :aliases => "-P",
46
- :default => "chef_solo",
47
- :desc => <<-D.gsub(/^\s+/, "").gsub(/\n/, " ")
48
- The default Kitchen Provisioner to use
49
- D
50
-
51
- class_option :create_gemfile,
52
- :type => :boolean,
53
- :default => false,
54
- :desc => <<-D.gsub(/^\s+/, "").gsub(/\n/, " ")
55
- Whether or not to create a Gemfile if one does not exist.
56
- Default: false
57
- D
58
-
59
- # Invoke the command.
60
- def init
61
- self.class.source_root(Kitchen.source_root.join("templates", "init"))
62
-
63
- create_kitchen_yaml
64
- create_chefignore
65
- prepare_rakefile
66
- prepare_thorfile
67
- create_test_dir
68
- prepare_gitignore
69
- prepare_gemfile
70
- add_drivers
71
- display_bundle_message
72
- end
73
-
74
- private
75
-
76
- # Creates the `.kitchen.yml` file.
77
- #
78
- # @api private
79
- def create_kitchen_yaml
80
- cookbook_name = if File.exist?(File.expand_path("metadata.rb"))
81
- MetadataChopper.extract("metadata.rb").first
82
- else
83
- nil
84
- end
85
- run_list = cookbook_name ? "recipe[#{cookbook_name}::default]" : nil
86
- driver_plugin = Array(options[:driver]).first || "dummy"
87
-
88
- template("kitchen.yml.erb", ".kitchen.yml",
89
- :driver_plugin => driver_plugin.sub(/^kitchen-/, ""),
90
- :provisioner => options[:provisioner],
91
- :run_list => Array(run_list)
92
- )
93
- end
94
-
95
- # Creates the `chefignore` file.
96
- #
97
- # @api private
98
- def create_chefignore
99
- template("chefignore.erb", "chefignore")
100
- end
101
-
102
- # @return [true,false] whether or not a Gemfile needs to be initialized
103
- # @api private
104
- def init_gemfile?
105
- File.exist?(File.join(destination_root, "Gemfile")) ||
106
- options[:create_gemfile]
107
- end
108
-
109
- # @return [true,false] whether or not a Rakefile needs to be initialized
110
- # @api private
111
- def init_rakefile?
112
- File.exist?(File.join(destination_root, "Rakefile")) &&
113
- not_in_file?("Rakefile", %r{require 'kitchen/rake_tasks'})
114
- end
115
-
116
- # @return [true,false] whether or not a Thorfile needs to be initialized
117
- # @api private
118
- def init_thorfile?
119
- File.exist?(File.join(destination_root, "Thorfile")) &&
120
- not_in_file?("Thorfile", %r{require 'kitchen/thor_tasks'})
121
- end
122
-
123
- # @return [true,false] whether or not a test directory needs to be
124
- # initialized
125
- # @api private
126
- def init_test_dir?
127
- Dir.glob("test/integration/*").select { |d| File.directory?(d) }.empty?
128
- end
129
-
130
- # @return [true,false] whether or not a `.gitignore` file needs to be
131
- # initialized
132
- # @api private
133
- def init_git?
134
- File.directory?(File.join(destination_root, ".git"))
135
- end
136
-
137
- # Prepares a Rakefile.
138
- #
139
- # @api private
140
- def prepare_rakefile
141
- return unless init_rakefile?
142
-
143
- rakedoc = <<-RAKE.gsub(/^ {10}/, "")
144
-
145
- begin
146
- require 'kitchen/rake_tasks'
147
- Kitchen::RakeTasks.new
148
- rescue LoadError
149
- puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
150
- end
151
- RAKE
152
- append_to_file(File.join(destination_root, "Rakefile"), rakedoc)
153
- end
154
-
155
- # Prepares a Thorfile.
156
- #
157
- # @api private
158
- def prepare_thorfile
159
- return unless init_thorfile?
160
-
161
- thordoc = <<-THOR.gsub(/^ {10}/, "")
162
-
163
- begin
164
- require 'kitchen/thor_tasks'
165
- Kitchen::ThorTasks.new
166
- rescue LoadError
167
- puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
168
- end
169
- THOR
170
- append_to_file(File.join(destination_root, "Thorfile"), thordoc)
171
- end
172
-
173
- # Create the default test directory
174
- #
175
- # @api private
176
- def create_test_dir
177
- empty_directory "test/integration/default" if init_test_dir?
178
- end
179
-
180
- # Prepares the .gitignore file
181
- #
182
- # @api private
183
- def prepare_gitignore
184
- return unless init_git?
185
-
186
- append_to_gitignore(".kitchen/")
187
- append_to_gitignore(".kitchen.local.yml")
188
- end
189
-
190
- # Appends a line to the .gitignore file.
191
- #
192
- # @api private
193
- def append_to_gitignore(line)
194
- create_file(".gitignore") unless File.exist?(File.join(destination_root, ".gitignore"))
195
-
196
- if IO.readlines(File.join(destination_root, ".gitignore")).grep(%r{^#{line}}).empty?
197
- append_to_file(".gitignore", "#{line}\n")
198
- end
199
- end
200
-
201
- # Prepares a Gemfile.
202
- #
203
- # @api private
204
- def prepare_gemfile
205
- return unless init_gemfile?
206
-
207
- create_gemfile_if_missing
208
- add_gem_to_gemfile
209
- end
210
-
211
- # Creates a Gemfile if missing
212
- #
213
- # @api private
214
- def create_gemfile_if_missing
215
- unless File.exist?(File.join(destination_root, "Gemfile"))
216
- create_file("Gemfile", %{source "https://rubygems.org"\n\n})
217
- end
218
- end
219
-
220
- # Appends entries to a Gemfile.
221
- #
222
- # @api private
223
- def add_gem_to_gemfile
224
- if not_in_file?("Gemfile", %r{gem ('|")test-kitchen('|")})
225
- append_to_file("Gemfile", %{gem "test-kitchen"\n})
226
- @display_bundle_msg = true
227
- end
228
- end
229
-
230
- # Appends driver gems to a Gemfile or installs them.
231
- #
232
- # @api private
233
- def add_drivers
234
- return if options[:driver].nil? || options[:driver].empty?
235
-
236
- Array(options[:driver]).each do |driver_gem|
237
- if File.exist?(File.join(destination_root, "Gemfile")) || options[:create_gemfile]
238
- add_driver_to_gemfile(driver_gem)
239
- else
240
- install_gem(driver_gem)
241
- end
242
- end
243
- end
244
-
245
- # Appends a driver gem to a Gemfile.
246
- #
247
- # @api private
248
- def add_driver_to_gemfile(driver_gem)
249
- if not_in_file?("Gemfile", %r{gem ('|")#{driver_gem}('|")})
250
- append_to_file("Gemfile", %{gem "#{driver_gem}"\n})
251
- @display_bundle_msg = true
252
- end
253
- end
254
-
255
- # Installs a driver gem.
256
- #
257
- # @api private
258
- def install_gem(driver_gem)
259
- unbundlerize { Gem::GemRunner.new.run(["install", driver_gem]) }
260
- rescue Gem::SystemExitException => e
261
- raise unless e.exit_code == 0
262
- end
263
-
264
- # Displays a bundle warning message to the user.
265
- #
266
- # @api private
267
- def display_bundle_message
268
- if @display_bundle_msg
269
- say "You must run `bundle install' to fetch any new gems.", :red
270
- end
271
- end
272
-
273
- # Determines whether or not a pattern is found in a file.
274
- #
275
- # @param filename [String] filename to read
276
- # @param regexp [Regexp] a regular expression
277
- # @return [true,false] whether or not a pattern is found in a file
278
- # @api private
279
- def not_in_file?(filename, regexp)
280
- IO.readlines(File.join(destination_root, filename)).grep(regexp).empty?
281
- end
282
-
283
- # Save off any Bundler/Ruby-related environment variables so that the
284
- # yielded block can run "bundler-free" (and restore at the end).
285
- #
286
- # @api private
287
- def unbundlerize
288
- keys = ENV.keys.select { |key| key =~ /^BUNDLER?_/ } + %w[RUBYOPT]
289
-
290
- keys.each { |key| ENV["__#{key}"] = ENV[key]; ENV.delete(key) }
291
- yield
292
- keys.each { |key| ENV[key] = ENV.delete("__#{key}") }
293
- end
294
- end
295
- end
296
- 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 "rubygems/gem_runner"
20
+ require "thor/group"
21
+
22
+ module Kitchen
23
+
24
+ module Generator
25
+
26
+ # A project initialization generator, to help prepare a cookbook project
27
+ # for testing with Kitchen.
28
+ #
29
+ # @author Fletcher Nichol <fnichol@nichol.ca>
30
+ class Init < Thor::Group
31
+
32
+ include Thor::Actions
33
+
34
+ class_option :driver,
35
+ :type => :array,
36
+ :aliases => "-D",
37
+ :default => "kitchen-vagrant",
38
+ :desc => <<-D.gsub(/^\s+/, "").gsub(/\n/, " ")
39
+ One or more Kitchen Driver gems to be installed or added to a
40
+ Gemfile
41
+ D
42
+
43
+ class_option :provisioner,
44
+ :type => :string,
45
+ :aliases => "-P",
46
+ :default => "chef_solo",
47
+ :desc => <<-D.gsub(/^\s+/, "").gsub(/\n/, " ")
48
+ The default Kitchen Provisioner to use
49
+ D
50
+
51
+ class_option :create_gemfile,
52
+ :type => :boolean,
53
+ :default => false,
54
+ :desc => <<-D.gsub(/^\s+/, "").gsub(/\n/, " ")
55
+ Whether or not to create a Gemfile if one does not exist.
56
+ Default: false
57
+ D
58
+
59
+ # Invoke the command.
60
+ def init
61
+ self.class.source_root(Kitchen.source_root.join("templates", "init"))
62
+
63
+ create_kitchen_yaml
64
+ create_chefignore
65
+ prepare_rakefile
66
+ prepare_thorfile
67
+ create_test_dir
68
+ prepare_gitignore
69
+ prepare_gemfile
70
+ add_drivers
71
+ display_bundle_message
72
+ end
73
+
74
+ private
75
+
76
+ # Creates the `.kitchen.yml` file.
77
+ #
78
+ # @api private
79
+ def create_kitchen_yaml
80
+ cookbook_name = if File.exist?(File.expand_path("metadata.rb"))
81
+ MetadataChopper.extract("metadata.rb").first
82
+ else
83
+ nil
84
+ end
85
+ run_list = cookbook_name ? "recipe[#{cookbook_name}::default]" : nil
86
+ driver_plugin = Array(options[:driver]).first || "dummy"
87
+
88
+ template("kitchen.yml.erb", ".kitchen.yml",
89
+ :driver_plugin => driver_plugin.sub(/^kitchen-/, ""),
90
+ :provisioner => options[:provisioner],
91
+ :run_list => Array(run_list)
92
+ )
93
+ end
94
+
95
+ # Creates the `chefignore` file.
96
+ #
97
+ # @api private
98
+ def create_chefignore
99
+ template("chefignore.erb", "chefignore")
100
+ end
101
+
102
+ # @return [true,false] whether or not a Gemfile needs to be initialized
103
+ # @api private
104
+ def init_gemfile?
105
+ File.exist?(File.join(destination_root, "Gemfile")) ||
106
+ options[:create_gemfile]
107
+ end
108
+
109
+ # @return [true,false] whether or not a Rakefile needs to be initialized
110
+ # @api private
111
+ def init_rakefile?
112
+ File.exist?(File.join(destination_root, "Rakefile")) &&
113
+ not_in_file?("Rakefile", %r{require 'kitchen/rake_tasks'})
114
+ end
115
+
116
+ # @return [true,false] whether or not a Thorfile needs to be initialized
117
+ # @api private
118
+ def init_thorfile?
119
+ File.exist?(File.join(destination_root, "Thorfile")) &&
120
+ not_in_file?("Thorfile", %r{require 'kitchen/thor_tasks'})
121
+ end
122
+
123
+ # @return [true,false] whether or not a test directory needs to be
124
+ # initialized
125
+ # @api private
126
+ def init_test_dir?
127
+ Dir.glob("test/integration/*").select { |d| File.directory?(d) }.empty?
128
+ end
129
+
130
+ # @return [true,false] whether or not a `.gitignore` file needs to be
131
+ # initialized
132
+ # @api private
133
+ def init_git?
134
+ File.directory?(File.join(destination_root, ".git"))
135
+ end
136
+
137
+ # Prepares a Rakefile.
138
+ #
139
+ # @api private
140
+ def prepare_rakefile
141
+ return unless init_rakefile?
142
+
143
+ rakedoc = <<-RAKE.gsub(/^ {10}/, "")
144
+
145
+ begin
146
+ require 'kitchen/rake_tasks'
147
+ Kitchen::RakeTasks.new
148
+ rescue LoadError
149
+ puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
150
+ end
151
+ RAKE
152
+ append_to_file(File.join(destination_root, "Rakefile"), rakedoc)
153
+ end
154
+
155
+ # Prepares a Thorfile.
156
+ #
157
+ # @api private
158
+ def prepare_thorfile
159
+ return unless init_thorfile?
160
+
161
+ thordoc = <<-THOR.gsub(/^ {10}/, "")
162
+
163
+ begin
164
+ require 'kitchen/thor_tasks'
165
+ Kitchen::ThorTasks.new
166
+ rescue LoadError
167
+ puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
168
+ end
169
+ THOR
170
+ append_to_file(File.join(destination_root, "Thorfile"), thordoc)
171
+ end
172
+
173
+ # Create the default test directory
174
+ #
175
+ # @api private
176
+ def create_test_dir
177
+ empty_directory "test/integration/default" if init_test_dir?
178
+ end
179
+
180
+ # Prepares the .gitignore file
181
+ #
182
+ # @api private
183
+ def prepare_gitignore
184
+ return unless init_git?
185
+
186
+ append_to_gitignore(".kitchen/")
187
+ append_to_gitignore(".kitchen.local.yml")
188
+ end
189
+
190
+ # Appends a line to the .gitignore file.
191
+ #
192
+ # @api private
193
+ def append_to_gitignore(line)
194
+ create_file(".gitignore") unless File.exist?(File.join(destination_root, ".gitignore"))
195
+
196
+ if IO.readlines(File.join(destination_root, ".gitignore")).grep(%r{^#{line}}).empty?
197
+ append_to_file(".gitignore", "#{line}\n")
198
+ end
199
+ end
200
+
201
+ # Prepares a Gemfile.
202
+ #
203
+ # @api private
204
+ def prepare_gemfile
205
+ return unless init_gemfile?
206
+
207
+ create_gemfile_if_missing
208
+ add_gem_to_gemfile
209
+ end
210
+
211
+ # Creates a Gemfile if missing
212
+ #
213
+ # @api private
214
+ def create_gemfile_if_missing
215
+ unless File.exist?(File.join(destination_root, "Gemfile"))
216
+ create_file("Gemfile", %{source "https://rubygems.org"\n\n})
217
+ end
218
+ end
219
+
220
+ # Appends entries to a Gemfile.
221
+ #
222
+ # @api private
223
+ def add_gem_to_gemfile
224
+ if not_in_file?("Gemfile", %r{gem ('|")test-kitchen('|")})
225
+ append_to_file("Gemfile", %{gem "test-kitchen"\n})
226
+ @display_bundle_msg = true
227
+ end
228
+ end
229
+
230
+ # Appends driver gems to a Gemfile or installs them.
231
+ #
232
+ # @api private
233
+ def add_drivers
234
+ return if options[:driver].nil? || options[:driver].empty?
235
+
236
+ Array(options[:driver]).each do |driver_gem|
237
+ if File.exist?(File.join(destination_root, "Gemfile")) || options[:create_gemfile]
238
+ add_driver_to_gemfile(driver_gem)
239
+ else
240
+ install_gem(driver_gem)
241
+ end
242
+ end
243
+ end
244
+
245
+ # Appends a driver gem to a Gemfile.
246
+ #
247
+ # @api private
248
+ def add_driver_to_gemfile(driver_gem)
249
+ if not_in_file?("Gemfile", %r{gem ('|")#{driver_gem}('|")})
250
+ append_to_file("Gemfile", %{gem "#{driver_gem}"\n})
251
+ @display_bundle_msg = true
252
+ end
253
+ end
254
+
255
+ # Installs a driver gem.
256
+ #
257
+ # @api private
258
+ def install_gem(driver_gem)
259
+ unbundlerize { Gem::GemRunner.new.run(["install", driver_gem]) }
260
+ rescue Gem::SystemExitException => e
261
+ raise unless e.exit_code == 0
262
+ end
263
+
264
+ # Displays a bundle warning message to the user.
265
+ #
266
+ # @api private
267
+ def display_bundle_message
268
+ if @display_bundle_msg
269
+ say "You must run `bundle install' to fetch any new gems.", :red
270
+ end
271
+ end
272
+
273
+ # Determines whether or not a pattern is found in a file.
274
+ #
275
+ # @param filename [String] filename to read
276
+ # @param regexp [Regexp] a regular expression
277
+ # @return [true,false] whether or not a pattern is found in a file
278
+ # @api private
279
+ def not_in_file?(filename, regexp)
280
+ IO.readlines(File.join(destination_root, filename)).grep(regexp).empty?
281
+ end
282
+
283
+ # Save off any Bundler/Ruby-related environment variables so that the
284
+ # yielded block can run "bundler-free" (and restore at the end).
285
+ #
286
+ # @api private
287
+ def unbundlerize
288
+ keys = ENV.keys.select { |key| key =~ /^BUNDLER?_/ } + %w[RUBYOPT]
289
+
290
+ keys.each { |key| ENV["__#{key}"] = ENV[key]; ENV.delete(key) }
291
+ yield
292
+ keys.each { |key| ENV[key] = ENV.delete("__#{key}") }
293
+ end
294
+ end
295
+ end
296
+ end