chef-dk 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/chef-dk/authenticated_http.rb +40 -0
  4. data/lib/chef-dk/chef_runner.rb +5 -0
  5. data/lib/chef-dk/command/exec.rb +4 -1
  6. data/lib/chef-dk/command/generate.rb +11 -0
  7. data/lib/chef-dk/command/generator_commands.rb +20 -365
  8. data/lib/chef-dk/command/generator_commands/app.rb +99 -0
  9. data/lib/chef-dk/command/generator_commands/attribute.rb +37 -0
  10. data/lib/chef-dk/command/generator_commands/base.rb +76 -0
  11. data/lib/chef-dk/command/generator_commands/cookbook.rb +100 -0
  12. data/lib/chef-dk/command/generator_commands/cookbook_code_file.rb +99 -0
  13. data/lib/chef-dk/command/generator_commands/cookbook_file.rb +45 -0
  14. data/lib/chef-dk/command/generator_commands/lwrp.rb +36 -0
  15. data/lib/chef-dk/command/generator_commands/recipe.rb +36 -0
  16. data/lib/chef-dk/command/generator_commands/repo.rb +96 -0
  17. data/lib/chef-dk/command/generator_commands/template.rb +45 -0
  18. data/lib/chef-dk/command/verify.rb +28 -0
  19. data/lib/chef-dk/component_test.rb +16 -3
  20. data/lib/chef-dk/cookbook_omnifetch.rb +2 -0
  21. data/lib/chef-dk/cookbook_profiler/identifiers.rb +3 -15
  22. data/lib/chef-dk/exceptions.rb +15 -0
  23. data/lib/chef-dk/generator.rb +102 -25
  24. data/lib/chef-dk/policyfile/community_cookbook_source.rb +0 -7
  25. data/lib/chef-dk/policyfile/{cookbook_spec.rb → cookbook_location_specification.rb} +35 -6
  26. data/lib/chef-dk/policyfile/cookbook_locks.rb +305 -0
  27. data/lib/chef-dk/policyfile/dsl.rb +26 -12
  28. data/lib/chef-dk/policyfile/read_cookbook_for_compat_mode_upload.rb +70 -0
  29. data/lib/chef-dk/policyfile/solution_dependencies.rb +204 -0
  30. data/lib/chef-dk/policyfile/storage_config.rb +77 -0
  31. data/lib/chef-dk/policyfile/uploader.rb +110 -0
  32. data/lib/chef-dk/policyfile_compiler.rb +59 -29
  33. data/lib/chef-dk/policyfile_lock.rb +104 -160
  34. data/lib/chef-dk/skeletons/code_generator/files/default/Berksfile +1 -1
  35. data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +0 -1
  36. data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +66 -0
  37. data/lib/chef-dk/skeletons/code_generator/files/default/repo/Rakefile +65 -0
  38. data/lib/chef-dk/skeletons/code_generator/files/default/repo/certificates/README.md +19 -0
  39. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/README-policy.md +9 -0
  40. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/README.md +54 -0
  41. data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/README.md +63 -0
  42. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/README.md +5 -0
  43. data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/README.md +16 -0
  44. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook.rb +7 -1
  45. data/lib/chef-dk/skeletons/code_generator/recipes/repo.rb +62 -0
  46. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.all_rights.erb +3 -0
  47. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.apache2.erb +201 -0
  48. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv2.erb +339 -0
  49. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv3.erb +674 -0
  50. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.mit.erb +21 -0
  51. data/lib/chef-dk/skeletons/code_generator/templates/default/default_recipe.rb.erb +1 -4
  52. data/lib/chef-dk/skeletons/code_generator/templates/default/metadata.rb.erb +3 -3
  53. data/lib/chef-dk/skeletons/code_generator/templates/default/repo/config/rake.rb.erb +38 -0
  54. data/lib/chef-dk/skeletons/code_generator/templates/default/repo/gitignore.erb +11 -0
  55. data/lib/chef-dk/version.rb +1 -1
  56. data/spec/shared/a_file_generator.rb +121 -0
  57. data/spec/shared/a_generated_file.rb +12 -0
  58. data/spec/shared/fixture_cookbook_checksums.rb +47 -0
  59. data/spec/spec_helper.rb +4 -2
  60. data/spec/unit/chef_runner_spec.rb +12 -5
  61. data/spec/unit/cli_spec.rb +4 -4
  62. data/spec/unit/command/base_spec.rb +1 -1
  63. data/spec/unit/command/exec_spec.rb +37 -27
  64. data/spec/unit/command/generate_spec.rb +3 -3
  65. data/spec/unit/command/generator_commands/app_spec.rb +131 -0
  66. data/spec/unit/command/generator_commands/attribute_spec.rb +32 -0
  67. data/spec/unit/command/generator_commands/cookbook_file_spec.rb +32 -0
  68. data/spec/unit/command/generator_commands/cookbook_spec.rb +205 -0
  69. data/spec/unit/command/generator_commands/lwrp_spec.rb +32 -0
  70. data/spec/unit/command/generator_commands/recipe_spec.rb +32 -0
  71. data/spec/unit/command/generator_commands/repo_spec.rb +287 -0
  72. data/spec/unit/command/generator_commands/template_spec.rb +32 -0
  73. data/spec/unit/command/shell_init_spec.rb +4 -4
  74. data/spec/unit/command/verify_spec.rb +9 -9
  75. data/spec/unit/commands_map_spec.rb +1 -1
  76. data/spec/unit/component_test_spec.rb +3 -3
  77. data/spec/unit/cookbook_profiler/git_spec.rb +7 -7
  78. data/spec/unit/cookbook_profiler/identifiers_spec.rb +12 -8
  79. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/Berksfile +1 -1
  80. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/Berksfile +1 -1
  81. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/Berksfile +1 -1
  82. data/spec/unit/fixtures/example_cookbook/Berksfile +1 -1
  83. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/README.md +4 -0
  84. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/chefignore +96 -0
  85. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/metadata.rb +8 -0
  86. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/recipes/default.rb +8 -0
  87. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/Berksfile +1 -1
  88. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/.kitchen.yml +16 -0
  89. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/README.md +4 -0
  90. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/metadata.rb +8 -0
  91. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/recipes/default.rb +8 -0
  92. data/spec/unit/generator_spec.rb +120 -0
  93. data/spec/unit/policyfile/{cookbook_spec_spec.rb → cookbook_location_specification_spec.rb} +83 -38
  94. data/spec/unit/policyfile/cookbook_locks_spec.rb +354 -0
  95. data/spec/unit/policyfile/read_cookbook_for_compat_mode_upload_spec.rb +85 -0
  96. data/spec/unit/policyfile/solution_dependencies_spec.rb +145 -0
  97. data/spec/unit/policyfile/storage_config_spec.rb +98 -0
  98. data/spec/unit/policyfile/uploader_spec.rb +292 -0
  99. data/spec/unit/policyfile_demands_spec.rb +177 -24
  100. data/spec/unit/policyfile_evaluation_spec.rb +40 -12
  101. data/spec/unit/{policyfile_builder_spec.rb → policyfile_lock_build_spec.rb} +179 -64
  102. data/spec/unit/policyfile_lock_install_spec.rb +138 -0
  103. data/spec/unit/policyfile_lock_validation_spec.rb +610 -0
  104. metadata +103 -59
  105. data/spec/unit/command/generator_commands_spec.rb +0 -504
