chef-dk 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (306) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +190 -190
  3. data/Gemfile +26 -26
  4. data/LICENSE +201 -201
  5. data/README.md +292 -276
  6. data/Rakefile +18 -18
  7. data/bin/chef +25 -25
  8. data/chef-dk.gemspec +62 -0
  9. data/lib/chef-dk.rb +19 -19
  10. data/lib/chef-dk/authenticated_http.rb +40 -40
  11. data/lib/chef-dk/builtin_commands.rb +60 -60
  12. data/lib/chef-dk/chef_runner.rb +98 -98
  13. data/lib/chef-dk/cli.rb +200 -200
  14. data/lib/chef-dk/command/base.rb +79 -79
  15. data/lib/chef-dk/command/clean_policy_cookbooks.rb +116 -116
  16. data/lib/chef-dk/command/clean_policy_revisions.rb +113 -113
  17. data/lib/chef-dk/command/delete_policy.rb +122 -122
  18. data/lib/chef-dk/command/delete_policy_group.rb +122 -122
  19. data/lib/chef-dk/command/diff.rb +316 -316
  20. data/lib/chef-dk/command/env.rb +90 -90
  21. data/lib/chef-dk/command/exec.rb +45 -45
  22. data/lib/chef-dk/command/export.rb +151 -151
  23. data/lib/chef-dk/command/gem.rb +47 -47
  24. data/lib/chef-dk/command/generate.rb +120 -120
  25. data/lib/chef-dk/command/generator_commands.rb +80 -80
  26. data/lib/chef-dk/command/generator_commands/app.rb +107 -107
  27. data/lib/chef-dk/command/generator_commands/attribute.rb +37 -37
  28. data/lib/chef-dk/command/generator_commands/base.rb +121 -121
  29. data/lib/chef-dk/command/generator_commands/cookbook.rb +153 -119
  30. data/lib/chef-dk/command/generator_commands/cookbook_code_file.rb +100 -100
  31. data/lib/chef-dk/command/generator_commands/cookbook_file.rb +45 -45
  32. data/lib/chef-dk/command/generator_commands/generator_generator.rb +177 -177
  33. data/lib/chef-dk/command/generator_commands/lwrp.rb +36 -36
  34. data/lib/chef-dk/command/generator_commands/policyfile.rb +127 -86
  35. data/lib/chef-dk/command/generator_commands/recipe.rb +36 -36
  36. data/lib/chef-dk/command/generator_commands/repo.rb +125 -96
  37. data/lib/chef-dk/command/generator_commands/template.rb +46 -46
  38. data/lib/chef-dk/command/install.rb +121 -121
  39. data/lib/chef-dk/command/provision.rb +438 -438
  40. data/lib/chef-dk/command/push.rb +118 -118
  41. data/lib/chef-dk/command/push_archive.rb +126 -126
  42. data/lib/chef-dk/command/shell_init.rb +180 -180
  43. data/lib/chef-dk/command/show_policy.rb +165 -165
  44. data/lib/chef-dk/command/undelete.rb +155 -155
  45. data/lib/chef-dk/command/update.rb +129 -129
  46. data/lib/chef-dk/command/verify.rb +534 -490
  47. data/lib/chef-dk/commands_map.rb +115 -115
  48. data/lib/chef-dk/completions/bash.sh.erb +5 -5
  49. data/lib/chef-dk/completions/chef.fish.erb +10 -10
  50. data/lib/chef-dk/completions/zsh.zsh.erb +21 -21
  51. data/lib/chef-dk/component_test.rb +173 -171
  52. data/lib/chef-dk/configurable.rb +57 -57
  53. data/lib/chef-dk/cookbook_metadata.rb +45 -45
  54. data/lib/chef-dk/cookbook_omnifetch.rb +32 -32
  55. data/lib/chef-dk/cookbook_profiler/git.rb +151 -151
  56. data/lib/chef-dk/cookbook_profiler/identifiers.rb +72 -72
  57. data/lib/chef-dk/cookbook_profiler/null_scm.rb +32 -32
  58. data/lib/chef-dk/exceptions.rb +126 -113
  59. data/lib/chef-dk/generator.rb +163 -163
  60. data/lib/chef-dk/helpers.rb +159 -159
  61. data/lib/chef-dk/pager.rb +106 -106
  62. data/lib/chef-dk/policyfile/chef_repo_cookbook_source.rb +138 -122
  63. data/lib/chef-dk/policyfile/chef_server_cookbook_source.rb +54 -54
  64. data/lib/chef-dk/policyfile/community_cookbook_source.rb +97 -82
  65. data/lib/chef-dk/policyfile/comparison_base.rb +124 -124
  66. data/lib/chef-dk/policyfile/cookbook_location_specification.rb +141 -133
  67. data/lib/chef-dk/policyfile/cookbook_locks.rb +466 -466
  68. data/lib/chef-dk/policyfile/cookbook_sources.rb +22 -21
  69. data/lib/chef-dk/policyfile/delivery_supermarket_source.rb +90 -0
  70. data/lib/chef-dk/policyfile/differ.rb +266 -266
  71. data/lib/chef-dk/policyfile/dsl.rb +223 -197
  72. data/lib/chef-dk/policyfile/lister.rb +232 -232
  73. data/lib/chef-dk/policyfile/null_cookbook_source.rb +45 -45
  74. data/lib/chef-dk/policyfile/read_cookbook_for_compat_mode_upload.rb +124 -124
  75. data/lib/chef-dk/policyfile/reports/install.rb +70 -70
  76. data/lib/chef-dk/policyfile/reports/table_printer.rb +58 -58
  77. data/lib/chef-dk/policyfile/reports/upload.rb +70 -70
  78. data/lib/chef-dk/policyfile/solution_dependencies.rb +298 -298
  79. data/lib/chef-dk/policyfile/storage_config.rb +100 -100
  80. data/lib/chef-dk/policyfile/undo_record.rb +142 -142
  81. data/lib/chef-dk/policyfile/undo_stack.rb +130 -130
  82. data/lib/chef-dk/policyfile/uploader.rb +213 -213
  83. data/lib/chef-dk/policyfile_compiler.rb +380 -322
  84. data/lib/chef-dk/policyfile_lock.rb +552 -552
  85. data/lib/chef-dk/policyfile_services/clean_policies.rb +95 -95
  86. data/lib/chef-dk/policyfile_services/clean_policy_cookbooks.rb +125 -125
  87. data/lib/chef-dk/policyfile_services/export_repo.rb +309 -309
  88. data/lib/chef-dk/policyfile_services/install.rb +125 -125
  89. data/lib/chef-dk/policyfile_services/push.rb +114 -114
  90. data/lib/chef-dk/policyfile_services/push_archive.rb +173 -173
  91. data/lib/chef-dk/policyfile_services/rm_policy.rb +142 -142
  92. data/lib/chef-dk/policyfile_services/rm_policy_group.rb +86 -86
  93. data/lib/chef-dk/policyfile_services/show_policy.rb +237 -237
  94. data/lib/chef-dk/policyfile_services/undelete.rb +108 -108
  95. data/lib/chef-dk/policyfile_services/update_attributes.rb +104 -104
  96. data/lib/chef-dk/service_exception_inspectors.rb +25 -25
  97. data/lib/chef-dk/service_exception_inspectors/base.rb +40 -40
  98. data/lib/chef-dk/service_exception_inspectors/http.rb +121 -121
  99. data/lib/chef-dk/service_exceptions.rb +143 -143
  100. data/lib/chef-dk/shell_out.rb +36 -36
  101. data/lib/chef-dk/skeletons/code_generator/files/default/Berksfile +3 -3
  102. data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +100 -100
  103. data/lib/chef-dk/skeletons/code_generator/files/default/cookbook_readmes/README-policy.md +9 -9
  104. data/lib/chef-dk/skeletons/code_generator/files/default/cookbook_readmes/README.md +54 -54
  105. data/lib/chef-dk/skeletons/code_generator/files/default/gitignore +16 -16
  106. data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +28 -28
  107. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/README.md +27 -27
  108. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +7 -7
  109. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/metadata.rb +3 -3
  110. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +8 -8
  111. data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/README.md +58 -58
  112. data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/example/example_item.json +3 -3
  113. data/lib/chef-dk/skeletons/code_generator/files/default/repo/dot-chef-repo.txt +6 -0
  114. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/README.md +9 -9
  115. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/example.json +12 -12
  116. data/lib/chef-dk/skeletons/code_generator/files/default/repo/policies/README.md +24 -0
  117. data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/README.md +9 -9
  118. data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/example.json +12 -12
  119. data/lib/chef-dk/skeletons/code_generator/files/default/serverspec_spec_helper.rb +8 -8
  120. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper.rb +2 -2
  121. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper_policyfile.rb +2 -0
  122. data/lib/chef-dk/skeletons/code_generator/metadata.rb +8 -8
  123. data/lib/chef-dk/skeletons/code_generator/recipes/app.rb +97 -97
  124. data/lib/chef-dk/skeletons/code_generator/recipes/attribute.rb +12 -12
  125. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook.rb +117 -104
  126. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook_file.rb +24 -24
  127. data/lib/chef-dk/skeletons/code_generator/recipes/lwrp.rb +23 -23
  128. data/lib/chef-dk/skeletons/code_generator/recipes/policyfile.rb +8 -8
  129. data/lib/chef-dk/skeletons/code_generator/recipes/recipe.rb +27 -27
  130. data/lib/chef-dk/skeletons/code_generator/recipes/repo.rb +67 -48
  131. data/lib/chef-dk/skeletons/code_generator/recipes/template.rb +32 -32
  132. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.all_rights.erb +3 -3
  133. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.apache2.erb +201 -201
  134. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv2.erb +339 -339
  135. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv3.erb +674 -674
  136. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.mit.erb +21 -21
  137. data/lib/chef-dk/skeletons/code_generator/templates/default/Policyfile.rb.erb +25 -20
  138. data/lib/chef-dk/skeletons/code_generator/templates/default/README.md.erb +4 -4
  139. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen.yml.erb +21 -16
  140. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen_policyfile.yml.erb +32 -27
  141. data/lib/chef-dk/skeletons/code_generator/templates/default/metadata.rb.erb +7 -7
  142. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe.rb.erb +5 -5
  143. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe_spec.rb.erb +20 -20
  144. data/lib/chef-dk/skeletons/code_generator/templates/default/repo/gitignore.erb +11 -11
  145. data/lib/chef-dk/skeletons/code_generator/templates/default/serverspec_default_spec.rb.erb +9 -9
  146. data/lib/chef-dk/ui.rb +58 -58
  147. data/lib/chef-dk/version.rb +20 -20
  148. data/lib/kitchen/provisioner/policyfile_zero.rb +189 -193
  149. data/spec/shared/a_file_generator.rb +125 -125
  150. data/spec/shared/a_generated_file.rb +12 -12
  151. data/spec/shared/command_with_ui_object.rb +11 -11
  152. data/spec/shared/custom_generator_cookbook.rb +117 -117
  153. data/spec/shared/fixture_cookbook_checksums.rb +47 -47
  154. data/spec/shared/setup_git_cookbooks.rb +53 -53
  155. data/spec/spec_helper.rb +50 -49
  156. data/spec/test_helpers.rb +84 -84
  157. data/spec/unit/chef_runner_spec.rb +111 -111
  158. data/spec/unit/cli_spec.rb +357 -357
  159. data/spec/unit/command/base_spec.rb +169 -169
  160. data/spec/unit/command/clean_policy_cookbooks_spec.rb +181 -181
  161. data/spec/unit/command/clean_policy_revisions_spec.rb +181 -181
  162. data/spec/unit/command/delete_policy_group_spec.rb +207 -207
  163. data/spec/unit/command/delete_policy_spec.rb +207 -207
  164. data/spec/unit/command/diff_spec.rb +312 -312
  165. data/spec/unit/command/env_spec.rb +52 -52
  166. data/spec/unit/command/exec_spec.rb +179 -179
  167. data/spec/unit/command/export_spec.rb +189 -189
  168. data/spec/unit/command/generate_spec.rb +142 -142
  169. data/spec/unit/command/generator_commands/app_spec.rb +169 -169
  170. data/spec/unit/command/generator_commands/attribute_spec.rb +32 -32
  171. data/spec/unit/command/generator_commands/cookbook_file_spec.rb +32 -32
  172. data/spec/unit/command/generator_commands/cookbook_spec.rb +450 -320
  173. data/spec/unit/command/generator_commands/generator_generator_spec.rb +229 -229
  174. data/spec/unit/command/generator_commands/lwrp_spec.rb +32 -32
  175. data/spec/unit/command/generator_commands/policyfile_spec.rb +225 -125
  176. data/spec/unit/command/generator_commands/recipe_spec.rb +34 -34
  177. data/spec/unit/command/generator_commands/repo_spec.rb +367 -283
  178. data/spec/unit/command/generator_commands/template_spec.rb +32 -32
  179. data/spec/unit/command/install_spec.rb +179 -179
  180. data/spec/unit/command/provision_spec.rb +592 -592
  181. data/spec/unit/command/push_archive_spec.rb +153 -153
  182. data/spec/unit/command/push_spec.rb +199 -199
  183. data/spec/unit/command/shell_init_spec.rb +329 -329
  184. data/spec/unit/command/show_policy_spec.rb +235 -235
  185. data/spec/unit/command/undelete_spec.rb +246 -246
  186. data/spec/unit/command/update_spec.rb +251 -251
  187. data/spec/unit/command/verify_spec.rb +325 -323
  188. data/spec/unit/commands_map_spec.rb +57 -57
  189. data/spec/unit/component_test_spec.rb +126 -126
  190. data/spec/unit/cookbook_metadata_spec.rb +98 -98
  191. data/spec/unit/cookbook_profiler/git_spec.rb +176 -176
  192. data/spec/unit/cookbook_profiler/identifiers_spec.rb +83 -83
  193. data/spec/unit/fixtures/chef-runner-cookbooks/test_cookbook/recipes/recipe_one.rb +9 -9
  194. data/spec/unit/fixtures/chef-runner-cookbooks/test_cookbook/recipes/recipe_two.rb +9 -9
  195. data/spec/unit/fixtures/command/cli_test_command.rb +26 -26
  196. data/spec/unit/fixtures/command/explicit_path_example.rb +7 -7
  197. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/.kitchen.yml +16 -16
  198. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/Berksfile +3 -3
  199. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/README.md +4 -4
  200. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/chefignore +96 -96
  201. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/metadata.rb +8 -8
  202. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/recipes/default.rb +8 -8
  203. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/.kitchen.yml +16 -16
  204. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/Berksfile +3 -3
  205. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/README.md +4 -4
  206. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/chefignore +96 -96
  207. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/metadata.rb +8 -8
  208. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/recipes/default.rb +8 -8
  209. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/.kitchen.yml +16 -16
  210. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/Berksfile +3 -3
  211. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/README.md +4 -4
  212. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/chefignore +96 -96
  213. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/metadata.rb +8 -8
  214. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/recipes/default.rb +8 -8
  215. data/spec/unit/fixtures/cookbooks_api/pruned_small_universe.json +1321 -1321
  216. data/spec/unit/fixtures/cookbooks_api/small_universe.json +2987 -2987
  217. data/spec/unit/fixtures/cookbooks_api/universe.json +1 -1
  218. data/spec/unit/fixtures/cookbooks_api/update_fixtures.rb +36 -36
  219. data/spec/unit/fixtures/dev_cookbooks/README.md +16 -16
  220. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/berkshelf/integration_test +2 -2
  221. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/berkshelf/verify_me +5 -5
  222. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/chef/verify_me +3 -3
  223. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/test-kitchen/verify_me +2 -2
  224. data/spec/unit/fixtures/example_cookbook/.gitignore +17 -17
  225. data/spec/unit/fixtures/example_cookbook/.kitchen.yml +16 -16
  226. data/spec/unit/fixtures/example_cookbook/Berksfile +3 -3
  227. data/spec/unit/fixtures/example_cookbook/README.md +4 -4
  228. data/spec/unit/fixtures/example_cookbook/chefignore +96 -96
  229. data/spec/unit/fixtures/example_cookbook/metadata.rb +8 -8
  230. data/spec/unit/fixtures/example_cookbook/recipes/default.rb +8 -8
  231. data/spec/unit/fixtures/example_cookbook_metadata_json_only/.gitignore +17 -17
  232. data/spec/unit/fixtures/example_cookbook_metadata_json_only/.kitchen.yml +16 -16
  233. data/spec/unit/fixtures/example_cookbook_metadata_json_only/Berksfile +3 -3
  234. data/spec/unit/fixtures/example_cookbook_metadata_json_only/README.md +4 -4
  235. data/spec/unit/fixtures/example_cookbook_metadata_json_only/chefignore +96 -96
  236. data/spec/unit/fixtures/example_cookbook_metadata_json_only/metadata.json +5 -5
  237. data/spec/unit/fixtures/example_cookbook_metadata_json_only/recipes/default.rb +8 -8
  238. data/spec/unit/fixtures/example_cookbook_no_metadata/.gitignore +17 -17
  239. data/spec/unit/fixtures/example_cookbook_no_metadata/.kitchen.yml +16 -16
  240. data/spec/unit/fixtures/example_cookbook_no_metadata/Berksfile +3 -3
  241. data/spec/unit/fixtures/example_cookbook_no_metadata/README.md +4 -4
  242. data/spec/unit/fixtures/example_cookbook_no_metadata/chefignore +96 -96
  243. data/spec/unit/fixtures/example_cookbook_no_metadata/recipes/default.rb +8 -8
  244. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/README.md +4 -4
  245. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/chefignore +96 -96
  246. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/metadata.rb +8 -8
  247. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/recipes/default.rb +8 -8
  248. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/Berksfile +3 -3
  249. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/README.md +4 -4
  250. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/chefignore +96 -96
  251. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/metadata.rb +9 -9
  252. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/recipes/default.rb +8 -8
  253. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/.kitchen.yml +16 -16
  254. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/Berksfile +3 -3
  255. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/README.md +4 -4
  256. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/chefignore +96 -96
  257. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/metadata.rb +8 -8
  258. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/recipes/default.rb +8 -8
  259. data/spec/unit/fixtures/local_path_cookbooks/metadata-missing/README.md +2 -2
  260. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/.kitchen.yml +16 -16
  261. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/README.md +4 -4
  262. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/metadata.rb +8 -8
  263. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/recipes/default.rb +8 -8
  264. data/spec/unit/generator_spec.rb +120 -120
  265. data/spec/unit/helpers_spec.rb +92 -92
  266. data/spec/unit/pager_spec.rb +119 -119
  267. data/spec/unit/policyfile/chef_repo_cookbook_source_spec.rb +93 -66
  268. data/spec/unit/policyfile/chef_server_cookbook_source_spec.rb +34 -34
  269. data/spec/unit/policyfile/community_cookbook_source_spec.rb +84 -51
  270. data/spec/unit/policyfile/comparison_base_spec.rb +343 -343
  271. data/spec/unit/policyfile/cookbook_location_specification_spec.rb +257 -252
  272. data/spec/unit/policyfile/cookbook_locks_spec.rb +529 -529
  273. data/spec/unit/policyfile/delivery_supermarket_source_spec.rb +130 -0
  274. data/spec/unit/policyfile/differ_spec.rb +687 -687
  275. data/spec/unit/policyfile/lister_spec.rb +272 -272
  276. data/spec/unit/policyfile/null_cookbook_source_spec.rb +35 -35
  277. data/spec/unit/policyfile/read_cookbook_for_compat_mode_upload_spec.rb +92 -92
  278. data/spec/unit/policyfile/reports/install_spec.rb +115 -115
  279. data/spec/unit/policyfile/reports/upload_spec.rb +96 -96
  280. data/spec/unit/policyfile/solution_dependencies_spec.rb +145 -145
  281. data/spec/unit/policyfile/storage_config_spec.rb +172 -172
  282. data/spec/unit/policyfile/undo_record_spec.rb +260 -260
  283. data/spec/unit/policyfile/undo_stack_spec.rb +266 -266
  284. data/spec/unit/policyfile/uploader_spec.rb +410 -410
  285. data/spec/unit/policyfile_demands_spec.rb +997 -876
  286. data/spec/unit/policyfile_evaluation_spec.rb +557 -441
  287. data/spec/unit/policyfile_lock_build_spec.rb +1056 -1056
  288. data/spec/unit/policyfile_lock_install_spec.rb +138 -138
  289. data/spec/unit/policyfile_lock_serialization_spec.rb +425 -425
  290. data/spec/unit/policyfile_lock_validation_spec.rb +611 -611
  291. data/spec/unit/policyfile_services/clean_policies_spec.rb +236 -236
  292. data/spec/unit/policyfile_services/clean_policy_cookbooks_spec.rb +275 -275
  293. data/spec/unit/policyfile_services/export_repo_spec.rb +439 -439
  294. data/spec/unit/policyfile_services/install_spec.rb +191 -191
  295. data/spec/unit/policyfile_services/push_archive_spec.rb +345 -345
  296. data/spec/unit/policyfile_services/push_spec.rb +233 -233
  297. data/spec/unit/policyfile_services/rm_policy_group_spec.rb +241 -241
  298. data/spec/unit/policyfile_services/rm_policy_spec.rb +266 -266
  299. data/spec/unit/policyfile_services/show_policy_spec.rb +889 -889
  300. data/spec/unit/policyfile_services/undelete_spec.rb +304 -304
  301. data/spec/unit/policyfile_services/update_attributes_spec.rb +217 -217
  302. data/spec/unit/service_exception_inspectors/base_spec.rb +43 -43
  303. data/spec/unit/service_exception_inspectors/http_spec.rb +140 -140
  304. data/spec/unit/shell_out_spec.rb +34 -34
  305. data/warning.txt +9 -0
  306. metadata +18 -5
