chef-dk 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +192 -0
  3. data/LICENSE +201 -0
  4. data/README.md +198 -0
  5. data/Rakefile +18 -0
  6. data/bin/chef +25 -0
  7. data/lib/chef-dk.rb +19 -0
  8. data/lib/chef-dk/builtin_commands.rb +31 -0
  9. data/lib/chef-dk/chef_runner.rb +83 -0
  10. data/lib/chef-dk/cli.rb +135 -0
  11. data/lib/chef-dk/command/base.rb +71 -0
  12. data/lib/chef-dk/command/exec.rb +33 -0
  13. data/lib/chef-dk/command/gem.rb +47 -0
  14. data/lib/chef-dk/command/generate.rb +97 -0
  15. data/lib/chef-dk/command/generator_commands.rb +417 -0
  16. data/lib/chef-dk/command/shell_init.rb +80 -0
  17. data/lib/chef-dk/command/verify.rb +226 -0
  18. data/lib/chef-dk/commands_map.rb +115 -0
  19. data/lib/chef-dk/component_test.rb +142 -0
  20. data/lib/chef-dk/cookbook_metadata.rb +36 -0
  21. data/lib/chef-dk/cookbook_omnifetch.rb +29 -0
  22. data/lib/chef-dk/cookbook_profiler/git.rb +95 -0
  23. data/lib/chef-dk/cookbook_profiler/identifiers.rb +79 -0
  24. data/lib/chef-dk/cookbook_profiler/null_scm.rb +32 -0
  25. data/lib/chef-dk/exceptions.rb +46 -0
  26. data/lib/chef-dk/generator.rb +70 -0
  27. data/lib/chef-dk/helpers.rb +95 -0
  28. data/lib/chef-dk/policyfile/chef_server_cookbook_source.rb +46 -0
  29. data/lib/chef-dk/policyfile/community_cookbook_source.rb +84 -0
  30. data/lib/chef-dk/policyfile/cookbook_sources.rb +20 -0
  31. data/lib/chef-dk/policyfile/cookbook_spec.rb +96 -0
  32. data/lib/chef-dk/policyfile/dsl.rb +148 -0
  33. data/lib/chef-dk/policyfile/null_cookbook_source.rb +37 -0
  34. data/lib/chef-dk/policyfile_compiler.rb +217 -0
  35. data/lib/chef-dk/policyfile_lock.rb +243 -0
  36. data/lib/chef-dk/shell_out.rb +36 -0
  37. data/lib/chef-dk/skeletons/code_generator/files/default/Berksfile +3 -0
  38. data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +96 -0
  39. data/lib/chef-dk/skeletons/code_generator/files/default/converge_spec.rb +9 -0
  40. data/lib/chef-dk/skeletons/code_generator/files/default/gitignore +16 -0
  41. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper.rb +8 -0
  42. data/lib/chef-dk/skeletons/code_generator/metadata.rb +8 -0
  43. data/lib/chef-dk/skeletons/code_generator/recipes/app.rb +65 -0
  44. data/lib/chef-dk/skeletons/code_generator/recipes/attribute.rb +12 -0
  45. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook.rb +50 -0
  46. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook_file.rb +24 -0
  47. data/lib/chef-dk/skeletons/code_generator/recipes/lwrp.rb +23 -0
  48. data/lib/chef-dk/skeletons/code_generator/recipes/recipe.rb +9 -0
  49. data/lib/chef-dk/skeletons/code_generator/recipes/template.rb +32 -0
  50. data/lib/chef-dk/skeletons/code_generator/templates/default/README.md.erb +4 -0
  51. data/lib/chef-dk/skeletons/code_generator/templates/default/attribute.rb.erb +0 -0
  52. data/lib/chef-dk/skeletons/code_generator/templates/default/cookbook_file.erb +0 -0
  53. data/lib/chef-dk/skeletons/code_generator/templates/default/default_recipe.rb.erb +8 -0
  54. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen.yml.erb +16 -0
  55. data/lib/chef-dk/skeletons/code_generator/templates/default/metadata.rb.erb +8 -0
  56. data/lib/chef-dk/skeletons/code_generator/templates/default/provider.rb.erb +0 -0
  57. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe.rb.erb +0 -0
  58. data/lib/chef-dk/skeletons/code_generator/templates/default/resource.rb.erb +0 -0
  59. data/lib/chef-dk/skeletons/code_generator/templates/default/template.erb +0 -0
  60. data/lib/chef-dk/version.rb +20 -0
  61. data/spec/shared/setup_git_cookbooks.rb +53 -0
  62. data/spec/spec_helper.rb +32 -0
  63. data/spec/test_helpers.rb +59 -0
  64. data/spec/unit/chef_runner_spec.rb +70 -0
  65. data/spec/unit/cli_spec.rb +151 -0
  66. data/spec/unit/command/base_spec.rb +88 -0
  67. data/spec/unit/command/exec_spec.rb +123 -0
  68. data/spec/unit/command/generate_spec.rb +102 -0
  69. data/spec/unit/command/generator_commands_spec.rb +504 -0
  70. data/spec/unit/command/shell_init_spec.rb +109 -0
  71. data/spec/unit/command/verify_spec.rb +311 -0
  72. data/spec/unit/commands_map_spec.rb +57 -0
  73. data/spec/unit/component_test_spec.rb +126 -0
  74. data/spec/unit/cookbook_metadata_spec.rb +62 -0
  75. data/spec/unit/cookbook_profiler/git_spec.rb +127 -0
  76. data/spec/unit/cookbook_profiler/identifiers_spec.rb +79 -0
  77. data/spec/unit/fixtures/chef-runner-cookbooks/test_cookbook/recipes/recipe_one.rb +9 -0
  78. data/spec/unit/fixtures/chef-runner-cookbooks/test_cookbook/recipes/recipe_two.rb +9 -0
  79. data/spec/unit/fixtures/command/cli_test_command.rb +26 -0
  80. data/spec/unit/fixtures/command/explicit_path_example.rb +7 -0
  81. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/.kitchen.yml +16 -0
  82. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/Berksfile +3 -0
  83. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/README.md +4 -0
  84. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/chefignore +96 -0
  85. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/metadata.rb +8 -0
  86. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/recipes/default.rb +8 -0
  87. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/.kitchen.yml +16 -0
  88. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/Berksfile +3 -0
  89. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/README.md +4 -0
  90. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/chefignore +96 -0
  91. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/metadata.rb +8 -0
  92. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/recipes/default.rb +8 -0
  93. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/.kitchen.yml +16 -0
  94. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/Berksfile +3 -0
  95. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/README.md +4 -0
  96. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/chefignore +96 -0
  97. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/metadata.rb +8 -0
  98. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/recipes/default.rb +8 -0
  99. data/spec/unit/fixtures/cookbooks_api/pruned_small_universe.json +1322 -0
  100. data/spec/unit/fixtures/cookbooks_api/small_universe.json +2987 -0
  101. data/spec/unit/fixtures/cookbooks_api/universe.json +1 -0
  102. data/spec/unit/fixtures/cookbooks_api/update_fixtures.rb +36 -0
  103. data/spec/unit/fixtures/dev_cookbooks/README.md +16 -0
  104. data/spec/unit/fixtures/dev_cookbooks/bar-cookbook.gitbundle +0 -0
  105. data/spec/unit/fixtures/eg_omnibus_dir/missing_apps/bin/.keep +0 -0
  106. data/spec/unit/fixtures/eg_omnibus_dir/missing_apps/embedded/.keep +0 -0
  107. data/spec/unit/fixtures/eg_omnibus_dir/missing_apps/embedded/bin/.keep +0 -0
  108. data/spec/unit/fixtures/eg_omnibus_dir/missing_component/bin/.keep +0 -0
  109. data/spec/unit/fixtures/eg_omnibus_dir/missing_component/embedded/apps/berkshelf/.keep +0 -0
  110. data/spec/unit/fixtures/eg_omnibus_dir/missing_component/embedded/apps/test-kitchen/.keep +0 -0
  111. data/spec/unit/fixtures/eg_omnibus_dir/missing_component/embedded/bin/.keep +0 -0
  112. data/spec/unit/fixtures/eg_omnibus_dir/valid/bin/.keep +0 -0
  113. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/berkshelf/integration_test +2 -0
  114. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/berkshelf/verify_me +5 -0
  115. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/chef-dk/.keep +0 -0
  116. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/chef/verify_me +3 -0
  117. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/test-kitchen/verify_me +2 -0
  118. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/bin/.keep +0 -0
  119. data/spec/unit/fixtures/example_app/Policyfile.rb +0 -0
  120. data/spec/unit/fixtures/example_cookbook/.gitignore +17 -0
  121. data/spec/unit/fixtures/example_cookbook/.kitchen.yml +16 -0
  122. data/spec/unit/fixtures/example_cookbook/Berksfile +3 -0
  123. data/spec/unit/fixtures/example_cookbook/README.md +4 -0
  124. data/spec/unit/fixtures/example_cookbook/chefignore +96 -0
  125. data/spec/unit/fixtures/example_cookbook/metadata.rb +8 -0
  126. data/spec/unit/fixtures/example_cookbook/recipes/default.rb +8 -0
  127. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/.kitchen.yml +16 -0
  128. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/Berksfile +3 -0
  129. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/README.md +4 -0
  130. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/chefignore +96 -0
  131. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/metadata.rb +8 -0
  132. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/recipes/default.rb +8 -0
  133. data/spec/unit/fixtures/local_path_cookbooks/metadata-missing/README.md +2 -0
  134. data/spec/unit/policyfile/chef_server_cookbook_source_spec.rb +34 -0
  135. data/spec/unit/policyfile/community_cookbook_source_spec.rb +51 -0
  136. data/spec/unit/policyfile/cookbook_spec_spec.rb +200 -0
  137. data/spec/unit/policyfile/null_cookbook_source_spec.rb +35 -0
  138. data/spec/unit/policyfile_builder_spec.rb +489 -0
  139. data/spec/unit/policyfile_demands_spec.rb +484 -0
  140. data/spec/unit/policyfile_evaluation_spec.rb +284 -0
  141. data/spec/unit/shell_out_spec.rb +34 -0
  142. metadata +422 -0
