chef-dk 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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