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,1056 +1,1056 @@
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
- }
242
- end
243
-
244
- it "has a cache path" do
245
- expect(policyfile_lock.cache_path).to eq(cache_path)
246
- end
247
-
248
- it "computes a minimal policyfile" do
249
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
250
- end
251
-
252
- it "generates a canonical revision string" do
253
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
254
- end
255
-
256
- it "generates a revision id" do
257
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
258
- end
259
-
260
- end
261
-
262
- context "with a policyfile containing attributes" do
263
-
264
- let(:policyfile_lock) do
265
- ChefDK::PolicyfileLock.build(storage_config) do |p|
266
-
267
- p.name = "minimal_policyfile"
268
-
269
- p.run_list = [ "recipe[foo]" ]
270
- p.cached_cookbook("foo") do |cb|
271
- cb.cache_key = "foo-1.0.0"
272
- end
273
-
274
- p.default_attributes = {
275
- "foo" => "bar",
276
- "aaa".encode('utf-16') => "aaa".encode('utf-16'),
277
- "ddd" => true,
278
- "ccc" => false,
279
- "bbb" => nil,
280
- "e" => 1.2,
281
- "f" => 5,
282
- "g" => 1_000_000_000_000_000.0,
283
- "nested" => { "a" => "b" }
284
- }
285
- p.override_attributes = { "foo2" => "baz" }
286
-
287
- end
288
- end
289
-
290
- let(:expected_canonical_revision_string) do
291
- <<-REVISION_STRING
292
- name:minimal_policyfile
293
- run-list-item:recipe[foo]
294
- cookbook:foo;id:467dc855408ce8b74f991c5dc2fd72a6aa369b60
295
- default_attributes:{"aaa":"aaa","bbb":null,"ccc":false,"ddd":true,"e":1.2,"f":5,"foo":"bar","g":1e+15,"nested":{"a":"b"}}
296
- override_attributes:{"foo2":"baz"}
297
- REVISION_STRING
298
- end
299
-
300
- let(:expected_revision_id) do
301
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
302
- end
303
-
304
- let(:compiled_policyfile) do
305
- {
306
- "revision_id" => expected_revision_id,
307
-
308
- "name" => "minimal_policyfile",
309
-
310
- "run_list" => ["recipe[foo]"],
311
-
312
- "cookbook_locks" => {
313
-
314
- "foo" => {
315
- "version" => "1.0.0",
316
- "identifier" => cookbook_foo_cksum,
317
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
318
- "cache_key" => "foo-1.0.0",
319
- "origin" => nil,
320
- "source_options" => nil
321
- },
322
- },
323
- "default_attributes" => {
324
- "foo" => "bar",
325
- "aaa".encode('utf-16') => "aaa".encode('utf-16'),
326
- "ddd" => true,
327
- "ccc" => false,
328
- "bbb" => nil,
329
- "e" => 1.2,
330
- "f" => 5,
331
- "g" => 1_000_000_000_000_000.0,
332
- "nested" => { "a" => "b" }
333
- },
334
- "override_attributes" => { "foo2" => "baz" },
335
-
336
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
337
- }
338
- end
339
-
340
- it "has a cache path" do
341
- expect(policyfile_lock.cache_path).to eq(cache_path)
342
- end
343
-
344
- it "computes a minimal policyfile" do
345
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
346
- end
347
-
348
- it "generates a canonical revision string" do
349
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
350
- end
351
-
352
- it "generates a revision id" do
353
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
354
- end
355
-
356
- end
357
-
358
- context "with a policyfile containing a local cookbook" do
359
-
360
- include_context "setup git cookbooks"
361
- include_context "setup git cookbook remote"
362
-
363
- let(:relative_paths_root) do
364
- tempdir
365
- end
366
-
367
- let(:policyfile_lock) do
368
- ChefDK::PolicyfileLock.build(storage_config) do |p|
369
-
370
- p.name = "dev_cookbook"
371
-
372
- p.run_list = [ "recipe[bar]" ]
373
- p.local_cookbook("bar") do |cb|
374
- cb.source = "bar"
375
- end
376
-
377
- end
378
- end
379
-
380
- let(:expected_canonical_revision_string) do
381
- <<-REVISION_STRING
382
- name:dev_cookbook
383
- run-list-item:recipe[bar]
384
- cookbook:bar;id:#{cookbook_bar_cksum}
385
- default_attributes:{}
386
- override_attributes:{}
387
- REVISION_STRING
388
- end
389
-
390
- let(:expected_revision_id) do
391
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
392
- end
393
-
394
- let(:compiled_policyfile) do
395
- {
396
-
397
- "revision_id" => expected_revision_id,
398
-
399
- "name" => "dev_cookbook",
400
-
401
- "run_list" => ["recipe[bar]"],
402
-
403
- "cookbook_locks" => {
404
-
405
- "bar" => {
406
- "version" => "0.1.0",
407
- "identifier" => cookbook_bar_cksum,
408
- "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
409
-
410
- "source" => "bar",
411
- "cache_key" => nil,
412
- "scm_info" => {
413
- "scm" => "git",
414
- "remote" => remote_url,
415
- "revision" => current_rev,
416
- "working_tree_clean" => true,
417
- "published" => true,
418
- "synchronized_remote_branches"=>["origin/master"]
419
- },
420
- "source_options" => nil
421
- },
422
- },
423
-
424
- "default_attributes" => {},
425
- "override_attributes" => {},
426
-
427
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
428
- }
429
- end
430
-
431
- it "computes a lockfile including git data" do
432
- actual_lock = policyfile_lock.to_lock
433
- expect(actual_lock).to eq(compiled_policyfile)
434
- end
435
-
436
- it "generates a canonical revision string" do
437
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
438
- end
439
-
440
- it "generates a revision id" do
441
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
442
- end
443
-
444
- end
445
-
446
- context "with a policyfile using custom identifiers" do
447
-
448
- include_context "setup git cookbooks"
449
-
450
- let(:relative_paths_root) do
451
- tempdir
452
- end
453
-
454
- let(:policyfile_lock) do
455
- ChefDK::PolicyfileLock.build(storage_config) do |p|
456
-
457
- p.name = "custom_identifier"
458
-
459
- p.run_list = [ "recipe[foo]" ]
460
-
461
- p.cached_cookbook("foo") do |cb|
462
- cb.cache_key = "foo-1.0.0"
463
-
464
- # Explicitly set the identifier and dotted decimal identifiers to the
465
- # version number (but it could be anything).
466
- cb.identifier = "1.0.0"
467
- cb.dotted_decimal_identifier ="1.0.0"
468
- end
469
-
470
- p.local_cookbook("bar") do |cb|
471
- cb.source = "bar"
472
- cb.identifier = "0.1.0"
473
- cb.dotted_decimal_identifier = "0.1.0"
474
- end
475
- end
476
-
477
- end
478
-
479
- let(:expected_canonical_revision_string) do
480
- <<-REVISION_STRING
481
- name:custom_identifier
482
- run-list-item:recipe[foo]
483
- cookbook:foo;id:1.0.0
484
- cookbook:bar;id:0.1.0
485
- default_attributes:{}
486
- override_attributes:{}
487
- REVISION_STRING
488
- end
489
-
490
- let(:expected_revision_id) do
491
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
492
- end
493
-
494
- let(:compiled_policyfile) do
495
- {
496
-
497
- "revision_id" => expected_revision_id,
498
-
499
- "name" => "custom_identifier",
500
-
501
- "run_list" => ["recipe[foo]"],
502
-
503
- "cookbook_locks" => {
504
-
505
- "foo" => {
506
- "version" => "1.0.0",
507
- "identifier" => "1.0.0",
508
- "dotted_decimal_identifier" => "1.0.0",
509
- "cache_key" => "foo-1.0.0",
510
- "origin" => nil,
511
- "source_options" => nil
512
- },
513
-
514
- "bar" => {
515
- "version" => "0.1.0",
516
- "identifier" => "0.1.0",
517
- "dotted_decimal_identifier" => "0.1.0",
518
-
519
- "source" => "bar",
520
- "cache_key" => nil,
521
- "scm_info" => {
522
- "scm" => "git",
523
- "remote" => nil,
524
- "revision" => current_rev,
525
- "working_tree_clean" => true,
526
- "published" => false,
527
- "synchronized_remote_branches"=>[]
528
- },
529
- "source_options" => nil
530
- },
531
- },
532
-
533
- "default_attributes" => {},
534
- "override_attributes" => {},
535
-
536
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
537
- }
538
- end
539
-
540
- it "generates a lockfile with custom identifiers" do
541
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
542
- end
543
-
544
- it "generates a canonical revision string" do
545
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
546
- end
547
-
548
- it "generates a revision id" do
549
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
550
- end
551
-
552
- end
553
-
554
- context "with a policyfile lock with a mix of cached and local cookbooks" do
555
-
556
- include_context "setup git cookbooks"
557
-
558
- let(:relative_paths_root) do
559
- tempdir
560
- end
561
-
562
- let(:policyfile_lock) do
563
-
564
- ChefDK::PolicyfileLock.build(storage_config) do |p|
565
-
566
- # Required
567
- p.name = "basic_example"
568
-
569
- # Required. Should be fully expanded without roles
570
- p.run_list = ["recipe[foo]", "recipe[bar]", "recipe[baz::non_default]"]
571
-
572
- # A cached_cookbook is stored in the cache directory in a subdirectory
573
- # given by 'cache_key'. It is assumed to be static (not modified by the
574
- # user).
575
- p.cached_cookbook("foo") do |cb|
576
- cb.cache_key = "foo-1.0.0"
577
-
578
- # Optional attribute that humans can use to understand where a cookbook
579
- # came from.
580
- cb.origin = "https://community.chef.io/api/cookbooks/foo/1.0.0"
581
- end
582
-
583
- p.local_cookbook("bar") do |cb|
584
- cb.source = "bar"
585
- end
586
-
587
- p.cached_cookbook("baz") do |cb|
588
- cb.cache_key = "baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb"
589
- cb.origin = "git://github.com/opscode-cookbooks/bar.git"
590
- end
591
-
592
- p.cached_cookbook("dep_of_bar") do |cb|
593
- cb.cache_key = "dep_of_bar-1.2.3"
594
- cb.origin = "https://chef-server.example.com/cookbooks/dep_of_bar/1.2.3"
595
- end
596
- end
597
-
598
- end
599
-
600
- let(:expected_canonical_revision_string) do
601
- <<-REVISION_STRING
602
- name:basic_example
603
- run-list-item:recipe[foo]
604
- run-list-item:recipe[bar]
605
- run-list-item:recipe[baz::non_default]
606
- cookbook:foo;id:#{cookbook_foo_cksum}
607
- cookbook:bar;id:#{cookbook_bar_cksum}
608
- cookbook:baz;id:#{cookbook_baz_cksum}
609
- cookbook:dep_of_bar;id:#{cookbook_dep_of_bar_cksum}
610
- default_attributes:{}
611
- override_attributes:{}
612
- REVISION_STRING
613
- end
614
-
615
- let(:expected_revision_id) do
616
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
617
- end
618
-
619
- let(:compiled_policyfile) do
620
- {
621
-
622
- "revision_id" => expected_revision_id,
623
-
624
- "name" => "basic_example",
625
-
626
- "run_list" => ["recipe[foo]", "recipe[bar]", "recipe[baz::non_default]"],
627
-
628
- "cookbook_locks" => {
629
-
630
- "foo" => {
631
- "version" => "1.0.0",
632
- "identifier" => cookbook_foo_cksum,
633
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
634
- "origin" => "https://community.chef.io/api/cookbooks/foo/1.0.0",
635
- "cache_key" => "foo-1.0.0",
636
- "source_options" => nil
637
- },
638
-
639
- "bar" => {
640
- "version" => "0.1.0",
641
- "identifier" => cookbook_bar_cksum,
642
- "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
643
- "source" => "bar",
644
- "cache_key" => nil,
645
-
646
- "scm_info" => {
647
- "scm" => "git",
648
- "remote" => nil,
649
- "revision" => current_rev,
650
- "working_tree_clean" => true,
651
- "published" => false,
652
- "synchronized_remote_branches"=>[]
653
- },
654
- "source_options" => nil
655
- },
656
-
657
- "baz" => {
658
- "version" => "1.2.3",
659
- "identifier"=> cookbook_baz_cksum,
660
- "dotted_decimal_identifier" => cookbook_baz_cksum_dotted,
661
- "cache_key" => "baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb",
662
- "origin" => "git://github.com/opscode-cookbooks/bar.git",
663
- "source_options" => nil
664
- },
665
-
666
- "dep_of_bar" => {
667
- "version" => "1.2.3",
668
- "identifier" => cookbook_dep_of_bar_cksum,
669
- "dotted_decimal_identifier" => cookbook_dep_of_bar_cksum_dotted,
670
- "origin" => "https://chef-server.example.com/cookbooks/dep_of_bar/1.2.3",
671
- "cache_key" => "dep_of_bar-1.2.3",
672
- "source_options" => nil
673
-
674
- },
675
-
676
- },
677
-
678
- "default_attributes" => {},
679
- "override_attributes" => {},
680
-
681
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
682
-
683
- }
684
- end
685
-
686
- it "generates a lockfile with the relevant profile data for each cookbook" do
687
- generated = policyfile_lock.to_lock
688
- expect(generated['name']).to eq(compiled_policyfile['name'])
689
- expect(generated['run_list']).to eq(compiled_policyfile['run_list'])
690
-
691
- generated_locks = generated['cookbook_locks']
692
- expected_locks = compiled_policyfile['cookbook_locks']
693
-
694
- # test individually so failures are easier to read
695
- expect(generated_locks['foo']).to eq(expected_locks['foo'])
696
- expect(generated_locks['bar']).to eq(expected_locks['bar'])
697
- expect(generated_locks['baz']).to eq(expected_locks['baz'])
698
- expect(generated_locks['dep_of_bar']).to eq(expected_locks['dep_of_bar'])
699
-
700
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
701
- end
702
-
703
- it "generates a canonical revision string" do
704
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
705
- end
706
-
707
- it "generates a revision id" do
708
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
709
- end
710
-
711
- end
712
-
713
- context "with solution dependencies specified" do
714
-
715
- let(:policyfile_lock) do
716
- ChefDK::PolicyfileLock.build(storage_config) do |p|
717
-
718
- p.name = "minimal_policyfile"
719
-
720
- p.run_list = [ "recipe[foo]" ]
721
- p.cached_cookbook("foo") do |cb|
722
- cb.cache_key = "foo-1.0.0"
723
- end
724
-
725
- p.dependencies do |deps|
726
- deps.add_cookbook_dep("foo", "1.0.0", [])
727
- end
728
-
729
- end
730
- end
731
-
732
- let(:expected_canonical_revision_string) do
733
- <<-REVISION_STRING
734
- name:minimal_policyfile
735
- run-list-item:recipe[foo]
736
- cookbook:foo;id:#{cookbook_foo_cksum}
737
- default_attributes:{}
738
- override_attributes:{}
739
- REVISION_STRING
740
- end
741
-
742
- let(:expected_revision_id) do
743
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
744
- end
745
-
746
- let(:compiled_policyfile) do
747
- {
748
-
749
- "revision_id" => expected_revision_id,
750
-
751
- "name" => "minimal_policyfile",
752
-
753
- "run_list" => ["recipe[foo]"],
754
-
755
- "cookbook_locks" => {
756
-
757
- "foo" => {
758
- "version" => "1.0.0",
759
- "identifier" => cookbook_foo_cksum,
760
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
761
- "cache_key" => "foo-1.0.0",
762
- "origin" => nil,
763
- "source_options" => nil
764
- },
765
- },
766
-
767
- "default_attributes" => {},
768
- "override_attributes" => {},
769
-
770
- "solution_dependencies" => {
771
- "Policyfile" => [],
772
- "dependencies" => {"foo (1.0.0)" => []}
773
- }
774
- }
775
- end
776
-
777
- it "computes a minimal policyfile" do
778
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
779
- end
780
-
781
- end
782
-
783
- context "with named run_lists specified" do
784
-
785
- let(:policyfile_lock) do
786
- ChefDK::PolicyfileLock.build(storage_config) do |p|
787
-
788
- p.name = "minimal_policyfile"
789
-
790
- p.run_list = [ "recipe[foo]" ]
791
-
792
- p.named_run_lists = { "rl2" => [ "recipe[foo::bar]" ] }
793
-
794
- p.cached_cookbook("foo") do |cb|
795
- cb.cache_key = "foo-1.0.0"
796
- end
797
-
798
- end
799
- end
800
-
801
- let(:expected_canonical_revision_string) do
802
- <<-REVISION_STRING
803
- name:minimal_policyfile
804
- run-list-item:recipe[foo]
805
- named-run-list:rl2;run-list-item:recipe[foo::bar]
806
- cookbook:foo;id:#{cookbook_foo_cksum}
807
- default_attributes:{}
808
- override_attributes:{}
809
- REVISION_STRING
810
- end
811
-
812
- let(:expected_revision_id) do
813
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
814
- end
815
-
816
- let(:compiled_policyfile) do
817
- {
818
-
819
- "revision_id" => expected_revision_id,
820
-
821
- "name" => "minimal_policyfile",
822
-
823
- "run_list" => ["recipe[foo]"],
824
-
825
- "named_run_lists" => { "rl2" => [ "recipe[foo::bar]" ] },
826
-
827
- "cookbook_locks" => {
828
-
829
- "foo" => {
830
- "version" => "1.0.0",
831
- "identifier" => cookbook_foo_cksum,
832
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
833
- "cache_key" => "foo-1.0.0",
834
- "origin" => nil,
835
- "source_options" => nil
836
- },
837
- },
838
-
839
- "default_attributes" => {},
840
- "override_attributes" => {},
841
-
842
- "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
843
- }
844
- end
845
-
846
- it "includes the named run lists in the compiled policyfile" do
847
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
848
- end
849
-
850
- it "generates a canonical revision string" do
851
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
852
- end
853
-
854
- it "generates a revision id" do
855
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
856
- end
857
-
858
- end
859
-
860
- describe "building a policyfile lock from a policyfile compiler" do
861
-
862
- include_context "setup git cookbooks"
863
-
864
- let(:relative_paths_root) do
865
- tempdir
866
- end
867
-
868
- let(:cached_cookbook_uri) { "https://supermarket.chef.io/api/v1/cookbooks/foo/versions/1.0.0/download" }
869
-
870
- let(:cached_location_spec) do
871
- double( "ChefDK::Policyfile::CookbookLocationSpecification",
872
- mirrors_canonical_upstream?: true,
873
- cache_key: "foo-1.0.0",
874
- uri: cached_cookbook_uri,
875
- source_options_for_lock: { "artifactserver" => cached_cookbook_uri, "version" => "1.0.0" })
876
- end
877
-
878
- let(:local_location_spec) do
879
- double( "ChefDK::Policyfile::CookbookLocationSpecification",
880
- mirrors_canonical_upstream?: false,
881
- relative_paths_root: relative_paths_root,
882
- relative_path: "bar",
883
- source_options_for_lock: { "path" => "bar" })
884
- end
885
-
886
- let(:policyfile_solution_dependencies) do
887
- ChefDK::Policyfile::SolutionDependencies.new.tap do |s|
888
- s.add_policyfile_dep("foo", "~> 1.0")
889
- s.add_cookbook_dep("foo", "1.0.0", [])
890
- s.add_cookbook_dep("bar", "0.1.0", [])
891
- end
892
- end
893
-
894
- let(:policyfile_default_attrs) do
895
- {
896
- "foo" => "bar",
897
- "abc" => { "def" => { "ghi" => "xyz" } },
898
- "baz" => {
899
- "more_nested_stuff" => "yup",
900
- "an_array" => ["a", "b", "c"]
901
- }
902
- }
903
- end
904
-
905
- let(:canonicalized_default_attrs) do
906
- elements = [
907
- %q{"abc":{"def":{"ghi":"xyz"}}},
908
- %q{"baz":{"an_array":["a","b","c"],"more_nested_stuff":"yup"}},
909
- %q{"foo":"bar"}
910
- ]
911
- "{" + elements.join(',') + "}"
912
- end
913
-
914
- let(:policyfile_override_attrs) do
915
- {
916
- "foo" => "bar",
917
- "abc" => { "def" => { "ghi" => "xyz" } },
918
- "baz" => {
919
- "more_nested_stuff" => "yup",
920
- "an_array" => ["a", "b", "c"]
921
- }
922
- }
923
- end
924
-
925
- let(:canonicalized_override_attrs) { canonicalized_default_attrs }
926
-
927
- let(:policyfile_compiler) do
928
- double( "ChefDK::PolicyfileCompiler",
929
- name: "my-policyfile",
930
- normalized_run_list: %w[recipe[foo::default] recipe[bar::default]],
931
- normalized_named_run_lists: { "rl2" => %w[recipe[bar::default]] },
932
- all_cookbook_location_specs: {"foo" => cached_location_spec, "bar" => local_location_spec},
933
- solution_dependencies: policyfile_solution_dependencies,
934
- default_attributes: policyfile_default_attrs,
935
- override_attributes: policyfile_override_attrs )
936
- end
937
-
938
- let(:policyfile_lock) do
939
- ChefDK::PolicyfileLock.build_from_compiler(policyfile_compiler, storage_config)
940
- end
941
-
942
-
943
- let(:expected_canonical_revision_string) do
944
- <<-REVISION_STRING
945
- name:my-policyfile
946
- run-list-item:recipe[foo::default]
947
- run-list-item:recipe[bar::default]
948
- named-run-list:rl2;run-list-item:recipe[bar::default]
949
- cookbook:foo;id:#{cookbook_foo_cksum}
950
- cookbook:bar;id:#{cookbook_bar_cksum}
951
- default_attributes:#{canonicalized_default_attrs}
952
- override_attributes:#{canonicalized_override_attrs}
953
- REVISION_STRING
954
- end
955
-
956
- let(:expected_revision_id) do
957
- Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
958
- end
959
-
960
- let(:compiled_policyfile) do
961
- {
962
-
963
- "revision_id" => expected_revision_id,
964
-
965
- "name" => "my-policyfile",
966
-
967
- "run_list" => ["recipe[foo::default]", "recipe[bar::default]"],
968
-
969
- "named_run_lists" => { "rl2" => ["recipe[bar::default]"] },
970
-
971
- "cookbook_locks" => {
972
-
973
- "foo" => {
974
- "version" => "1.0.0",
975
- "identifier" => cookbook_foo_cksum,
976
- "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
977
- "cache_key" => "foo-1.0.0",
978
- "origin" => cached_cookbook_uri,
979
- "source_options" => { "artifactserver" => cached_cookbook_uri, "version" => "1.0.0" }
980
- },
981
-
982
- "bar" => {
983
- "version" => "0.1.0",
984
- "identifier" => cookbook_bar_cksum,
985
- "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
986
- "source" => "bar",
987
- "cache_key" => nil,
988
-
989
- "scm_info" => {
990
- "scm" => "git",
991
- "remote" => nil,
992
- "revision" => current_rev,
993
- "working_tree_clean" => true,
994
- "published" => false,
995
- "synchronized_remote_branches"=>[]
996
- },
997
- "source_options" => { "path" => "bar" }
998
- }
999
- },
1000
-
1001
- "default_attributes" => {
1002
- "foo" => "bar",
1003
- "abc" => { "def" => { "ghi" => "xyz" } },
1004
- "baz" => {
1005
- "more_nested_stuff" => "yup",
1006
- "an_array" => ["a", "b", "c"]
1007
- }
1008
- },
1009
-
1010
- "override_attributes" => {
1011
- "foo" => "bar",
1012
- "abc" => { "def" => { "ghi" => "xyz" } },
1013
- "baz" => {
1014
- "more_nested_stuff" => "yup",
1015
- "an_array" => ["a", "b", "c"]
1016
- }
1017
- },
1018
- "solution_dependencies" => {
1019
- "Policyfile" => [ [ "foo", "~> 1.0" ] ],
1020
- "dependencies" => { "foo (1.0.0)" => [], "bar (0.1.0)" => [] }
1021
- }
1022
- }
1023
- end
1024
-
1025
- it "adds a cached cookbook lock generator for the compiler's cached cookbook" do
1026
- expect(policyfile_lock.cookbook_locks).to have_key("foo")
1027
- cb_lock = policyfile_lock.cookbook_locks["foo"]
1028
- expect(cb_lock.origin).to eq(cached_location_spec.uri)
1029
- expect(cb_lock.cache_key).to eq(cached_location_spec.cache_key)
1030
- end
1031
-
1032
- it "adds a local cookbook lock generator for the compiler's local cookbook" do
1033
- expect(policyfile_lock.cookbook_locks).to have_key("bar")
1034
- cb_lock = policyfile_lock.cookbook_locks["bar"]
1035
- expect(cb_lock.source).to eq(local_location_spec.relative_path)
1036
- end
1037
-
1038
- it "sets named run lists on the policyfile lock" do
1039
- expect(policyfile_lock.named_run_lists).to eq("rl2" => %w[recipe[bar::default]])
1040
- end
1041
-
1042
- it "generates a lockfile data structure" do
1043
- expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
1044
- end
1045
-
1046
- it "generates a canonical revision string" do
1047
- expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
1048
- end
1049
-
1050
- it "generates a revision id" do
1051
- expect(policyfile_lock.revision_id).to eq(expected_revision_id)
1052
- end
1053
-
1054
- end
1055
-
1056
- 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
+ }
242
+ end
243
+
244
+ it "has a cache path" do
245
+ expect(policyfile_lock.cache_path).to eq(cache_path)
246
+ end
247
+
248
+ it "computes a minimal policyfile" do
249
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
250
+ end
251
+
252
+ it "generates a canonical revision string" do
253
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
254
+ end
255
+
256
+ it "generates a revision id" do
257
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
258
+ end
259
+
260
+ end
261
+
262
+ context "with a policyfile containing attributes" do
263
+
264
+ let(:policyfile_lock) do
265
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
266
+
267
+ p.name = "minimal_policyfile"
268
+
269
+ p.run_list = [ "recipe[foo]" ]
270
+ p.cached_cookbook("foo") do |cb|
271
+ cb.cache_key = "foo-1.0.0"
272
+ end
273
+
274
+ p.default_attributes = {
275
+ "foo" => "bar",
276
+ "aaa".encode('utf-16') => "aaa".encode('utf-16'),
277
+ "ddd" => true,
278
+ "ccc" => false,
279
+ "bbb" => nil,
280
+ "e" => 1.2,
281
+ "f" => 5,
282
+ "g" => 1_000_000_000_000_000.0,
283
+ "nested" => { "a" => "b" }
284
+ }
285
+ p.override_attributes = { "foo2" => "baz" }
286
+
287
+ end
288
+ end
289
+
290
+ let(:expected_canonical_revision_string) do
291
+ <<-REVISION_STRING
292
+ name:minimal_policyfile
293
+ run-list-item:recipe[foo]
294
+ cookbook:foo;id:467dc855408ce8b74f991c5dc2fd72a6aa369b60
295
+ default_attributes:{"aaa":"aaa","bbb":null,"ccc":false,"ddd":true,"e":1.2,"f":5,"foo":"bar","g":1e+15,"nested":{"a":"b"}}
296
+ override_attributes:{"foo2":"baz"}
297
+ REVISION_STRING
298
+ end
299
+
300
+ let(:expected_revision_id) do
301
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
302
+ end
303
+
304
+ let(:compiled_policyfile) do
305
+ {
306
+ "revision_id" => expected_revision_id,
307
+
308
+ "name" => "minimal_policyfile",
309
+
310
+ "run_list" => ["recipe[foo]"],
311
+
312
+ "cookbook_locks" => {
313
+
314
+ "foo" => {
315
+ "version" => "1.0.0",
316
+ "identifier" => cookbook_foo_cksum,
317
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
318
+ "cache_key" => "foo-1.0.0",
319
+ "origin" => nil,
320
+ "source_options" => nil
321
+ },
322
+ },
323
+ "default_attributes" => {
324
+ "foo" => "bar",
325
+ "aaa".encode('utf-16') => "aaa".encode('utf-16'),
326
+ "ddd" => true,
327
+ "ccc" => false,
328
+ "bbb" => nil,
329
+ "e" => 1.2,
330
+ "f" => 5,
331
+ "g" => 1_000_000_000_000_000.0,
332
+ "nested" => { "a" => "b" }
333
+ },
334
+ "override_attributes" => { "foo2" => "baz" },
335
+
336
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
337
+ }
338
+ end
339
+
340
+ it "has a cache path" do
341
+ expect(policyfile_lock.cache_path).to eq(cache_path)
342
+ end
343
+
344
+ it "computes a minimal policyfile" do
345
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
346
+ end
347
+
348
+ it "generates a canonical revision string" do
349
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
350
+ end
351
+
352
+ it "generates a revision id" do
353
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
354
+ end
355
+
356
+ end
357
+
358
+ context "with a policyfile containing a local cookbook" do
359
+
360
+ include_context "setup git cookbooks"
361
+ include_context "setup git cookbook remote"
362
+
363
+ let(:relative_paths_root) do
364
+ tempdir
365
+ end
366
+
367
+ let(:policyfile_lock) do
368
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
369
+
370
+ p.name = "dev_cookbook"
371
+
372
+ p.run_list = [ "recipe[bar]" ]
373
+ p.local_cookbook("bar") do |cb|
374
+ cb.source = "bar"
375
+ end
376
+
377
+ end
378
+ end
379
+
380
+ let(:expected_canonical_revision_string) do
381
+ <<-REVISION_STRING
382
+ name:dev_cookbook
383
+ run-list-item:recipe[bar]
384
+ cookbook:bar;id:#{cookbook_bar_cksum}
385
+ default_attributes:{}
386
+ override_attributes:{}
387
+ REVISION_STRING
388
+ end
389
+
390
+ let(:expected_revision_id) do
391
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
392
+ end
393
+
394
+ let(:compiled_policyfile) do
395
+ {
396
+
397
+ "revision_id" => expected_revision_id,
398
+
399
+ "name" => "dev_cookbook",
400
+
401
+ "run_list" => ["recipe[bar]"],
402
+
403
+ "cookbook_locks" => {
404
+
405
+ "bar" => {
406
+ "version" => "0.1.0",
407
+ "identifier" => cookbook_bar_cksum,
408
+ "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
409
+
410
+ "source" => "bar",
411
+ "cache_key" => nil,
412
+ "scm_info" => {
413
+ "scm" => "git",
414
+ "remote" => remote_url,
415
+ "revision" => current_rev,
416
+ "working_tree_clean" => true,
417
+ "published" => true,
418
+ "synchronized_remote_branches"=>["origin/master"]
419
+ },
420
+ "source_options" => nil
421
+ },
422
+ },
423
+
424
+ "default_attributes" => {},
425
+ "override_attributes" => {},
426
+
427
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
428
+ }
429
+ end
430
+
431
+ it "computes a lockfile including git data" do
432
+ actual_lock = policyfile_lock.to_lock
433
+ expect(actual_lock).to eq(compiled_policyfile)
434
+ end
435
+
436
+ it "generates a canonical revision string" do
437
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
438
+ end
439
+
440
+ it "generates a revision id" do
441
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
442
+ end
443
+
444
+ end
445
+
446
+ context "with a policyfile using custom identifiers" do
447
+
448
+ include_context "setup git cookbooks"
449
+
450
+ let(:relative_paths_root) do
451
+ tempdir
452
+ end
453
+
454
+ let(:policyfile_lock) do
455
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
456
+
457
+ p.name = "custom_identifier"
458
+
459
+ p.run_list = [ "recipe[foo]" ]
460
+
461
+ p.cached_cookbook("foo") do |cb|
462
+ cb.cache_key = "foo-1.0.0"
463
+
464
+ # Explicitly set the identifier and dotted decimal identifiers to the
465
+ # version number (but it could be anything).
466
+ cb.identifier = "1.0.0"
467
+ cb.dotted_decimal_identifier ="1.0.0"
468
+ end
469
+
470
+ p.local_cookbook("bar") do |cb|
471
+ cb.source = "bar"
472
+ cb.identifier = "0.1.0"
473
+ cb.dotted_decimal_identifier = "0.1.0"
474
+ end
475
+ end
476
+
477
+ end
478
+
479
+ let(:expected_canonical_revision_string) do
480
+ <<-REVISION_STRING
481
+ name:custom_identifier
482
+ run-list-item:recipe[foo]
483
+ cookbook:foo;id:1.0.0
484
+ cookbook:bar;id:0.1.0
485
+ default_attributes:{}
486
+ override_attributes:{}
487
+ REVISION_STRING
488
+ end
489
+
490
+ let(:expected_revision_id) do
491
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
492
+ end
493
+
494
+ let(:compiled_policyfile) do
495
+ {
496
+
497
+ "revision_id" => expected_revision_id,
498
+
499
+ "name" => "custom_identifier",
500
+
501
+ "run_list" => ["recipe[foo]"],
502
+
503
+ "cookbook_locks" => {
504
+
505
+ "foo" => {
506
+ "version" => "1.0.0",
507
+ "identifier" => "1.0.0",
508
+ "dotted_decimal_identifier" => "1.0.0",
509
+ "cache_key" => "foo-1.0.0",
510
+ "origin" => nil,
511
+ "source_options" => nil
512
+ },
513
+
514
+ "bar" => {
515
+ "version" => "0.1.0",
516
+ "identifier" => "0.1.0",
517
+ "dotted_decimal_identifier" => "0.1.0",
518
+
519
+ "source" => "bar",
520
+ "cache_key" => nil,
521
+ "scm_info" => {
522
+ "scm" => "git",
523
+ "remote" => nil,
524
+ "revision" => current_rev,
525
+ "working_tree_clean" => true,
526
+ "published" => false,
527
+ "synchronized_remote_branches"=>[]
528
+ },
529
+ "source_options" => nil
530
+ },
531
+ },
532
+
533
+ "default_attributes" => {},
534
+ "override_attributes" => {},
535
+
536
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
537
+ }
538
+ end
539
+
540
+ it "generates a lockfile with custom identifiers" do
541
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
542
+ end
543
+
544
+ it "generates a canonical revision string" do
545
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
546
+ end
547
+
548
+ it "generates a revision id" do
549
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
550
+ end
551
+
552
+ end
553
+
554
+ context "with a policyfile lock with a mix of cached and local cookbooks" do
555
+
556
+ include_context "setup git cookbooks"
557
+
558
+ let(:relative_paths_root) do
559
+ tempdir
560
+ end
561
+
562
+ let(:policyfile_lock) do
563
+
564
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
565
+
566
+ # Required
567
+ p.name = "basic_example"
568
+
569
+ # Required. Should be fully expanded without roles
570
+ p.run_list = ["recipe[foo]", "recipe[bar]", "recipe[baz::non_default]"]
571
+
572
+ # A cached_cookbook is stored in the cache directory in a subdirectory
573
+ # given by 'cache_key'. It is assumed to be static (not modified by the
574
+ # user).
575
+ p.cached_cookbook("foo") do |cb|
576
+ cb.cache_key = "foo-1.0.0"
577
+
578
+ # Optional attribute that humans can use to understand where a cookbook
579
+ # came from.
580
+ cb.origin = "https://community.chef.io/api/cookbooks/foo/1.0.0"
581
+ end
582
+
583
+ p.local_cookbook("bar") do |cb|
584
+ cb.source = "bar"
585
+ end
586
+
587
+ p.cached_cookbook("baz") do |cb|
588
+ cb.cache_key = "baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb"
589
+ cb.origin = "git://github.com/opscode-cookbooks/bar.git"
590
+ end
591
+
592
+ p.cached_cookbook("dep_of_bar") do |cb|
593
+ cb.cache_key = "dep_of_bar-1.2.3"
594
+ cb.origin = "https://chef-server.example.com/cookbooks/dep_of_bar/1.2.3"
595
+ end
596
+ end
597
+
598
+ end
599
+
600
+ let(:expected_canonical_revision_string) do
601
+ <<-REVISION_STRING
602
+ name:basic_example
603
+ run-list-item:recipe[foo]
604
+ run-list-item:recipe[bar]
605
+ run-list-item:recipe[baz::non_default]
606
+ cookbook:foo;id:#{cookbook_foo_cksum}
607
+ cookbook:bar;id:#{cookbook_bar_cksum}
608
+ cookbook:baz;id:#{cookbook_baz_cksum}
609
+ cookbook:dep_of_bar;id:#{cookbook_dep_of_bar_cksum}
610
+ default_attributes:{}
611
+ override_attributes:{}
612
+ REVISION_STRING
613
+ end
614
+
615
+ let(:expected_revision_id) do
616
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
617
+ end
618
+
619
+ let(:compiled_policyfile) do
620
+ {
621
+
622
+ "revision_id" => expected_revision_id,
623
+
624
+ "name" => "basic_example",
625
+
626
+ "run_list" => ["recipe[foo]", "recipe[bar]", "recipe[baz::non_default]"],
627
+
628
+ "cookbook_locks" => {
629
+
630
+ "foo" => {
631
+ "version" => "1.0.0",
632
+ "identifier" => cookbook_foo_cksum,
633
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
634
+ "origin" => "https://community.chef.io/api/cookbooks/foo/1.0.0",
635
+ "cache_key" => "foo-1.0.0",
636
+ "source_options" => nil
637
+ },
638
+
639
+ "bar" => {
640
+ "version" => "0.1.0",
641
+ "identifier" => cookbook_bar_cksum,
642
+ "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
643
+ "source" => "bar",
644
+ "cache_key" => nil,
645
+
646
+ "scm_info" => {
647
+ "scm" => "git",
648
+ "remote" => nil,
649
+ "revision" => current_rev,
650
+ "working_tree_clean" => true,
651
+ "published" => false,
652
+ "synchronized_remote_branches"=>[]
653
+ },
654
+ "source_options" => nil
655
+ },
656
+
657
+ "baz" => {
658
+ "version" => "1.2.3",
659
+ "identifier"=> cookbook_baz_cksum,
660
+ "dotted_decimal_identifier" => cookbook_baz_cksum_dotted,
661
+ "cache_key" => "baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb",
662
+ "origin" => "git://github.com/opscode-cookbooks/bar.git",
663
+ "source_options" => nil
664
+ },
665
+
666
+ "dep_of_bar" => {
667
+ "version" => "1.2.3",
668
+ "identifier" => cookbook_dep_of_bar_cksum,
669
+ "dotted_decimal_identifier" => cookbook_dep_of_bar_cksum_dotted,
670
+ "origin" => "https://chef-server.example.com/cookbooks/dep_of_bar/1.2.3",
671
+ "cache_key" => "dep_of_bar-1.2.3",
672
+ "source_options" => nil
673
+
674
+ },
675
+
676
+ },
677
+
678
+ "default_attributes" => {},
679
+ "override_attributes" => {},
680
+
681
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
682
+
683
+ }
684
+ end
685
+
686
+ it "generates a lockfile with the relevant profile data for each cookbook" do
687
+ generated = policyfile_lock.to_lock
688
+ expect(generated['name']).to eq(compiled_policyfile['name'])
689
+ expect(generated['run_list']).to eq(compiled_policyfile['run_list'])
690
+
691
+ generated_locks = generated['cookbook_locks']
692
+ expected_locks = compiled_policyfile['cookbook_locks']
693
+
694
+ # test individually so failures are easier to read
695
+ expect(generated_locks['foo']).to eq(expected_locks['foo'])
696
+ expect(generated_locks['bar']).to eq(expected_locks['bar'])
697
+ expect(generated_locks['baz']).to eq(expected_locks['baz'])
698
+ expect(generated_locks['dep_of_bar']).to eq(expected_locks['dep_of_bar'])
699
+
700
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
701
+ end
702
+
703
+ it "generates a canonical revision string" do
704
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
705
+ end
706
+
707
+ it "generates a revision id" do
708
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
709
+ end
710
+
711
+ end
712
+
713
+ context "with solution dependencies specified" do
714
+
715
+ let(:policyfile_lock) do
716
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
717
+
718
+ p.name = "minimal_policyfile"
719
+
720
+ p.run_list = [ "recipe[foo]" ]
721
+ p.cached_cookbook("foo") do |cb|
722
+ cb.cache_key = "foo-1.0.0"
723
+ end
724
+
725
+ p.dependencies do |deps|
726
+ deps.add_cookbook_dep("foo", "1.0.0", [])
727
+ end
728
+
729
+ end
730
+ end
731
+
732
+ let(:expected_canonical_revision_string) do
733
+ <<-REVISION_STRING
734
+ name:minimal_policyfile
735
+ run-list-item:recipe[foo]
736
+ cookbook:foo;id:#{cookbook_foo_cksum}
737
+ default_attributes:{}
738
+ override_attributes:{}
739
+ REVISION_STRING
740
+ end
741
+
742
+ let(:expected_revision_id) do
743
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
744
+ end
745
+
746
+ let(:compiled_policyfile) do
747
+ {
748
+
749
+ "revision_id" => expected_revision_id,
750
+
751
+ "name" => "minimal_policyfile",
752
+
753
+ "run_list" => ["recipe[foo]"],
754
+
755
+ "cookbook_locks" => {
756
+
757
+ "foo" => {
758
+ "version" => "1.0.0",
759
+ "identifier" => cookbook_foo_cksum,
760
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
761
+ "cache_key" => "foo-1.0.0",
762
+ "origin" => nil,
763
+ "source_options" => nil
764
+ },
765
+ },
766
+
767
+ "default_attributes" => {},
768
+ "override_attributes" => {},
769
+
770
+ "solution_dependencies" => {
771
+ "Policyfile" => [],
772
+ "dependencies" => {"foo (1.0.0)" => []}
773
+ }
774
+ }
775
+ end
776
+
777
+ it "computes a minimal policyfile" do
778
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
779
+ end
780
+
781
+ end
782
+
783
+ context "with named run_lists specified" do
784
+
785
+ let(:policyfile_lock) do
786
+ ChefDK::PolicyfileLock.build(storage_config) do |p|
787
+
788
+ p.name = "minimal_policyfile"
789
+
790
+ p.run_list = [ "recipe[foo]" ]
791
+
792
+ p.named_run_lists = { "rl2" => [ "recipe[foo::bar]" ] }
793
+
794
+ p.cached_cookbook("foo") do |cb|
795
+ cb.cache_key = "foo-1.0.0"
796
+ end
797
+
798
+ end
799
+ end
800
+
801
+ let(:expected_canonical_revision_string) do
802
+ <<-REVISION_STRING
803
+ name:minimal_policyfile
804
+ run-list-item:recipe[foo]
805
+ named-run-list:rl2;run-list-item:recipe[foo::bar]
806
+ cookbook:foo;id:#{cookbook_foo_cksum}
807
+ default_attributes:{}
808
+ override_attributes:{}
809
+ REVISION_STRING
810
+ end
811
+
812
+ let(:expected_revision_id) do
813
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
814
+ end
815
+
816
+ let(:compiled_policyfile) do
817
+ {
818
+
819
+ "revision_id" => expected_revision_id,
820
+
821
+ "name" => "minimal_policyfile",
822
+
823
+ "run_list" => ["recipe[foo]"],
824
+
825
+ "named_run_lists" => { "rl2" => [ "recipe[foo::bar]" ] },
826
+
827
+ "cookbook_locks" => {
828
+
829
+ "foo" => {
830
+ "version" => "1.0.0",
831
+ "identifier" => cookbook_foo_cksum,
832
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
833
+ "cache_key" => "foo-1.0.0",
834
+ "origin" => nil,
835
+ "source_options" => nil
836
+ },
837
+ },
838
+
839
+ "default_attributes" => {},
840
+ "override_attributes" => {},
841
+
842
+ "solution_dependencies" => { "Policyfile" => [], "dependencies" => {} }
843
+ }
844
+ end
845
+
846
+ it "includes the named run lists in the compiled policyfile" do
847
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
848
+ end
849
+
850
+ it "generates a canonical revision string" do
851
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
852
+ end
853
+
854
+ it "generates a revision id" do
855
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
856
+ end
857
+
858
+ end
859
+
860
+ describe "building a policyfile lock from a policyfile compiler" do
861
+
862
+ include_context "setup git cookbooks"
863
+
864
+ let(:relative_paths_root) do
865
+ tempdir
866
+ end
867
+
868
+ let(:cached_cookbook_uri) { "https://supermarket.chef.io/api/v1/cookbooks/foo/versions/1.0.0/download" }
869
+
870
+ let(:cached_location_spec) do
871
+ double( "ChefDK::Policyfile::CookbookLocationSpecification",
872
+ mirrors_canonical_upstream?: true,
873
+ cache_key: "foo-1.0.0",
874
+ uri: cached_cookbook_uri,
875
+ source_options_for_lock: { "artifactserver" => cached_cookbook_uri, "version" => "1.0.0" })
876
+ end
877
+
878
+ let(:local_location_spec) do
879
+ double( "ChefDK::Policyfile::CookbookLocationSpecification",
880
+ mirrors_canonical_upstream?: false,
881
+ relative_paths_root: relative_paths_root,
882
+ relative_path: "bar",
883
+ source_options_for_lock: { "path" => "bar" })
884
+ end
885
+
886
+ let(:policyfile_solution_dependencies) do
887
+ ChefDK::Policyfile::SolutionDependencies.new.tap do |s|
888
+ s.add_policyfile_dep("foo", "~> 1.0")
889
+ s.add_cookbook_dep("foo", "1.0.0", [])
890
+ s.add_cookbook_dep("bar", "0.1.0", [])
891
+ end
892
+ end
893
+
894
+ let(:policyfile_default_attrs) do
895
+ {
896
+ "foo" => "bar",
897
+ "abc" => { "def" => { "ghi" => "xyz" } },
898
+ "baz" => {
899
+ "more_nested_stuff" => "yup",
900
+ "an_array" => ["a", "b", "c"]
901
+ }
902
+ }
903
+ end
904
+
905
+ let(:canonicalized_default_attrs) do
906
+ elements = [
907
+ %q{"abc":{"def":{"ghi":"xyz"}}},
908
+ %q{"baz":{"an_array":["a","b","c"],"more_nested_stuff":"yup"}},
909
+ %q{"foo":"bar"}
910
+ ]
911
+ "{" + elements.join(',') + "}"
912
+ end
913
+
914
+ let(:policyfile_override_attrs) do
915
+ {
916
+ "foo" => "bar",
917
+ "abc" => { "def" => { "ghi" => "xyz" } },
918
+ "baz" => {
919
+ "more_nested_stuff" => "yup",
920
+ "an_array" => ["a", "b", "c"]
921
+ }
922
+ }
923
+ end
924
+
925
+ let(:canonicalized_override_attrs) { canonicalized_default_attrs }
926
+
927
+ let(:policyfile_compiler) do
928
+ double( "ChefDK::PolicyfileCompiler",
929
+ name: "my-policyfile",
930
+ normalized_run_list: %w[recipe[foo::default] recipe[bar::default]],
931
+ normalized_named_run_lists: { "rl2" => %w[recipe[bar::default]] },
932
+ all_cookbook_location_specs: {"foo" => cached_location_spec, "bar" => local_location_spec},
933
+ solution_dependencies: policyfile_solution_dependencies,
934
+ default_attributes: policyfile_default_attrs,
935
+ override_attributes: policyfile_override_attrs )
936
+ end
937
+
938
+ let(:policyfile_lock) do
939
+ ChefDK::PolicyfileLock.build_from_compiler(policyfile_compiler, storage_config)
940
+ end
941
+
942
+
943
+ let(:expected_canonical_revision_string) do
944
+ <<-REVISION_STRING
945
+ name:my-policyfile
946
+ run-list-item:recipe[foo::default]
947
+ run-list-item:recipe[bar::default]
948
+ named-run-list:rl2;run-list-item:recipe[bar::default]
949
+ cookbook:foo;id:#{cookbook_foo_cksum}
950
+ cookbook:bar;id:#{cookbook_bar_cksum}
951
+ default_attributes:#{canonicalized_default_attrs}
952
+ override_attributes:#{canonicalized_override_attrs}
953
+ REVISION_STRING
954
+ end
955
+
956
+ let(:expected_revision_id) do
957
+ Digest::SHA256.new.hexdigest(expected_canonical_revision_string)
958
+ end
959
+
960
+ let(:compiled_policyfile) do
961
+ {
962
+
963
+ "revision_id" => expected_revision_id,
964
+
965
+ "name" => "my-policyfile",
966
+
967
+ "run_list" => ["recipe[foo::default]", "recipe[bar::default]"],
968
+
969
+ "named_run_lists" => { "rl2" => ["recipe[bar::default]"] },
970
+
971
+ "cookbook_locks" => {
972
+
973
+ "foo" => {
974
+ "version" => "1.0.0",
975
+ "identifier" => cookbook_foo_cksum,
976
+ "dotted_decimal_identifier" => cookbook_foo_cksum_dotted,
977
+ "cache_key" => "foo-1.0.0",
978
+ "origin" => cached_cookbook_uri,
979
+ "source_options" => { "artifactserver" => cached_cookbook_uri, "version" => "1.0.0" }
980
+ },
981
+
982
+ "bar" => {
983
+ "version" => "0.1.0",
984
+ "identifier" => cookbook_bar_cksum,
985
+ "dotted_decimal_identifier" => cookbook_bar_cksum_dotted,
986
+ "source" => "bar",
987
+ "cache_key" => nil,
988
+
989
+ "scm_info" => {
990
+ "scm" => "git",
991
+ "remote" => nil,
992
+ "revision" => current_rev,
993
+ "working_tree_clean" => true,
994
+ "published" => false,
995
+ "synchronized_remote_branches"=>[]
996
+ },
997
+ "source_options" => { "path" => "bar" }
998
+ }
999
+ },
1000
+
1001
+ "default_attributes" => {
1002
+ "foo" => "bar",
1003
+ "abc" => { "def" => { "ghi" => "xyz" } },
1004
+ "baz" => {
1005
+ "more_nested_stuff" => "yup",
1006
+ "an_array" => ["a", "b", "c"]
1007
+ }
1008
+ },
1009
+
1010
+ "override_attributes" => {
1011
+ "foo" => "bar",
1012
+ "abc" => { "def" => { "ghi" => "xyz" } },
1013
+ "baz" => {
1014
+ "more_nested_stuff" => "yup",
1015
+ "an_array" => ["a", "b", "c"]
1016
+ }
1017
+ },
1018
+ "solution_dependencies" => {
1019
+ "Policyfile" => [ [ "foo", "~> 1.0" ] ],
1020
+ "dependencies" => { "foo (1.0.0)" => [], "bar (0.1.0)" => [] }
1021
+ }
1022
+ }
1023
+ end
1024
+
1025
+ it "adds a cached cookbook lock generator for the compiler's cached cookbook" do
1026
+ expect(policyfile_lock.cookbook_locks).to have_key("foo")
1027
+ cb_lock = policyfile_lock.cookbook_locks["foo"]
1028
+ expect(cb_lock.origin).to eq(cached_location_spec.uri)
1029
+ expect(cb_lock.cache_key).to eq(cached_location_spec.cache_key)
1030
+ end
1031
+
1032
+ it "adds a local cookbook lock generator for the compiler's local cookbook" do
1033
+ expect(policyfile_lock.cookbook_locks).to have_key("bar")
1034
+ cb_lock = policyfile_lock.cookbook_locks["bar"]
1035
+ expect(cb_lock.source).to eq(local_location_spec.relative_path)
1036
+ end
1037
+
1038
+ it "sets named run lists on the policyfile lock" do
1039
+ expect(policyfile_lock.named_run_lists).to eq("rl2" => %w[recipe[bar::default]])
1040
+ end
1041
+
1042
+ it "generates a lockfile data structure" do
1043
+ expect(policyfile_lock.to_lock).to eq(compiled_policyfile)
1044
+ end
1045
+
1046
+ it "generates a canonical revision string" do
1047
+ expect(policyfile_lock.canonical_revision_string).to eq(expected_canonical_revision_string)
1048
+ end
1049
+
1050
+ it "generates a revision id" do
1051
+ expect(policyfile_lock.revision_id).to eq(expected_revision_id)
1052
+ end
1053
+
1054
+ end
1055
+
1056
+ end