chef-dk 0.3.0 → 0.3.5

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -0
  3. data/lib/chef-dk/cli.rb +7 -5
  4. data/lib/chef-dk/command/generate.rb +2 -0
  5. data/lib/chef-dk/command/generator_commands.rb +8 -0
  6. data/lib/chef-dk/command/generator_commands/base.rb +4 -1
  7. data/lib/chef-dk/command/generator_commands/policyfile.rb +83 -0
  8. data/lib/chef-dk/command/install.rb +4 -5
  9. data/lib/chef-dk/command/push.rb +4 -5
  10. data/lib/chef-dk/command/verify.rb +3 -2
  11. data/lib/chef-dk/component_test.rb +7 -2
  12. data/lib/chef-dk/exceptions.rb +3 -34
  13. data/lib/chef-dk/helpers.rb +20 -2
  14. data/lib/chef-dk/policyfile/cookbook_locks.rb +19 -1
  15. data/lib/chef-dk/policyfile/read_cookbook_for_compat_mode_upload.rb +11 -1
  16. data/lib/chef-dk/policyfile/storage_config.rb +23 -0
  17. data/lib/chef-dk/policyfile/uploader.rb +1 -1
  18. data/lib/chef-dk/policyfile_services/install.rb +19 -32
  19. data/lib/chef-dk/policyfile_services/push.rb +17 -27
  20. data/lib/chef-dk/service_exception_inspectors.rb +25 -0
  21. data/lib/chef-dk/service_exception_inspectors/base.rb +40 -0
  22. data/lib/chef-dk/service_exception_inspectors/http.rb +121 -0
  23. data/lib/chef-dk/service_exceptions.rb +77 -0
  24. data/lib/chef-dk/skeletons/code_generator/recipes/policyfile.rb +8 -0
  25. data/lib/chef-dk/skeletons/code_generator/templates/default/Policyfile.rb.erb +16 -0
  26. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen.yml.erb +1 -1
  27. data/lib/chef-dk/version.rb +1 -1
  28. data/spec/unit/cli_spec.rb +126 -65
  29. data/spec/unit/command/exec_spec.rb +7 -2
  30. data/spec/unit/command/generator_commands/cookbook_spec.rb +27 -1
  31. data/spec/unit/command/generator_commands/policyfile_spec.rb +125 -0
  32. data/spec/unit/command/install_spec.rb +3 -4
  33. data/spec/unit/command/push_spec.rb +6 -7
  34. data/spec/unit/command/shell_init_spec.rb +5 -1
  35. data/spec/unit/cookbook_profiler/git_spec.rb +2 -2
  36. data/spec/unit/policyfile/cookbook_locks_spec.rb +58 -0
  37. data/spec/unit/policyfile/read_cookbook_for_compat_mode_upload_spec.rb +8 -1
  38. data/spec/unit/policyfile/storage_config_spec.rb +75 -1
  39. data/spec/unit/policyfile/uploader_spec.rb +31 -0
  40. data/spec/unit/policyfile_lock_validation_spec.rb +13 -12
  41. data/spec/unit/policyfile_services/install_spec.rb +5 -3
  42. data/spec/unit/policyfile_services/push_spec.rb +7 -5
  43. data/spec/unit/service_exception_inspectors/base_spec.rb +43 -0
  44. data/spec/unit/service_exception_inspectors/http_spec.rb +140 -0
  45. metadata +41 -2
@@ -125,9 +125,8 @@ describe ChefDK::Command::Install do
125
125
  it "displays the exception and cause" do
126
126
  expected_error_text=<<-E
127
127
  Error: install failed
128
- Reason: StandardError
128
+ Reason: (StandardError) some operation failed
129
129
 
130
- some operation failed
131
130
  E
132
131
 
133
132
  command.run
@@ -141,9 +140,9 @@ E
141
140
  it "displays the exception and cause with backtrace" do
142
141
  expected_error_text=<<-E
143
142
  Error: install failed
144
- Reason: StandardError
143
+ Reason: (StandardError) some operation failed
144
+
145
145
 
146
- some operation failed
147
146
  E
148
147
 
149
148
  expected_error_text << backtrace.join("\n") << "\n"
@@ -147,7 +147,7 @@ describe ChefDK::Command::Push do
147
147
  end
148
148
 
149
149
  let(:exception) do
150
- ChefDK::PolicyfilePushError.new("install failed", cause)
150
+ ChefDK::PolicyfilePushError.new("push failed", cause)
151
151
  end
152
152
 
153
153
  before do
@@ -162,10 +162,9 @@ describe ChefDK::Command::Push do
162
162
  command.run(params)