@@ -0,0 +1,98 @@
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/policyfile/storage_config'
20
+
21
+ describe ChefDK::Policyfile::StorageConfig do
22
+
23
+ let(:config_options) { {} }
24
+
25
+ let(:storage_config) do
26
+ described_class.new(config_options)
27
+ end
28
+
29
+ context "with explicit path options" do
30
+
31
+ let(:cache_path) do
32
+ File.expand_path("spec/unit/fixtures/cookbook_cache", project_root)
33
+ end
34
+
35
+ let(:relative_paths_root) do
36
+ File.expand_path("spec/unit/fixtures/", project_root)
37
+ end
38
+
39
+ let(:config_options) do
40
+ { cache_path: cache_path, relative_paths_root: relative_paths_root }
41
+ end
42
+
43
+ it "uses the provided option for relative_paths_root" do
44
+ expect(storage_config.relative_paths_root).to eq(relative_paths_root)
45
+ end
46
+
47
+ it "uses the provided cache_path" do
48
+ expect(storage_config.cache_path).to eq(cache_path)
49
+ end
50
+ end
51
+
52
+ context "with default options" do
53
+
54
+ it "defaults to the CookbookOmnifetch configured cache path" do
55
+ expect(storage_config.cache_path).to eq(CookbookOmnifetch.storage_path)
56
+ end
57
+
58
+ it "defaults to the current working directory for relative_paths_root" do
59
+ expect(storage_config.relative_paths_root).to eq(Dir.pwd)
60
+ end
61
+ end
62
+
63
+ describe "updating storage config for policyfile location" do
64
+
65
+ before do
66
+ storage_config.use_policyfile("/path/to/Policyfile.rb")
67
+ end
68
+
69
+ it "updates the relative_paths_root to be relative to a policyfile" do
70
+ expect(storage_config.relative_paths_root).to eq("/path/to")
71
+ end
72
+
73
+ it "stores the location of the policyfile" do
74
+ expect(storage_config.policyfile_filename).to eq("/path/to/Policyfile.rb")
75
+ end
76
+
77
+ end
78
+
79
+
80
+ describe "updating storage config for policyfile lock location" do
81
+
82
+ before do
83
+ storage_config.use_policyfile_lock("/path/to/Policyfile.lock.json")
84
+ end
85
+
86
+ it "updates the relative_paths_root to be relative to a policyfile" do
87
+ expect(storage_config.relative_paths_root).to eq("/path/to")
88
+ end
89
+
90
+ it "stores the location of the policyfile" do
91
+ expect(storage_config.policyfile_lock_filename).to eq("/path/to/Policyfile.lock.json")
92
+ end
93
+
94
+ end
95
+
96
+
97
+ end
98
+
@@ -0,0 +1,292 @@
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/policyfile/uploader'
20
+
21
+ # We load this here to ensure we get the "verifying doubles" behavior from
22
+ # RSpec. It's not used by Policyfile::Uploader, but it's a collaborator.
23
+ require 'chef-dk/authenticated_http'
24
+
25
+ describe ChefDK::Policyfile::Uploader do
26
+
27
+ let(:policyfile_lock_data) do
28
+ {
29
+ "name"=> "example",
30
+ "run_list"=> [ "recipe[omnibus::default]" ],
31
+ "cookbook_locks"=> {
32
+ "omnibus"=> {
33
+ "version"=> "2.2.0",
34
+ "identifier"=> "64b3e64306cff223206348e46af545b19032b170",
35
+ "dotted_decimal_identifier"=> "28345299219435506.9887234981653237.76628930769264",
36
+ "cache_key"=> "omnibus-2cf98f9797cacce9c8688fc4e74858b858e2bc14",
37
+ "origin"=> "git@github.com:opscode-cookbooks/omnibus.git",
38
+ "source_options"=> {
39
+ "git"=> "git@github.com:opscode-cookbooks/omnibus.git",
40
+ "revision"=> "2cf98f9797cacce9c8688fc4e74858b858e2bc14",
41
+ "branch"=> "master"
42
+ }
43
+ }
44
+ }
45
+ }
46
+ end
47
+
48
+ let(:policyfile_lock) { instance_double("ChefDK::PolicyfileLock", name: "example",
49
+ to_lock: policyfile_lock_data) }
50
+
51
+ let(:policy_group) { "unit-test" }
52
+
53
+ let(:http_client) { instance_double("ChefDK::AuthenticatedHTTP") }
54
+
55
+ let(:uploader) { described_class.new(policyfile_lock, policy_group, http_client: http_client) }
56
+
57
+ let(:policyfile_as_data_bag_item) do
58
+
59
+ policyfile_as_data_bag_item = {
60
+ "id" => "example-unit-test",
61
+ "name" => "data_bag_item_policyfiles_example-unit-test",
62
+ "data_bag" => "policyfiles"
63
+ }
64
+ policyfile_as_data_bag_item["raw_data"] = policyfile_lock_data.dup
65
+ policyfile_as_data_bag_item["raw_data"]["id"] = "example-unit-test"
66
+ policyfile_as_data_bag_item["json_class"] = "Chef::DataBagItem"
67
+ policyfile_as_data_bag_item
68
+ end
69
+
70
+ it "has a lockfile" do
71
+ expect(uploader.policyfile_lock).to eq(policyfile_lock)
72
+ end
73
+
74
+ it "has a policy group" do
75
+ expect(uploader.policy_group).to eq(policy_group)
76
+ end
77
+
78
+ it "has an HTTP client" do
79
+ expect(uploader.http_client).to eq(http_client)
80
+ end
81
+
82
+ context "when created without an HTTP client" do
83
+
84
+ let(:http_client) { nil }
85
+
86
+ it "creates an HTTP client with default config" do
87
+ skip "TODO: determine correct behavior"
88
+ end
89
+
90
+ end
91
+
92
+
93
+ describe "creating uploading documents in compat mode" do
94
+
95
+ let(:cookbook_locks) { {} }
96
+ let(:cookbook_versions) { {} }
97
+
98
+ let(:existing_cookbook_on_remote) do
99
+ {"apt"=>
100
+ {"url"=>"http://localhost:8889/cookbooks/apt",
101
+ "versions"=>
102
+ [{"url"=>
103
+ "http://localhost:8889/cookbooks/apt/46097674477573307.43471642740453733.243606720748315",
104
+ "version"=>"46097674477573307.43471642740453733.243606720748315"}]},
105
+ "build-essential"=>
106
+ {"url"=>"http://localhost:8889/cookbooks/build-essential",
107
+ "versions"=>
108
+ [{"url"=>
109
+ "http://localhost:8889/cookbooks/build-essential/67369247788170534.26353953100055918.55660493423796",
110
+ "version"=>"67369247788170534.26353953100055918.55660493423796"}]},
111
+ "java"=>
112
+ {"url"=>"http://localhost:8889/cookbooks/java",
113
+ "versions"=>
114
+ [{"url"=>
115
+ "http://localhost:8889/cookbooks/java/5664982062912610.52588194571203830.6215746262253",
116
+ "version"=>"5664982062912610.52588194571203830.6215746262253"}]},
117
+ "jenkins"=>
118
+ {"url"=>"http://localhost:8889/cookbooks/jenkins",
119
+ "versions"=>
120
+ [{"url"=>
121
+ "http://localhost:8889/cookbooks/jenkins/69194928762630300.30177357398946006.269829039948647",
122
+ "version"=>"69194928762630300.30177357398946006.269829039948647"}]}
123
+ }
124
+ end
125
+
126
+ before do
127
+ allow(policyfile_lock).to receive(:cookbook_locks).and_return(cookbook_locks)
128
+ end
129
+
130
+ def lock_double(name, dotted_decimal_id)
131
+ cache_path = "/home/user/cache_path/#{name}"
132
+
133
+ lock = instance_double("ChefDK::Policyfile::CookbookLock",
134
+ name: name,
135
+ dotted_decimal_identifier: dotted_decimal_id,
136
+ cookbook_path: cache_path)
137
+
138
+ cookbook_version = instance_double("Chef::CookbookVersion",
139
+ name: name,
140
+ version: dotted_decimal_id)
141
+
142
+ allow(ChefDK::Policyfile::ReadCookbookForCompatModeUpload).
143
+ to receive(:load).
144
+ with(name, dotted_decimal_id, cache_path).
145
+ and_return(cookbook_version)
146
+
147
+ cookbook_versions[name] = cookbook_version
148
+ cookbook_locks[name] = lock
149
+
150
+ lock
151
+ end
152
+
153
+ it "ensures a data bag named 'policyfiles' exists" do
154
+ expect(http_client).to receive(:post).with('data', {"name" => "policyfiles"})
155
+ uploader.data_bag_create
156
+ end
157
+
158
+ it "does not error when the 'policyfiles' data bag exists" do
159
+ response = double("Net::HTTP response", code: "409")
160
+ error = Net::HTTPServerException.new("conflict", response)
161
+ expect(http_client).to receive(:post).with('data', {"name" => "policyfiles"}).and_raise(error)
162
+ expect { uploader.data_bag_create }.to_not raise_error
163
+ end
164
+
165
+ it "uploads the policyfile as a data bag item" do
166
+ response = double("Net::HTTP response", code: "404")
167
+ error = Net::HTTPServerException.new("Not Found", response)
168
+ expect(http_client).to receive(:put).
169
+ with('data/policyfiles/example-unit-test', policyfile_as_data_bag_item).
170
+ and_raise(error)
171
+ expect(http_client).to receive(:post).
172
+ with('data/policyfiles', policyfile_as_data_bag_item)
173
+
174
+ uploader.data_bag_item_create
175
+ end
176
+
177
+ it "replaces an existing policyfile on the server if it exists" do
178
+ expect(http_client).to receive(:put).
179
+ with('data/policyfiles/example-unit-test', policyfile_as_data_bag_item)
180
+
181
+ uploader.data_bag_item_create
182
+ end
183
+
184
+ it "enumerates the cookbooks already on the server" do
185
+ expect(http_client).to receive(:get).with('cookbooks?num_versions=all').and_return(existing_cookbook_on_remote)
186
+ expect(uploader.existing_cookbook_on_remote).to eq(existing_cookbook_on_remote)
187
+ end
188
+
189
+ context "with an empty policyfile lock" do
190
+
191
+ it "has an empty list of cookbooks for possible upload" do
192
+ expect(policyfile_lock).to receive(:validate_cookbooks!)
193
+
194
+ expect(uploader.cookbook_versions_for_policy).to eq([])
195
+ end
196
+
197
+ it "has an empty list of cookbooks that need to be uploaded" do
198
+ expect(policyfile_lock).to receive(:validate_cookbooks!)
199
+
200
+ expect(uploader.cookbook_versions_to_upload).to eq([])
201
+ end
202
+
203
+ end
204
+
205
+ context "with a set of cookbooks that don't exist on the server" do
206
+
207
+ before do
208
+ lock_double("my_apache2", "123.456.789")
209
+ lock_double("my_jenkins", "321.654.987")
210
+ end
211
+
212
+ it "lists the cookbooks in the lock as possibly needing to be uploaded" do
213
+ expect(policyfile_lock).to receive(:validate_cookbooks!)
214
+
215
+ expect(uploader.cookbook_versions_for_policy).to eq(cookbook_versions.values)
216
+ end
217
+
218
+ it "lists all cookbooks in the lock as needing to be uploaded" do
219
+ expect(policyfile_lock).to receive(:validate_cookbooks!)
220
+ expect(http_client).to receive(:get).with('cookbooks?num_versions=all').and_return(existing_cookbook_on_remote)
221
+
222
+ expect(uploader.cookbook_versions_to_upload).to eq(cookbook_versions.values)
223
+ end
224
+
225
+ it "uploads the cookbooks and then the policy" do
226
+ expect(policyfile_lock).to receive(:validate_cookbooks!)
227
+ expect(http_client).to receive(:get).with('cookbooks?num_versions=all').and_return(existing_cookbook_on_remote)
228
+
229
+ cookbook_uploader = instance_double("Chef::CookbookUploader")
230
+ expect(Chef::CookbookUploader).to receive(:new).
231
+ with(cookbook_versions.values, :rest => http_client).
232
+ and_return(cookbook_uploader)
233
+ expect(cookbook_uploader).to receive(:upload_cookbooks)
234
+
235
+ # behavior for these tested above
236
+ expect(uploader).to receive(:data_bag_create)
237
+ expect(uploader).to receive(:data_bag_item_create)
238
+
239
+ uploader.upload
240
+ end
241
+
242
+ end
243
+
244
+ context "with a set of cookbooks where some already exist on the server" do
245
+
246
+ before do
247
+ # These are new:
248
+ lock_double("my_apache2", "123.456.789")
249
+ lock_double("my_jenkins", "321.654.987")
250
+
251
+ # Have this one:
252
+ lock_double("build-essential", "67369247788170534.26353953100055918.55660493423796")
253
+ end
254
+
255
+ let(:expected_cookbooks_for_upload) do
256
+ [
257
+ cookbook_versions["my_apache2"],
258
+ cookbook_versions["my_jenkins"]
259
+ ]
260
+ end
261
+
262
+ it "lists only cookbooks not on the server as needing to be uploaded" do
263
+ expect(policyfile_lock).to receive(:validate_cookbooks!)
264
+ expect(http_client).to receive(:get).with('cookbooks?num_versions=all').and_return(existing_cookbook_on_remote)
265
+
266
+
267
+ expect(uploader.cookbook_versions_to_upload).to eq(expected_cookbooks_for_upload)
268
+ end
269
+
270
+ it "uploads the cookbooks and then the policy" do
271
+ expect(policyfile_lock).to receive(:validate_cookbooks!)
272
+ expect(http_client).to receive(:get).with('cookbooks?num_versions=all').and_return(existing_cookbook_on_remote)
273
+
274
+ cookbook_uploader = instance_double("Chef::CookbookUploader")
275
+ expect(Chef::CookbookUploader).to receive(:new).
276
+ with(expected_cookbooks_for_upload, :rest => http_client).
277
+ and_return(cookbook_uploader)
278
+ expect(cookbook_uploader).to receive(:upload_cookbooks)
279
+
280
+ # behavior for these tested above
281
+ expect(uploader).to receive(:data_bag_create)
282
+ expect(uploader).to receive(:data_bag_item_create)
283
+
284
+ uploader.upload
285
+ end
286
+
287
+ end
288
+
289
+ end
290
+
291
+ end
292
+
@@ -29,8 +29,6 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
29
29
  let(:policyfile) do