@@ -1,876 +1,997 @@
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_compiler'
20
-
21
- describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph demands" do
22
-
23
- let(:run_list) { [] }
24
-
25
- let(:default_source) { nil }
26
-
27
- let(:external_cookbook_universe) { {} }
28
-
29
- let(:policyfile) do
30
- policyfile = ChefDK::PolicyfileCompiler.new.build do |p|
31
-
32
- p.default_source(*default_source) if default_source
33
- p.run_list(*run_list)
34
-
35
- allow(p.default_source.first).to receive(:universe_graph).and_return(external_cookbook_universe)
36
- end
37
-
38
- policyfile
39
- end
40
-
41
- let(:demands) { policyfile.graph_demands }
42
-
43
- shared_context("community default source") do
44
-
45
- let(:default_source) { [:community] }
46
-
47
- let(:external_cookbook_universe) do
48
- {
49
- "nginx" => {
50
- "1.0.0" => [ [ "apt", "~> 2.0" ], [ "yum", "~> 1.0" ] ],
51
- "1.2.0" => [ [ "apt", "~> 2.1" ], [ "yum", "~> 1.0" ] ],
52
- "2.0.0" => [ [ "apt", "~> 3.0" ], [ "yum", "~> 1.0" ], [ "ohai", "~> 2.0" ] ]
53
- },
54
-
55
- "mysql" => {
56
- "3.0.0" => [ [ "apt", "~> 2.0" ], [ "yum", "~> 1.0" ] ],
57
- "4.0.0" => [ [ "apt", "~> 2.4" ], [ "yum", "~> 1.1" ] ],
58
- "5.0.0" => [ ],
59
- },
60
-
61
- "local-cookbook" => {
62
- "9.9.9" => [ ["local-cookbook-on-community-dep", "= 1.0.0"] ]
63
- },
64
-
65
- "git-sourced-cookbook" => {
66
- "10.10.10" => [ ["git-sourced-cookbook-dep", "= 1.0.0"] ]
67
- },
68
-
69
- "remote-cb" => {
70
- "0.1.0" => [ ],
71
- "1.1.1" => [ ]
72
- },
73
-
74
- "remote-cb-two" => {
75
- "0.1.0" => [ ],
76
- "1.1.1" => [ ]
77
- },
78
-
79
- "local-cookbook-dep-one" => {
80
- "1.5.0" => [ ]
81
- },
82
-
83
- "git-sourced-cookbook-dep" => {
84
- "2.8.0" => [ ]
85
- }
86
-
87
- }
88
- end
89
- end
90
-
91
- shared_context("chef server default source") do
92
-
93
- let(:default_source) { [:chef_server, "https://chef.example.com"] }
94
-
95
- let(:external_cookbook_universe) do
96
- {
97
- "nginx" => {
98
- "1.0.0" => [ [ "apt", "~> 2.0" ], [ "yum", "~> 1.0" ] ],
99
- },
100
-
101
- "mysql" => {
102
- "5.0.0" => [ ],
103
- },
104
-
105
- "local-cookbook" => {
106
- "9.9.9" => [ ["local-cookbook-on-community-dep", "= 1.0.0"] ]
107
- },
108
-
109
- "remote-cb" => {
110
- "1.1.1" => [ ]
111
- },
112
-
113
- "git-sourced-cookbook" => {
114
- "10.10.10" => [ ["git-sourced-cookbook-dep", "= 1.0.0"] ]
115
- },
116
-
117
- "private-cookbook" => {
118
- "0.1.0" => [ ]
119
- },
120
-
121
- "local-cookbook-dep-one" => {
122
- "1.6.0" => [ ]
123
- },
124
-
125
- "git-sourced-cookbook-dep" => {
126
- "2.9.0" => [ ]
127
- }
128
-
129
-
130
- }
131
- end
132
- end
133
-
134
- describe "when normalizing run_list items" do
135
-
136
- it "normalizes a bare cookbook name" do
137
- policyfile.run_list("local-cookbook")
138
- expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::default]"])
139
- end
140
-
141
- it "normalizes a bare cookbook::recipe item" do
142
- policyfile.run_list("local-cookbook::server")
143
- expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::server]"])
144
- end
145
-
146
- it "normalizes a recipe[] item with implicit default" do
147
- policyfile.run_list("recipe[local-cookbook]")
148
- expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::default]"])
149
- end
150
-
151
- it "does not modify a fully qualified recipe" do
152
- policyfile.run_list("recipe[local-cookbook::jazz_hands]")
153
- expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::jazz_hands]"])
154
- end
155
-
156
- describe "in an alternate run list" do
157
-
158
- it "normalizes a bare cookbook name" do
159
- policyfile.named_run_list(:foo, "local-cookbook")
160
- expect(policyfile.normalized_named_run_lists[:foo]).to eq(["recipe[local-cookbook::default]"])
161
- end
162
-
163
- it "normalizes a bare cookbook::recipe item" do
164
- policyfile.named_run_list(:foo, "local-cookbook::server")
165
- expect(policyfile.normalized_named_run_lists[:foo]).to eq(["recipe[local-cookbook::server]"])
166
- end
167
-
168
- it "normalizes a recipe[] item with implicit default" do
169
- policyfile.named_run_list(:foo, "recipe[local-cookbook]")
170
- expect(policyfile.normalized_named_run_lists[:foo]).to eq(["recipe[local-cookbook::default]"])
171
- end
172
-
173
- it "does not modify a fully qualified recipe" do
174
- policyfile.named_run_list(:foo, "recipe[local-cookbook::jazz_hands]")
175
- expect(policyfile.normalized_named_run_lists[:foo]).to eq(["recipe[local-cookbook::jazz_hands]"])
176
- end
177
-
178
- end
179
- end
180
-
181
- before do
182
- expect(policyfile.errors).to eq([])
183
- end
184
-
185
- context "Given no local or git cookbooks, no default source, and an empty run list" do
186
-
187
- let(:run_list) { [] }
188
-
189
- it "has an empty set of demands" do
190
- expect(demands).to eq([])
191
- end
192
-
193
- it "uses an empty universe for dependencies" do
194
- expect(policyfile.artifacts_graph).to eq({})
195
- end
196
-
197
- it "has an empty solution" do
198
- expect(policyfile).to receive(:ensure_cache_dir_exists)
199
- expect(policyfile.graph_solution).to eq({})
200
- end
201
-
202
- it "has an empty set of solution_dependencies" do
203
- expected_solution_deps = {
204
- "Policyfile" => [],
205
- "dependencies" => {}
206
- }
207
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
208
- end
209
- end
210
-
211
- context "Given a run list and no local or git cookbooks" do
212
-
213
- let(:run_list) { ["remote-cb"] }
214
-
215
- context "with no default source" do
216
-
217
- it "fails to locate the cookbook" do
218
- expect { policyfile.graph_solution }.to raise_error(Solve::Errors::NoSolutionError)
219
- end
220
-
221
- context "when the policyfile also has a `cookbook` entry for the run list item" do
222
-
223
- before do
224
- policyfile.dsl.cookbook "remote-cb"
225
- end
226
-
227
- it "fails to locate the cookbook" do
228
- expect { policyfile.graph_solution }.to raise_error(Solve::Errors::NoSolutionError)
229
- end
230
-
231
- end
232
-
233
- end
234
-
235
- context "And the default source is the community site" do
236
-
237
- include_context "community default source"
238
-
239
- it "has an unconstrained demand on the required cookbooks" do
240
- expect(demands).to eq([["remote-cb", ">= 0.0.0"]])
241
- end
242
-
243
- it "uses the community site universe for dependencies" do
244
- expect(policyfile.artifacts_graph).to eq(external_cookbook_universe)
245
- end
246
-
247
- it "uses the community cookbook in the solution" do
248
- expect(policyfile).to receive(:ensure_cache_dir_exists)
249
- expect(policyfile.graph_solution).to eq({"remote-cb" => "1.1.1"})
250
- end
251
-
252
- it "includes the cookbook in the solution dependencies" do
253
- expected_solution_deps = {
254
- "Policyfile" => [],
255
- "dependencies" => { "remote-cb (1.1.1)" => [] }
256
- }
257
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
258
- end
259
-
260
- end
261
-
262
- context "And the default source is the chef-server" do
263
-
264
- include_context "chef server default source"
265
-
266
- it "has an unconstrained demand on the required cookbooks" do
267
- expect(demands).to eq([["remote-cb", ">= 0.0.0"]])
268
- end
269
-
270
- it "uses the chef-server universe for dependencies" do
271
- expect(policyfile.artifacts_graph).to eq(external_cookbook_universe)
272
- end
273
-
274
- it "uses the chef-server cookbook in the solution" do
275
- expect(policyfile).to receive(:ensure_cache_dir_exists)
276
- expect(policyfile.graph_solution).to eq({"remote-cb" => "1.1.1"})
277
- end
278
- end
279
- end
280
-
281
- context "Given a local cookbook and only that cookbook in the run list" do
282
-
283
- let(:run_list) { ['local-cookbook'] }
284
-
285
- before do
286
- policyfile.dsl.cookbook('local-cookbook', path: "/foo")
287
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
288
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([])
289
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached).and_return(true)
290
- end
291
-
292
- it "demands a solution using the local cookbook" do
293
- expect(demands).to eq([["local-cookbook", "= 2.3.4"]])
294
- end
295
-
296
- it "includes the local cookbook in the artifact universe" do
297
- expected_artifacts_graph = {
298
- "local-cookbook" => { "2.3.4" => [] }
299
- }
300
- expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
301
- end
302
-
303
- it "includes the cookbook in the solution dependencies" do
304
- expected_solution_deps = {
305
- "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
306
- "dependencies" => { "local-cookbook (2.3.4)" => [] }
307
- }
308
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
309
- end
310
-
311
- end
312
-
313
- context "Given a local cookbook with a dependency and only the local cookbook in the run list" do
314
-
315
- let(:run_list) { ['local-cookbook'] }
316
-
317
- context "And the default source is the community site" do
318
-
319
- include_context "community default source"
320
-
321
- before do
322
- policyfile.dsl.cookbook("local-cookbook", path: "foo/")
323
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
324
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
325
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([ [ "local-cookbook-dep-one", "~> 1.0"] ])
326
- end
327
-
328
- it "demands a solution using the local cookbook" do
329
- expect(demands).to eq([["local-cookbook", "= 2.3.4"]])
330
- end
331
-
332
- it "overrides the community site universe with the local cookbook and its dependencies" do
333
- expected_artifacts_graph = external_cookbook_universe.dup
334
- expected_artifacts_graph["local-cookbook"] = {
335
- "2.3.4" => [ [ "local-cookbook-dep-one", "~> 1.0" ] ]
336
- }
337
- expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
338
- end
339
-
340
- it "uses the local cookbook in the solution and gets dependencies remotely" do
341
- expect(policyfile).to receive(:ensure_cache_dir_exists)
342
- expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "local-cookbook-dep-one" => "1.5.0"})
343
- end
344
-
345
- it "includes the cookbook and dependencies in the solution dependencies" do
346
- expected_solution_deps = {
347
- "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
348
- "dependencies" => {
349
- "local-cookbook (2.3.4)" => [[ "local-cookbook-dep-one", "~> 1.0"]],
350
- "local-cookbook-dep-one (1.5.0)" => []
351
- }
352
-
353
- }
354
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
355
- end
356
-
357
- end
358
- context "And the default source is the chef server" do
359
-
360
- include_context "chef server default source"
361
-
362
- before do
363
- policyfile.dsl.cookbook("local-cookbook", path: "foo/")
364
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
365
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
366
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([ [ "local-cookbook-dep-one", "~> 1.0"] ])
367
- end
368
-
369
- it "demands a solution using the local cookbook" do
370
- expect(demands).to eq([["local-cookbook", "= 2.3.4"]])
371
- end
372
-
373
- it "overrides the chef server universe with the local cookbook and its dependencies" do
374
- # all versions of "local-cookbook" from the cookbook site universe
375
- # should be removed so we won't run into trouble if there's a community
376
- # cookbook with the same name and version but different deps.
377
- expected_artifacts_graph = external_cookbook_universe.dup
378
- expected_artifacts_graph["local-cookbook"] = {
379
- "2.3.4" => [ [ "local-cookbook-dep-one", "~> 1.0" ] ]
380
- }
381
- expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
382
- end
383
-
384
- it "uses the local cookbook in the solution and gets dependencies remotely" do
385
- expect(policyfile).to receive(:ensure_cache_dir_exists)
386
- expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "local-cookbook-dep-one" => "1.6.0"})
387
- end
388
-
389
- it "includes the cookbook and dependencies in the solution dependencies" do
390
- expected_solution_deps = {
391
- "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
392
- "dependencies" => {
393
- "local-cookbook (2.3.4)" => [[ "local-cookbook-dep-one", "~> 1.0"]],
394
- "local-cookbook-dep-one (1.6.0)" => []
395
- }
396
-
397
- }
398
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
399
- end
400
-
401
- end
402
- end
403
-
404
- context "Given a git-sourced cookbook with no dependencies and only the git cookbook in the run list" do
405
-
406
- let(:run_list) { ["git-sourced-cookbook"] }
407
-
408
- before do
409
- policyfile.dsl.cookbook("git-sourced-cookbook", git: "git://git.example.org:user/a-cookbook.git")
410
- allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:ensure_cached)
411
- allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:version).and_return("8.6.7")
412
- allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:dependencies).and_return([ ])
413
- end
414
-
415
- it "demands a solution using the git sourced cookbook" do
416
- expect(demands).to eq([["git-sourced-cookbook", "= 8.6.7"]])
417
- end
418
-
419
- it "includes the git-sourced cookbook in the universe graph" do
420
- expected_artifacts_graph = {
421
- "git-sourced-cookbook" => { "8.6.7" => [ ] }
422
- }
423
- expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
424
- end
425
-
426
- it "uses the git sourced cookbook in the solution" do
427
- expect(policyfile).to receive(:ensure_cache_dir_exists)
428
- expect(policyfile.graph_solution).to eq({"git-sourced-cookbook" => "8.6.7"})
429
- end
430
-
431
- it "includes the cookbook and dependencies in the solution dependencies" do
432
- expected_solution_deps = {
433
- "Policyfile" => [ [ "git-sourced-cookbook", ">= 0.0.0" ] ],
434
- "dependencies" => {
435
- "git-sourced-cookbook (8.6.7)" => []
436
- }
437
-
438
- }
439
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
440
- end
441
-
442
- end
443
-
444
- context "Given a git-sourced cookbook with a dependency and only the git cookbook in the run list" do
445
-
446
- let(:run_list) { ["git-sourced-cookbook"] }
447
-
448
- before do
449
- policyfile.dsl.cookbook("git-sourced-cookbook", git: "git://git.example.org:user/a-cookbook.git")
450
- allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:ensure_cached)
451
- allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:version).and_return("8.6.7")
452
- allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:dependencies).and_return([ ["git-sourced-cookbook-dep", "~> 2.2" ] ])
453
- end
454
-
455
- context "And the default source is the community site" do
456
-
457
- include_context "community default source"
458
-
459
- it "demands a solution using the git sourced cookbook" do
460
- expect(demands).to eq([["git-sourced-cookbook", "= 8.6.7"]])
461
- end
462
-
463
- it "overrides the community site universe with the git-sourced cookbook and deps" do
464
- expected_artifacts_graph = external_cookbook_universe.dup
465
- expected_artifacts_graph["git-sourced-cookbook"] = {
466
- "8.6.7" => [ ["git-sourced-cookbook-dep", "~> 2.2" ] ]
467
- }
468
- expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
469
- end
470
-
471
- it "uses the git sourced cookbook with remote dependencies in the solution" do
472
- expect(policyfile).to receive(:ensure_cache_dir_exists)
473
- expect(policyfile.graph_solution).to eq({"git-sourced-cookbook" => "8.6.7", "git-sourced-cookbook-dep" => "2.8.0"})
474
- end
475
-
476
- it "includes the cookbook and dependencies in the solution dependencies" do
477
- expected_solution_deps = {
478
- "Policyfile" => [ [ "git-sourced-cookbook", ">= 0.0.0" ] ],
479
- "dependencies" => {
480
- "git-sourced-cookbook (8.6.7)" => [ [ "git-sourced-cookbook-dep", "~> 2.2" ] ],
481
- "git-sourced-cookbook-dep (2.8.0)" => []
482
- }
483
-
484
- }
485
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
486
- end
487
-
488
- end
489
-
490
- context "And the default source is the chef server" do
491
-
492
- include_context "chef server default source"
493
-
494
- it "demands a solution using the git sourced cookbook" do
495
- expect(demands).to eq([["git-sourced-cookbook", "= 8.6.7"]])
496
- end
497
-
498
- it "overrides the chef server universe with the git-sourced cookbook and deps" do
499
- expected_artifacts_graph = external_cookbook_universe.dup
500
- expected_artifacts_graph["git-sourced-cookbook"] = {
501
- "8.6.7" => [ ["git-sourced-cookbook-dep", "~> 2.2" ] ]
502
- }
503
- expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
504
- end
505
-
506
- it "uses the git sourced cookbook with remote dependencies in the solution" do
507
- expect(policyfile).to receive(:ensure_cache_dir_exists)
508
- expect(policyfile.graph_solution).to eq({"git-sourced-cookbook" => "8.6.7", "git-sourced-cookbook-dep" => "2.9.0"})
509
- end
510
-
511
- it "includes the cookbook and dependencies in the solution dependencies" do
512
- expected_solution_deps = {
513
- "Policyfile" => [ [ "git-sourced-cookbook", ">= 0.0.0" ] ],
514
- "dependencies" => {
515
- "git-sourced-cookbook (8.6.7)" => [ [ "git-sourced-cookbook-dep", "~> 2.2" ] ],
516
- "git-sourced-cookbook-dep (2.9.0)" => []
517
- }
518
-
519
- }
520
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
521
- end
522
-
523
- end
524
- end
525
-
526
- context "Given a local cookbook with a run list containing the local cookbook and another cookbook" do
527
-
528
- let(:run_list) { ['local-cookbook', 'remote-cb'] }
529
-
530
- before do
531
- policyfile.dsl.cookbook("local-cookbook", path: "foo/")
532
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
533
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
534
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([])
535
- end
536
-
537
- context "And the default source is the community site" do
538
-
539
- include_context "community default source"
540
-
541
- it "demands a solution with the local cookbook and any version of the other cookbook" do
542
- expect(demands).to eq([["local-cookbook", "= 2.3.4"], ["remote-cb", ">= 0.0.0"]])
543
- end
544
-
545
- it "overrides the community universe with the local cookbook and deps" do
546
- expected_artifacts_graph = external_cookbook_universe.dup
547
- expected_artifacts_graph["local-cookbook"] = { "2.3.4" => [ ] }
548
- expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
549
- end
550
-
551
- it "uses the locally specified cookbook and remote cookbooks in the solution" do
552
- expect(policyfile).to receive(:ensure_cache_dir_exists)
553
- expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "remote-cb" => "1.1.1"})
554
- end
555
-
556
- it "includes the cookbook and dependencies in the solution dependencies" do
557
- expected_solution_deps = {
558
- "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
559
- "dependencies" => {
560
- "local-cookbook (2.3.4)" => [],
561
- "remote-cb (1.1.1)" => []
562
- }
563
-
564
- }
565
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
566
- end
567
-
568
- end
569
-
570
- context "And the default source is the chef server" do
571
-
572
- include_context "chef server default source"
573
-
574
- it "demands a solution with the local cookbook and any version of the other cookbook" do
575
- expect(demands).to eq([["local-cookbook", "= 2.3.4"], ["remote-cb", ">= 0.0.0"]])
576
- end
577
-
578
- it "overrides the chef-server universe with the local cookbook and deps" do
579
- expected_artifacts_graph = external_cookbook_universe.dup
580
- expected_artifacts_graph["local-cookbook"] = { "2.3.4" => [ ] }
581
- expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
582
- end
583
-
584
- it "uses the locally specified cookbook and remote cookbooks in the solution" do
585
- expect(policyfile).to receive(:ensure_cache_dir_exists)
586
- expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "remote-cb" => "1.1.1"})
587
- end
588
-
589
- it "includes the cookbook and dependencies in the solution dependencies" do
590
- expected_solution_deps = {
591
- "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
592
- "dependencies" => {
593
- "local-cookbook (2.3.4)" => [],
594
- "remote-cb (1.1.1)" => []
595
- }
596
-
597
- }
598
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
599
- end
600
-
601
- end
602
- end
603
-
604
- context "given a cookbook with a version constraint in the policyfile" do
605
-
606
- include_context "community default source"
607
-
608
- let(:run_list) { ['remote-cb'] }
609
-
610
- before do
611
- policyfile.dsl.cookbook("remote-cb", "~> 0.1")
612
- end
613
-
614
- it "demands a solution that matches the version constraint in the policyfile" do
615
- expect(demands).to eq([["remote-cb", "~> 0.1"]])
616
- end
617
-
618
- it "emits a solution that satisfies the policyfile constraint" do
619
- expect(policyfile).to receive(:ensure_cache_dir_exists)
620
- expect(policyfile.graph_solution).to eq({"remote-cb" => "0.1.0"})
621
- end
622
-
623
- it "includes the policyfile constraint in the solution dependencies" do
624
- expected_solution_deps = {
625
- "Policyfile" => [ [ "remote-cb", "~> 0.1" ] ],
626
- "dependencies" => {
627
- "remote-cb (0.1.0)" => []
628
- }
629
-
630
- }
631
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
632
- end
633
- end
634
-
635
- context "given a cookbook that isn't in the run list is specified with a version constraint in the policyfile" do
636
-
637
- include_context "community default source"
638
-
639
- let(:run_list) { ['local-cookbook'] }
640
-
641
- before do
642
- policyfile.dsl.cookbook("remote-cb", "~> 0.1")
643
-
644
- policyfile.dsl.cookbook("local-cookbook", path: "foo/")
645
-
646
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
647
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
648
- allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([])
649
- end
650
-
651
- it "demands a solution that matches the version constraint in the policyfile" do
652
- expect(demands).to eq([["local-cookbook", "= 2.3.4"], ["remote-cb", "~> 0.1"]])
653
- end
654
-
655
- it "emits a solution that satisfies the policyfile constraint" do
656
- expect(policyfile).to receive(:ensure_cache_dir_exists)
657
- expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "remote-cb" => "0.1.0"})
658
- end
659
-
660
- it "includes the policyfile constraint in the solution dependencies" do
661
- expected_solution_deps = {
662
- "Policyfile" => [ [ "remote-cb", "~> 0.1" ], [ "local-cookbook", ">= 0.0.0"] ],
663
- "dependencies" => {
664
- "local-cookbook (2.3.4)" => [],
665
- "remote-cb (0.1.0)" => []
666
- }
667
-
668
- }
669
- expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
670
- end
671
- end
672
-
673
- context "Given a run_list and named run_lists" do
674
-
675
- before do
676
- policyfile.dsl.named_run_list(:foo, 'local-cookbook', 'nginx')
677
- policyfile.dsl.named_run_list(:bar, 'remote-cb', 'nginx')
678
- policyfile.dsl.run_list('private-cookbook', 'nginx')
679
- end
680
-
681
- it "demands a solution that satisfies all of the run lists, with no duplicates" do
682
- expect(policyfile.graph_demands).to include(["private-cookbook", ">= 0.0.0"])
683
- expect(policyfile.graph_demands).to include(["nginx", ">= 0.0.0"])
684
- expect(policyfile.graph_demands).to include(["remote-cb", ">= 0.0.0"])
685
- expect(policyfile.graph_demands).to include(["local-cookbook", ">= 0.0.0"])
686
-
687
- # ensure there are no duplicates:
688
- expected_demands = [["private-cookbook", ">= 0.0.0"],
689
- ["nginx", ">= 0.0.0"],
690
- ["local-cookbook", ">= 0.0.0"],
691
- ["remote-cb", ">= 0.0.0"]]
692
- expect(policyfile.graph_demands).to eq(expected_demands)
693
- end
694
-
695
- end
696
-
697
- context "when using multiple default sources" do
698
-
699
- include_context "community default source"
700
-
701
- let(:run_list) { [ 'repo-cookbook-one', 'remote-cb', 'remote-cb-two' ] }
702
-
703
- before do
704
- policyfile.default_source(:chef_repo, "path/to/repo")
705
- allow(policyfile.default_source.last).to receive(:universe_graph).and_return(repo_cookbook_universe)
706
- end
707
-
708
- context "when the graphs don't conflict" do
709
-
710
- before do
711
- # This is on the community site
712
- policyfile.dsl.cookbook("remote-cb")
713
- end
714
-
715
- let(:repo_cookbook_universe) do
716
- {
717
- "repo-cookbook-one" => {
718
- "1.0.0" => [ ]
719
- },
720
-
721
- "repo-cookbook-two" => {
722
- "9.9.9" => [ ["repo-cookbook-on-community-dep", "= 1.0.0"] ]
723
- },
724
-
725
- "private-cookbook" => {
726
- "0.1.0" => [ ]
727
- }
728
- }
729
- end
730
-
731
- it "merges the graphs" do
732
- merged = policyfile.remote_artifacts_graph
733
- expected = external_cookbook_universe.merge(repo_cookbook_universe)
734
-
735
- expect(merged).to eq(expected)
736
- end
737
-
738
- it "solves the graph demands using cookbooks from both sources" do
739
- expected = {"repo-cookbook-one" => "1.0.0", "remote-cb" => "1.1.1", "remote-cb-two" => "1.1.1"}
740
- expect(policyfile.graph_solution).to eq(expected)
741
- end
742
-
743
- it "finds the location of a cookbook declared via explicit `cookbook` with no source options" do
744
- community_source = policyfile.default_source.first
745
-
746
- expected_source_options = { artifactserver: "https://chef.example/url", version: "1.1.1" }
747
-
748
- expect(community_source).to be_a(ChefDK::Policyfile::CommunityCookbookSource)
749
- expect(community_source).to receive(:source_options_for).
750
- with("remote-cb", "1.1.1").
751
- and_return(expected_source_options)
752
-
753
- location_spec = policyfile.create_spec_for_cookbook("remote-cb", "1.1.1")
754
- expect(location_spec.source_options).to eq(expected_source_options)
755
- end
756
-
757
- it "sources cookbooks from the correct source when the cookbook doesn't have a `cookbook` entry" do
758
- # these don't have `cookbook` entries in the Policyfile.rb, so they are nil
759
- expect(policyfile.cookbook_location_spec_for("repo-cookbook-one")).to be_nil
760
- expect(policyfile.cookbook_location_spec_for("remote-cb-two")).to be_nil
761
-
762
- # We have to stub #source_options_for or else we'd need to stub the
763
- # source options data inside the source object. That's getting a bit
764
- # too deep into the source object's internals.
765
-
766
- expected_repo_options = { path: "path/to/cookbook", version: "1.0.0" }
767
- repo_source = policyfile.default_source.last
768
- expect(repo_source).to be_a(ChefDK::Policyfile::ChefRepoCookbookSource)
769
- expect(repo_source).to receive(:source_options_for).
770
- with("repo-cookbook-one", "1.0.0").
771
- and_return(expected_repo_options)
772
-
773
-
774
- repo_cb_location = policyfile.create_spec_for_cookbook("repo-cookbook-one", "1.0.0")
775
- expect(repo_cb_location.source_options).to eq(expected_repo_options)
776
-
777
- expected_server_options = { artifactserver: "https://chef.example/url", version: "1.1.1" }
778
- community_source = policyfile.default_source.first
779
- expect(community_source).to be_a(ChefDK::Policyfile::CommunityCookbookSource)
780
- expect(community_source).to receive(:source_options_for).
781
- with("remote-cb-two", "1.1.1").
782
- and_return(expected_server_options)
783
-
784
- remote_cb_location = policyfile.create_spec_for_cookbook("remote-cb-two", "1.1.1")
785
- expect(remote_cb_location.source_options).to eq(expected_server_options)
786
- end
787
-
788
- end
789
-
790
- context "when the graphs conflict" do
791
-
792
- let(:repo_cookbook_universe) do
793
- {
794
- "repo-cookbook-one" => {
795
- "1.0.0" => [ ]
796
- },
797
-
798
- "repo-cookbook-two" => {
799
- "9.9.9" => [ ["repo-cookbook-on-community-dep", "= 1.0.0"] ]
800
- },
801
-
802
- "private-cookbook" => {
803
- "0.1.0" => [ ]
804
- },
805
-
806
- # NOTE: cookbooks are considered to conflict when both sources have
807
- # cookbooks with the same name, regardless of whether any version
808
- # numbers overlap.
809
- #
810
- # The before block does the equivalent to putting this in the
811
- # Policyfile.rb:
812
- #
813
- # cookbook "remote-cb"
814
- #
815
- # This makes the compiler take a slightly different code path than if
816
- # the cookbook was just in the dep graphs.
817
- "remote-cb" => {
818
- "99.99.99" => [ ]
819
- },
820
-
821
- # This also conflicts, but only via the graphs
822
- "remote-cb-two" => {
823
- "1.2.3" => [ ]
824
- }
825
-
826
- }
827
- end
828
-
829
- context "and no explicit source is given for the conflicting cookbook" do
830
-
831
- before do
832
- # This is on the community site
833
- policyfile.dsl.cookbook("remote-cb")
834
- end
835
-
836
- it "raises an error describing the conflict" do
837
- expected_err = <<-ERROR
838
- Source supermarket(https://supermarket.chef.io) and chef_repo(path/to/repo) contain conflicting cookbooks:
839
- - remote-cb
840
- - remote-cb-two
841
- ERROR
842
-
843
- expect { policyfile.remote_artifacts_graph }.to raise_error do |error|
844
- expect(error).to be_a(ChefDK::CookbookSourceConflict)
845
- expect(error.message).to eq(expected_err)
846
- end
847
- end
848
- end
849
-
850
- context "and the conflicting cookbook has an explicit source in the Policyfile" do
851
-
852
- before do
853
- # This is on the community site
854
- policyfile.dsl.cookbook("remote-cb", path: "path/to/remote-cb")
855
- policyfile.dsl.cookbook("remote-cb-two", git: "git://git.example:user/remote-cb-two.git")
856
- policyfile.error!
857
- end
858
-
859
- it "solves the graph" do
860
- expect { policyfile.remote_artifacts_graph }.to_not raise_error
861
- end
862
-
863
- it "assigns the correct source options to the cookbook" do
864
- remote_cb_source_opts = policyfile.cookbook_location_spec_for("remote-cb").source_options
865
- expect(remote_cb_source_opts).to eq(path: "path/to/remote-cb")
866
-
867
- remote_cb_two_source_opts = policyfile.cookbook_location_spec_for("remote-cb-two").source_options
868
- expect(remote_cb_two_source_opts).to eq(git: "git://git.example:user/remote-cb-two.git")
869
- end
870
- end
871
-
872
- end
873
-
874
- end
875
-
876
- end
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_compiler'
20
+
21
+ describe ChefDK::PolicyfileCompiler, "when expressing the Policyfile graph demands" do
22
+
23
+ let(:run_list) { [] }
24
+
25
+ let(:default_source) { nil }
26
+
27
+ let(:external_cookbook_universe) { {} }
28
+
29
+ let(:policyfile) do
30
+ policyfile = ChefDK::PolicyfileCompiler.new.build do |p|
31
+
32
+ p.default_source(*default_source) if default_source
33
+ p.run_list(*run_list)
34
+
35
+ allow(p.default_source.first).to receive(:universe_graph).and_return(external_cookbook_universe)
36
+ end
37
+
38
+ policyfile
39
+ end
40
+
41
+ let(:demands) { policyfile.graph_demands }
42
+
43
+ shared_context("community default source") do
44
+
45
+ let(:default_source) { [:community] }
46
+
47
+ let(:external_cookbook_universe) do
48
+ {
49
+ "nginx" => {
50
+ "1.0.0" => [ [ "apt", "~> 2.0" ], [ "yum", "~> 1.0" ] ],
51
+ "1.2.0" => [ [ "apt", "~> 2.1" ], [ "yum", "~> 1.0" ] ],
52
+ "2.0.0" => [ [ "apt", "~> 3.0" ], [ "yum", "~> 1.0" ], [ "ohai", "~> 2.0" ] ]
53
+ },
54
+
55
+ "mysql" => {
56
+ "3.0.0" => [ [ "apt", "~> 2.0" ], [ "yum", "~> 1.0" ] ],
57
+ "4.0.0" => [ [ "apt", "~> 2.4" ], [ "yum", "~> 1.1" ] ],
58
+ "5.0.0" => [ ],
59
+ },
60
+
61
+ "local-cookbook" => {
62
+ "9.9.9" => [ ["local-cookbook-on-community-dep", "= 1.0.0"] ]
63
+ },
64
+
65
+ "git-sourced-cookbook" => {
66
+ "10.10.10" => [ ["git-sourced-cookbook-dep", "= 1.0.0"] ]
67
+ },
68
+
69
+ "remote-cb" => {
70
+ "0.1.0" => [ ],
71
+ "1.1.1" => [ ]
72
+ },
73
+
74
+ "remote-cb-two" => {
75
+ "0.1.0" => [ ],
76
+ "1.1.1" => [ ]
77
+ },
78
+
79
+ "local-cookbook-dep-one" => {
80
+ "1.5.0" => [ ]
81
+ },
82
+
83
+ "git-sourced-cookbook-dep" => {
84
+ "2.8.0" => [ ]
85
+ }
86
+
87
+ }
88
+ end
89
+ end
90
+
91
+ shared_context("chef server default source") do
92
+
93
+ let(:default_source) { [:chef_server, "https://chef.example.com"] }
94
+
95
+ let(:external_cookbook_universe) do
96
+ {
97
+ "nginx" => {
98
+ "1.0.0" => [ [ "apt", "~> 2.0" ], [ "yum", "~> 1.0" ] ],
99
+ },
100
+
101
+ "mysql" => {
102
+ "5.0.0" => [ ],
103
+ },
104
+
105
+ "local-cookbook" => {
106
+ "9.9.9" => [ ["local-cookbook-on-community-dep", "= 1.0.0"] ]
107
+ },
108
+
109
+ "remote-cb" => {
110
+ "1.1.1" => [ ]
111
+ },
112
+
113
+ "git-sourced-cookbook" => {
114
+ "10.10.10" => [ ["git-sourced-cookbook-dep", "= 1.0.0"] ]
115
+ },
116
+
117
+ "private-cookbook" => {
118
+ "0.1.0" => [ ]
119
+ },
120
+
121
+ "local-cookbook-dep-one" => {
122
+ "1.6.0" => [ ]
123
+ },
124
+
125
+ "git-sourced-cookbook-dep" => {
126
+ "2.9.0" => [ ]
127
+ }
128
+
129
+
130
+ }
131
+ end
132
+ end
133
+
134
+ describe "when normalizing run_list items" do
135
+
136
+ it "normalizes a bare cookbook name" do
137
+ policyfile.run_list("local-cookbook")
138
+ expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::default]"])
139
+ end
140
+
141
+ it "normalizes a bare cookbook::recipe item" do
142
+ policyfile.run_list("local-cookbook::server")
143
+ expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::server]"])
144
+ end
145
+
146
+ it "normalizes a recipe[] item with implicit default" do
147
+ policyfile.run_list("recipe[local-cookbook]")
148
+ expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::default]"])
149
+ end
150
+
151
+ it "does not modify a fully qualified recipe" do
152
+ policyfile.run_list("recipe[local-cookbook::jazz_hands]")
153
+ expect(policyfile.normalized_run_list).to eq(["recipe[local-cookbook::jazz_hands]"])
154
+ end
155
+
156
+ describe "in an alternate run list" do
157
+
158
+ it "normalizes a bare cookbook name" do
159
+ policyfile.named_run_list(:foo, "local-cookbook")
160
+ expect(policyfile.normalized_named_run_lists[:foo]).to eq(["recipe[local-cookbook::default]"])
161
+ end
162
+
163
+ it "normalizes a bare cookbook::recipe item" do
164
+ policyfile.named_run_list(:foo, "local-cookbook::server")
165
+ expect(policyfile.normalized_named_run_lists[:foo]).to eq(["recipe[local-cookbook::server]"])
166
+ end
167
+
168
+ it "normalizes a recipe[] item with implicit default" do
169
+ policyfile.named_run_list(:foo, "recipe[local-cookbook]")
170
+ expect(policyfile.normalized_named_run_lists[:foo]).to eq(["recipe[local-cookbook::default]"])
171
+ end
172
+
173
+ it "does not modify a fully qualified recipe" do
174
+ policyfile.named_run_list(:foo, "recipe[local-cookbook::jazz_hands]")
175
+ expect(policyfile.normalized_named_run_lists[:foo]).to eq(["recipe[local-cookbook::jazz_hands]"])
176
+ end
177
+
178
+ end
179
+ end
180
+
181
+ before do
182
+ expect(policyfile.errors).to eq([])
183
+ end
184
+
185
+ context "Given no local or git cookbooks, no default source, and an empty run list" do
186
+
187
+ let(:run_list) { [] }
188
+
189
+ it "has an empty set of demands" do
190
+ expect(demands).to eq([])
191
+ end
192
+
193
+ it "uses an empty universe for dependencies" do
194
+ expect(policyfile.artifacts_graph).to eq({})
195
+ end
196
+
197
+ it "has an empty solution" do
198
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
199
+ expect(policyfile.graph_solution).to eq({})
200
+ end
201
+
202
+ it "has an empty set of solution_dependencies" do
203
+ expected_solution_deps = {
204
+ "Policyfile" => [],
205
+ "dependencies" => {}
206
+ }
207
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
208
+ end
209
+ end
210
+
211
+ context "Given a run list and no local or git cookbooks" do
212
+
213
+ let(:run_list) { ["remote-cb"] }
214
+
215
+ context "with no default source" do
216
+
217
+ it "fails to locate the cookbook" do
218
+ expect { policyfile.graph_solution }.to raise_error(Solve::Errors::NoSolutionError)
219
+ end
220
+
221
+ context "when the policyfile also has a `cookbook` entry for the run list item" do
222
+
223
+ before do
224
+ policyfile.dsl.cookbook "remote-cb"
225
+ end
226
+
227
+ it "fails to locate the cookbook" do
228
+ expect { policyfile.graph_solution }.to raise_error(Solve::Errors::NoSolutionError)
229
+ end
230
+
231
+ end
232
+
233
+ end
234
+
235
+ context "And the default source is the community site" do
236
+
237
+ include_context "community default source"
238
+
239
+ it "has an unconstrained demand on the required cookbooks" do
240
+ expect(demands).to eq([["remote-cb", ">= 0.0.0"]])
241
+ end
242
+
243
+ it "uses the community site universe for dependencies" do
244
+ expect(policyfile.artifacts_graph).to eq(external_cookbook_universe)
245
+ end
246
+
247
+ it "uses the community cookbook in the solution" do
248
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
249
+ expect(policyfile.graph_solution).to eq({"remote-cb" => "1.1.1"})
250
+ end
251
+
252
+ it "includes the cookbook in the solution dependencies" do
253
+ expected_solution_deps = {
254
+ "Policyfile" => [],
255
+ "dependencies" => { "remote-cb (1.1.1)" => [] }
256
+ }
257
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
258
+ end
259
+
260
+ end
261
+
262
+ context "And the default source is the chef-server" do
263
+
264
+ include_context "chef server default source"
265
+
266
+ it "has an unconstrained demand on the required cookbooks" do
267
+ expect(demands).to eq([["remote-cb", ">= 0.0.0"]])
268
+ end
269
+
270
+ it "uses the chef-server universe for dependencies" do
271
+ expect(policyfile.artifacts_graph).to eq(external_cookbook_universe)
272
+ end
273
+
274
+ it "uses the chef-server cookbook in the solution" do
275
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
276
+ expect(policyfile.graph_solution).to eq({"remote-cb" => "1.1.1"})
277
+ end
278
+ end
279
+ end
280
+
281
+ context "Given a local cookbook and only that cookbook in the run list" do
282
+
283
+ let(:run_list) { ['local-cookbook'] }
284
+
285
+ before do
286
+ policyfile.dsl.cookbook('local-cookbook', path: "/foo")
287
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
288
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([])
289
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached).and_return(true)
290
+ end
291
+
292
+ it "demands a solution using the local cookbook" do
293
+ expect(demands).to eq([["local-cookbook", "= 2.3.4"]])
294
+ end
295
+
296
+ it "includes the local cookbook in the artifact universe" do
297
+ expected_artifacts_graph = {
298
+ "local-cookbook" => { "2.3.4" => [] }
299
+ }
300
+ expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
301
+ end
302
+
303
+ it "includes the cookbook in the solution dependencies" do
304
+ expected_solution_deps = {
305
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
306
+ "dependencies" => { "local-cookbook (2.3.4)" => [] }
307
+ }
308
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
309
+ end
310
+
311
+ end
312
+
313
+ context "Given a local cookbook with a dependency and only the local cookbook in the run list" do
314
+
315
+ let(:run_list) { ['local-cookbook'] }
316
+
317
+ context "And the default source is the community site" do
318
+
319
+ include_context "community default source"
320
+
321
+ before do
322
+ policyfile.dsl.cookbook("local-cookbook", path: "foo/")
323
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
324
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
325
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([ [ "local-cookbook-dep-one", "~> 1.0"] ])
326
+ end
327
+
328
+ it "demands a solution using the local cookbook" do
329
+ expect(demands).to eq([["local-cookbook", "= 2.3.4"]])
330
+ end
331
+
332
+ it "overrides the community site universe with the local cookbook and its dependencies" do
333
+ expected_artifacts_graph = external_cookbook_universe.dup
334
+ expected_artifacts_graph["local-cookbook"] = {
335
+ "2.3.4" => [ [ "local-cookbook-dep-one", "~> 1.0" ] ]
336
+ }
337
+ expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
338
+ end
339
+
340
+ it "uses the local cookbook in the solution and gets dependencies remotely" do
341
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
342
+ expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "local-cookbook-dep-one" => "1.5.0"})
343
+ end
344
+
345
+ it "includes the cookbook and dependencies in the solution dependencies" do
346
+ expected_solution_deps = {
347
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
348
+ "dependencies" => {
349
+ "local-cookbook (2.3.4)" => [[ "local-cookbook-dep-one", "~> 1.0"]],
350
+ "local-cookbook-dep-one (1.5.0)" => []
351
+ }
352
+
353
+ }
354
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
355
+ end
356
+
357
+ end
358
+ context "And the default source is the chef server" do
359
+
360
+ include_context "chef server default source"
361
+
362
+ before do
363
+ policyfile.dsl.cookbook("local-cookbook", path: "foo/")
364
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
365
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
366
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([ [ "local-cookbook-dep-one", "~> 1.0"] ])
367
+ end
368
+
369
+ it "demands a solution using the local cookbook" do
370
+ expect(demands).to eq([["local-cookbook", "= 2.3.4"]])
371
+ end
372
+
373
+ it "overrides the chef server universe with the local cookbook and its dependencies" do
374
+ # all versions of "local-cookbook" from the cookbook site universe
375
+ # should be removed so we won't run into trouble if there's a community
376
+ # cookbook with the same name and version but different deps.
377
+ expected_artifacts_graph = external_cookbook_universe.dup
378
+ expected_artifacts_graph["local-cookbook"] = {
379
+ "2.3.4" => [ [ "local-cookbook-dep-one", "~> 1.0" ] ]
380
+ }
381
+ expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
382
+ end
383
+
384
+ it "uses the local cookbook in the solution and gets dependencies remotely" do
385
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
386
+ expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "local-cookbook-dep-one" => "1.6.0"})
387
+ end
388
+
389
+ it "includes the cookbook and dependencies in the solution dependencies" do
390
+ expected_solution_deps = {
391
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
392
+ "dependencies" => {
393
+ "local-cookbook (2.3.4)" => [[ "local-cookbook-dep-one", "~> 1.0"]],
394
+ "local-cookbook-dep-one (1.6.0)" => []
395
+ }
396
+
397
+ }
398
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
399
+ end
400
+
401
+ end
402
+ end
403
+
404
+ context "Given a git-sourced cookbook with no dependencies and only the git cookbook in the run list" do
405
+
406
+ let(:run_list) { ["git-sourced-cookbook"] }
407
+
408
+ before do
409
+ policyfile.dsl.cookbook("git-sourced-cookbook", git: "git://git.example.org:user/a-cookbook.git")
410
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:ensure_cached)
411
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:version).and_return("8.6.7")
412
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:dependencies).and_return([ ])
413
+ end
414
+
415
+ it "demands a solution using the git sourced cookbook" do
416
+ expect(demands).to eq([["git-sourced-cookbook", "= 8.6.7"]])
417
+ end
418
+
419
+ it "includes the git-sourced cookbook in the universe graph" do
420
+ expected_artifacts_graph = {
421
+ "git-sourced-cookbook" => { "8.6.7" => [ ] }
422
+ }
423
+ expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
424
+ end
425
+
426
+ it "uses the git sourced cookbook in the solution" do
427
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
428
+ expect(policyfile.graph_solution).to eq({"git-sourced-cookbook" => "8.6.7"})
429
+ end
430
+
431
+ it "includes the cookbook and dependencies in the solution dependencies" do
432
+ expected_solution_deps = {
433
+ "Policyfile" => [ [ "git-sourced-cookbook", ">= 0.0.0" ] ],
434
+ "dependencies" => {
435
+ "git-sourced-cookbook (8.6.7)" => []
436
+ }
437
+
438
+ }
439
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
440
+ end
441
+
442
+ end
443
+
444
+ context "Given a git-sourced cookbook with a dependency and only the git cookbook in the run list" do
445
+
446
+ let(:run_list) { ["git-sourced-cookbook"] }
447
+
448
+ before do
449
+ policyfile.dsl.cookbook("git-sourced-cookbook", git: "git://git.example.org:user/a-cookbook.git")
450
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:ensure_cached)
451
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:version).and_return("8.6.7")
452
+ allow(policyfile.cookbook_location_spec_for("git-sourced-cookbook")).to receive(:dependencies).and_return([ ["git-sourced-cookbook-dep", "~> 2.2" ] ])
453
+ end
454
+
455
+ context "And the default source is the community site" do
456
+
457
+ include_context "community default source"
458
+
459
+ it "demands a solution using the git sourced cookbook" do
460
+ expect(demands).to eq([["git-sourced-cookbook", "= 8.6.7"]])
461
+ end
462
+
463
+ it "overrides the community site universe with the git-sourced cookbook and deps" do
464
+ expected_artifacts_graph = external_cookbook_universe.dup
465
+ expected_artifacts_graph["git-sourced-cookbook"] = {
466
+ "8.6.7" => [ ["git-sourced-cookbook-dep", "~> 2.2" ] ]
467
+ }
468
+ expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
469
+ end
470
+
471
+ it "uses the git sourced cookbook with remote dependencies in the solution" do
472
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
473
+ expect(policyfile.graph_solution).to eq({"git-sourced-cookbook" => "8.6.7", "git-sourced-cookbook-dep" => "2.8.0"})
474
+ end
475
+
476
+ it "includes the cookbook and dependencies in the solution dependencies" do
477
+ expected_solution_deps = {
478
+ "Policyfile" => [ [ "git-sourced-cookbook", ">= 0.0.0" ] ],
479
+ "dependencies" => {
480
+ "git-sourced-cookbook (8.6.7)" => [ [ "git-sourced-cookbook-dep", "~> 2.2" ] ],
481
+ "git-sourced-cookbook-dep (2.8.0)" => []
482
+ }
483
+
484
+ }
485
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
486
+ end
487
+
488
+ end
489
+
490
+ context "And the default source is the chef server" do
491
+
492
+ include_context "chef server default source"
493
+
494
+ it "demands a solution using the git sourced cookbook" do
495
+ expect(demands).to eq([["git-sourced-cookbook", "= 8.6.7"]])
496
+ end
497
+
498
+ it "overrides the chef server universe with the git-sourced cookbook and deps" do
499
+ expected_artifacts_graph = external_cookbook_universe.dup
500
+ expected_artifacts_graph["git-sourced-cookbook"] = {
501
+ "8.6.7" => [ ["git-sourced-cookbook-dep", "~> 2.2" ] ]
502
+ }
503
+ expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
504
+ end
505
+
506
+ it "uses the git sourced cookbook with remote dependencies in the solution" do
507
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
508
+ expect(policyfile.graph_solution).to eq({"git-sourced-cookbook" => "8.6.7", "git-sourced-cookbook-dep" => "2.9.0"})
509
+ end
510
+
511
+ it "includes the cookbook and dependencies in the solution dependencies" do
512
+ expected_solution_deps = {
513
+ "Policyfile" => [ [ "git-sourced-cookbook", ">= 0.0.0" ] ],
514
+ "dependencies" => {
515
+ "git-sourced-cookbook (8.6.7)" => [ [ "git-sourced-cookbook-dep", "~> 2.2" ] ],
516
+ "git-sourced-cookbook-dep (2.9.0)" => []
517
+ }
518
+
519
+ }
520
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
521
+ end
522
+
523
+ end
524
+ end
525
+
526
+ context "Given a local cookbook with a run list containing the local cookbook and another cookbook" do
527
+
528
+ let(:run_list) { ['local-cookbook', 'remote-cb'] }
529
+
530
+ before do
531
+ policyfile.dsl.cookbook("local-cookbook", path: "foo/")
532
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
533
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
534
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([])
535
+ end
536
+
537
+ context "And the default source is the community site" do
538
+
539
+ include_context "community default source"
540
+
541
+ it "demands a solution with the local cookbook and any version of the other cookbook" do
542
+ expect(demands).to eq([["local-cookbook", "= 2.3.4"], ["remote-cb", ">= 0.0.0"]])
543
+ end
544
+
545
+ it "overrides the community universe with the local cookbook and deps" do
546
+ expected_artifacts_graph = external_cookbook_universe.dup
547
+ expected_artifacts_graph["local-cookbook"] = { "2.3.4" => [ ] }
548
+ expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
549
+ end
550
+
551
+ it "uses the locally specified cookbook and remote cookbooks in the solution" do
552
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
553
+ expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "remote-cb" => "1.1.1"})
554
+ end
555
+
556
+ it "includes the cookbook and dependencies in the solution dependencies" do
557
+ expected_solution_deps = {
558
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
559
+ "dependencies" => {
560
+ "local-cookbook (2.3.4)" => [],
561
+ "remote-cb (1.1.1)" => []
562
+ }
563
+
564
+ }
565
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
566
+ end
567
+
568
+ end
569
+
570
+ context "And the default source is the chef server" do
571
+
572
+ include_context "chef server default source"
573
+
574
+ it "demands a solution with the local cookbook and any version of the other cookbook" do
575
+ expect(demands).to eq([["local-cookbook", "= 2.3.4"], ["remote-cb", ">= 0.0.0"]])
576
+ end
577
+
578
+ it "overrides the chef-server universe with the local cookbook and deps" do
579
+ expected_artifacts_graph = external_cookbook_universe.dup
580
+ expected_artifacts_graph["local-cookbook"] = { "2.3.4" => [ ] }
581
+ expect(policyfile.artifacts_graph).to eq(expected_artifacts_graph)
582
+ end
583
+
584
+ it "uses the locally specified cookbook and remote cookbooks in the solution" do
585
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
586
+ expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "remote-cb" => "1.1.1"})
587
+ end
588
+
589
+ it "includes the cookbook and dependencies in the solution dependencies" do
590
+ expected_solution_deps = {
591
+ "Policyfile" => [ [ "local-cookbook", ">= 0.0.0" ] ],
592
+ "dependencies" => {
593
+ "local-cookbook (2.3.4)" => [],
594
+ "remote-cb (1.1.1)" => []
595
+ }
596
+
597
+ }
598
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
599
+ end
600
+
601
+ end
602
+ end
603
+
604
+ context "given a cookbook with a version constraint in the policyfile" do
605
+
606
+ include_context "community default source"
607
+
608
+ let(:run_list) { ['remote-cb'] }
609
+
610
+ before do
611
+ policyfile.dsl.cookbook("remote-cb", "~> 0.1")
612
+ end
613
+
614
+ it "demands a solution that matches the version constraint in the policyfile" do
615
+ expect(demands).to eq([["remote-cb", "~> 0.1"]])
616
+ end
617
+
618
+ it "emits a solution that satisfies the policyfile constraint" do
619
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
620
+ expect(policyfile.graph_solution).to eq({"remote-cb" => "0.1.0"})
621
+ end
622
+
623
+ it "includes the policyfile constraint in the solution dependencies" do
624
+ expected_solution_deps = {
625
+ "Policyfile" => [ [ "remote-cb", "~> 0.1" ] ],
626
+ "dependencies" => {
627
+ "remote-cb (0.1.0)" => []
628
+ }
629
+
630
+ }
631
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
632
+ end
633
+ end
634
+
635
+ context "given a cookbook that isn't in the run list is specified with a version constraint in the policyfile" do
636
+
637
+ include_context "community default source"
638
+
639
+ let(:run_list) { ['local-cookbook'] }
640
+
641
+ before do
642
+ policyfile.dsl.cookbook("remote-cb", "~> 0.1")
643
+
644
+ policyfile.dsl.cookbook("local-cookbook", path: "foo/")
645
+
646
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:ensure_cached)
647
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:version).and_return("2.3.4")
648
+ allow(policyfile.cookbook_location_spec_for("local-cookbook")).to receive(:dependencies).and_return([])
649
+ end
650
+
651
+ it "demands a solution that matches the version constraint in the policyfile" do
652
+ expect(demands).to eq([["local-cookbook", "= 2.3.4"], ["remote-cb", "~> 0.1"]])
653
+ end
654
+
655
+ it "emits a solution that satisfies the policyfile constraint" do
656
+ expect(policyfile).to receive(:ensure_cache_dir_exists)
657
+ expect(policyfile.graph_solution).to eq({"local-cookbook" => "2.3.4", "remote-cb" => "0.1.0"})
658
+ end
659
+
660
+ it "includes the policyfile constraint in the solution dependencies" do
661
+ expected_solution_deps = {
662
+ "Policyfile" => [ [ "remote-cb", "~> 0.1" ], [ "local-cookbook", ">= 0.0.0"] ],
663
+ "dependencies" => {
664
+ "local-cookbook (2.3.4)" => [],
665
+ "remote-cb (0.1.0)" => []
666
+ }
667
+
668
+ }
669
+ expect(policyfile.solution_dependencies.to_lock).to eq(expected_solution_deps)
670
+ end
671
+ end
672
+
673
+ context "Given a run_list and named run_lists" do
674
+
675
+ before do
676
+ policyfile.dsl.named_run_list(:foo, 'local-cookbook', 'nginx')
677
+ policyfile.dsl.named_run_list(:bar, 'remote-cb', 'nginx')
678
+ policyfile.dsl.run_list('private-cookbook', 'nginx')
679
+ end
680
+
681
+ it "demands a solution that satisfies all of the run lists, with no duplicates" do
682
+ expect(policyfile.graph_demands).to include(["private-cookbook", ">= 0.0.0"])
683
+ expect(policyfile.graph_demands).to include(["nginx", ">= 0.0.0"])
684
+ expect(policyfile.graph_demands).to include(["remote-cb", ">= 0.0.0"])
685
+ expect(policyfile.graph_demands).to include(["local-cookbook", ">= 0.0.0"])
686
+
687
+ # ensure there are no duplicates:
688
+ expected_demands = [["private-cookbook", ">= 0.0.0"],
689
+ ["nginx", ">= 0.0.0"],
690
+ ["local-cookbook", ">= 0.0.0"],
691
+ ["remote-cb", ">= 0.0.0"]]
692
+ expect(policyfile.graph_demands).to eq(expected_demands)
693
+ end
694
+
695
+ end
696
+
697
+ context "when using multiple default sources" do
698
+
699
+ include_context "community default source"
700
+
701
+ let(:run_list) { [ 'repo-cookbook-one', 'remote-cb', 'remote-cb-two' ] }
702
+
703
+ before do
704
+ policyfile.default_source(:chef_repo, "path/to/repo")
705
+ allow(policyfile.default_source.last).to receive(:universe_graph).and_return(repo_cookbook_universe)
706
+ end
707
+
708
+ context "when the graphs don't conflict" do
709
+
710
+ before do
711
+ # This is on the community site
712
+ policyfile.dsl.cookbook("remote-cb")
713
+ end
714
+
715
+ let(:repo_cookbook_universe) do
716
+ {
717
+ "repo-cookbook-one" => {
718
+ "1.0.0" => [ ]
719
+ },
720
+
721
+ "repo-cookbook-two" => {
722
+ "9.9.9" => [ ["repo-cookbook-on-community-dep", "= 1.0.0"] ]
723
+ },
724
+
725
+ "private-cookbook" => {
726
+ "0.1.0" => [ ]
727
+ }
728
+ }
729
+ end
730
+
731
+ it "merges the graphs" do
732
+ merged = policyfile.remote_artifacts_graph
733
+ expected = external_cookbook_universe.merge(repo_cookbook_universe)
734
+
735
+ expect(merged).to eq(expected)
736
+ end
737
+
738
+ it "solves the graph demands using cookbooks from both sources" do
739
+ expected = {"repo-cookbook-one" => "1.0.0", "remote-cb" => "1.1.1", "remote-cb-two" => "1.1.1"}
740
+ expect(policyfile.graph_solution).to eq(expected)
741
+ end
742
+
743
+ it "finds the location of a cookbook declared via explicit `cookbook` with no source options" do
744
+ community_source = policyfile.default_source.first
745
+
746
+ expected_source_options = { artifactserver: "https://chef.example/url", version: "1.1.1" }
747
+
748
+ expect(community_source).to be_a(ChefDK::Policyfile::CommunityCookbookSource)
749
+ expect(community_source).to receive(:source_options_for).
750
+ with("remote-cb", "1.1.1").
751
+ and_return(expected_source_options)
752
+
753
+ location_spec = policyfile.create_spec_for_cookbook("remote-cb", "1.1.1")
754
+ expect(location_spec.source_options).to eq(expected_source_options)
755
+ end
756
+
757
+ it "sources cookbooks from the correct source when the cookbook doesn't have a `cookbook` entry" do
758
+ # these don't have `cookbook` entries in the Policyfile.rb, so they are nil
759
+ expect(policyfile.cookbook_location_spec_for("repo-cookbook-one")).to be_nil
760
+ expect(policyfile.cookbook_location_spec_for("remote-cb-two")).to be_nil
761
+
762
+ # We have to stub #source_options_for or else we'd need to stub the
763
+ # source options data inside the source object. That's getting a bit
764
+ # too deep into the source object's internals.
765
+
766
+ expected_repo_options = { path: "path/to/cookbook", version: "1.0.0" }
767
+ repo_source = policyfile.default_source.last
768
+ expect(repo_source).to be_a(ChefDK::Policyfile::ChefRepoCookbookSource)
769
+ expect(repo_source).to receive(:source_options_for).
770
+ with("repo-cookbook-one", "1.0.0").
771
+ and_return(expected_repo_options)
772
+
773
+
774
+ repo_cb_location = policyfile.create_spec_for_cookbook("repo-cookbook-one", "1.0.0")
775
+ expect(repo_cb_location.source_options).to eq(expected_repo_options)
776
+
777
+ expected_server_options = { artifactserver: "https://chef.example/url", version: "1.1.1" }
778
+ community_source = policyfile.default_source.first
779
+ expect(community_source).to be_a(ChefDK::Policyfile::CommunityCookbookSource)
780
+ expect(community_source).to receive(:source_options_for).
781
+ with("remote-cb-two", "1.1.1").
782
+ and_return(expected_server_options)
783
+
784
+ remote_cb_location = policyfile.create_spec_for_cookbook("remote-cb-two", "1.1.1")
785
+ expect(remote_cb_location.source_options).to eq(expected_server_options)
786
+ end
787
+
788
+ end
789
+
790
+ context "when the graphs conflict" do
791
+
792
+ let(:repo_cookbook_universe) do
793
+ {
794
+ "repo-cookbook-one" => {
795
+ "1.0.0" => [ ]
796
+ },
797
+
798
+ "repo-cookbook-two" => {
799
+ "9.9.9" => [ ["repo-cookbook-on-community-dep", "= 1.0.0"] ]
800
+ },
801
+
802
+ "private-cookbook" => {
803
+ "0.1.0" => [ ]
804
+ },
805
+
806
+ # NOTE: cookbooks are considered to conflict when both sources have
807
+ # cookbooks with the same name, regardless of whether any version
808
+ # numbers overlap.
809
+ #
810
+ # The before block does the equivalent to putting this in the
811
+ # Policyfile.rb:
812
+ #
813
+ # cookbook "remote-cb"
814
+ #
815
+ # This makes the compiler take a slightly different code path than if
816
+ # the cookbook was just in the dep graphs.
817
+ "remote-cb" => {
818
+ "99.99.99" => [ ]
819
+ },
820
+
821
+ # This also conflicts, but only via the graphs
822
+ "remote-cb-two" => {
823
+ "1.2.3" => [ ]
824
+ },
825
+
826
+ # This has a dependency on a conflicting cookbook
827
+ "dep_on_conflicting_cookbook" => {
828
+
829
+ # Only the older cookbook has the conflicting dep, however we don't
830
+ # know how the dependency solver will solve this without doing more
831
+ # inspection of the graph, so the expected behavior is to error if
832
+ # any possible solution could have a conflict.
833
+ "1.0.0" => [ ["remote-cb-two", ">= 0.0.0" ] ],
834
+ "2.0.0" => [ ]
835
+
836
+ }
837
+
838
+ }
839
+ end
840
+
841
+ context "and the conflicting cookbook is in the run list" do
842
+
843
+ let(:run_list) { [ 'repo-cookbook-one', 'remote-cb', 'remote-cb-two' ] }
844
+
845
+ context "and no explicit source is given for the conflicting cookbook" do
846
+
847
+ before do
848
+ # This is on the community site
849
+ policyfile.dsl.cookbook("remote-cb")
850
+ end
851
+
852
+ it "raises an error describing the conflict" do
853
+ repo_path = File.expand_path("path/to/repo")
854
+
855
+ expected_err = <<-ERROR
856
+ Source supermarket(https://supermarket.chef.io) and chef_repo(#{repo_path}) contain conflicting cookbooks:
857
+ - remote-cb
858
+ - remote-cb-two
859
+
860
+ You can set a preferred source to resolve this issue with code like:
861
+
862
+ default_source :supermarket, "https://supermarket.chef.io" do |s|
863
+ s.preferred_for "remote-cb", "remote-cb-two"
864
+ end
865
+ ERROR
866
+
867
+ expect { policyfile.remote_artifacts_graph }.to raise_error do |error|
868
+ expect(error).to be_a(ChefDK::CookbookSourceConflict)
869
+ expect(error.message).to eq(expected_err)
870
+ end
871
+ end
872
+ end
873
+
874
+ context "and the conflicting cookbook has an explicit source in the Policyfile" do
875
+
876
+ before do
877
+ # This is on the community site
878
+ policyfile.dsl.cookbook("remote-cb", path: "path/to/remote-cb")
879
+ policyfile.dsl.cookbook("remote-cb-two", git: "git://git.example:user/remote-cb-two.git")
880
+ policyfile.error!
881
+ end
882
+
883
+ it "solves the graph" do
884
+ expect { policyfile.remote_artifacts_graph }.to_not raise_error
885
+ end
886
+
887
+ it "assigns the correct source options to the cookbook" do
888
+ remote_cb_source_opts = policyfile.cookbook_location_spec_for("remote-cb").source_options
889
+ expect(remote_cb_source_opts).to eq(path: "path/to/remote-cb")
890
+
891
+ remote_cb_two_source_opts = policyfile.cookbook_location_spec_for("remote-cb-two").source_options
892
+ expect(remote_cb_two_source_opts).to eq(git: "git://git.example:user/remote-cb-two.git")
893
+ end
894
+ end
895
+
896
+ context "and the conflicting cookbook has a preferred source" do
897
+
898
+ let(:community_source) { policyfile.dsl.default_source.first }
899
+
900
+ let(:repo_source) { policyfile.dsl.default_source.last }
901
+
902
+ let(:full_universe_graph) do
903
+ {
904
+ "remote-cb" => {
905
+ "1.1.1" => {
906
+ "download_url" => "https://supermarket.chef.io/api/v1/cookbooks/remote-cb/versions/1.1.1/download"
907
+ }
908
+ }
909
+ }
910
+ end
911
+
912
+ let(:cookbook_version_paths) do
913
+ {
914
+ "remote-cb-two" => {
915
+ "1.1.1" => "path/to/repo/remote-cb-two"
916
+ }
917
+ }
918
+ end
919
+
920
+ before do
921
+ community_source.preferred_for 'remote-cb'
922
+ allow(community_source).to receive(:full_community_graph).and_return(full_universe_graph)
923
+ allow(repo_source).to receive(:cookbook_version_paths).and_return(cookbook_version_paths)
924
+ repo_source.preferred_for 'remote-cb-two'
925
+ end
926
+
927
+ it "solves the graph" do
928
+ expect { policyfile.remote_artifacts_graph }.to_not raise_error
929
+ end
930
+
931
+ it "assigns the correct source options to the cookbook" do
932
+ expected_remote_cb_source_opts = {
933
+ artifactserver: "https://supermarket.chef.io/api/v1/cookbooks/remote-cb/versions/1.1.1/download",
934
+ version: "1.1.1"
935
+ }
936
+ actual_remote_cb_source_opts = policyfile.create_spec_for_cookbook("remote-cb", "1.1.1").source_options
937
+ expect(actual_remote_cb_source_opts).to eq(expected_remote_cb_source_opts)
938
+
939
+ expected_remote_cb_two_source_opts = {
940
+ path: "path/to/repo/remote-cb-two",
941
+ version: "1.1.1"
942
+ }
943
+ actual_remote_cb_two_source_opts = policyfile.create_spec_for_cookbook("remote-cb-two", "1.1.1").source_options
944
+ expect(actual_remote_cb_two_source_opts).to eq(expected_remote_cb_two_source_opts)
945
+ end
946
+
947
+ end
948
+
949
+ end
950
+
951
+ context "when top-level cookbooks don't conflict, but dependencies could" do
952
+
953
+ let(:run_list) { [ "dep_on_conflicting_cookbook" ] }
954
+
955
+ it "raises an error describing the conflict" do
956
+ repo_path = File.expand_path("path/to/repo")
957
+
958
+ expected_err = <<-ERROR
959
+ Source supermarket(https://supermarket.chef.io) and chef_repo(#{repo_path}) contain conflicting cookbooks:
960
+ - remote-cb-two
961
+
962
+ You can set a preferred source to resolve this issue with code like:
963
+
964
+ default_source :supermarket, "https://supermarket.chef.io" do |s|
965
+ s.preferred_for "remote-cb-two"
966
+ end
967
+ ERROR
968
+
969
+ expect { policyfile.remote_artifacts_graph }.to raise_error do |error|
970
+ expect(error).to be_a(ChefDK::CookbookSourceConflict)
971
+ expect(error.message).to eq(expected_err)
972
+ end
973
+ end
974
+ end
975
+
976
+ context "when the conflicting cookbook could not be in the solution set" do
977
+
978
+ let(:run_list) { [ 'local_cookbook' ] }
979
+
980
+ it "creates the merged graph without error" do
981
+ expect { policyfile.remote_artifacts_graph }.to_not raise_error
982
+ expect { policyfile.graph }.to_not raise_error
983
+ end
984
+
985
+ it "has an empty set of artifacts for the conflicting cookbook" do
986
+ expect(policyfile.remote_artifacts_graph["remote-cb"]).to eq({})
987
+ expect(policyfile.remote_artifacts_graph["remote-cb-two"]).to eq({})
988
+ end
989
+
990
+ end
991
+
992
+
993
+ end
994
+
995
+ end
996
+
997
+ end