163
163
 
164
164
  expected_output=<<-E
165
- Error: install failed
166
- Reason: StandardError
165
+ Error: push failed
166
+ Reason: (StandardError) some operation failed
167
167
 
168
- some operation failed
169
168
  E
170
169
 
171
170
  expect(ui.output).to eq(expected_output)
@@ -182,10 +181,10 @@ E
182
181
  command.run(params)
183
182
 
184
183
  expected_output=<<-E
185
- Error: install failed
186
- Reason: StandardError
184
+ Error: push failed
185
+ Reason: (StandardError) some operation failed
186
+
187
187
 
188
- some operation failed
189
188
  E
190
189
  expected_output << backtrace.join("\n") << "\n"
191
190
 
@@ -30,11 +30,15 @@ describe ChefDK::Command::ShellInit do
30
30
  end
31
31
  end
32
32
 
33
+ before do
34
+ stub_const("File::PATH_SEPARATOR", ':')
35
+ end
36
+
33
37
  let(:argv) { ['bash'] }
34
38
 
35
39
  let(:user_bin_dir) { File.expand_path(File.join(Gem.user_dir, 'bin')) }
36
40
 
37
- let(:expected_path) { "#{omnibus_bin_dir}:#{user_bin_dir}:#{omnibus_embedded_bin_dir}:#{ENV['PATH']}" }
41
+ let(:expected_path) { [omnibus_bin_dir, user_bin_dir, omnibus_embedded_bin_dir, ENV['PATH']].join(File::PATH_SEPARATOR) }
38
42
 
39
43
  let(:expected_gem_root) { Gem.default_dir.to_s }
40
44
 
@@ -32,7 +32,7 @@ describe ChefDK::CookbookProfiler::Git do
32
32
  end
33
33
 
34
34
  def edit_repo
35
- File.open(File.join(cookbook_path, "README.md"), "a+") { |f| f.puts "some unpublished changes" }
35
+ with_file(File.join(cookbook_path, "README.md"), "ab+") { |f| f.puts "some unpublished changes" }
36
36
  end
37
37
 
38
38
  context "given a clean repo with no remotes" do
@@ -93,7 +93,7 @@ describe ChefDK::CookbookProfiler::Git do
93
93
  edit_repo
94
94
  system_command('git config --local user.name "Alice"', cwd: cookbook_path).error!
95
95
  system_command('git config --local user.email "alice@example.com"', cwd: cookbook_path).error!
96
- system_command("git commit -a -m 'update readme' --author 'Alice <alice@example.com>'", cwd: cookbook_path).error!
96
+ system_command('git commit -a -m "update readme" --author "Alice <alice@example.com>"', cwd: cookbook_path).error!
97
97
  end
98
98
 
99
99
  it "reports that the repo is clean" do
@@ -244,6 +244,64 @@ describe ChefDK::Policyfile::LocalCookbook do
244
244
 
245
245
  end
246
246
 
247
+ describe "selecting an SCM profiler" do
248
+
249
+ let(:cookbook_source_relpath) { "nginx" }
250
+
251
+ let(:cookbook_source_path) do
252
+ path = File.join(tempdir, cookbook_source_relpath)
253
+ FileUtils.mkdir_p(path)
254
+ path
255
+ end
256
+
257
+ before do
258
+ cookbook_lock.source = cookbook_source_path
259
+ end
260
+
261
+ after do
262
+ clear_tempdir
263
+ end
264
+
265
+ context "when the cookbook is in a git-repo" do
266
+
267
+ before do
268
+ FileUtils.mkdir_p(git_dir_path)
269
+ end
270
+
271
+ context "when the cookbook is a self-contained git repo" do
272
+
273
+ let(:git_dir_path) { File.join(cookbook_source_path, ".git") }
274
+
275
+ it "selects the git profiler" do
276
+ expect(cookbook_lock.scm_profiler).to be_an_instance_of(ChefDK::CookbookProfiler::Git)
277
+ end
278
+
279
+ end
280
+
281
+ context "when the cookbook is a subdirectory of a git repo" do
282
+
283
+ let(:cookbook_source_relpath) { "cookbook_repo/nginx" }
284
+
285
+ let(:git_dir_path) { File.join(tempdir, "cookbook_repo/.git") }
286
+
287
+ it "selects the git profiler" do
288
+ expect(cookbook_lock.scm_profiler).to be_an_instance_of(ChefDK::CookbookProfiler::Git)
289
+ end
290
+
291
+ end
292
+
293
+ end
294
+
295
+ context "when the cookbook is not in a git repo" do
296
+
297
+ it "selects the null profiler" do
298
+ expect(cookbook_lock.scm_profiler).to be_an_instance_of(ChefDK::CookbookProfiler::NullSCM)
299
+ end
300
+
301
+ end
302
+
303
+ end
304
+
247
305
  context "when loading data from a serialized form" do