30
30
  policyfile = ChefDK::PolicyfileCompiler.new.build do |p|
31
31
 
32
- p.policyfile_filename = "/no-such-place/Policyfile.rb"
33
-
34
32
  p.default_source(*default_source) if default_source
35
33
  p.run_list(*run_list)
36
34
 
@@ -128,6 +126,29 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
128
126
  end
129
127
  end
130
128
 
129
+ describe "when normalizing run_list items" do
130
+
131
+ it "normalizes a bare cookbook name" do
132
+ policyfile.run_list("local-cookbook")
133
+ expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::default]"])
134
+ end
135
+
136
+ it "normalizes a bare cookbook::recipe item" do
137
+ policyfile.run_list("local-cookbook::server")
138
+ expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::server]"])
139
+ end
140
+
141
+ it "normalizes a recipe[] item with implicit default" do
142
+ policyfile.run_list("recipe[local-cookbook]")
143
+ expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::default]"])
144
+ end
145
+
146
+ it "does not modify a fully qualified recipe" do
147
+ policyfile.run_list("recipe[local-cookbook::jazz_hands]")
148
+ expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::jazz_hands]"])
149
+ end
150
+
151
+ end
131
152
 
132
153
  before do
133
154
  expect(policyfile.errors).to eq([])
