chef-dk 0.13.21 → 0.14.25

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