248
306
 
249
307
  let(:previous_lock_data) do
@@ -17,9 +17,12 @@
17
17
 
18
18
  require 'spec_helper'
19
19
  require 'chef-dk/policyfile/read_cookbook_for_compat_mode_upload'
20
+ require 'chef-dk/helpers'
20
21
 
21
22
  describe ChefDK::Policyfile::ReadCookbookForCompatModeUpload do
22
23
 
24
+ include ChefDK::Helpers
25
+
23
26
  let(:cookbook_name) { "noignore" }
24
27
 
25
28
  let(:version_override) { "123.456.789" }
@@ -56,6 +59,10 @@ describe ChefDK::Policyfile::ReadCookbookForCompatModeUpload do
56
59
  expect(reader.cookbook_version.frozen_version?).to be true
57
60
  end
58
61
 
62
+ it "fixes up the cookbook manifest name" do
63
+ expect(reader.cookbook_version.manifest["name"]).to eq("noignore-#{version_override}")
64
+ end
65
+
59
66
  context "when a cookbook has a chefignore file" do
60
67
 
61
68
  let(:directory_path) { File.join(fixtures_path, "cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb") }
@@ -70,7 +77,7 @@ describe ChefDK::Policyfile::ReadCookbookForCompatModeUpload do
70
77
 
71
78
  before do
72
79
  FileUtils.cp_r(directory_path, copied_cookbook_path)
73
- File.open(chefignored_file, "w+") { |f| f.puts "This file should not affect the cookbooks checksum" }
80
+ with_file(chefignored_file) { |f| f.puts "This file should not affect the cookbooks checksum" }
74
81
  end
75
82
 
76
83
  after do
@@ -74,6 +74,47 @@ describe ChefDK::Policyfile::StorageConfig do
74
74
  expect(storage_config.policyfile_filename).to eq("/path/to/Policyfile.rb")
75
75
  end
76
76
 