@@ -0,0 +1,504 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2014 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'spec_helper'
19
+ require 'chef-dk/command/generator_commands'
20
+
21
+ describe ChefDK::Command::GeneratorCommands::App do
22
+
23
+ let(:argv) { %w[new_app] }
24
+
25
+ let(:stdout_io) { StringIO.new }
26
+ let(:stderr_io) { StringIO.new }
27
+
28
+ let(:expected_cookbook_file_relpaths) do
29
+ %w[
30
+ .gitignore
31
+ .kitchen.yml
32
+ README.md
33
+ cookbooks/new_app/Berksfile
34
+ cookbooks/new_app/chefignore
35
+ cookbooks/new_app/metadata.rb
36
+ cookbooks/new_app/recipes
37
+ cookbooks/new_app/recipes/default.rb
38
+ ]
39
+ end
40
+
41
+ let(:expected_cookbook_files) do
42
+ expected_cookbook_file_relpaths.map do |relpath|
43
+ File.join(tempdir, "new_app", relpath)
44
+ end
45
+ end
46
+
47
+ subject(:cookbook_generator) { described_class.new(argv) }
48
+
49
+ def generator_context
50
+ ChefDK::Generator.context
51
+ end
52
+
53
+ before do
54
+ ChefDK::Generator.reset
55
+ end
56
+
57
+ context "when given the name of the cookbook to generate" do
58
+
59
+ before do
60
+ reset_tempdir
61
+ end
62
+
63
+ it "configures the generator context" do
64
+ cookbook_generator.read_and_validate_params
65
+ cookbook_generator.setup_context
66
+ expect(generator_context.app_root).to eq(Dir.pwd)
67
+ expect(generator_context.app_name).to eq("new_app")
68
+ expect(generator_context.cookbook_root).to eq(File.join(Dir.pwd, "new_app", "cookbooks"))
69
+ expect(generator_context.cookbook_name).to eq("new_app")
70
+ end
71
+
72
+ describe "generated files" do
73
+ it "creates a new cookbook" do
74
+ Dir.chdir(tempdir) do
75
+ cookbook_generator.chef_runner.stub(:stdout).and_return(stdout_io)
76
+ cookbook_generator.run
77
+ end
78
+ generated_files = Dir.glob(File.join(tempdir, "new_app", "**", "*"), File::FNM_DOTMATCH)
79
+ expected_cookbook_files.each do |expected_file|
80
+ expect(generated_files).to include(expected_file)
81
+ end
82
+ end
83
+
84
+ shared_examples_for "a generated file" do |context_var|
85
+ before do
86
+ Dir.chdir(tempdir) do
87
+ cookbook_generator.chef_runner.stub(:stdout).and_return(stdout_io)
88
+ cookbook_generator.run
89
+ end
90
+ end
91
+
92
+ it "should contain #{context_var} from the generator context" do
93
+ File.read(file).should match line
94
+ end
95
+ end
96
+
97
+ describe "README.md" do
98
+ let(:file) { File.join(tempdir, "new_app", "README.md") }
99
+
100
+ include_examples "a generated file", :cookbook_name do
101
+ let(:line) { "# new_app" }
102
+ end
103
+ end
104
+
105
+ describe ".kitchen.yml" do
106
+ let(:file) { File.join(tempdir, "new_app", ".kitchen.yml") }
107
+
108
+ include_examples "a generated file", :cookbook_name do
109
+ let(:line) { /\s*- recipe\[new_app::default\]/ }
110
+ end
111
+ end
112
+
113
+ describe "cookbooks/new_app/metadata.rb" do
114
+ let(:file) { File.join(tempdir, "new_app", "cookbooks", "new_app", "metadata.rb") }
115
+
116
+ include_examples "a generated file", :cookbook_name do
117
+ let(:line) { /name\s+'new_app'/ }
118
+ end
119
+ end
120
+
121
+ describe "cookbooks/new_app/recipes/default.rb" do
122
+ let(:file) { File.join(tempdir, "new_app", "cookbooks", "new_app", "recipes", "default.rb") }
123
+
124
+ include_examples "a generated file", :cookbook_name do
125
+ let(:line) { "# Cookbook Name:: new_app" }
126
+ end
127
+ end
128
+ end
129
+
130
+ end
131
+
132
+ end
133
+
134
+ describe ChefDK::Command::GeneratorCommands::Cookbook do
135
+
136
+ let(:argv) { %w[new_cookbook] }
137
+
138
+ let(:stdout_io) { StringIO.new }
139
+ let(:stderr_io) { StringIO.new }
140
+
141
+ let(:expected_cookbook_file_relpaths) do
142
+ %w[
143
+ .gitignore
144
+ .kitchen.yml
145
+ Berksfile
146
+ chefignore
147
+ metadata.rb
148
+ README.md
149
+ recipes
150
+ recipes/default.rb
151
+ ]
152
+ end
153
+
154
+ let(:expected_cookbook_files) do
155
+ expected_cookbook_file_relpaths.map do |relpath|
156
+ File.join(tempdir, "new_cookbook", relpath)
157
+ end
158
+ end
159
+
160
+ subject(:cookbook_generator) do
161
+ g = described_class.new(argv)
162
+ g.stub(:cookbook_path_in_git_repo?).and_return(false)
163
+ g
164
+ end
165
+
166
+ def generator_context
167
+ ChefDK::Generator.context
168
+ end
169
+
170
+ before do
171
+ ChefDK::Generator.reset
172
+ end
173
+
174
+ it "configures the chef runner" do
175
+ expect(cookbook_generator.chef_runner).to be_a(ChefDK::ChefRunner)
176
+ expect(cookbook_generator.chef_runner.cookbook_path).to eq(File.expand_path('lib/chef-dk/skeletons', project_root))
177
+ end
178
+
179
+ context "when given invalid/incomplete arguments" do
180
+
181
+ let(:expected_help_message) do
182
+ "Usage: chef generate cookbook NAME [options]\n"
183
+ end
184
+
185
+
186
+ def with_argv(argv)
187
+ generator = described_class.new(argv)
188
+ generator.stub(:stdout).and_return(stdout_io)
189
+ generator.stub(:stderr).and_return(stderr_io)
190
+ generator
191
+ end
192
+
193
+ it "prints usage when args are empty" do
194
+ with_argv([]).run
195
+ expect(stdout_io.string).to eq(expected_help_message)
196
+ end
197
+
198
+ end
199
+
200
+ context "when given the name of the cookbook to generate" do
201
+
202
+ let(:argv) { %w[new_cookbook] }
203
+
204
+ before do
205
+ reset_tempdir
206
+ end
207
+
208
+ it "configures the generator context" do
209
+ cookbook_generator.read_and_validate_params
210
+ cookbook_generator.setup_context
211
+ expect(generator_context.cookbook_root).to eq(Dir.pwd)
212
+ expect(generator_context.cookbook_name).to eq("new_cookbook")
213
+ end
214
+
215
+ it "creates a new cookbook" do
216
+ Dir.chdir(tempdir) do
217
+ cookbook_generator.chef_runner.stub(:stdout).and_return(stdout_io)
218
+ cookbook_generator.run
219
+ end
220
+ generated_files = Dir.glob("#{tempdir}/new_cookbook/**/*", File::FNM_DOTMATCH)
221
+ expected_cookbook_files.each do |expected_file|
222
+ expect(generated_files).to include(expected_file)
223
+ end
224
+ end
225
+
226
+ shared_examples_for "a generated file" do |context_var|
227
+ before do
228
+ Dir.chdir(tempdir) do
229
+ cookbook_generator.chef_runner.stub(:stdout).and_return(stdout_io)
230
+ cookbook_generator.run
231
+ end
232
+ end
233
+
234
+ it "should contain #{context_var} from the generator context" do
235
+ File.read(file).should match line
236
+ end
237
+ end
238
+
239
+ describe "README.md" do
240
+ let(:file) { File.join(tempdir, "new_cookbook", "README.md") }
241
+
242
+ include_examples "a generated file", :cookbook_name do
243
+ let(:line) { "# new_cookbook" }
244
+ end
245
+ end
246
+
247
+ describe ".kitchen.yml" do
248
+ let(:file) { File.join(tempdir, "new_cookbook", ".kitchen.yml") }
249
+
250
+ include_examples "a generated file", :cookbook_name do
251
+ let(:line) { /\s*- recipe\[new_cookbook::default\]/ }
252
+ end
253
+ end
254
+
255
+ describe "metadata.rb" do
256
+ let(:file) { File.join(tempdir, "new_cookbook", "metadata.rb") }
257
+
258
+ include_examples "a generated file", :cookbook_name do
259
+ let(:line) { /name\s+'new_cookbook'/ }
260
+ end
261
+ end
262
+
263
+ describe "recipes/default.rb" do
264
+ let(:file) { File.join(tempdir, "new_cookbook", "recipes", "default.rb") }
265
+
266
+ include_examples "a generated file", :cookbook_name do
267
+ let(:line) { "# Cookbook Name:: new_cookbook" }
268
+ end
269
+ end
270
+
271
+ end
272
+
273
+ context "when given the path to the cookbook to generate" do
274
+ let(:argv) { [ File.join(tempdir, "a_new_cookbook") ] }
275
+
276
+ before do
277
+ reset_tempdir
278
+ end
279
+
280
+ it "configures the generator context" do
281
+ cookbook_generator.read_and_validate_params
282
+ cookbook_generator.setup_context
283
+ expect(generator_context.cookbook_root).to eq(tempdir)
284
+ expect(generator_context.cookbook_name).to eq("a_new_cookbook")
285
+ end
286
+
287
+ end
288
+
289
+ context "when given a generator-cookbook path" do
290
+ let(:generator_cookbook_path) { File.join(tempdir, 'a_generator_cookbook') }
291
+ let(:argv) { ["new_cookbook", "--generator-cookbook", generator_cookbook_path] }
292
+
293
+ before do
294
+ reset_tempdir
295
+ end
296
+
297
+ it "configures the generator context" do
298
+ cookbook_generator.read_and_validate_params
299
+ cookbook_generator.setup_context
300
+ expect(generator_context.cookbook_root).to eq(Dir.pwd)
301
+ expect(generator_context.cookbook_name).to eq("new_cookbook")
302
+ expect(cookbook_generator.chef_runner.cookbook_path).to eq(generator_cookbook_path)
303
+ end
304
+
305
+ it "creates a new cookbook" do
306
+ Dir.chdir(tempdir) do
307
+ cookbook_generator.chef_runner.stub(:stdout).and_return(stdout_io)
308
+ cookbook_generator.run
309
+ end
310
+ generated_files = Dir.glob("#{tempdir}/new_cookbook/**/*", File::FNM_DOTMATCH)
311
+ expected_cookbook_files.each do |expected_file|
312
+ expect(generated_files).to include(expected_file)
313
+ end
314
+ end
315
+ end
316
+
317
+ end
318
+
319
+ shared_examples_for "a file generator" do
320
+
321
+ let(:stdout_io) { StringIO.new }
322
+ let(:stderr_io) { StringIO.new }
323
+
324
+ def stdout
325
+ stdout_io.string
326
+ end
327
+
328
+ def stderr
329
+ stderr_io.string
330
+ end
331
+
332
+ let(:expected_cookbook_root) { tempdir }
333
+ let(:cookbook_name) { "example_cookbook" }
334
+
335
+ let(:cookbook_path) { File.join(tempdir, cookbook_name) }
336
+
337
+ subject(:recipe_generator) do
338
+ generator = described_class.new(argv)
339
+ generator.stub(:stdout).and_return(stdout_io)
340
+ generator.stub(:stderr).and_return(stderr_io)
341
+ generator
342
+ end
343
+
344
+ def generator_context
345
+ ChefDK::Generator.context
346
+ end
347
+
348
+ before do
349
+ ChefDK::Generator.reset
350
+ reset_tempdir
351
+ end
352
+
353
+ context "when argv is empty" do
354
+ let(:argv) { [] }
355
+
356
+ it "emits an error message and exits" do
357
+ expected_stdout = "Usage: chef generate #{generator_name} [path/to/cookbook] NAME [options]"
358
+
359
+ expect(recipe_generator.run).to eq(1)
360
+ expect(stdout).to include(expected_stdout)
361
+ end
362
+ end
363
+
364
+ context "when CWD is a cookbook" do
365
+
366
+ let(:argv) { [ new_file_name ] }
367
+
368
+ before do
369
+ FileUtils.cp_r(File.join(fixtures_path, "example_cookbook"), tempdir)
370
+ end
371
+
372
+ it "configures the generator context" do
373
+ Dir.chdir(cookbook_path) do
374
+ recipe_generator.read_and_validate_params
375
+ recipe_generator.setup_context
376
+
377
+ expect(generator_context.cookbook_root).to eq(expected_cookbook_root)
378
+ expect(generator_context.cookbook_name).to eq(cookbook_name)
379
+ expect(generator_context.new_file_basename).to eq(new_file_name)
380
+ end
381
+ end
382
+
383
+ it "creates a new recipe" do
384
+ Dir.chdir(cookbook_path) do
385
+ recipe_generator.chef_runner.stub(:stdout).and_return(stdout_io)
386
+ recipe_generator.run
387
+ end
388
+
389
+ generated_files.each do |expected_file|
390
+ expect(File).to exist(File.join(cookbook_path, expected_file))
391
+ end
392
+ end
393
+
394
+ end
395
+
396
+ context "when CWD is not a cookbook" do
397
+ context "and path to the cookbook is not given in the agv" do
398
+ let(:argv) { [ new_file_name ] }
399
+
400
+ it "emits an error message and exits" do
401
+ expected_stdout = "Usage: chef generate #{generator_name} [path/to/cookbook] NAME [options]"
402
+ expected_stderr = "Error: Directory #{Dir.pwd} is not a cookbook\n"
403
+
404
+ expect(recipe_generator.run).to eq(1)
405
+ expect(stdout).to include(expected_stdout)
406
+ expect(stderr).to eq(expected_stderr)
407
+ end
408
+ end
409
+
410
+ context "and path to the cookbook is given in the argv" do
411
+ let(:argv) { [cookbook_path, new_file_name ] }
412
+
413
+ before do
414
+ FileUtils.cp_r(File.join(fixtures_path, "example_cookbook"), tempdir)
415
+ end
416
+
417
+ it "configures the generator context" do
418
+ recipe_generator.read_and_validate_params
419
+ recipe_generator.setup_context
420
+
421
+ expect(generator_context.cookbook_root).to eq(File.dirname(cookbook_path))
422
+ expect(generator_context.cookbook_name).to eq(cookbook_name)
423
+ expect(generator_context.new_file_basename).to eq(new_file_name)
424
+ end
425
+
426
+ it "creates a new recipe" do
427
+ recipe_generator.chef_runner.stub(:stdout).and_return(stdout_io)
428
+ recipe_generator.run
429
+
430
+ generated_files.each do |expected_file|
431
+ expect(File).to exist(File.join(cookbook_path, expected_file))
432
+ end
433
+ end
434
+
435
+ end
436
+ end
437
+
438
+ end
439
+
440
+ describe ChefDK::Command::GeneratorCommands::Recipe do
441
+
442
+ include_examples "a file generator" do
443
+
444
+ let(:generator_name) { "recipe" }
445
+ let(:generated_files) { [ "recipes/new_recipe.rb" ] }
446
+ let(:new_file_name) { "new_recipe" }
447
+
448
+ end
449
+ end
450
+
451
+ describe ChefDK::Command::GeneratorCommands::Attribute do
452
+
453
+ include_examples "a file generator" do
454
+
455
+ let(:generator_name) { "attribute" }
456
+ let(:generated_files) { [ "attributes/new_attribute_file.rb" ] }
457
+ let(:new_file_name) { "new_attribute_file" }
458
+
459
+ end
460
+ end
461
+
462
+ describe ChefDK::Command::GeneratorCommands::LWRP do
463
+
464
+ include_examples "a file generator" do
465
+
466
+ let(:generator_name) { "lwrp" }
467
+ let(:generated_files) { [ "resources/new_lwrp.rb", "providers/new_lwrp.rb" ] }
468
+ let(:new_file_name) { "new_lwrp" }
469
+
470
+ end
471
+ end
472
+
473
+ describe ChefDK::Command::GeneratorCommands::Template do
474
+
475
+ include_examples "a file generator" do
476
+
477
+ let(:generator_name) { "template" }
478
+ let(:generated_files) { [ "templates/default/new_template.txt.erb" ] }
479
+ let(:new_file_name) { "new_template.txt" }
480
+
481
+ end
482
+ end
483
+
484
+ describe ChefDK::Command::GeneratorCommands::Template do
485
+
486
+ include_examples "a file generator" do
487
+
488
+ let(:generator_name) { "template" }
489
+ let(:generated_files) { [ "templates/default/new_template.erb" ] }
490
+ let(:new_file_name) { "new_template.erb" }
491
+
492
+ end
493
+ end
494
+
495
+ describe ChefDK::Command::GeneratorCommands::CookbookFile do
496
+
497
+ include_examples "a file generator" do
498
+
499
+ let(:generator_name) { "file" }
500
+ let(:generated_files) { [ "files/default/new_file.txt" ] }
501
+ let(:new_file_name) { "new_file.txt" }
502
+
503
+ end
504
+ end