@@ -149,6 +170,14 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
149
170
  expect(policyfile).to receive(:ensure_cache_dir_exists)
150
171
  expect(policyfile.graph_solution).to eq({})
151
172
  end
173
+
174
+ it "has an empty set of solution_dependencies" do
175
+ expected_solution_deps = {
176
+ "Policyfile" => [],
177
+ "dependencies" => {}
178
+ }
179
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
180
+ end
152
181
  end
153
182
 
154
183
  context "Given a run list and no local or git cookbooks" do
@@ -172,6 +201,14 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
172
201
  expect(policyfile.graph_solution).to eq({"remote-cb" => "1.1.1"})
173
202
  end
174
203
 
204
+ it "includes the cookbook in the solution dependencies" do
205
+ expected_solution_deps = {
206
+ "Policyfile" => [],
207
+ "dependencies" => { "remote-cb (1.1.1)" => [] }
208
+ }
209
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
210
+ end
211
+
175
212
  end
176
213
 
177
214
  context "And the default source is the chef-server" do
@@ -199,8 +236,9 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
199
236
 
200
237
  before do
201
238
  policyfile.dsl.cookbook('local-cookbook', path: "/foo")
202
- policyfile.cookbook_spec_for("local-cookbook").stub(:version).and_return("2.3.4")
203
- policyfile.cookbook_spec_for("local-cookbook").stub(:dependencies).and_return([])
239
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
240
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([])
241
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached).and_return(true)
204
242
  end
