chef-cli 1.0.3

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