chef-dk 0.8.0 → 0.9.0

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