205
243
 
206
244
  it "demands a solution using the local cookbook" do
@@ -214,6 +252,14 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
214
252
  expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
215
253
  end
216
254
 
255
+ it "includes the cookbook in the solution dependencies" do
256
+ expected_solution_deps = {
257
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
258
+ "dependencies" => { "local-cookbook (2.3.4)" => [] }
259
+ }
260
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
261
+ end
262
+
217
263
  end
218
264
 
219
265
  context "Given a local cookbook with a dependency and only the local cookbook in the run list" do
@@ -226,9 +272,9 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
226
272
 
227
273
  before do
228
274
  policyfile.dsl.cookbook("local-cookbook", path: "foo/")
229
- policyfile.cookbook_spec_for("local-cookbook").stub(:ensure_cached)
230
- policyfile.cookbook_spec_for("local-cookbook").stub(:version).and_return("2.3.4")
231
- policyfile.cookbook_spec_for("local-cookbook").stub(:dependencies).and_return([ [ "local-cookbook-dep-one", "~> 1.0"] ])
275
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
276
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
277
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([ [ "local-cookbook-dep-one", "~> 1.0"] ])
232
278
  end
233
279
 
234
280
  it "demands a solution using the local cookbook" do
@@ -248,6 +294,18 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
248
294
  expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "local-cookbook-dep-one" => "1.5.0"})
