chef-dk 2.4.17 → 2.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +121 -119
  3. data/Gemfile.lock +802 -817
  4. data/LICENSE +201 -201
  5. data/README.md +333 -333
  6. data/Rakefile +74 -74
  7. data/acceptance/.shared/kitchen_acceptance/.kitchen.digitalocean.yml +27 -27
  8. data/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml +287 -287
  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 +21 -20
  13. data/acceptance/Gemfile.lock +334 -334
  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/chef-dk.gemspec +60 -60
  24. data/lib/chef-dk.rb +19 -19
  25. data/lib/chef-dk/authenticated_http.rb +22 -22
  26. data/lib/chef-dk/builtin_commands.rb +59 -59
  27. data/lib/chef-dk/chef_runner.rb +114 -114
  28. data/lib/chef-dk/chef_server_api_multi.rb +73 -73
  29. data/lib/chef-dk/cli.rb +201 -201
  30. data/lib/chef-dk/command/base.rb +79 -79
  31. data/lib/chef-dk/command/clean_policy_cookbooks.rb +114 -114
  32. data/lib/chef-dk/command/clean_policy_revisions.rb +111 -111
  33. data/lib/chef-dk/command/delete_policy.rb +120 -120
  34. data/lib/chef-dk/command/delete_policy_group.rb +120 -120
  35. data/lib/chef-dk/command/diff.rb +315 -315
  36. data/lib/chef-dk/command/env.rb +89 -89
  37. data/lib/chef-dk/command/exec.rb +44 -44
  38. data/lib/chef-dk/command/export.rb +155 -155
  39. data/lib/chef-dk/command/gem.rb +47 -47
  40. data/lib/chef-dk/command/generate.rb +125 -125
  41. data/lib/chef-dk/command/generator_commands.rb +83 -83
  42. data/lib/chef-dk/command/generator_commands/app.rb +106 -106
  43. data/lib/chef-dk/command/generator_commands/attribute.rb +36 -36
  44. data/lib/chef-dk/command/generator_commands/base.rb +157 -157
  45. data/lib/chef-dk/command/generator_commands/build_cookbook.rb +125 -125
  46. data/lib/chef-dk/command/generator_commands/chef_exts/generator_desc_resource.rb +85 -85
  47. data/lib/chef-dk/command/generator_commands/chef_exts/quieter_doc_formatter.rb +38 -38
  48. data/lib/chef-dk/command/generator_commands/chef_exts/recipe_dsl_ext.rb +39 -39
  49. data/lib/chef-dk/command/generator_commands/cookbook.rb +241 -241
  50. data/lib/chef-dk/command/generator_commands/cookbook_code_file.rb +100 -100
  51. data/lib/chef-dk/command/generator_commands/cookbook_file.rb +45 -45
  52. data/lib/chef-dk/command/generator_commands/generator_generator.rb +174 -174
  53. data/lib/chef-dk/command/generator_commands/helpers.rb +36 -36
  54. data/lib/chef-dk/command/generator_commands/policyfile.rb +126 -126
  55. data/lib/chef-dk/command/generator_commands/recipe.rb +36 -36
  56. data/lib/chef-dk/command/generator_commands/repo.rb +123 -123
  57. data/lib/chef-dk/command/generator_commands/resource.rb +36 -36
  58. data/lib/chef-dk/command/generator_commands/template.rb +46 -46
  59. data/lib/chef-dk/command/install.rb +120 -120
  60. data/lib/chef-dk/command/provision.rb +436 -436
  61. data/lib/chef-dk/command/push.rb +117 -117
  62. data/lib/chef-dk/command/push_archive.rb +125 -125
  63. data/lib/chef-dk/command/shell_init.rb +179 -179
  64. data/lib/chef-dk/command/show_policy.rb +163 -163
  65. data/lib/chef-dk/command/undelete.rb +154 -154
  66. data/lib/chef-dk/command/update.rb +133 -133
  67. data/lib/chef-dk/command/verify.rb +629 -629
  68. data/lib/chef-dk/commands_map.rb +113 -113
  69. data/lib/chef-dk/completions/bash.sh.erb +5 -5
  70. data/lib/chef-dk/completions/chef.fish.erb +10 -10
  71. data/lib/chef-dk/completions/zsh.zsh.erb +21 -21
  72. data/lib/chef-dk/component_test.rb +227 -227
  73. data/lib/chef-dk/configurable.rb +88 -88
  74. data/lib/chef-dk/cookbook_metadata.rb +45 -45
  75. data/lib/chef-dk/cookbook_omnifetch.rb +32 -32
  76. data/lib/chef-dk/cookbook_profiler/git.rb +151 -151
  77. data/lib/chef-dk/cookbook_profiler/identifiers.rb +72 -72
  78. data/lib/chef-dk/cookbook_profiler/null_scm.rb +31 -31
  79. data/lib/chef-dk/exceptions.rb +150 -150
  80. data/lib/chef-dk/generator.rb +165 -165
  81. data/lib/chef-dk/helpers.rb +176 -176
  82. data/lib/chef-dk/pager.rb +105 -105
  83. data/lib/chef-dk/policyfile/artifactory_cookbook_source.rb +102 -102
  84. data/lib/chef-dk/policyfile/attribute_merge_checker.rb +110 -110
  85. data/lib/chef-dk/policyfile/chef_repo_cookbook_source.rb +138 -138
  86. data/lib/chef-dk/policyfile/chef_server_cookbook_source.rb +99 -99
  87. data/lib/chef-dk/policyfile/chef_server_lock_fetcher.rb +164 -164
  88. data/lib/chef-dk/policyfile/community_cookbook_source.rb +95 -95
  89. data/lib/chef-dk/policyfile/comparison_base.rb +123 -123
  90. data/lib/chef-dk/policyfile/cookbook_location_specification.rb +154 -154
  91. data/lib/chef-dk/policyfile/cookbook_locks.rb +466 -466
  92. data/lib/chef-dk/policyfile/cookbook_sources.rb +23 -23
  93. data/lib/chef-dk/policyfile/delivery_supermarket_source.rb +89 -89
  94. data/lib/chef-dk/policyfile/differ.rb +263 -263
  95. data/lib/chef-dk/policyfile/dsl.rb +288 -288
  96. data/lib/chef-dk/policyfile/included_policies_cookbook_source.rb +156 -156
  97. data/lib/chef-dk/policyfile/lister.rb +229 -229
  98. data/lib/chef-dk/policyfile/local_lock_fetcher.rb +123 -122
  99. data/lib/chef-dk/policyfile/lock_applier.rb +80 -80
  100. data/lib/chef-dk/policyfile/null_cookbook_source.rb +49 -49
  101. data/lib/chef-dk/policyfile/policyfile_location_specification.rb +122 -122
  102. data/lib/chef-dk/policyfile/read_cookbook_for_compat_mode_upload.rb +124 -124
  103. data/lib/chef-dk/policyfile/reports/install.rb +69 -69
  104. data/lib/chef-dk/policyfile/reports/table_printer.rb +57 -57
  105. data/lib/chef-dk/policyfile/reports/upload.rb +70 -70
  106. data/lib/chef-dk/policyfile/solution_dependencies.rb +312 -312
  107. data/lib/chef-dk/policyfile/source_uri.rb +57 -57
  108. data/lib/chef-dk/policyfile/storage_config.rb +102 -102
  109. data/lib/chef-dk/policyfile/undo_record.rb +139 -139
  110. data/lib/chef-dk/policyfile/undo_stack.rb +128 -128
  111. data/lib/chef-dk/policyfile/uploader.rb +213 -213
  112. data/lib/chef-dk/policyfile_compiler.rb +528 -528
  113. data/lib/chef-dk/policyfile_lock.rb +581 -581
  114. data/lib/chef-dk/policyfile_services/clean_policies.rb +95 -95
  115. data/lib/chef-dk/policyfile_services/clean_policy_cookbooks.rb +123 -123
  116. data/lib/chef-dk/policyfile_services/export_repo.rb +420 -420
  117. data/lib/chef-dk/policyfile_services/install.rb +162 -162
  118. data/lib/chef-dk/policyfile_services/push.rb +112 -112
  119. data/lib/chef-dk/policyfile_services/push_archive.rb +200 -200
  120. data/lib/chef-dk/policyfile_services/rm_policy.rb +141 -141
  121. data/lib/chef-dk/policyfile_services/rm_policy_group.rb +85 -85
  122. data/lib/chef-dk/policyfile_services/show_policy.rb +236 -236
  123. data/lib/chef-dk/policyfile_services/undelete.rb +108 -108
  124. data/lib/chef-dk/policyfile_services/update_attributes.rb +110 -110
  125. data/lib/chef-dk/service_exception_inspectors.rb +24 -24
  126. data/lib/chef-dk/service_exception_inspectors/base.rb +39 -39
  127. data/lib/chef-dk/service_exception_inspectors/http.rb +119 -119
  128. data/lib/chef-dk/service_exceptions.rb +142 -142
  129. data/lib/chef-dk/shell_out.rb +36 -36
  130. data/lib/chef-dk/skeletons/code_generator/files/default/Berksfile +4 -4
  131. data/lib/chef-dk/skeletons/code_generator/files/default/build_cookbook/.kitchen.yml +21 -21
  132. data/lib/chef-dk/skeletons/code_generator/files/default/build_cookbook/README.md +146 -146
  133. data/lib/chef-dk/skeletons/code_generator/files/default/build_cookbook/test-fixture-recipe.rb +9 -9
  134. data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +107 -107
  135. data/lib/chef-dk/skeletons/code_generator/files/default/cookbook_readmes/README-policy.md +9 -9
  136. data/lib/chef-dk/skeletons/code_generator/files/default/cookbook_readmes/README.md +54 -54
  137. data/lib/chef-dk/skeletons/code_generator/files/default/delivery-config.json +17 -17
  138. data/lib/chef-dk/skeletons/code_generator/files/default/delivery-project.toml +36 -36
  139. data/lib/chef-dk/skeletons/code_generator/files/default/gitignore +22 -22
  140. data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +24 -24
  141. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/README.md +27 -27
  142. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +8 -8
  143. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/metadata.rb +7 -7
  144. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +9 -9
  145. data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/README.md +56 -56
  146. data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/example/example_item.json +3 -3
  147. data/lib/chef-dk/skeletons/code_generator/files/default/repo/dot-chef-repo.txt +6 -6
  148. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/README.md +9 -9
  149. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/example.json +12 -12
  150. data/lib/chef-dk/skeletons/code_generator/files/default/repo/policies/README.md +24 -24
  151. data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/README.md +9 -9
  152. data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/example.json +12 -12
  153. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper.rb +3 -3
  154. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper_policyfile.rb +3 -3
  155. data/lib/chef-dk/skeletons/code_generator/metadata.rb +8 -8
  156. data/lib/chef-dk/skeletons/code_generator/recipes/app.rb +89 -89
  157. data/lib/chef-dk/skeletons/code_generator/recipes/attribute.rb +13 -13
  158. data/lib/chef-dk/skeletons/code_generator/recipes/build_cookbook.rb +177 -177
  159. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook.rb +152 -152
  160. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook_file.rb +25 -25
  161. data/lib/chef-dk/skeletons/code_generator/recipes/helpers.rb +21 -21
  162. data/lib/chef-dk/skeletons/code_generator/recipes/policyfile.rb +9 -9
  163. data/lib/chef-dk/skeletons/code_generator/recipes/recipe.rb +52 -52
  164. data/lib/chef-dk/skeletons/code_generator/recipes/repo.rb +68 -68
  165. data/lib/chef-dk/skeletons/code_generator/recipes/resource.rb +13 -13
  166. data/lib/chef-dk/skeletons/code_generator/recipes/template.rb +32 -32
  167. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.all_rights.erb +3 -3
  168. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.apachev2.erb +201 -201
  169. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv2.erb +339 -339
  170. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv3.erb +674 -674
  171. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.mit.erb +21 -21
  172. data/lib/chef-dk/skeletons/code_generator/templates/default/Policyfile.rb.erb +25 -25
  173. data/lib/chef-dk/skeletons/code_generator/templates/default/README.md.erb +4 -4
  174. data/lib/chef-dk/skeletons/code_generator/templates/default/build_cookbook/Berksfile.erb +7 -7
  175. data/lib/chef-dk/skeletons/code_generator/templates/default/build_cookbook/metadata.rb.erb +10 -10
  176. data/lib/chef-dk/skeletons/code_generator/templates/default/build_cookbook/recipe.rb.erb +8 -8
  177. data/lib/chef-dk/skeletons/code_generator/templates/default/helpers.rb.erb +39 -39
  178. data/lib/chef-dk/skeletons/code_generator/templates/default/inspec_default_test.rb.erb +18 -18
  179. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen.yml.erb +26 -26
  180. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen_policyfile.yml.erb +33 -33
  181. data/lib/chef-dk/skeletons/code_generator/templates/default/metadata.rb.erb +20 -20
  182. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe.rb.erb +5 -5
  183. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe_spec.rb.erb +35 -35
  184. data/lib/chef-dk/skeletons/code_generator/templates/default/repo/gitignore.erb +128 -128
  185. data/lib/chef-dk/skeletons/code_generator/templates/default/resource.rb.erb +1 -1
  186. data/lib/chef-dk/ui.rb +57 -57
  187. data/lib/chef-dk/version.rb +20 -20
  188. data/lib/kitchen/provisioner/policyfile_zero.rb +195 -195
  189. data/omnibus_overrides.rb +22 -22
  190. data/spec/shared/a_file_generator.rb +125 -125
  191. data/spec/shared/a_generated_file.rb +12 -12
  192. data/spec/shared/command_with_ui_object.rb +11 -11
  193. data/spec/shared/custom_generator_cookbook.rb +136 -136
  194. data/spec/shared/fixture_cookbook_checksums.rb +46 -46
  195. data/spec/shared/setup_git_committer_config.rb +54 -54
  196. data/spec/shared/setup_git_cookbooks.rb +53 -53
  197. data/spec/spec_helper.rb +51 -51
  198. data/spec/test_helpers.rb +84 -84
  199. data/spec/unit/chef_runner_spec.rb +139 -139
  200. data/spec/unit/chef_server_api_multi_spec.rb +120 -120
  201. data/spec/unit/cli_spec.rb +377 -377
  202. data/spec/unit/command/base_spec.rb +172 -172
  203. data/spec/unit/command/clean_policy_cookbooks_spec.rb +180 -180
  204. data/spec/unit/command/clean_policy_revisions_spec.rb +180 -180
  205. data/spec/unit/command/delete_policy_group_spec.rb +206 -206
  206. data/spec/unit/command/delete_policy_spec.rb +206 -206
  207. data/spec/unit/command/diff_spec.rb +311 -311
  208. data/spec/unit/command/env_spec.rb +52 -52
  209. data/spec/unit/command/exec_spec.rb +178 -178
  210. data/spec/unit/command/export_spec.rb +199 -199
  211. data/spec/unit/command/generate_spec.rb +142 -142
  212. data/spec/unit/command/generator_commands/app_spec.rb +166 -166
  213. data/spec/unit/command/generator_commands/attribute_spec.rb +31 -31
  214. data/spec/unit/command/generator_commands/base_spec.rb +181 -181
  215. data/spec/unit/command/generator_commands/build_cookbook_spec.rb +377 -377
  216. data/spec/unit/command/generator_commands/chef_exts/generator_desc_resource_spec.rb +97 -97
  217. data/spec/unit/command/generator_commands/chef_exts/recipe_dsl_ext_spec.rb +111 -111
  218. data/spec/unit/command/generator_commands/cookbook_file_spec.rb +31 -31
  219. data/spec/unit/command/generator_commands/cookbook_spec.rb +756 -756
  220. data/spec/unit/command/generator_commands/generator_generator_spec.rb +227 -227
  221. data/spec/unit/command/generator_commands/helpers_spec.rb +31 -31
  222. data/spec/unit/command/generator_commands/policyfile_spec.rb +223 -223
  223. data/spec/unit/command/generator_commands/recipe_spec.rb +37 -37
  224. data/spec/unit/command/generator_commands/repo_spec.rb +374 -374
  225. data/spec/unit/command/generator_commands/resource_spec.rb +31 -31
  226. data/spec/unit/command/generator_commands/template_spec.rb +31 -31
  227. data/spec/unit/command/install_spec.rb +179 -179
  228. data/spec/unit/command/provision_spec.rb +589 -589
  229. data/spec/unit/command/push_archive_spec.rb +153 -153
  230. data/spec/unit/command/push_spec.rb +198 -198
  231. data/spec/unit/command/shell_init_spec.rb +339 -339
  232. data/spec/unit/command/show_policy_spec.rb +234 -234
  233. data/spec/unit/command/undelete_spec.rb +244 -244
  234. data/spec/unit/command/update_spec.rb +283 -283
  235. data/spec/unit/command/verify_spec.rb +341 -341
  236. data/spec/unit/commands_map_spec.rb +57 -57
  237. data/spec/unit/component_test_spec.rb +128 -128
  238. data/spec/unit/configurable_spec.rb +68 -68
  239. data/spec/unit/cookbook_metadata_spec.rb +96 -96
  240. data/spec/unit/cookbook_profiler/git_spec.rb +176 -176
  241. data/spec/unit/cookbook_profiler/identifiers_spec.rb +81 -81
  242. data/spec/unit/fixtures/chef-runner-cookbooks/test_cookbook/recipes/recipe_one.rb +9 -9
  243. data/spec/unit/fixtures/chef-runner-cookbooks/test_cookbook/recipes/recipe_two.rb +9 -9
  244. data/spec/unit/fixtures/command/cli_test_command.rb +26 -26
  245. data/spec/unit/fixtures/command/explicit_path_example.rb +7 -7
  246. data/spec/unit/fixtures/configurable/test_config_loader.rb +5 -5
  247. data/spec/unit/fixtures/configurable/test_configurable.rb +10 -10
  248. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/.kitchen.yml +16 -16
  249. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/Berksfile +3 -3
  250. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/README.md +4 -4
  251. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/chefignore +96 -96
  252. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/metadata.rb +8 -8
  253. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/recipes/default.rb +8 -8
  254. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/.kitchen.yml +16 -16
  255. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/Berksfile +3 -3
  256. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/README.md +4 -4
  257. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/chefignore +96 -96
  258. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/metadata.rb +8 -8
  259. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/recipes/default.rb +8 -8
  260. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/.kitchen.yml +16 -16
  261. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/Berksfile +3 -3
  262. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/README.md +4 -4
  263. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/chefignore +96 -96
  264. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/metadata.rb +8 -8
  265. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/recipes/default.rb +8 -8
  266. data/spec/unit/fixtures/cookbooks_api/chef_server_universe.json +56 -56
  267. data/spec/unit/fixtures/cookbooks_api/pruned_chef_server_universe.json +30 -30
  268. data/spec/unit/fixtures/cookbooks_api/pruned_small_universe.json +1321 -1321
  269. data/spec/unit/fixtures/cookbooks_api/small_universe.json +2987 -2987
  270. data/spec/unit/fixtures/cookbooks_api/universe.json +1 -1
  271. data/spec/unit/fixtures/cookbooks_api/update_fixtures.rb +33 -33
  272. data/spec/unit/fixtures/dev_cookbooks/README.md +16 -16
  273. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/berkshelf/integration_test +2 -2
  274. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/berkshelf/verify_me +5 -5
  275. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/chef/verify_me +3 -3
  276. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/test-kitchen/verify_me +2 -2
  277. data/spec/unit/fixtures/example_cookbook/.gitignore +17 -17
  278. data/spec/unit/fixtures/example_cookbook/.kitchen.yml +16 -16
  279. data/spec/unit/fixtures/example_cookbook/Berksfile +3 -3
  280. data/spec/unit/fixtures/example_cookbook/README.md +4 -4
  281. data/spec/unit/fixtures/example_cookbook/chefignore +96 -96
  282. data/spec/unit/fixtures/example_cookbook/metadata.rb +8 -8
  283. data/spec/unit/fixtures/example_cookbook/recipes/default.rb +8 -8
  284. data/spec/unit/fixtures/example_cookbook_metadata_json_only/.gitignore +17 -17
  285. data/spec/unit/fixtures/example_cookbook_metadata_json_only/.kitchen.yml +16 -16
  286. data/spec/unit/fixtures/example_cookbook_metadata_json_only/Berksfile +3 -3
  287. data/spec/unit/fixtures/example_cookbook_metadata_json_only/README.md +4 -4
  288. data/spec/unit/fixtures/example_cookbook_metadata_json_only/chefignore +96 -96
  289. data/spec/unit/fixtures/example_cookbook_metadata_json_only/metadata.json +5 -5
  290. data/spec/unit/fixtures/example_cookbook_metadata_json_only/recipes/default.rb +8 -8
  291. data/spec/unit/fixtures/example_cookbook_no_metadata/.gitignore +17 -17
  292. data/spec/unit/fixtures/example_cookbook_no_metadata/.kitchen.yml +16 -16
  293. data/spec/unit/fixtures/example_cookbook_no_metadata/Berksfile +3 -3
  294. data/spec/unit/fixtures/example_cookbook_no_metadata/README.md +4 -4
  295. data/spec/unit/fixtures/example_cookbook_no_metadata/chefignore +96 -96
  296. data/spec/unit/fixtures/example_cookbook_no_metadata/recipes/default.rb +8 -8
  297. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/README.md +4 -4
  298. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/chefignore +96 -96
  299. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/metadata.rb +8 -8
  300. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/recipes/default.rb +8 -8
  301. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/Berksfile +3 -3
  302. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/README.md +4 -4
  303. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/chefignore +96 -96
  304. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/metadata.rb +9 -9
  305. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/recipes/default.rb +8 -8
  306. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/.kitchen.yml +16 -16
  307. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/Berksfile +3 -3
  308. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/README.md +4 -4
  309. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/chefignore +96 -96
  310. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/metadata.rb +8 -8
  311. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/recipes/default.rb +8 -8
  312. data/spec/unit/fixtures/local_path_cookbooks/metadata-missing/README.md +2 -2
  313. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/.kitchen.yml +16 -16
  314. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/README.md +4 -4
  315. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/metadata.rb +8 -8
  316. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/recipes/default.rb +8 -8
  317. data/spec/unit/generator_spec.rb +119 -119
  318. data/spec/unit/pager_spec.rb +117 -117
  319. data/spec/unit/policyfile/artifactory_cookbook_source_spec.rb +59 -59
  320. data/spec/unit/policyfile/attribute_merge_checker_spec.rb +80 -80
  321. data/spec/unit/policyfile/chef_repo_cookbook_source_spec.rb +93 -93
  322. data/spec/unit/policyfile/chef_server_cookbook_source_spec.rb +55 -55
  323. data/spec/unit/policyfile/chef_server_lock_fetcher_spec.rb +161 -161
  324. data/spec/unit/policyfile/community_cookbook_source_spec.rb +83 -83
  325. data/spec/unit/policyfile/comparison_base_spec.rb +340 -340
  326. data/spec/unit/policyfile/cookbook_location_specification_spec.rb +347 -347
  327. data/spec/unit/policyfile/cookbook_locks_spec.rb +527 -527
  328. data/spec/unit/policyfile/delivery_supermarket_source_spec.rb +129 -129
  329. data/spec/unit/policyfile/differ_spec.rb +686 -686
  330. data/spec/unit/policyfile/included_policies_cookbook_source_spec.rb +242 -242
  331. data/spec/unit/policyfile/lister_spec.rb +268 -268
  332. data/spec/unit/policyfile/local_lock_fetcher_spec.rb +173 -161
  333. data/spec/unit/policyfile/lock_applier_spec.rb +100 -100
  334. data/spec/unit/policyfile/null_cookbook_source_spec.rb +34 -34
  335. data/spec/unit/policyfile/read_cookbook_for_compat_mode_upload_spec.rb +92 -92
  336. data/spec/unit/policyfile/reports/install_spec.rb +114 -114
  337. data/spec/unit/policyfile/reports/upload_spec.rb +94 -94
  338. data/spec/unit/policyfile/solution_dependencies_spec.rb +170 -170
  339. data/spec/unit/policyfile/source_uri_spec.rb +36 -36
  340. data/spec/unit/policyfile/storage_config_spec.rb +180 -180
  341. data/spec/unit/policyfile/undo_record_spec.rb +258 -258
  342. data/spec/unit/policyfile/undo_stack_spec.rb +265 -265
  343. data/spec/unit/policyfile/uploader_spec.rb +409 -409
  344. data/spec/unit/policyfile_demands_spec.rb +1197 -1197
  345. data/spec/unit/policyfile_evaluation_spec.rb +638 -638
  346. data/spec/unit/policyfile_includes_dsl_spec.rb +159 -159
  347. data/spec/unit/policyfile_includes_spec.rb +720 -720
  348. data/spec/unit/policyfile_install_with_includes_spec.rb +232 -232
  349. data/spec/unit/policyfile_lock_build_spec.rb +1065 -1065
  350. data/spec/unit/policyfile_lock_install_spec.rb +137 -137
  351. data/spec/unit/policyfile_lock_serialization_spec.rb +424 -424
  352. data/spec/unit/policyfile_lock_validation_spec.rb +608 -608
  353. data/spec/unit/policyfile_services/clean_policies_spec.rb +236 -236
  354. data/spec/unit/policyfile_services/clean_policy_cookbooks_spec.rb +272 -272
  355. data/spec/unit/policyfile_services/export_repo_spec.rb +478 -478
  356. data/spec/unit/policyfile_services/install_spec.rb +209 -209
  357. data/spec/unit/policyfile_services/push_archive_spec.rb +374 -374
  358. data/spec/unit/policyfile_services/push_spec.rb +249 -249
  359. data/spec/unit/policyfile_services/rm_policy_group_spec.rb +237 -237
  360. data/spec/unit/policyfile_services/rm_policy_spec.rb +263 -263
  361. data/spec/unit/policyfile_services/show_policy_spec.rb +887 -887
  362. data/spec/unit/policyfile_services/undelete_spec.rb +302 -302
  363. data/spec/unit/policyfile_services/update_attributes_spec.rb +229 -229
  364. data/spec/unit/policyfile_services/update_spec.rb +140 -140
  365. data/spec/unit/service_exception_inspectors/base_spec.rb +41 -41
  366. data/spec/unit/service_exception_inspectors/http_spec.rb +138 -138
  367. data/spec/unit/shell_out_spec.rb +34 -34
  368. data/tasks/announce.rb +57 -57
  369. data/tasks/bin/bundle-platform.bat +2 -2
  370. data/tasks/dependencies.rb +89 -89
  371. data/tasks/templates/prerelease.md.erb +35 -35
  372. data/tasks/templates/release.md.erb +34 -34
  373. data/warning.txt +9 -9
  374. metadata +5 -5
