chef-dk 0.3.0 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
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