249
295
  end
250
296
 
297
+ it "includes the cookbook and dependencies in the solution dependencies" do
298
+ expected_solution_deps = {
299
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
300
+ "dependencies" => {
301
+ "local-cookbook (2.3.4)" => [[ "local-cookbook-dep-one", "~> 1.0"]],
302
+ "local-cookbook-dep-one (1.5.0)" => []
303
+ }
304
+
305
+ }
306
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
307
+ end
308
+
251
309
  end
252
310
  context "And the default source is the chef server" do
253
311
 
@@ -255,9 +313,9 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
255
313
 
256
314
  before do
257
315
  policyfile.dsl.cookbook("local-cookbook", path: "foo/")
258
- policyfile.cookbook_spec_for("local-cookbook").stub(:ensure_cached)
259
- policyfile.cookbook_spec_for("local-cookbook").stub(:version).and_return("2.3.4")
260
- policyfile.cookbook_spec_for("local-cookbook").stub(:dependencies).and_return([ [ "local-cookbook-dep-one", "~> 1.0"] ])
316
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
317
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
318
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([ [ "local-cookbook-dep-one", "~> 1.0"] ])
261
319
  end
262
320
 
263
321
  it "demands a solution using the local cookbook" do
@@ -280,6 +338,18 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
280
338
  expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "local-cookbook-dep-one" => "1.6.0"})