@@ -1,1065 +1,1065 @@
1
- # -*- coding: UTF-8 -*-
2
- #
3
- # Copyright:: Copyright (c) 2014 Chef Software Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require "spec_helper"
20
- require "shared/setup_git_cookbooks"
21
- require "shared/fixture_cookbook_checksums"
22
- require "chef-dk/policyfile/storage_config"
23
- require "chef-dk/policyfile_lock.rb"
24
-
25
- describe ChefDK::PolicyfileLock, "building a lockfile" do
26
-
27
- include_context "fixture cookbooks checksums"
28
-
29
- # For debugging giant nested hashes...
30
- def expect_hash_equal(actual, expected)
31
- expected.each do |key, expected_value|
32
- expect(actual).to have_key(key)
33
- if expected_value.kind_of?(Hash)
34
- expect_hash_equal(actual[key], expected_value)
35
- else
36
- expect(actual[key]).to eq(expected_value)
37
- end
38
- end
39
- expect(actual).to eq(expected)
40
- end
41
-
42
- let(:cache_path) do
43
- File.expand_path("spec/unit/fixtures/cookbook_cache", project_root)
44
- end
45
-
46
- let(:relative_paths_root) do
47
- File.expand_path("spec/unit/fixtures/", project_root)
48
- end
49
-
50
- let(:storage_config) do
51
- ChefDK::Policyfile::StorageConfig.new( cache_path: cache_path, relative_paths_root: relative_paths_root )
52
- end
53
-
54
- context "when a cached cookbook omits the cache key" do
55
-
56
- let(:policyfile_lock) do
57
- ChefDK::PolicyfileLock.build(storage_config) do |p|
58
-
59
- p.name = "invalid_cache_key_policyfile"
60
-
61
- p.run_list = [ "recipe[foo]" ]
62
-
63
- p.cached_cookbook("nosuchthing") do |cb|
64
- end
65
- end
66
- end
67
-
68
- it "raises a descriptive error" do
69
- expect { policyfile_lock.to_lock }.to raise_error(ChefDK::CachedCookbookNotFound)
70
- end
71
-
72
- end
73
-
74
- context "when a local cookbook omits the path" do
75
-
76
- let(:policyfile_lock) do
77
- ChefDK::PolicyfileLock.build(storage_config) do |p|
78
-
79
- p.name = "invalid_local_cookbook"
80
-
81
- p.run_list = [ "recipe[foo]" ]
82
-
83
- p.local_cookbook("nosuchthing") do |cb|
84
- end
85
- end
86
- end
87
-
88
- it "raises a descriptive error" do
89
- expect { policyfile_lock.to_lock }.to raise_error(ChefDK::LocalCookbookNotFound)
90
- end
91
- end
92
-
93
- context "when a local cookbook has an incorrect path" do
94
-
95
- let(:policyfile_lock) do
96
- ChefDK::PolicyfileLock.build(storage_config) do |p|
97
-
98
- p.name = "invalid_local_cookbook"
99
-
100
- p.run_list = [ "recipe[foo]" ]
101
-
102
- p.local_cookbook("nosuchthing") do |cb|
103
- cb.source = "nopenopenope"
104
- end
105
- end
106
- end
107
-
108
- it "raises a descriptive error" do
109
- expect { policyfile_lock.to_lock }.to raise_error(ChefDK::LocalCookbookNotFound)
110
- end
111
- end
112
-
113
- context "when a cookbook is not in the cache" do
114
-
115
- let(:policyfile_lock) do
116
- ChefDK::PolicyfileLock.build(storage_config) do |p|
117
-
118
- p.name = "invalid_cache_key_policyfile"
119
-
120
- p.run_list = [ "recipe[foo]" ]
121
-
122
- p.cached_cookbook("nosuchthing") do |cb|
123
- cb.cache_key = "nosuchthing-1.0.0"
124
- end
125
- end
126
- end
127
-
128
- it "raises a descriptive error" do
129
- expect { policyfile_lock.to_lock }.to raise_error(ChefDK::CachedCookbookNotFound)
130
- end
131
-
132
- end
133
-
134
- describe "policyfiles with invalid attributes" do
135
-
136
- let(:policyfile_lock) do
137
- ChefDK::PolicyfileLock.build(storage_config) do |p|
138
-
139
- p.name = "invalid_cache_key_policyfile"
140
-
141
- p.run_list = [ "recipe[foo]" ]
142
-
143
- p.cached_cookbook("foo") do |cb|
144
- cb.cache_key = "foo-1.0.0"
145
- end
146
-
147
- p.default_attributes = default_attributes
148
- end
149
- end
150
-
151
- context "invalid floats - infinity" do
152
-
153
- let(:default_attributes) { { "infinity" => Float::INFINITY } }
154
-
155
- it "raises a descriptive error" do
156
- expect { policyfile_lock.to_lock }.to raise_error(ChefDK::InvalidPolicyfileAttribute)
157
- end
158
- end
159
-
160
- context "invalid floats - nan" do
161
-
162
- let(:default_attributes) { { "infinity" => Float::NAN } }
163
-
164
- it "raises a descriptive error" do
165
- expect { policyfile_lock.to_lock }.to raise_error(ChefDK::InvalidPolicyfileAttribute)
166
- end
167
- end
168
-
169
- context "non-string hash/object keys" do
170
-
171
- let(:default_attributes) { { 1906 => "lol nope" } }
172
-
173
- it "raises a descriptive error" do
174
- expect { policyfile_lock.to_lock }.to raise_error(ChefDK::InvalidPolicyfileAttribute)
175
- end
176
- end
177
-
178
- context "values that are not Hash/Array/String/Float/Integer/true/false/nil" do
179
-
180
- let(:default_attributes) { { "raw object" => Object.new } }
181
-
182
- it "raises a descriptive error" do
183
- expect { policyfile_lock.to_lock }.to raise_error(ChefDK::InvalidPolicyfileAttribute)
184
- end
185
- end
186
-
187
- end
188
-
189
- context "with a minimal policyfile" do
190
-
191
- let(:policyfile_lock) do
192
- ChefDK::PolicyfileLock.build(storage_config) do |p|
193
-
194
- p.name = "minimal_policyfile"
195
-
196
- p.run_list = [ "recipe[foo]" ]
197
- p.cached_cookbook("foo") do |cb|
198
- cb.cache_key = "foo-1.0.0"
199
- end
200
-
201
- end
202
- end
203
-
204
- let(:expected_canonical_revision_string) do
205
- <<-REVISION_STRING
206
- name:minimal_policyfile
207
- run-list-item:recipe[foo]
208
- cookbook:foo;id:467dc855408ce8b74f991c5dc2fd72a6aa369b60
209
- default_attributes:{}
210
- override_attributes:{}
211
- REVISION_STRING
212
- end
213
-
214
- let(:expected_revision_id) do
215
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
216
- end
217
-
218
- let(:compiled_policyfile) do
219
- {
220
- "revision_id" => expected_revision_id,
221
-
222
- "name" => "minimal_policyfile",
223
-
224
- "run_list" => ["recipe[foo]"],
225
-
226
- "cookbook_locks" => {
227
-
228
- "foo" => {
229
- "version" => "1.0.0",
230
- "identifier" => cookbook_foo_cksum,
231
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
232
- "cache_key" => "foo-1.0.0",
233
- "origin" => nil,
234
- "source_options" => nil,
235
- },
236
- },
237
- "default_attributes" => {},
238
- "override_attributes" => {},
239
-
240
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
241
- "included_policy_locks" => [],
242
- }
243
- end
244
-
245
- it "has a cache path" do
246
- expect(policyfile_lock.cache_path).to eq(cache_path)
247
- end
248
-
249
- it "computes a minimal policyfile" do
250
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
251
- end
252
-
253
- it "generates a canonical revision string" do
254
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
255
- end
256
-
257
- it "generates a revision id" do
258
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
259
- end
260
-
261
- end
262
-
263
- context "with a policyfile containing attributes" do
264
-
265
- let(:policyfile_lock) do
266
- ChefDK::PolicyfileLock.build(storage_config) do |p|
267
-
268
- p.name = "minimal_policyfile"
269
-
270
- p.run_list = [ "recipe[foo]" ]
271
- p.cached_cookbook("foo") do |cb|
272
- cb.cache_key = "foo-1.0.0"
273
- end
274
-
275
- p.default_attributes = {
276
- "foo" => "bar",
277
- "aaa".encode("utf-16") => "aaa".encode("utf-16"),
278
- "ddd" => true,
279
- "ccc" => false,
280
- "bbb" => nil,
281
- "e" => 1.2,
282
- "f" => 5,
283
- "g" => 1_000_000_000_000_000.0,
284
- "nested" => { "a" => "b" },
285
- }
286
- p.override_attributes = { "foo2" => "baz" }
287
-
288
- end
289
- end
290
-
291
- let(:expected_canonical_revision_string) do
292
- <<-REVISION_STRING
293
- name:minimal_policyfile
294
- run-list-item:recipe[foo]
295
- cookbook:foo;id:467dc855408ce8b74f991c5dc2fd72a6aa369b60
296
- default_attributes:{"aaa":"aaa","bbb":null,"ccc":false,"ddd":true,"e":1.2,"f":5,"foo":"bar","g":1e+15,"nested":{"a":"b"}}
297
- override_attributes:{"foo2":"baz"}
298
- REVISION_STRING
299
- end
300
-
301
- let(:expected_revision_id) do
302
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
303
- end
304
-
305
- let(:compiled_policyfile) do
306
- {
307
- "revision_id" => expected_revision_id,
308
-
309
- "name" => "minimal_policyfile",
310
-
311
- "run_list" => ["recipe[foo]"],
312
-
313
- "cookbook_locks" => {
314
-
315
- "foo" => {
316
- "version" => "1.0.0",
317
- "identifier" => cookbook_foo_cksum,
318
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
319
- "cache_key" => "foo-1.0.0",
320
- "origin" => nil,
321
- "source_options" => nil,
322
- },
323
- },
324
- "default_attributes" => {
325
- "foo" => "bar",
326
- "aaa".encode("utf-16") => "aaa".encode("utf-16"),
327
- "ddd" => true,
328
- "ccc" => false,
329
- "bbb" => nil,
330
- "e" => 1.2,
331
- "f" => 5,
332
- "g" => 1_000_000_000_000_000.0,
333
- "nested" => { "a" => "b" },
334
- },
335
- "override_attributes" => { "foo2" => "baz" },
336
-
337
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
338
- "included_policy_locks" => [],
339
- }
340
- end
341
-
342
- it "has a cache path" do
343
- expect(policyfile_lock.cache_path).to eq(cache_path)
344
- end
345
-
346
- it "computes a minimal policyfile" do
347
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
348
- end
349
-
350
- it "generates a canonical revision string" do
351
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
352
- end
353
-
354
- it "generates a revision id" do
355
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
356
- end
357
-
358
- end
359
-
360
- context "with a policyfile containing a local cookbook" do
361
-
362
- include_context "setup git cookbooks"
363
- include_context "setup git cookbook remote"
364
-
365
- let(:relative_paths_root) do
366
- tempdir
367
- end
368
-
369
- let(:policyfile_lock) do
370
- ChefDK::PolicyfileLock.build(storage_config) do |p|
371
-
372
- p.name = "dev_cookbook"
373
-
374
- p.run_list = [ "recipe[bar]" ]
375
- p.local_cookbook("bar") do |cb|
376
- cb.source = "bar"
377
- end
378
-
379
- end
380
- end
381
-
382
- let(:expected_canonical_revision_string) do
383
- <<-REVISION_STRING
384
- name:dev_cookbook
385
- run-list-item:recipe[bar]
386
- cookbook:bar;id:#{cookbook_bar_cksum}
387
- default_attributes:{}
388
- override_attributes:{}
389
- REVISION_STRING
390
- end
391
-
392
- let(:expected_revision_id) do
393
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
394
- end
395
-
396
- let(:compiled_policyfile) do
397
- {
398
-
399
- "revision_id" => expected_revision_id,
400
-
401
- "name" => "dev_cookbook",
402
-
403
- "run_list" => ["recipe[bar]"],
404
-
405
- "cookbook_locks" => {
406
-
407
- "bar" => {
408
- "version" => "0.1.0",
409
- "identifier" => cookbook_bar_cksum,
410
- "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
411
-
412
- "source" => "bar",
413
- "cache_key" => nil,
414
- "scm_info" => {
415
- "scm" => "git",
416
- "remote" => remote_url,
417
- "revision" => current_rev,
418
- "working_tree_clean" => true,
419
- "published" => true,
420
- "synchronized_remote_branches" => ["origin/master"],
421
- },
422
- "source_options" => nil,
423
- },
424
- },
425
-
426
- "default_attributes" => {},
427
- "override_attributes" => {},
428
-
429
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
430
- "included_policy_locks" => [],
431
- }
432
- end
433
-
434
- it "computes a lockfile including git data" do
435
- actual_lock = policyfile_lock.to_lock
436
- expect(actual_lock).to eq(compiled_policyfile)
437
- end
438
-
439
- it "generates a canonical revision string" do
440
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
441
- end
442
-
443
- it "generates a revision id" do
444
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
445
- end
446
-
447
- end
448
-
449
- context "with a policyfile using custom identifiers" do
450
-
451
- include_context "setup git cookbooks"
452
-
453
- let(:relative_paths_root) do
454
- tempdir
455
- end
456
-
457
- let(:policyfile_lock) do
458
- ChefDK::PolicyfileLock.build(storage_config) do |p|
459
-
460
- p.name = "custom_identifier"
461
-
462
- p.run_list = [ "recipe[foo]" ]
463
-
464
- p.cached_cookbook("foo") do |cb|
465
- cb.cache_key = "foo-1.0.0"
466
-
467
- # Explicitly set the identifier and dotted decimal identifiers to the
468
- # version number (but it could be anything).
469
- cb.identifier = "1.0.0"
470
- cb.dotted_decimal_identifier = "1.0.0"
471
- end
472
-
473
- p.local_cookbook("bar") do |cb|
474
- cb.source = "bar"
475
- cb.identifier = "0.1.0"
476
- cb.dotted_decimal_identifier = "0.1.0"
477
- end
478
- end
479
-
480
- end
481
-
482
- let(:expected_canonical_revision_string) do
483
- <<-REVISION_STRING
484
- name:custom_identifier
485
- run-list-item:recipe[foo]
486
- cookbook:bar;id:0.1.0
487
- cookbook:foo;id:1.0.0
488
- default_attributes:{}
489
- override_attributes:{}
490
- REVISION_STRING
491
- end
492
-
493
- let(:expected_revision_id) do
494
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
495
- end
496
-
497
- let(:compiled_policyfile) do
498
- {
499
-
500
- "revision_id" => expected_revision_id,
501
-
502
- "name" => "custom_identifier",
503
-
504
- "run_list" => ["recipe[foo]"],
505
-
506
- "cookbook_locks" => {
507
-
508
- "bar" => {
509
- "version" => "0.1.0",
510
- "identifier" => "0.1.0",
511
- "dotted_decimal_identifier" => "0.1.0",
512
-
513
- "source" => "bar",
514
- "cache_key" => nil,
515
- "scm_info" => {
516
- "scm" => "git",
517
- "remote" => nil,
518
- "revision" => current_rev,
519
- "working_tree_clean" => true,
520
- "published" => false,
521
- "synchronized_remote_branches" => [],
522
- },
523
- "source_options" => nil,
524
- },
525
-
526
- "foo" => {
527
- "version" => "1.0.0",
528
- "identifier" => "1.0.0",
529
- "dotted_decimal_identifier" => "1.0.0",
530
- "cache_key" => "foo-1.0.0",
531
- "origin" => nil,
532
- "source_options" => nil,
533
- },
534
-
535
- },
536
-
537
- "default_attributes" => {},
538
- "override_attributes" => {},
539
-
540
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
541
- "included_policy_locks" => [],
542
- }
543
- end
544
-
545
- it "generates a lockfile with custom identifiers" do
546
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
547
- end
548
-
549
- it "generates a canonical revision string" do
550
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
551
- end
552
-
553
- it "generates a revision id" do
554
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
555
- end
556
-
557
- end
558
-
559
- context "with a policyfile lock with a mix of cached and local cookbooks" do
560
-
561
- include_context "setup git cookbooks"
562
-
563
- let(:relative_paths_root) do
564
- tempdir
565
- end
566
-
567
- let(:policyfile_lock) do
568
-
569
- ChefDK::PolicyfileLock.build(storage_config) do |p|
570
-
571
- # Required
572
- p.name = "basic_example"
573
-
574
- # Required. Should be fully expanded without roles
575
- p.run_list = ["recipe[foo]", "recipe[bar]", "recipe[baz::non_default]"]
576
-
577
- # A cached_cookbook is stored in the cache directory in a subdirectory
578
- # given by 'cache_key'. It is assumed to be static (not modified by the
579
- # user).
580
- p.cached_cookbook("foo") do |cb|
581
- cb.cache_key = "foo-1.0.0"
582
-
583
- # Optional attribute that humans can use to understand where a cookbook
584
- # came from.
585
- cb.origin = "https://community.chef.io/api/cookbooks/foo/1.0.0"
586
- end
587
-
588
- p.local_cookbook("bar") do |cb|
589
- cb.source = "bar"
590
- end
591
-
592
- p.cached_cookbook("baz") do |cb|
593
- cb.cache_key = "baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb"
594
- cb.origin = "git://github.com/chef-cookbooks/bar.git"
595
- end
596
-
597
- p.cached_cookbook("dep_of_bar") do |cb|
598
- cb.cache_key = "dep_of_bar-1.2.3"
599
- cb.origin = "https://chef-server.example.com/cookbooks/dep_of_bar/1.2.3"
600
- end
601
- end
602
-
603
- end
604
-
605
- let(:expected_canonical_revision_string) do
606
- <<-REVISION_STRING
607
- name:basic_example
608
- run-list-item:recipe[foo]
609
- run-list-item:recipe[bar]
610
- run-list-item:recipe[baz::non_default]
611
- cookbook:bar;id:#{cookbook_bar_cksum}
612
- cookbook:baz;id:#{cookbook_baz_cksum}
613
- cookbook:dep_of_bar;id:#{cookbook_dep_of_bar_cksum}
614
- cookbook:foo;id:#{cookbook_foo_cksum}
615
- default_attributes:{}
616
- override_attributes:{}
617
- REVISION_STRING
618
- end
619
-
620
- let(:expected_revision_id) do
621
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
622
- end
623
-
624
- let(:compiled_policyfile) do
625
- {
626
-
627
- "revision_id" => expected_revision_id,
628
-
629
- "name" => "basic_example",
630
-
631
- "run_list" => ["recipe[foo]", "recipe[bar]", "recipe[baz::non_default]"],
632
-
633
- "cookbook_locks" => {
634
-
635
- "bar" => {
636
- "version" => "0.1.0",
637
- "identifier" => cookbook_bar_cksum,
638
- "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
639
- "source" => "bar",
640
- "cache_key" => nil,
641
-
642
- "scm_info" => {
643
- "scm" => "git",
644
- "remote" => nil,
645
- "revision" => current_rev,
646
- "working_tree_clean" => true,
647
- "published" => false,
648
- "synchronized_remote_branches" => [],
649
- },
650
- "source_options" => nil,
651
- },
652
-
653
- "baz" => {
654
- "version" => "1.2.3",
655
- "identifier" => cookbook_baz_cksum,
656
- "dotted_decimal_identifier" => cookbook_baz_cksum_dotted,
657
- "cache_key" => "baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb",
658
- "origin" => "git://github.com/chef-cookbooks/bar.git",
659
- "source_options" => nil,
660
- },
661
-
662
- "dep_of_bar" => {
663
- "version" => "1.2.3",
664
- "identifier" => cookbook_dep_of_bar_cksum,
665
- "dotted_decimal_identifier" => cookbook_dep_of_bar_cksum_dotted,
666
- "origin" => "https://chef-server.example.com/cookbooks/dep_of_bar/1.2.3",
667
- "cache_key" => "dep_of_bar-1.2.3",
668
- "source_options" => nil,
669
-
670
- },
671
-
672
- "foo" => {
673
- "version" => "1.0.0",
674
- "identifier" => cookbook_foo_cksum,
675
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
676
- "origin" => "https://community.chef.io/api/cookbooks/foo/1.0.0",
677
- "cache_key" => "foo-1.0.0",
678
- "source_options" => nil,
679
- },
680
-
681
- },
682
-
683
- "default_attributes" => {},
684
- "override_attributes" => {},
685
-
686
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
687
- "included_policy_locks" => [],
688
- }
689
- end
690
-
691
- it "generates a lockfile with the relevant profile data for each cookbook" do
692
- generated = policyfile_lock.to_lock
693
- expect(generated["name"]).to eq(compiled_policyfile["name"])
694
- expect(generated["run_list"]).to eq(compiled_policyfile["run_list"])
695
-
696
- generated_locks = generated["cookbook_locks"]
697
- expected_locks = compiled_policyfile["cookbook_locks"]
698
-
699
- # test individually so failures are easier to read
700
- expect(generated_locks["foo"]).to eq(expected_locks["foo"])
701
- expect(generated_locks["bar"]).to eq(expected_locks["bar"])
702
- expect(generated_locks["baz"]).to eq(expected_locks["baz"])
703
- expect(generated_locks["dep_of_bar"]).to eq(expected_locks["dep_of_bar"])
704
-
705
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
706
- end
707
-
708
- it "generates a canonical revision string" do
709
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
710
- end
711
-
712
- it "generates a revision id" do
713
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
714
- end
715
-
716
- end
717
-
718
- context "with solution dependencies specified" do
719
-
720
- let(:policyfile_lock) do
721
- ChefDK::PolicyfileLock.build(storage_config) do |p|
722
-
723
- p.name = "minimal_policyfile"
724
-
725
- p.run_list = [ "recipe[foo]" ]
726
- p.cached_cookbook("foo") do |cb|
727
- cb.cache_key = "foo-1.0.0"
728
- end
729
-
730
- p.dependencies do |deps|
731
- deps.add_cookbook_dep("foo", "1.0.0", [])
732
- end
733
-
734
- end
735
- end
736
-
737
- let(:expected_canonical_revision_string) do
738
- <<-REVISION_STRING
739
- name:minimal_policyfile
740
- run-list-item:recipe[foo]
741
- cookbook:foo;id:#{cookbook_foo_cksum}
742
- default_attributes:{}
743
- override_attributes:{}
744
- REVISION_STRING
745
- end
746
-
747
- let(:expected_revision_id) do
748
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
749
- end
750
-
751
- let(:compiled_policyfile) do
752
- {
753
-
754
- "revision_id" => expected_revision_id,
755
-
756
- "name" => "minimal_policyfile",
757
-
758
- "run_list" => ["recipe[foo]"],
759
-
760
- "cookbook_locks" => {
761
-
762
- "foo" => {
763
- "version" => "1.0.0",
764
- "identifier" => cookbook_foo_cksum,
765
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
766
- "cache_key" => "foo-1.0.0",
767
- "origin" => nil,
768
- "source_options" => nil,
769
- },
770
- },
771
-
772
- "default_attributes" => {},
773
- "override_attributes" => {},
774
-
775
- "solution_dependencies" => {
776
- "Policyfile" => [],
777
- "dependencies" => { "foo (1.0.0)" => [] },
778
- },
779
- "included_policy_locks" => [],
780
- }
781
- end
782
-
783
- it "computes a minimal policyfile" do
784
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
785
- end
786
-
787
- end
788
-
789
- context "with named run_lists specified" do
790
-
791
- let(:policyfile_lock) do
792
- ChefDK::PolicyfileLock.build(storage_config) do |p|
793
-
794
- p.name = "minimal_policyfile"
795
-
796
- p.run_list = [ "recipe[foo]" ]
797
-
798
- p.named_run_lists = { "rl2" => [ "recipe[foo::bar]" ] }
799
-
800
- p.cached_cookbook("foo") do |cb|
801
- cb.cache_key = "foo-1.0.0"
802
- end
803
-
804
- end
805
- end
806
-
807
- let(:expected_canonical_revision_string) do
808
- <<-REVISION_STRING
809
- name:minimal_policyfile
810
- run-list-item:recipe[foo]
811
- named-run-list:rl2;run-list-item:recipe[foo::bar]
812
- cookbook:foo;id:#{cookbook_foo_cksum}
813
- default_attributes:{}
814
- override_attributes:{}
815
- REVISION_STRING
816
- end
817
-
818
- let(:expected_revision_id) do
819
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
820
- end
821
-
822
- let(:compiled_policyfile) do
823
- {
824
-
825
- "revision_id" => expected_revision_id,
826
-
827
- "name" => "minimal_policyfile",
828
-
829
- "run_list" => ["recipe[foo]"],
830
-
831
- "named_run_lists" => { "rl2" => [ "recipe[foo::bar]" ] },
832
-
833
- "cookbook_locks" => {
834
-
835
- "foo" => {
836
- "version" => "1.0.0",
837
- "identifier" => cookbook_foo_cksum,
838
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
839
- "cache_key" => "foo-1.0.0",
840
- "origin" => nil,
841
- "source_options" => nil,
842
- },
843
- },
844
-
845
- "default_attributes" => {},
846
- "override_attributes" => {},
847
-
848
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
849
- "included_policy_locks" => [],
850
- }
851
- end
852
-
853
- it "includes the named run lists in the compiled policyfile" do
854
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
855
- end
856
-
857
- it "generates a canonical revision string" do
858
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
859
- end
860
-
861
- it "generates a revision id" do
862
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
863
- end
864
-
865
- end
866
-
867
- describe "building a policyfile lock from a policyfile compiler" do
868
-
869
- include_context "setup git cookbooks"
870
-
871
- let(:relative_paths_root) do
872
- tempdir
873
- end
874
-
875
- let(:cached_cookbook_uri) { "https://supermarket.chef.io/api/v1/cookbooks/foo/versions/1.0.0/download" }
876
-
877
- let(:cached_location_spec) do
878
- double( "ChefDK::Policyfile::CookbookLocationSpecification",
879
- mirrors_canonical_upstream?: true,
880
- cache_key: "foo-1.0.0",
881
- uri: cached_cookbook_uri,
882
- source_options_for_lock: { "artifactserver" => cached_cookbook_uri, "version" => "1.0.0" })
883
- end
884
-
885
- let(:local_location_spec) do
886
- double( "ChefDK::Policyfile::CookbookLocationSpecification",
887
- mirrors_canonical_upstream?: false,
888
- relative_paths_root: relative_paths_root,
889
- relative_path: "bar",
890
- source_options_for_lock: { "path" => "bar" })
891
- end
892
-
893
- let(:policyfile_solution_dependencies) do
894
- ChefDK::Policyfile::SolutionDependencies.new.tap do |s|
895
- s.add_policyfile_dep("foo", "~> 1.0")
896
- s.add_cookbook_dep("foo", "1.0.0", [])
897
- s.add_cookbook_dep("bar", "0.1.0", [])
898
- end
899
- end
900
-
901
- let(:policyfile_default_attrs) do
902
- {
903
- "foo" => "bar",
904
- "abc" => { "def" => { "ghi" => "xyz" } },
905
- "baz" => {
906
- "more_nested_stuff" => "yup",
907
- "an_array" => %w{a b c},
908
- },
909
- }
910
- end
911
-
912
- let(:canonicalized_default_attrs) do
913
- elements = [
914
- %q{"abc":{"def":{"ghi":"xyz"}}},
915
- %q{"baz":{"an_array":["a","b","c"],"more_nested_stuff":"yup"}},
916
- %q{"foo":"bar"},
917
- ]
918
- "{" + elements.join(",") + "}"
919
- end
920
-
921
- let(:policyfile_override_attrs) do
922
- {
923
- "foo" => "bar",
924
- "abc" => { "def" => { "ghi" => "xyz" } },
925
- "baz" => {
926
- "more_nested_stuff" => "yup",
927
- "an_array" => %w{a b c},
928
- },
929
- }
930
- end
931
-
932
- let(:canonicalized_override_attrs) { canonicalized_default_attrs }
933
-
934
- let(:policyfile_compiler) do
935
- double( "ChefDK::PolicyfileCompiler",
936
- name: "my-policyfile",
937
- normalized_run_list: %w{recipe[foo::default] recipe[bar::default]},
938
- normalized_named_run_lists: { "rl2" => %w{recipe[bar::default]} },
939
- all_cookbook_location_specs: { "foo" => cached_location_spec, "bar" => local_location_spec },
940
- solution_dependencies: policyfile_solution_dependencies,
941
- default_attributes: policyfile_default_attrs,
942
- override_attributes: policyfile_override_attrs,
943
- included_policies: []
944
- )
945
- end
946
-
947
- let(:policyfile_lock) do
948
- ChefDK::PolicyfileLock.build_from_compiler(policyfile_compiler, storage_config)
949
- end
950
-
951
- let(:expected_canonical_revision_string) do
952
- <<-REVISION_STRING
953
- name:my-policyfile
954
- run-list-item:recipe[foo::default]
955
- run-list-item:recipe[bar::default]
956
- named-run-list:rl2;run-list-item:recipe[bar::default]
957
- cookbook:bar;id:#{cookbook_bar_cksum}
958
- cookbook:foo;id:#{cookbook_foo_cksum}
959
- default_attributes:#{canonicalized_default_attrs}
960
- override_attributes:#{canonicalized_override_attrs}
961
- REVISION_STRING
962
- end
963
-
964
- let(:expected_revision_id) do
965
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
966
- end
967
-
968
- let(:compiled_policyfile) do
969
- {
970
-
971
- "revision_id" => expected_revision_id,
972
-
973
- "name" => "my-policyfile",
974
-
975
- "run_list" => ["recipe[foo::default]", "recipe[bar::default]"],
976
-
977
- "named_run_lists" => { "rl2" => ["recipe[bar::default]"] },
978
-
979
- "cookbook_locks" => {
980
-
981
- "foo" => {
982
- "version" => "1.0.0",
983
- "identifier" => cookbook_foo_cksum,
984
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
985
- "cache_key" => "foo-1.0.0",
986
- "origin" => cached_cookbook_uri,
987
- "source_options" => { "artifactserver" => cached_cookbook_uri, "version" => "1.0.0" },
988
- },
989
-
990
- "bar" => {
991
- "version" => "0.1.0",
992
- "identifier" => cookbook_bar_cksum,
993
- "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
994
- "source" => "bar",
995
- "cache_key" => nil,
996
-
997
- "scm_info" => {
998
- "scm" => "git",
999
- "remote" => nil,
1000
- "revision" => current_rev,
1001
- "working_tree_clean" => true,
1002
- "published" => false,
1003
- "synchronized_remote_branches" => [],
1004
- },
1005
- "source_options" => { "path" => "bar" },
1006
- },
1007
- },
1008
-
1009
- "default_attributes" => {
1010
- "foo" => "bar",
1011
- "abc" => { "def" => { "ghi" => "xyz" } },
1012
- "baz" => {
1013
- "more_nested_stuff" => "yup",
1014
- "an_array" => %w{a b c},
1015
- },
1016
- },
1017
-
1018
- "override_attributes" => {
1019
- "foo" => "bar",
1020
- "abc" => { "def" => { "ghi" => "xyz" } },
1021
- "baz" => {
1022
- "more_nested_stuff" => "yup",
1023
- "an_array" => %w{a b c},
1024
- },
1025
- },
1026
- "solution_dependencies" => {
1027
- "Policyfile" => [ [ "foo", "~> 1.0" ] ],
1028
- "dependencies" => { "foo (1.0.0)" => [], "bar (0.1.0)" => [] },
1029
- },
1030
- "included_policy_locks" => [],
1031
- }
1032
- end
1033
-
1034
- it "adds a cached cookbook lock generator for the compiler's cached cookbook" do
1035
- expect(policyfile_lock.cookbook_locks).to have_key("foo")
1036
- cb_lock = policyfile_lock.cookbook_locks["foo"]
1037
- expect(cb_lock.origin).to eq(cached_location_spec.uri)
1038
- expect(cb_lock.cache_key).to eq(cached_location_spec.cache_key)
1039
- end
1040
-
1041
- it "adds a local cookbook lock generator for the compiler's local cookbook" do
1042
- expect(policyfile_lock.cookbook_locks).to have_key("bar")
1043
- cb_lock = policyfile_lock.cookbook_locks["bar"]
1044
- expect(cb_lock.source).to eq(local_location_spec.relative_path)
1045
- end
1046
-
1047
- it "sets named run lists on the policyfile lock" do
1048
- expect(policyfile_lock.named_run_lists).to eq("rl2" => %w{recipe[bar::default]})
1049
- end
1050
-
1051
- it "generates a lockfile data structure" do
1052
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
1053
- end
1054
-
1055
- it "generates a canonical revision string" do
1056
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
1057
- end
1058
-
1059
- it "generates a revision id" do
1060
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
1061
- end
1062
-
1063
- end
1064
-
1065
- end
1
+ # -*- coding: UTF-8 -*-
2
+ #
3
+ # Copyright:: Copyright (c) 2014 Chef Software Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require "spec_helper"
20
+ require "shared/setup_git_cookbooks"
21
+ require "shared/fixture_cookbook_checksums"
22
+ require "chef-dk/policyfile/storage_config"
23
+ require "chef-dk/policyfile_lock.rb"
24
+
25
+ describe ChefDK::PolicyfileLock, "building a lockfile" do
26
+
27
+ include_context "fixture cookbooks checksums"
28
+
29
+ # For debugging giant nested hashes...
30
+ def expect_hash_equal(actual, expected)
31
+ expected.each do |key, expected_value|
32
+ expect(actual).to have_key(key)
33
+ if expected_value.kind_of?(Hash)
34
+ expect_hash_equal(actual[key], expected_value)
35
+ else
36
+ expect(actual[key]).to eq(expected_value)
37
+ end
38
+ end
39
+ expect(actual).to eq(expected)
40
+ end
41
+
42
+ let(:cache_path) do
43
+ File.expand_path("spec/unit/fixtures/cookbook_cache", project_root)
44
+ end
45
+
46
+ let(:relative_paths_root) do
47
+ File.expand_path("spec/unit/fixtures/", project_root)
48
+ end
49
+
50
+ let(:storage_config) do
51
+ ChefDK::Policyfile::StorageConfig.new( cache_path: cache_path, relative_paths_root: relative_paths_root )
52
+ end
53
+
54
+ context "when a cached cookbook omits the cache key" do
55
+
56
+ let(:policyfile_lock) do
57
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
58
+
59
+ p.name = "invalid_cache_key_policyfile"
60
+
61
+ p.run_list = [ "recipe[foo]" ]
62
+
63
+ p.cached_cookbook("nosuchthing") do |cb|
64
+ end
65
+ end
66
+ end
67
+
68
+ it "raises a descriptive error" do
69
+ expect { policyfile_lock.to_lock }.to raise_error(ChefDK::CachedCookbookNotFound)
70
+ end
71
+
72
+ end
73
+
74
+ context "when a local cookbook omits the path" do
75
+
76
+ let(:policyfile_lock) do
77
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
78
+
79
+ p.name = "invalid_local_cookbook"
80
+
81
+ p.run_list = [ "recipe[foo]" ]
82
+
83
+ p.local_cookbook("nosuchthing") do |cb|
84
+ end
85
+ end
86
+ end
87
+
88
+ it "raises a descriptive error" do
89
+ expect { policyfile_lock.to_lock }.to raise_error(ChefDK::LocalCookbookNotFound)
90
+ end
91
+ end
92
+
93
+ context "when a local cookbook has an incorrect path" do
94
+
95
+ let(:policyfile_lock) do
96
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
97
+
98
+ p.name = "invalid_local_cookbook"
99
+
100
+ p.run_list = [ "recipe[foo]" ]
101
+
102
+ p.local_cookbook("nosuchthing") do |cb|
103
+ cb.source = "nopenopenope"
104
+ end
105
+ end
106
+ end
107
+
108
+ it "raises a descriptive error" do
109
+ expect { policyfile_lock.to_lock }.to raise_error(ChefDK::LocalCookbookNotFound)
110
+ end
111
+ end
112
+
113
+ context "when a cookbook is not in the cache" do
114
+
115
+ let(:policyfile_lock) do
116
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
117
+
118
+ p.name = "invalid_cache_key_policyfile"
119
+
120
+ p.run_list = [ "recipe[foo]" ]
121
+
122
+ p.cached_cookbook("nosuchthing") do |cb|
123
+ cb.cache_key = "nosuchthing-1.0.0"
124
+ end
125
+ end
126
+ end
127
+
128
+ it "raises a descriptive error" do
129
+ expect { policyfile_lock.to_lock }.to raise_error(ChefDK::CachedCookbookNotFound)
130
+ end
131
+
132
+ end
133
+
134
+ describe "policyfiles with invalid attributes" do
135
+
136
+ let(:policyfile_lock) do
137
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
138
+
139
+ p.name = "invalid_cache_key_policyfile"
140
+
141
+ p.run_list = [ "recipe[foo]" ]
142
+
143
+ p.cached_cookbook("foo") do |cb|
144
+ cb.cache_key = "foo-1.0.0"
145
+ end
146
+
147
+ p.default_attributes = default_attributes
148
+ end
149
+ end
150
+
151
+ context "invalid floats - infinity" do
152
+
153
+ let(:default_attributes) { { "infinity" => Float::INFINITY } }
154
+
155
+ it "raises a descriptive error" do
156
+ expect { policyfile_lock.to_lock }.to raise_error(ChefDK::InvalidPolicyfileAttribute)
157
+ end
158
+ end
159
+
160
+ context "invalid floats - nan" do
161
+
162
+ let(:default_attributes) { { "infinity" => Float::NAN } }
163
+
164
+ it "raises a descriptive error" do
165
+ expect { policyfile_lock.to_lock }.to raise_error(ChefDK::InvalidPolicyfileAttribute)
166
+ end
167
+ end
168
+
169
+ context "non-string hash/object keys" do
170
+
171
+ let(:default_attributes) { { 1906 => "lol nope" } }
172
+
173
+ it "raises a descriptive error" do
174
+ expect { policyfile_lock.to_lock }.to raise_error(ChefDK::InvalidPolicyfileAttribute)
175
+ end
176
+ end
177
+
178
+ context "values that are not Hash/Array/String/Float/Integer/true/false/nil" do
179
+
180
+ let(:default_attributes) { { "raw object" => Object.new } }
181
+
182
+ it "raises a descriptive error" do
183
+ expect { policyfile_lock.to_lock }.to raise_error(ChefDK::InvalidPolicyfileAttribute)
184
+ end
185
+ end
186
+
187
+ end
188
+
189
+ context "with a minimal policyfile" do
190
+
191
+ let(:policyfile_lock) do
192
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
193
+
194
+ p.name = "minimal_policyfile"
195
+
196
+ p.run_list = [ "recipe[foo]" ]
197
+ p.cached_cookbook("foo") do |cb|
198
+ cb.cache_key = "foo-1.0.0"
199
+ end
200
+
201
+ end
202
+ end
203
+
204
+ let(:expected_canonical_revision_string) do
205
+ <<-REVISION_STRING
206
+ name:minimal_policyfile
207
+ run-list-item:recipe[foo]
208
+ cookbook:foo;id:467dc855408ce8b74f991c5dc2fd72a6aa369b60
209
+ default_attributes:{}
210
+ override_attributes:{}
211
+ REVISION_STRING
212
+ end
213
+
214
+ let(:expected_revision_id) do
215
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
216
+ end
217
+
218
+ let(:compiled_policyfile) do
219
+ {
220
+ "revision_id" => expected_revision_id,
221
+
222
+ "name" => "minimal_policyfile",
223
+
224
+ "run_list" => ["recipe[foo]"],
225
+
226
+ "cookbook_locks" => {
227
+
228
+ "foo" => {
229
+ "version" => "1.0.0",
230
+ "identifier" => cookbook_foo_cksum,
231
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
232
+ "cache_key" => "foo-1.0.0",
233
+ "origin" => nil,
234
+ "source_options" => nil,
235
+ },
236
+ },
237
+ "default_attributes" => {},
238
+ "override_attributes" => {},
239
+
240
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
241
+ "included_policy_locks" => [],
242
+ }
243
+ end
244
+
245
+ it "has a cache path" do
246
+ expect(policyfile_lock.cache_path).to eq(cache_path)
247
+ end
248
+
249
+ it "computes a minimal policyfile" do
250
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
251
+ end
252
+
253
+ it "generates a canonical revision string" do
254
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
255
+ end
256
+
257
+ it "generates a revision id" do
258
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
259
+ end
260
+
261
+ end
262
+
263
+ context "with a policyfile containing attributes" do
264
+
265
+ let(:policyfile_lock) do
266
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
267
+
268
+ p.name = "minimal_policyfile"
269
+
270
+ p.run_list = [ "recipe[foo]" ]
271
+ p.cached_cookbook("foo") do |cb|
272
+ cb.cache_key = "foo-1.0.0"
273
+ end
274
+
275
+ p.default_attributes = {
276
+ "foo" => "bar",
277
+ "aaa".encode("utf-16") => "aaa".encode("utf-16"),
278
+ "ddd" => true,
279
+ "ccc" => false,
280
+ "bbb" => nil,
281
+ "e" => 1.2,
282
+ "f" => 5,
283
+ "g" => 1_000_000_000_000_000.0,
284
+ "nested" => { "a" => "b" },
285
+ }
286
+ p.override_attributes = { "foo2" => "baz" }
287
+
288
+ end
289
+ end
290
+
291
+ let(:expected_canonical_revision_string) do
292
+ <<-REVISION_STRING
293
+ name:minimal_policyfile
294
+ run-list-item:recipe[foo]
295
+ cookbook:foo;id:467dc855408ce8b74f991c5dc2fd72a6aa369b60
296
+ default_attributes:{"aaa":"aaa","bbb":null,"ccc":false,"ddd":true,"e":1.2,"f":5,"foo":"bar","g":1e+15,"nested":{"a":"b"}}
297
+ override_attributes:{"foo2":"baz"}
298
+ REVISION_STRING
299
+ end
300
+
301
+ let(:expected_revision_id) do
302
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
303
+ end
304
+
305
+ let(:compiled_policyfile) do
306
+ {
307
+ "revision_id" => expected_revision_id,
308
+
309
+ "name" => "minimal_policyfile",
310
+
311
+ "run_list" => ["recipe[foo]"],
312
+
313
+ "cookbook_locks" => {
314
+
315
+ "foo" => {
316
+ "version" => "1.0.0",
317
+ "identifier" => cookbook_foo_cksum,
318
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
319
+ "cache_key" => "foo-1.0.0",
320
+ "origin" => nil,
321
+ "source_options" => nil,
322
+ },
323
+ },
324
+ "default_attributes" => {
325
+ "foo" => "bar",
326
+ "aaa".encode("utf-16") => "aaa".encode("utf-16"),
327
+ "ddd" => true,
328
+ "ccc" => false,
329
+ "bbb" => nil,
330
+ "e" => 1.2,
331
+ "f" => 5,
332
+ "g" => 1_000_000_000_000_000.0,
333
+ "nested" => { "a" => "b" },
334
+ },
335
+ "override_attributes" => { "foo2" => "baz" },
336
+
337
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
338
+ "included_policy_locks" => [],
339
+ }
340
+ end
341
+
342
+ it "has a cache path" do
343
+ expect(policyfile_lock.cache_path).to eq(cache_path)
344
+ end
345
+
346
+ it "computes a minimal policyfile" do
347
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
348
+ end
349
+
350
+ it "generates a canonical revision string" do
351
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
352
+ end
353
+
354
+ it "generates a revision id" do
355
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
356
+ end
357
+
358
+ end
359
+
360
+ context "with a policyfile containing a local cookbook" do
361
+
362
+ include_context "setup git cookbooks"
363
+ include_context "setup git cookbook remote"
364
+
365
+ let(:relative_paths_root) do
366
+ tempdir
367
+ end
368
+
369
+ let(:policyfile_lock) do
370
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
371
+
372
+ p.name = "dev_cookbook"
373
+
374
+ p.run_list = [ "recipe[bar]" ]
375
+ p.local_cookbook("bar") do |cb|
376
+ cb.source = "bar"
377
+ end
378
+
379
+ end
380
+ end
381
+
382
+ let(:expected_canonical_revision_string) do
383
+ <<-REVISION_STRING
384
+ name:dev_cookbook
385
+ run-list-item:recipe[bar]
386
+ cookbook:bar;id:#{cookbook_bar_cksum}
387
+ default_attributes:{}
388
+ override_attributes:{}
389
+ REVISION_STRING
390
+ end
391
+
392
+ let(:expected_revision_id) do
393
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
394
+ end
395
+
396
+ let(:compiled_policyfile) do
397
+ {
398
+
399
+ "revision_id" => expected_revision_id,
400
+
401
+ "name" => "dev_cookbook",
402
+
403
+ "run_list" => ["recipe[bar]"],
404
+
405
+ "cookbook_locks" => {
406
+
407
+ "bar" => {
408
+ "version" => "0.1.0",
409
+ "identifier" => cookbook_bar_cksum,
410
+ "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
411
+
412
+ "source" => "bar",
413
+ "cache_key" => nil,
414
+ "scm_info" => {
415
+ "scm" => "git",
416
+ "remote" => remote_url,
417
+ "revision" => current_rev,
418
+ "working_tree_clean" => true,
419
+ "published" => true,
420
+ "synchronized_remote_branches" => ["origin/master"],
421
+ },
422
+ "source_options" => nil,
423
+ },
424
+ },
425
+
426
+ "default_attributes" => {},
427
+ "override_attributes" => {},
428
+
429
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
430
+ "included_policy_locks" => [],
431
+ }
432
+ end
433
+
434
+ it "computes a lockfile including git data" do
435
+ actual_lock = policyfile_lock.to_lock
436
+ expect(actual_lock).to eq(compiled_policyfile)
437
+ end
438
+
439
+ it "generates a canonical revision string" do
440
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
441
+ end
442
+
443
+ it "generates a revision id" do
444
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
445
+ end
446
+
447
+ end
448
+
449
+ context "with a policyfile using custom identifiers" do
450
+
451
+ include_context "setup git cookbooks"
452
+
453
+ let(:relative_paths_root) do
454
+ tempdir
455
+ end
456
+
457
+ let(:policyfile_lock) do
458
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
459
+
460
+ p.name = "custom_identifier"
461
+
462
+ p.run_list = [ "recipe[foo]" ]
463
+
464
+ p.cached_cookbook("foo") do |cb|
465
+ cb.cache_key = "foo-1.0.0"
466
+
467
+ # Explicitly set the identifier and dotted decimal identifiers to the
468
+ # version number (but it could be anything).
469
+ cb.identifier = "1.0.0"
470
+ cb.dotted_decimal_identifier = "1.0.0"
471
+ end
472
+
473
+ p.local_cookbook("bar") do |cb|
474
+ cb.source = "bar"
475
+ cb.identifier = "0.1.0"
476
+ cb.dotted_decimal_identifier = "0.1.0"
477
+ end
478
+ end
479
+
480
+ end
481
+
482
+ let(:expected_canonical_revision_string) do
483
+ <<-REVISION_STRING
484
+ name:custom_identifier
485
+ run-list-item:recipe[foo]
486
+ cookbook:bar;id:0.1.0
487
+ cookbook:foo;id:1.0.0
488
+ default_attributes:{}
489
+ override_attributes:{}
490
+ REVISION_STRING
491
+ end
492
+
493
+ let(:expected_revision_id) do
494
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
495
+ end
496
+
497
+ let(:compiled_policyfile) do
498
+ {
499
+
500
+ "revision_id" => expected_revision_id,
501
+
502
+ "name" => "custom_identifier",
503
+
504
+ "run_list" => ["recipe[foo]"],
505
+
506
+ "cookbook_locks" => {
507
+
508
+ "bar" => {
509
+ "version" => "0.1.0",
510
+ "identifier" => "0.1.0",
511
+ "dotted_decimal_identifier" => "0.1.0",
512
+
513
+ "source" => "bar",
514
+ "cache_key" => nil,
515
+ "scm_info" => {
516
+ "scm" => "git",
517
+ "remote" => nil,
518
+ "revision" => current_rev,
519
+ "working_tree_clean" => true,
520
+ "published" => false,
521
+ "synchronized_remote_branches" => [],
522
+ },
523
+ "source_options" => nil,
524
+ },
525
+
526
+ "foo" => {
527
+ "version" => "1.0.0",
528
+ "identifier" => "1.0.0",
529
+ "dotted_decimal_identifier" => "1.0.0",
530
+ "cache_key" => "foo-1.0.0",
531
+ "origin" => nil,
532
+ "source_options" => nil,
533
+ },
534
+
535
+ },
536
+
537
+ "default_attributes" => {},
538
+ "override_attributes" => {},
539
+
540
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
541
+ "included_policy_locks" => [],
542
+ }
543
+ end
544
+
545
+ it "generates a lockfile with custom identifiers" do
546
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
547
+ end
548
+
549
+ it "generates a canonical revision string" do
550
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
551
+ end
552
+
553
+ it "generates a revision id" do
554
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
555
+ end
556
+
557
+ end
558
+
559
+ context "with a policyfile lock with a mix of cached and local cookbooks" do
560
+
561
+ include_context "setup git cookbooks"
562
+
563
+ let(:relative_paths_root) do
564
+ tempdir
565
+ end
566
+
567
+ let(:policyfile_lock) do
568
+
569
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
570
+
571
+ # Required
572
+ p.name = "basic_example"
573
+
574
+ # Required. Should be fully expanded without roles
575
+ p.run_list = ["recipe[foo]", "recipe[bar]", "recipe[baz::non_default]"]
576
+
577
+ # A cached_cookbook is stored in the cache directory in a subdirectory
578
+ # given by 'cache_key'. It is assumed to be static (not modified by the
579
+ # user).
580
+ p.cached_cookbook("foo") do |cb|
581
+ cb.cache_key = "foo-1.0.0"
582
+
583
+ # Optional attribute that humans can use to understand where a cookbook
584
+ # came from.
585
+ cb.origin = "https://community.chef.io/api/cookbooks/foo/1.0.0"
586
+ end
587
+
588
+ p.local_cookbook("bar") do |cb|
589
+ cb.source = "bar"
590
+ end
591
+
592
+ p.cached_cookbook("baz") do |cb|
593
+ cb.cache_key = "baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb"
594
+ cb.origin = "git://github.com/chef-cookbooks/bar.git"
595
+ end
596
+
597
+ p.cached_cookbook("dep_of_bar") do |cb|
598
+ cb.cache_key = "dep_of_bar-1.2.3"
599
+ cb.origin = "https://chef-server.example.com/cookbooks/dep_of_bar/1.2.3"
600
+ end
601
+ end
602
+
603
+ end
604
+
605
+ let(:expected_canonical_revision_string) do
606
+ <<-REVISION_STRING
607
+ name:basic_example
608
+ run-list-item:recipe[foo]
609
+ run-list-item:recipe[bar]
610
+ run-list-item:recipe[baz::non_default]
611
+ cookbook:bar;id:#{cookbook_bar_cksum}
612
+ cookbook:baz;id:#{cookbook_baz_cksum}
613
+ cookbook:dep_of_bar;id:#{cookbook_dep_of_bar_cksum}
614
+ cookbook:foo;id:#{cookbook_foo_cksum}
615
+ default_attributes:{}
616
+ override_attributes:{}
617
+ REVISION_STRING
618
+ end
619
+
620
+ let(:expected_revision_id) do
621
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
622
+ end
623
+
624
+ let(:compiled_policyfile) do
625
+ {
626
+
627
+ "revision_id" => expected_revision_id,
628
+
629
+ "name" => "basic_example",
630
+
631
+ "run_list" => ["recipe[foo]", "recipe[bar]", "recipe[baz::non_default]"],
632
+
633
+ "cookbook_locks" => {
634
+
635
+ "bar" => {
636
+ "version" => "0.1.0",
637
+ "identifier" => cookbook_bar_cksum,
638
+ "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
639
+ "source" => "bar",
640
+ "cache_key" => nil,
641
+
642
+ "scm_info" => {
643
+ "scm" => "git",
644
+ "remote" => nil,
645
+ "revision" => current_rev,
646
+ "working_tree_clean" => true,
647
+ "published" => false,
648
+ "synchronized_remote_branches" => [],
649
+ },
650
+ "source_options" => nil,
651
+ },
652
+
653
+ "baz" => {
654
+ "version" => "1.2.3",
655
+ "identifier" => cookbook_baz_cksum,
656
+ "dotted_decimal_identifier" => cookbook_baz_cksum_dotted,
657
+ "cache_key" => "baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb",
658
+ "origin" => "git://github.com/chef-cookbooks/bar.git",
659
+ "source_options" => nil,
660
+ },
661
+
662
+ "dep_of_bar" => {
663
+ "version" => "1.2.3",
664
+ "identifier" => cookbook_dep_of_bar_cksum,
665
+ "dotted_decimal_identifier" => cookbook_dep_of_bar_cksum_dotted,
666
+ "origin" => "https://chef-server.example.com/cookbooks/dep_of_bar/1.2.3",
667
+ "cache_key" => "dep_of_bar-1.2.3",
668
+ "source_options" => nil,
669
+
670
+ },
671
+
672
+ "foo" => {
673
+ "version" => "1.0.0",
674
+ "identifier" => cookbook_foo_cksum,
675
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
676
+ "origin" => "https://community.chef.io/api/cookbooks/foo/1.0.0",
677
+ "cache_key" => "foo-1.0.0",
678
+ "source_options" => nil,
679
+ },
680
+
681
+ },
682
+
683
+ "default_attributes" => {},
684
+ "override_attributes" => {},
685
+
686
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
687
+ "included_policy_locks" => [],
688
+ }
689
+ end
690
+
691
+ it "generates a lockfile with the relevant profile data for each cookbook" do
692
+ generated = policyfile_lock.to_lock
693
+ expect(generated["name"]).to eq(compiled_policyfile["name"])
694
+ expect(generated["run_list"]).to eq(compiled_policyfile["run_list"])
695
+
696
+ generated_locks = generated["cookbook_locks"]
697
+ expected_locks = compiled_policyfile["cookbook_locks"]
698
+
699
+ # test individually so failures are easier to read
700
+ expect(generated_locks["foo"]).to eq(expected_locks["foo"])
701
+ expect(generated_locks["bar"]).to eq(expected_locks["bar"])
702
+ expect(generated_locks["baz"]).to eq(expected_locks["baz"])
703
+ expect(generated_locks["dep_of_bar"]).to eq(expected_locks["dep_of_bar"])
704
+
705
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
706
+ end
707
+
708
+ it "generates a canonical revision string" do
709
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
710
+ end
711
+
712
+ it "generates a revision id" do
713
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
714
+ end
715
+
716
+ end
717
+
718
+ context "with solution dependencies specified" do
719
+
720
+ let(:policyfile_lock) do
721
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
722
+
723
+ p.name = "minimal_policyfile"
724
+
725
+ p.run_list = [ "recipe[foo]" ]
726
+ p.cached_cookbook("foo") do |cb|
727
+ cb.cache_key = "foo-1.0.0"
728
+ end
729
+
730
+ p.dependencies do |deps|
731
+ deps.add_cookbook_dep("foo", "1.0.0", [])
732
+ end
733
+
734
+ end
735
+ end
736
+
737
+ let(:expected_canonical_revision_string) do
738
+ <<-REVISION_STRING
739
+ name:minimal_policyfile
740
+ run-list-item:recipe[foo]
741
+ cookbook:foo;id:#{cookbook_foo_cksum}
742
+ default_attributes:{}
743
+ override_attributes:{}
744
+ REVISION_STRING
745
+ end
746
+
747
+ let(:expected_revision_id) do
748
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
749
+ end
750
+
751
+ let(:compiled_policyfile) do
752
+ {
753
+
754
+ "revision_id" => expected_revision_id,
755
+
756
+ "name" => "minimal_policyfile",
757
+
758
+ "run_list" => ["recipe[foo]"],
759
+
760
+ "cookbook_locks" => {
761
+
762
+ "foo" => {
763
+ "version" => "1.0.0",
764
+ "identifier" => cookbook_foo_cksum,
765
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
766
+ "cache_key" => "foo-1.0.0",
767
+ "origin" => nil,
768
+ "source_options" => nil,
769
+ },
770
+ },
771
+
772
+ "default_attributes" => {},
773
+ "override_attributes" => {},
774
+
775
+ "solution_dependencies" => {
776
+ "Policyfile" => [],
777
+ "dependencies" => { "foo (1.0.0)" => [] },
778
+ },
779
+ "included_policy_locks" => [],
780
+ }
781
+ end
782
+
783
+ it "computes a minimal policyfile" do
784
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
785
+ end
786
+
787
+ end
788
+
789
+ context "with named run_lists specified" do
790
+
791
+ let(:policyfile_lock) do
792
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
793
+
794
+ p.name = "minimal_policyfile"
795
+
796
+ p.run_list = [ "recipe[foo]" ]
797
+
798
+ p.named_run_lists = { "rl2" => [ "recipe[foo::bar]" ] }
799
+
800
+ p.cached_cookbook("foo") do |cb|
801
+ cb.cache_key = "foo-1.0.0"
802
+ end
803
+
804
+ end
805
+ end
806
+
807
+ let(:expected_canonical_revision_string) do
808
+ <<-REVISION_STRING
809
+ name:minimal_policyfile
810
+ run-list-item:recipe[foo]
811
+ named-run-list:rl2;run-list-item:recipe[foo::bar]
812
+ cookbook:foo;id:#{cookbook_foo_cksum}
813
+ default_attributes:{}
814
+ override_attributes:{}
815
+ REVISION_STRING
816
+ end
817
+
818
+ let(:expected_revision_id) do
819
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
820
+ end
821
+
822
+ let(:compiled_policyfile) do
823
+ {
824
+
825
+ "revision_id" => expected_revision_id,
826
+
827
+ "name" => "minimal_policyfile",
828
+
829
+ "run_list" => ["recipe[foo]"],
830
+
831
+ "named_run_lists" => { "rl2" => [ "recipe[foo::bar]" ] },
832
+
833
+ "cookbook_locks" => {
834
+
835
+ "foo" => {
836
+ "version" => "1.0.0",
837
+ "identifier" => cookbook_foo_cksum,
838
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
839
+ "cache_key" => "foo-1.0.0",
840
+ "origin" => nil,
841
+ "source_options" => nil,
842
+ },
843
+ },
844
+
845
+ "default_attributes" => {},
846
+ "override_attributes" => {},
847
+
848
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} },
849
+ "included_policy_locks" => [],
850
+ }
851
+ end
852
+
853
+ it "includes the named run lists in the compiled policyfile" do
854
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
855
+ end
856
+
857
+ it "generates a canonical revision string" do
858
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
859
+ end
860
+
861
+ it "generates a revision id" do
862
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
863
+ end
864
+
865
+ end
866
+
867
+ describe "building a policyfile lock from a policyfile compiler" do
868
+
869
+ include_context "setup git cookbooks"
870
+
871
+ let(:relative_paths_root) do
872
+ tempdir
873
+ end
874
+
875
+ let(:cached_cookbook_uri) { "https://supermarket.chef.io/api/v1/cookbooks/foo/versions/1.0.0/download" }
876
+
877
+ let(:cached_location_spec) do
878
+ double( "ChefDK::Policyfile::CookbookLocationSpecification",
879
+ mirrors_canonical_upstream?: true,
880
+ cache_key: "foo-1.0.0",
881
+ uri: cached_cookbook_uri,
882
+ source_options_for_lock: { "artifactserver" => cached_cookbook_uri, "version" => "1.0.0" })
883
+ end
884
+
885
+ let(:local_location_spec) do
886
+ double( "ChefDK::Policyfile::CookbookLocationSpecification",
887
+ mirrors_canonical_upstream?: false,
888
+ relative_paths_root: relative_paths_root,
889
+ relative_path: "bar",
890
+ source_options_for_lock: { "path" => "bar" })
891
+ end
892
+
893
+ let(:policyfile_solution_dependencies) do
894
+ ChefDK::Policyfile::SolutionDependencies.new.tap do |s|
895
+ s.add_policyfile_dep("foo", "~> 1.0")
896
+ s.add_cookbook_dep("foo", "1.0.0", [])
897
+ s.add_cookbook_dep("bar", "0.1.0", [])
898
+ end
899
+ end
900
+
901
+ let(:policyfile_default_attrs) do
902
+ {
903
+ "foo" => "bar",
904
+ "abc" => { "def" => { "ghi" => "xyz" } },
905
+ "baz" => {
906
+ "more_nested_stuff" => "yup",
907
+ "an_array" => %w{a b c},
908
+ },
909
+ }
910
+ end
911
+
912
+ let(:canonicalized_default_attrs) do
913
+ elements = [
914
+ %q{"abc":{"def":{"ghi":"xyz"}}},
915
+ %q{"baz":{"an_array":["a","b","c"],"more_nested_stuff":"yup"}},
916
+ %q{"foo":"bar"},
917
+ ]
918
+ "{" + elements.join(",") + "}"
919
+ end
920
+
921
+ let(:policyfile_override_attrs) do
922
+ {
923
+ "foo" => "bar",
924
+ "abc" => { "def" => { "ghi" => "xyz" } },
925
+ "baz" => {
926
+ "more_nested_stuff" => "yup",
927
+ "an_array" => %w{a b c},
928
+ },
929
+ }
930
+ end
931
+
932
+ let(:canonicalized_override_attrs) { canonicalized_default_attrs }
933
+
934
+ let(:policyfile_compiler) do
935
+ double( "ChefDK::PolicyfileCompiler",
936
+ name: "my-policyfile",
937
+ normalized_run_list: %w{recipe[foo::default] recipe[bar::default]},
938
+ normalized_named_run_lists: { "rl2" => %w{recipe[bar::default]} },
939
+ all_cookbook_location_specs: { "foo" => cached_location_spec, "bar" => local_location_spec },
940
+ solution_dependencies: policyfile_solution_dependencies,
941
+ default_attributes: policyfile_default_attrs,
942
+ override_attributes: policyfile_override_attrs,
943
+ included_policies: []
944
+ )
945
+ end
946
+
947
+ let(:policyfile_lock) do
948
+ ChefDK::PolicyfileLock.build_from_compiler(policyfile_compiler, storage_config)
949
+ end
950
+
951
+ let(:expected_canonical_revision_string) do
952
+ <<-REVISION_STRING
953
+ name:my-policyfile
954
+ run-list-item:recipe[foo::default]
955
+ run-list-item:recipe[bar::default]
956
+ named-run-list:rl2;run-list-item:recipe[bar::default]
957
+ cookbook:bar;id:#{cookbook_bar_cksum}
958
+ cookbook:foo;id:#{cookbook_foo_cksum}
959
+ default_attributes:#{canonicalized_default_attrs}
960
+ override_attributes:#{canonicalized_override_attrs}
961
+ REVISION_STRING
962
+ end
963
+
964
+ let(:expected_revision_id) do
965
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
966
+ end
967
+
968
+ let(:compiled_policyfile) do
969
+ {
970
+
971
+ "revision_id" => expected_revision_id,
972
+
973
+ "name" => "my-policyfile",
974
+
975
+ "run_list" => ["recipe[foo::default]", "recipe[bar::default]"],
976
+
977
+ "named_run_lists" => { "rl2" => ["recipe[bar::default]"] },
978
+
979
+ "cookbook_locks" => {
980
+
981
+ "foo" => {
982
+ "version" => "1.0.0",
983
+ "identifier" => cookbook_foo_cksum,
984
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
985
+ "cache_key" => "foo-1.0.0",
986
+ "origin" => cached_cookbook_uri,
987
+ "source_options" => { "artifactserver" => cached_cookbook_uri, "version" => "1.0.0" },
988
+ },
989
+
990
+ "bar" => {
991
+ "version" => "0.1.0",
992
+ "identifier" => cookbook_bar_cksum,
993
+ "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
994
+ "source" => "bar",
995
+ "cache_key" => nil,
996
+
997
+ "scm_info" => {
998
+ "scm" => "git",
999
+ "remote" => nil,
1000
+ "revision" => current_rev,
1001
+ "working_tree_clean" => true,
1002
+ "published" => false,
1003
+ "synchronized_remote_branches" => [],
1004
+ },
1005
+ "source_options" => { "path" => "bar" },
1006
+ },
1007
+ },
1008
+
1009
+ "default_attributes" => {
1010
+ "foo" => "bar",
1011
+ "abc" => { "def" => { "ghi" => "xyz" } },
1012
+ "baz" => {
1013
+ "more_nested_stuff" => "yup",
1014
+ "an_array" => %w{a b c},
1015
+ },
1016
+ },
1017
+
1018
+ "override_attributes" => {
1019
+ "foo" => "bar",
1020
+ "abc" => { "def" => { "ghi" => "xyz" } },
1021
+ "baz" => {
1022
+ "more_nested_stuff" => "yup",
1023
+ "an_array" => %w{a b c},
1024
+ },
1025
+ },
1026
+ "solution_dependencies" => {
1027
+ "Policyfile" => [ [ "foo", "~> 1.0" ] ],
1028
+ "dependencies" => { "foo (1.0.0)" => [], "bar (0.1.0)" => [] },
1029
+ },
1030
+ "included_policy_locks" => [],
1031
+ }
1032
+ end
1033
+
1034
+ it "adds a cached cookbook lock generator for the compiler's cached cookbook" do
1035
+ expect(policyfile_lock.cookbook_locks).to have_key("foo")
1036
+ cb_lock = policyfile_lock.cookbook_locks["foo"]
1037
+ expect(cb_lock.origin).to eq(cached_location_spec.uri)
1038
+ expect(cb_lock.cache_key).to eq(cached_location_spec.cache_key)
1039
+ end
1040
+
1041
+ it "adds a local cookbook lock generator for the compiler's local cookbook" do
1042
+ expect(policyfile_lock.cookbook_locks).to have_key("bar")
1043
+ cb_lock = policyfile_lock.cookbook_locks["bar"]
1044
+ expect(cb_lock.source).to eq(local_location_spec.relative_path)
1045
+ end
1046
+
1047
+ it "sets named run lists on the policyfile lock" do
1048
+ expect(policyfile_lock.named_run_lists).to eq("rl2" => %w{recipe[bar::default]})
1049
+ end
1050
+
1051
+ it "generates a lockfile data structure" do
1052
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
1053
+ end
1054
+
1055
+ it "generates a canonical revision string" do
1056
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
1057
+ end
1058
+
1059
+ it "generates a revision id" do
1060
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
1061
+ end
1062
+
1063
+ end
1064
+
1065
+ end