77
+ it "generates the location of the policyfile lock" do
78
+ expect(storage_config.policyfile_lock_filename).to eq("/path/to/Policyfile.lock.json")
79
+ end
80
+
81
+ it "gives the expanded path to the policyfile" do
82
+ expect(storage_config.policyfile_expanded_path).to eq(File.expand_path('/path/to/Policyfile.rb'))
83
+ end
84
+
85
+ context "when the policyfile is given as a relative path" do
86
+
87
+ before do
88
+ storage_config.use_policyfile("Policyfile.rb")
89
+ end
90
+
91
+ it "updates the relative_paths_root to be relative to a policyfile" do
92
+ expect(storage_config.relative_paths_root).to eq(".")
93
+ end
94
+
95
+ it "stores the location of the policyfile" do
96
+ expect(storage_config.policyfile_filename).to eq("Policyfile.rb")
97
+ end
98
+
99
+ it "generates the location of the policyfile lock" do
100
+ expect(storage_config.policyfile_lock_filename).to eq("Policyfile.lock.json")
101
+ end
102
+
103
+ it "gives the expanded path to the policyfile" do
104
+ expect(storage_config.policyfile_expanded_path).to eq(File.expand_path("Policyfile.rb", "."))
105
+ end
106
+
107
+ end
108
+
109
+ context "when the policyfile file name doesn't have a .rb extension" do
110
+
111
+ it "raises an error" do
112
+ err_string = %q{Policyfile filenames must end with `.rb' extension (you gave: `Policyfile')}
113
+ expect { storage_config.use_policyfile("Policyfile") }.to raise_error(ChefDK::InvalidPolicyfileFilename, err_string)
114
+ end
115
+
116
+ end
117
+
77
118
  end
78
119
 
79
120
 
@@ -87,10 +128,43 @@ describe ChefDK::Policyfile::StorageConfig do
87
128
  expect(storage_config.relative_paths_root).to eq("/path/to")
88
129
  end
89
130
 
90
- it "stores the location of the policyfile" do
131
+ it "stores the location of the policyfile lock" do
91
132
  expect(storage_config.policyfile_lock_filename).to eq("/path/to/Policyfile.lock.json")
92
133
  end
93
134
 
135
+ it "stores the location of the policyfile" do
136
+ expect(storage_config.policyfile_filename).to eq("/path/to/Policyfile.rb")
137
+ end
138
+
139
+ it "gives the expanded path to the policyfile lock" do
140
+ expect(storage_config.policyfile_lock_expanded_path).to eq(File.expand_path("/path/to/Policyfile.lock.json"))
141
+ end
142
+
143
+ context "when given a relative path to the policyfile lock" do
144
+
145
+ before do
146
+ storage_config.use_policyfile_lock("Policyfile.lock.json")
147
+ end
148
+
149
+ it "updates the relative_paths_root to be relative to a policyfile" do
150
+ expect(storage_config.relative_paths_root).to eq(".")
151
+ end
152
+
153
+ it "stores the location of the policyfile" do
154
+ expect(storage_config.policyfile_filename).to eq("Policyfile.rb")
155
+ end
156
+
157
+ it "generates the location of the policyfile lock" do
158
+ expect(storage_config.policyfile_lock_filename).to eq("Policyfile.lock.json")
159
+ end
160
+
161
+ it "gives the expanded path to the policyfile" do
162
+ expect(storage_config.policyfile_lock_expanded_path).to eq(File.expand_path("Policyfile.lock.json", "."))
163
+ end
164
+
165
+
166
+ end
167
+
94
168
  end
95
169
 
96
170
 
@@ -283,6 +283,37 @@ describe ChefDK::Policyfile::Uploader do
283
283
 
284
284
  end
285
285
 
286
+ context "with a set of cookbooks that all exist on the server" do
287
+
288
+ before do
289
+ # Have this one:
290
+ lock_double("build-essential", "67369247788170534.26353953100055918.55660493423796")
291
+ end
292
+
293
+ let(:expected_cookbooks_for_upload) do
294
+ []
295
+ end
296
+
297
+ it "lists no cookbooks as needing to be uploaded" do
298
+ expect(policyfile_lock).to receive(:validate_cookbooks!)
299
+ expect(http_client).to receive(:get).with('cookbooks?num_versions=all').and_return(existing_cookbook_on_remote)
300
+
301
+ expect(uploader.cookbook_versions_to_upload).to eq(expected_cookbooks_for_upload)
302
+ end
303
+
304
+ it "skips cookbooks uploads, then uploads the policy" do
305
+ expect(policyfile_lock).to receive(:validate_cookbooks!)
306
+ expect(http_client).to receive(:get).with('cookbooks?num_versions=all').and_return(existing_cookbook_on_remote)
307
+
308
+ expect(uploader.uploader).to_not receive(:upload_cookbooks)
309
+
310
+ # behavior for these tested above
311
+ expect(uploader).to receive(:data_bag_create)
312
+ expect(uploader).to receive(:data_bag_item_create)
313
+
314
+ uploader.upload
315
+ end
316
+ end
286
317
  end
287
318
 
288
319
  end
@@ -20,6 +20,8 @@ require 'chef-dk/policyfile_lock.rb'
20
20
 
21
21
  describe ChefDK::PolicyfileLock, "validating locked cookbooks" do
22
22
 
23
+ include ChefDK::Helpers
24
+
23
25
  let(:pristine_cache_path) do
24
26
  File.expand_path("spec/unit/fixtures/cookbook_cache", project_root)
25
27
  end
@@ -158,7 +160,7 @@ E
158
160
 
159
161
  before do
160
162
  ensure_metadata_as_expected!
161
- File.open(metadata_path, "w+") { |f| f.print(new_metadata) }
163
+ with_file(metadata_path) { |f| f.print(new_metadata) }
162
164
  end
163
165
 
164
166
  it "reports the unexpected cookbook and fails validation" do
@@ -187,7 +189,7 @@ E
187
189
 
188
190
  before do
189
191
  ensure_metadata_as_expected!
190
- File.open(metadata_path, "w+") { |f| f.print(new_metadata) }
192
+ with_file(metadata_path) { |f| f.print(new_metadata) }
191
193
  policyfile_lock.validate_cookbooks! # no error
192
194
  end
193
195
 
@@ -197,7 +199,6 @@ E
197
199
 
198
200
  it "updates the content identifier" do
199
201
  old_id = lock_generator.lock_data_for("local-cookbook").identifier
200
-
201
202
  expect(cookbook_lock_data.identifier).to_not eq(old_id)
202
203
  expect(cookbook_lock_data.identifier).to eq("d71622904ed89b1e0066bb4ae823b2a7b49a615a")
203
204
  end
@@ -235,7 +236,7 @@ E
235
236
 
236
237
  before do
237
238
  ensure_metadata_as_expected!
238
- File.open(metadata_path, "w+") { |f| f.print(new_metadata) }
239
+ with_file(metadata_path) { |f| f.print(new_metadata) }
239
240
  end
240
241
 
241
242
  it "reports the dependency conflict and fails validation" do
@@ -259,7 +260,7 @@ E
259
260
 
260
261
  before do
261
262
  ensure_metadata_as_expected!
262
- File.open(recipe_path, "w+") { |f| f.print(new_recipe) }
263
+ with_file(recipe_path) { |f| f.print(new_recipe) }
263
264
  policyfile_lock.validate_cookbooks! # no error
264
265
  end
265
266
 
@@ -297,7 +298,7 @@ E
297
298
 
298
299
  before do
299
300
  ensure_metadata_as_expected!
300
- File.open(metadata_path, "w+") { |f| f.print(new_metadata) }
301
+ with_file(metadata_path) { |f| f.print(new_metadata) }
301
302
  policyfile_lock.validate_cookbooks! # no error
302
303
  end
303
304
 
@@ -344,7 +345,7 @@ E
344
345
 
345
346
  before do
346
347
  ensure_metadata_as_expected!
347
- File.open(metadata_path, "w+") { |f| f.print(new_metadata) }
348
+ with_file(metadata_path) { |f| f.print(new_metadata) }
348
349
  end
349
350
 
350
351
  it "reports the not-satisfied dependency and validation fails" do
@@ -384,7 +385,7 @@ E
384
385
 
385
386
  before do
386
387
  ensure_metadata_as_expected!
387
- File.open(metadata_path, "w+") { |f| f.print(new_metadata) }
388
+ with_file(metadata_path) { |f| f.print(new_metadata) }
388
389
  policyfile_lock.validate_cookbooks! # no error
389
390
  end
390
391
 
@@ -418,7 +419,7 @@ E
418
419
 
419
420
  before do
420
421
  ensure_metadata_as_expected!
421
- File.open(metadata_path, "w+") { |f| f.print(new_metadata) }
422
+ with_file(metadata_path) { |f| f.print(new_metadata) }
422
423
  end
423
424
 
424
425
  it "reports the not-satisfied dependency and validation fails" do
@@ -509,8 +510,8 @@ E
509
510
 
510
511
  before do
511
512
  ensure_metadata_as_expected!
512
- File.open(metadata_path, "w+") { |f| f.print(new_metadata_local_cookbook) }
513
- File.open(metadata_path_another_local_cookbook, "w+") { |f| f.print(new_metadata_another_local_cookbook) }
513
+ with_file(metadata_path) { |f| f.print(new_metadata_local_cookbook) }
514
+ with_file(metadata_path_another_local_cookbook) { |f| f.print(new_metadata_another_local_cookbook) }
514
515
  policyfile_lock.validate_cookbooks! # no error
515
516
  end
516
517
 
@@ -597,7 +598,7 @@ E
597
598
  before do
598
599
  ensure_metadata_as_expected!
599
600
  policyfile_lock
600
- File.open(metadata_path, "w+") { |f| f.print(new_metadata) }
601
+ with_file(metadata_path) { |f| f.print(new_metadata) }
601
602
  end
602
603
 
603
604
  it "reports the modified cached cookbook and validation fails" do
@@ -20,6 +20,8 @@ require 'chef-dk/policyfile_services/install'
20
20
 
21
21
  describe ChefDK::PolicyfileServices::Install do
22
22
 
23
+ include ChefDK::Helpers
24
+
23
25
  let(:working_dir) do
24
26
  path = File.join(tempdir, "policyfile_services_test_working_dir")
25
27
  Dir.mkdir(path)
@@ -76,11 +78,11 @@ E
76
78
  context "when a Policyfile exists" do
77
79
 
78
80
  before do
79
- File.open(policyfile_rb_path, "w+") { |f| f.print(policyfile_content) }
81
+ with_file(policyfile_rb_path) { |f| f.print(policyfile_content) }
80
82
  end
81
83
 
82
84
  it "infers that the Policyfile.rb is located at $CWD/Policyfile.rb" do
83
- expect(install_service.policyfile_path).to eq(policyfile_rb_path)
85
+ expect(install_service.policyfile_expanded_path).to eq(policyfile_rb_path)
84
86
  end
85
87
 
86
88
  it "reads the policyfile from disk" do
@@ -156,7 +158,7 @@ E
156
158
  let(:policyfile_lock_name) { "MyPolicy.lock.json" }
157
159
 
158
160
  it "infers that the Policyfile.rb is located at $CWD/$POLICYFILE_NAME" do
159
- expect(install_service.policyfile_path).to eq(policyfile_rb_path)
161
+ expect(install_service.policyfile_expanded_path).to eq(policyfile_rb_path)
160
162
  end
161
163
 
162
164
  it "reads the policyfile from disk" do