281
339
  end
282
340
 
341
+ it "includes the cookbook and dependencies in the solution dependencies" do
342
+ expected_solution_deps = {
343
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
344
+ "dependencies" => {
345
+ "local-cookbook (2.3.4)" => [[ "local-cookbook-dep-one", "~> 1.0"]],
346
+ "local-cookbook-dep-one (1.6.0)" => []
347
+ }
348
+
349
+ }
350
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
351
+ end
352
+
283
353
  end
284
354
  end
285
355
 
@@ -289,9 +359,9 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
289
359
 
290
360
  before do
291
361
  policyfile.dsl.cookbook("git-sourced-cookbook", git: "git://git.example.org:user/a-cookbook.git")
292
- policyfile.cookbook_spec_for("git-sourced-cookbook").stub(:ensure_cached)
293
- policyfile.cookbook_spec_for("git-sourced-cookbook").stub(:version).and_return("8.6.7")
294
- policyfile.cookbook_spec_for("git-sourced-cookbook").stub(:dependencies).and_return([ ])
362
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:ensure_cached)
363
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:version).and_return("8.6.7")
364
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:dependencies).and_return([ ])
295
365
  end
296
366
 
297
367
  it "demands a solution using the git sourced cookbook" do
@@ -309,6 +379,18 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
309
379
  expect(policyfile).to receive(:ensure_cache_dir_exists)
310
380
  expect(policyfile.graph_solution).to eq({"git-sourced-cookbook" => "8.6.7"})
311
381
  end
382
+
383
+ it "includes the cookbook and dependencies in the solution dependencies" do
384
+ expected_solution_deps = {
385
+ "Policyfile" => [ [ "git-sourced-cookbook", ">= 0.0.0" ] ],
386
+ "dependencies" => {
387
+ "git-sourced-cookbook (8.6.7)" => []
388
+ }
389
+
390
+ }
391
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
392
+ end
393
+
312
394
  end
313
395
 
314
396
  context "Given a git-sourced cookbook with a dependency and only the git cookbook in the run list" do
@@ -317,9 +399,9 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
317
399
 
318
400
  before do
319
401
  policyfile.dsl.cookbook("git-sourced-cookbook", git: "git://git.example.org:user/a-cookbook.git")
320
- policyfile.cookbook_spec_for("git-sourced-cookbook").stub(:ensure_cached)
321
- policyfile.cookbook_spec_for("git-sourced-cookbook").stub(:version).and_return("8.6.7")
322
- policyfile.cookbook_spec_for("git-sourced-cookbook").stub(:dependencies).and_return([ ["git-sourced-cookbook-dep", "~> 2.2" ] ])
402
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:ensure_cached)
403
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:version).and_return("8.6.7")
404
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:dependencies).and_return([ ["git-sourced-cookbook-dep", "~> 2.2" ] ])
323
405
  end
324
406
 
325
407
  context "And the default source is the community site" do
@@ -342,6 +424,19 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
342
424
  expect(policyfile).to receive(:ensure_cache_dir_exists)
343
425
  expect(policyfile.graph_solution).to eq({"git-sourced-cookbook" => "8.6.7", "git-sourced-cookbook-dep" => "2.8.0"})
344
426
  end
427
+
428
+ it "includes the cookbook and dependencies in the solution dependencies" do
429
+ expected_solution_deps = {
430
+ "Policyfile" => [ [ "git-sourced-cookbook", ">= 0.0.0" ] ],
431
+ "dependencies" => {
432
+ "git-sourced-cookbook (8.6.7)" => [ [ "git-sourced-cookbook-dep", "~> 2.2" ] ],
433
+ "git-sourced-cookbook-dep (2.8.0)" => []
434
+ }
435
+
436
+ }
437
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
438
+ end
439
+
345
440
  end
346
441
 
347
442
  context "And the default source is the chef server" do
@@ -364,6 +459,19 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
364
459
  expect(policyfile).to receive(:ensure_cache_dir_exists)
365
460
  expect(policyfile.graph_solution).to eq({"git-sourced-cookbook" => "8.6.7", "git-sourced-cookbook-dep" => "2.9.0"})
366
461
  end
462
+
463
+ it "includes the cookbook and dependencies in the solution dependencies" do
464
+ expected_solution_deps = {
465
+ "Policyfile" => [ [ "git-sourced-cookbook", ">= 0.0.0" ] ],
466
+ "dependencies" => {
467
+ "git-sourced-cookbook (8.6.7)" => [ [ "git-sourced-cookbook-dep", "~> 2.2" ] ],
468
+ "git-sourced-cookbook-dep (2.9.0)" => []
469
+ }
470
+
471
+ }
472
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
473
+ end
474
+
367
475
  end
368
476
  end
369
477
 
@@ -373,9 +481,9 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
373
481
 
374
482
  before do
375
483
  policyfile.dsl.cookbook("local-cookbook", path: "foo/")
376
- policyfile.cookbook_spec_for("local-cookbook").stub(:ensure_cached)
377
- policyfile.cookbook_spec_for("local-cookbook").stub(:version).and_return("2.3.4")
378
- policyfile.cookbook_spec_for("local-cookbook").stub(:dependencies).and_return([])
484
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
485
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
486
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([])
379
487
  end
380
488
 
381
489
  context "And the default source is the community site" do
@@ -397,6 +505,18 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
397
505
  expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "remote-cb" => "1.1.1"})
398
506
  end
399
507
 
508
+ it "includes the cookbook and dependencies in the solution dependencies" do
509
+ expected_solution_deps = {
510
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
511
+ "dependencies" => {
512
+ "local-cookbook (2.3.4)" => [],
513
+ "remote-cb (1.1.1)" => []
514
+ }
515
+
516
+ }
517
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
518
+ end
519
+
400
520
  end
401
521
 
402
522
  context "And the default source is the chef server" do
@@ -418,6 +538,18 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
418
538
  expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "remote-cb" => "1.1.1"})
419
539
  end
420
540
 
541
+ it "includes the cookbook and dependencies in the solution dependencies" do
542
+ expected_solution_deps = {
543
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
544
+ "dependencies" => {
545
+ "local-cookbook (2.3.4)" => [],
546
+ "remote-cb (1.1.1)" => []
547
+ }
548
+
549
+ }
550
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
551
+ end
552
+
421
553
  end
422
554
  end
423
555
 
@@ -440,6 +572,16 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
440
572
  expect(policyfile.graph_solution).to eq({"remote-cb" => "0.1.0"})
441
573
  end
442
574
 
575
+ it "includes the policyfile constraint in the solution dependencies" do
576
+ expected_solution_deps = {
577
+ "Policyfile" => [ [ "remote-cb", "~> 0.1" ] ],
578
+ "dependencies" => {
579
+ "remote-cb (0.1.0)" => []
580
+ }
581
+
582
+ }
583
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
584
+ end
443
585
  end
444
586
 
445
587
  context "given a cookbook that isn't in the run list is specified with a version constraint in the policyfile" do
@@ -453,9 +595,9 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
453
595
 
454
596
  policyfile.dsl.cookbook("local-cookbook", path: "foo/")
455
597
 
456
- policyfile.cookbook_spec_for("local-cookbook").stub(:ensure_cached)
457
- policyfile.cookbook_spec_for("local-cookbook").stub(:version).and_return("2.3.4")
458
- policyfile.cookbook_spec_for("local-cookbook").stub(:dependencies).and_return([])
598
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
599
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
600
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([])
459
601
  end
460
602
 
461
603
  it "demands a solution that matches the version constraint in the policyfile" do
@@ -468,16 +610,27 @@ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph deman
468
610
  end
469
611
 
470
612
  it "builds a policyfile lock from the constraints" do
471
- pending
613
+ skip
472
614
  expect(policyfile).to receive(:cache_path).and_return(Pathname.new("~/.nopenope/cache"))
473
615
  expect(policyfile.lock).to eq(:wat)
474
616
  end
475
617
 
618
+ it "includes the policyfile constraint in the solution dependencies" do
619
+ expected_solution_deps = {
620
+ "Policyfile" => [ [ "remote-cb", "~> 0.1" ], [ "local-cookbook", ">= 0.0.0"] ],
621
+ "dependencies" => {
622
+ "local-cookbook (2.3.4)" => [],
623
+ "remote-cb (0.1.0)" => []
624
+ }
625
+
626
+ }
627
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
628
+ end
476
629
  end
477
630
 
478
631
  context "Given a run_list with roles" do
479
632
  it "expands the roles from the given role source" do
480
- pending
633
+ skip
481
634
  end
482
635
  end
483
636