chef-cli 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,265 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2018 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require_relative "../policyfile_lock"
19
+ require_relative "../exceptions"
20
+ require_relative "../helpers"
21
+ require "mixlib/shellout" unless defined?(Mixlib::ShellOut)
22
+ require "tmpdir" unless defined?(Dir.mktmpdir)
23
+
24
+ module ChefCLI
25
+ module Policyfile
26
+
27
+ # A Policyfile lock fetcher that can read a lock file from a git repository.
28
+ #
29
+ # @author Ryan Hass
30
+ # @author Daniel DeLeo
31
+ #
32
+ # @since 3.0
33
+ #
34
+ class GitLockFetcher
35
+ attr_accessor :name
36
+ attr_accessor :source_options
37
+ attr_accessor :storage_config
38
+
39
+ attr_reader :uri
40
+ attr_reader :revision
41
+ attr_reader :path
42
+ attr_reader :branch
43
+ attr_reader :tag
44
+ attr_reader :ref
45
+
46
+ # Initialize a GitLockFetcher
47
+ #
48
+ # @param name [String] The name of the policyfile
49
+ # @param source_options [Hash] A hash with a :path key pointing at the location
50
+ # of the lock
51
+ def initialize(name, source_options, storage_config)
52
+ @name = name
53
+ @storage_config = storage_config
54
+ @source_options = symbolize_keys(source_options)
55
+ @revision = @source_options[:revision]
56
+ @path = @source_options[:path] || @source_options[:rel]
57
+ @uri = @source_options[:git]
58
+ @branch = @source_options[:branch]
59
+ @tag = @source_options[:tag]
60
+ @ref = @source_options[:ref]
61
+
62
+ # The revision to parse
63
+ @rev_parse = @source_options[:ref] || @source_options[:branch] || @source_options[:tag] || "master"
64
+ end
65
+
66
+ # @return [True] if there were no errors with the provided source_options
67
+ # @return [False] if there were errors with the provided source_options
68
+ def valid?
69
+ errors.empty?
70
+ end
71
+
72
+ # Check the options provided when craeting this class for errors
73
+ #
74
+ # @return [Array<String>] A list of errors found
75
+ def errors
76
+ error_messages = []
77
+ [:git].each do |key|
78
+ error_messages << "include_policy for #{name} is missing key #{key}" unless source_options[key]
79
+ end
80
+
81
+ error_messages
82
+ end
83
+
84
+ # @return [Hash] The source_options that describe how to fetch this exact lock again
85
+ def source_options_for_lock
86
+ source_options.merge({
87
+ revision: revision,
88
+ })
89
+ end
90
+
91
+ # Applies source options from a lock file. This is used to make sure that the same
92
+ # policyfile lock is loaded that was locked
93
+ #
94
+ # @param options_from_lock [Hash] The source options loaded from a policyfile lock
95
+ def apply_locked_source_options(options_from_lock)
96
+ options = options_from_lock.inject({}) do |acc, (key, value)|
97
+ acc[key.to_sym] = value
98
+ acc
99
+ end
100
+ source_options.merge!(options)
101
+ raise ChefCLI::InvalidLockfile, "Invalid source_options provided from lock data: #{options_from_lock_file.inspect}" if !valid?
102
+ end
103
+
104
+ # @return [Hash] of the policyfile lock data
105
+ def lock_data
106
+ @lock_data ||= fetch_lock_data.tap do |data|
107
+ data["cookbook_locks"].each do |cookbook_name, cookbook_lock|
108
+ if cookbook_lock["source_options"].key?("path")
109
+ cookbook_lock["source_options"].tap do |opt|
110
+ opt["git"] = uri unless opt.key?("git")
111
+ opt["revision"] = revision unless opt.key?("revision")
112
+ opt["branch"] = branch unless opt.key?("branch") || branch.nil?
113
+ opt["tag"] = tag unless opt.key?("tag") || branch.nil?
114
+ opt["ref"] = ref unless opt.key?("ref") || ref.nil?
115
+
116
+ path_keys = %w{path rel}.map { |path_key| path_key if opt.key?(path_key) }.compact
117
+
118
+ path_keys.each do |name|
119
+ # We can safely grab the entire cookbook when the Policyfile defines a cookbook path of itself (".")
120
+ if opt[name] == "."
121
+ opt.delete(name)
122
+ next
123
+ end
124
+
125
+ # Mutate the path key to a rel key so that we identify the source_type
126
+ # as a git repo and not a local directory. Git also doesn't like paths
127
+ # prefixed with `./` and cannot use relative paths outside the repo.
128
+ # http://rubular.com/r/JYpdYHT19p
129
+ pattern = /(^..\/)|(^.\/)/
130
+ opt["rel"] = opt[name].gsub(pattern, "")
131
+ end
132
+
133
+ # Delete the path key if present to ensure we use the git source_type
134
+ opt.delete("path")
135
+ end
136
+ end # cookbook_lock["source_options"]
137
+ end # data["cookbook_locks"].each
138
+ end # fetch_lock_data.tap
139
+
140
+ @lock_data
141
+ end
142
+
143
+ private
144
+
145
+ # Helper method to normalize data.
146
+ #
147
+ # @param [Hash] hash Hash with symbols and/or strings as keys.
148
+ # @return [Hash] Hash with only symbols as keys.
149
+ def symbolize_keys(hash)
150
+ hash.inject({}) { |memo, (k, v)| memo[k.to_sym] = v; memo }
151
+ end
152
+
153
+ def fetch_lock_data
154
+ install unless installed?
155
+ FFI_Yajl::Parser.parse(
156
+ show_file(rev_parse, lockfile_path)
157
+ )
158
+ end
159
+
160
+ # COPYPASTA from CookbookOmnifetch
161
+ def installed?
162
+ !!(revision && cache_path.exist?)
163
+ end
164
+
165
+ # COPYPASTA from CookbookOmnifetch::GitLocation and Berkshelf::GitLocation
166
+ # then munged since we do not have Policyfile validation in scope.
167
+ # Install into the chefcli cookbook store. This method leverages a cached
168
+ # git copy.
169
+ def install
170
+ if cached?
171
+ Dir.chdir(cache_path) do
172
+ git %{fetch --force --tags #{uri} "refs/heads/*:refs/heads/*"}
173
+ end
174
+ else
175
+ git %{clone #{uri} "#{cache_path}" --bare --no-hardlinks}
176
+ end
177
+
178
+ Dir.chdir(cache_path) do
179
+ @revision ||= git %{rev-parse #{rev_parse}}
180
+ end
181
+ end
182
+
183
+ def rev_parse
184
+ source_options[:revision] || @rev_parse
185
+ end
186
+
187
+ # Shows contents of a file from a shallow or full clone repository for a
188
+ # given git version.
189
+ #
190
+ # This method was originally made before I slammed a bunch of copypasta
191
+ # code in which is generally more tied to a specific git ref.
192
+ #
193
+ # @param version Git version as a tag, branch, or ref.
194
+ # @param file Full path to file including filename in repository
195
+ #
196
+ # @return [String] Content of specified file for a given revision.
197
+ def show_file(version, file)
198
+ git("show #{version}:#{file}", cwd: cache_path)
199
+ end
200
+
201
+ # COPYPASTA from CookbookOmnifetch
202
+ # Location an executable in the current user's $PATH
203
+ #
204
+ # @return [String, nil]
205
+ # the path to the executable, or +nil+ if not present
206
+ def which(executable)
207
+ if File.file?(executable) && File.executable?(executable)
208
+ executable
209
+ elsif ENV["PATH"]
210
+ path = ENV["PATH"].split(File::PATH_SEPARATOR).find do |p|
211
+ File.executable?(File.join(p, executable))
212
+ end
213
+ path && File.expand_path(executable, path)
214
+ end
215
+ end
216
+
217
+ # COPYPASTA from CookbookOmnifetch::Git
218
+ # Perform a git command.
219
+ #
220
+ # @param [String] command
221
+ # the command to run
222
+ # @param [Boolean] error
223
+ # whether to raise error if the command fails
224
+ #
225
+ # @raise [String]
226
+ # the +$stdout+ from the command
227
+ def git(command, options = {})
228
+ error = options[:error] || true
229
+ unless which("git") || which("git.exe") || which("git.bat")
230
+ raise GitNotInstalled
231
+ end
232
+
233
+ response = Mixlib::ShellOut.new(%{git #{command}}, options)
234
+ response.run_command
235
+
236
+ if error && response.error?
237
+ raise GitError.new "#{command} #{cache_path}: #{response.stderr}"
238
+ end
239
+
240
+ response.stdout.strip
241
+ end
242
+
243
+ # COPYPASTA from CookbookOmnifetch::Git (then munged by me)
244
+ # The path where this git repository is cached.
245
+ #
246
+ # @return [Pathname]
247
+ def cache_path
248
+ Pathname.new(File.expand_path(File.join(ChefCLI::Helpers.package_home, "cache")))
249
+ .join(".cache", "git", Digest::SHA1.hexdigest(uri))
250
+ end
251
+
252
+ # COPYPASTA from CookbookOmnifetch::Git
253
+ # Determine if this git repo has already been downloaded.
254
+ #
255
+ # @return [Boolean]
256
+ def cached?
257
+ cache_path.exist?
258
+ end
259
+
260
+ def lockfile_path
261
+ @path.nil? ? "Policyfile.lock.json" : @path
262
+ end
263
+ end
264
+ end
265
+ end
@@ -0,0 +1,156 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2014-2018 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require_relative "../ui"
19
+
20
+ module ChefCLI
21
+ module Policyfile
22
+ class IncludedPoliciesCookbookSource
23
+
24
+ class ConflictingCookbookVersions < StandardError
25
+ end
26
+
27
+ class ConflictingCookbookDependencies < StandardError
28
+ end
29
+
30
+ class ConflictingCookbookSources < StandardError
31
+ end
32
+
33
+ # Why do we need this class?
34
+ # If we rely on default sources, we may not have the the universe of cookbooks
35
+ # provided in the included policies
36
+ #
37
+ # This is not meant to be used from the DSL
38
+
39
+ # A list of included policies
40
+ attr_reader :included_policy_location_specs
41
+ # UI object for output
42
+ attr_accessor :ui
43
+
44
+ # Constructor
45
+ #
46
+ def initialize(included_policy_location_specs)
47
+ @included_policy_location_specs = included_policy_location_specs
48
+ @ui = UI.new
49
+ @preferred_cookbooks = []
50
+ yield self if block_given?
51
+ end
52
+
53
+ def default_source_args
54
+ [:included_policies, []]
55
+ end
56
+
57
+ def check_for_conflicts!
58
+ source_options
59
+ universe_graph
60
+ end
61
+
62
+ # All are preferred here
63
+ def preferred_source_for?(cookbook_name)
64
+ universe_graph.include?(cookbook_name)
65
+ end
66
+
67
+ def preferred_cookbooks
68
+ universe_graph.keys
69
+ end
70
+
71
+ def ==(other)
72
+ other.kind_of?(self.class) && other.included_policy_location_specs == included_policy_location_specs
73
+ end
74
+
75
+ # Calls the slurp_metadata! helper once to calculate the @universe_graph
76
+ # and @cookbook_version_paths metadata. Returns the @universe_graph.
77
+ #
78
+ # @return [Hash] universe_graph
79
+ def universe_graph
80
+ @universe_graph ||= build_universe
81
+ end
82
+
83
+ # Returns the metadata (path and version) for an individual cookbook
84
+ #
85
+ # @return [Hash] metadata for a single cookbook version
86
+ def source_options_for(cookbook_name, cookbook_version)
87
+ source_options[cookbook_name][cookbook_version]
88
+ end
89
+
90
+ def null?
91
+ false
92
+ end
93
+
94
+ def desc
95
+ "included_policies()"
96
+ end
97
+
98
+ private
99
+
100
+ def build_universe
101
+ included_policy_location_specs.inject({}) do |acc, policy_spec|
102
+ lock = policy_spec.policyfile_lock
103
+ cookbook_dependencies = lock.solution_dependencies.cookbook_dependencies
104
+ cookbook_dependencies.each do |(cookbook, deps)|
105
+ name = cookbook.name
106
+ version = cookbook.version
107
+ mapped_deps = deps.map do |dep|
108
+ [dep[0], dep[1].to_s]
109
+ end
110
+ if acc[name]
111
+ if acc[name][version]
112
+ if acc[name][version] != mapped_deps
113
+ raise ConflictingCookbookDependencies.new("Conflicting dependencies provided for cookbook #{name}")
114
+ end
115
+ else
116
+ raise ConflictingCookbookVersions.new("Multiple versions provided for cookbook #{name}")
117
+ end
118
+ else
119
+ acc[name] = {}
120
+ acc[name][version] = mapped_deps
121
+ end
122
+ end
123
+ acc
124
+ end
125
+ end
126
+
127
+ def source_options
128
+ @source_options ||= build_source_options
129
+ end
130
+
131
+ ## Collect all the source options
132
+ def build_source_options
133
+ included_policy_location_specs.inject({}) do |acc, policy_spec|
134
+ lock = policy_spec.policyfile_lock
135
+ lock.cookbook_locks.each do |(name, cookbook_lock)|
136
+ version = cookbook_lock.version
137
+ if acc[name]
138
+ if acc[name][version]
139
+ if acc[name][version] != cookbook_lock.source_options
140
+ raise ConflictingCookbookSources.new("Conflicting sources provided for cookbook #{name}")
141
+ end
142
+ else
143
+ raise ConflictingCookbookVersions.new("Multiple sources provided for cookbook #{name}")
144
+ end
145
+ else
146
+ acc[name] = {}
147
+ acc[name][version] = cookbook_lock.source_options
148
+ end
149
+ end
150
+ acc
151
+ end
152
+ end
153
+
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,229 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2015 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "set" unless defined?(Set)
19
+
20
+ require "chef/server_api"
21
+ require_relative "../service_exceptions"
22
+
23
+ module ChefCLI
24
+ module Policyfile
25
+
26
+ class RevIDLockDataMap
27
+
28
+ attr_reader :policy_name
29
+ attr_reader :lock_info_by_rev_id
30
+
31
+ def initialize(policy_name, lock_info_by_rev_id)
32
+ @policy_name = policy_name
33
+ @lock_info_by_rev_id = lock_info_by_rev_id
34
+ end
35
+
36
+ def cb_info_for(rev_id, cookbook_name)
37
+ lock = lock_info_by_rev_id[rev_id]
38
+ cookbook_lock = lock["cookbook_locks"][cookbook_name]
39
+
40
+ if cookbook_lock
41
+ [cookbook_lock["version"], cookbook_lock["identifier"] ]
42
+ else
43
+ nil
44
+ end
45
+ end
46
+
47
+ def cbs_with_differing_ids
48
+ cbs_with_differing_ids = Set.new
49
+ all_cookbook_names.each do |cookbook_name|
50
+ all_identifiers = lock_info_by_rev_id.inject(Set.new) do |id_set, (_rev_id, rev_info)|
51
+ cookbook_lock = rev_info["cookbook_locks"][cookbook_name]
52
+ identifier = cookbook_lock && cookbook_lock["identifier"]
53
+ id_set << identifier
54
+ end
55
+ cbs_with_differing_ids << cookbook_name if all_identifiers.size > 1
56
+ end
57
+ cbs_with_differing_ids
58
+ end
59
+
60
+ def all_cookbook_names
61
+ lock_info_by_rev_id.inject(Set.new) do |cb_set, (_rev_id, rev_info)|
62
+ cb_set.merge(rev_info["cookbook_locks"].keys)
63
+ end
64
+ end
65
+ end
66
+
67
+ class PolicyGroupRevIDMap
68
+
69
+ include Enumerable
70
+
71
+ attr_reader :policy_name
72
+ attr_reader :revision_ids_by_group
73
+
74
+ def initialize(policy_name, revision_ids_by_group)
75
+ @policy_name = policy_name
76
+ @revision_ids_by_group = revision_ids_by_group
77
+ end
78
+
79
+ def unique_revision_ids
80
+ revision_ids_by_group.values.uniq
81
+ end
82
+
83
+ def policy_group_names
84
+ revision_ids_by_group.keys
85
+ end
86
+
87
+ def max_group_name_length
88
+ policy_group_names.map(&:size).max
89
+ end
90
+
91
+ def format_revision_ids
92
+ revision_ids_by_group.inject({}) do |map, (group_name, rev_id)|
93
+ map[group_name] = yield rev_id
94
+ map
95
+ end
96
+ end
97
+
98
+ def empty?
99
+ policy_group_names.empty?
100
+ end
101
+
102
+ def each
103
+ revision_ids_by_group.each do |group_name, rev_id|
104
+ yield group_name, rev_id
105
+ end
106
+ end
107
+ end
108
+
109
+ class Lister
110
+
111
+ attr_accessor :policy_lock_content
112
+
113
+ attr_reader :config
114
+
115
+ def initialize(config: nil)
116
+ @config = config
117
+ @policies_by_name = nil
118
+ @policies_by_group = nil
119
+ @policy_lock_content = {}
120
+ @active_revisions = nil
121
+ end
122
+
123
+ # A Hash with the following format
124
+ # {
125
+ # "appserver" => {
126
+ # "1111111111111111111111111111111111111111111111111111111111111111" => {},
127
+ # "2222222222222222222222222222222222222222222222222222222222222222" => {}
128
+ # },
129
+ def policies_by_name
130
+ @policies_by_name || fetch_policy_lists
131
+ @policies_by_name
132
+ end
133
+
134
+ # A Hash with the following format:
135
+ # "dev" => {
136
+ # "appserver" => "1111111111111111111111111111111111111111111111111111111111111111",
137
+ # "load-balancer" => "5555555555555555555555555555555555555555555555555555555555555555",
138
+ # "db" => "9999999999999999999999999999999999999999999999999999999999999999"
139
+ # }
140
+ def policies_by_group
141
+ @policies_by_group || fetch_policy_lists
142
+ @policies_by_group
143
+ end
144
+
145
+ def revision_info_for(policy_name, _revision_id_list)
146
+ RevIDLockDataMap.new(policy_name, policy_lock_content[policy_name])
147
+ end
148
+
149
+ def revision_ids_by_group_for_each_policy
150
+ policies_by_name.each do |policy_name, _policies|
151
+ rev_id_by_group = revision_ids_by_group_for(policy_name)
152
+ yield policy_name, rev_id_by_group
153
+ end
154
+ end
155
+
156
+ def revision_ids_by_group_for(policy_name)
157
+ map = policies_by_group.inject({}) do |rev_id_map, (group_name, rev_id_map_for_group)|
158
+ rev_id_map[group_name] = rev_id_map_for_group[policy_name]
159
+ rev_id_map
160
+ end
161
+ PolicyGroupRevIDMap.new(policy_name, map)
162
+ end
163
+
164
+ def orphaned_revisions(policy_name)
165
+ orphans = []
166
+ policies_by_name[policy_name].each do |rev_id, _data|
167
+ orphans << rev_id unless active_revisions.include?(rev_id)
168
+ end
169
+ orphans
170
+ end
171
+
172
+ def active_revisions
173
+ @active_revisions ||= policies_by_group.inject(Set.new) do |set, (_group, policy_name_rev_id_map)|
174
+ policy_name_rev_id_map.each do |policy_name, rev_id|
175
+ set << rev_id
176
+ end
177
+ set
178
+ end
179
+ end
180
+
181
+ def empty?
182
+ policies_by_name.empty? && policies_by_group.empty?
183
+ end
184
+
185
+ def http_client
186
+ @http_client ||= Chef::ServerAPI.new(config.chef_server_url,
187
+ signing_key_filename: config.client_key,
188
+ client_name: config.node_name)
189
+ end
190
+
191
+ # @api private
192
+ # Sets internal copy of policyfile data to policies_by_name and
193
+ # policies_by_group. Used for internal testing.
194
+ def set!(policies_by_name, policies_by_group)
195
+ @policies_by_name = policies_by_name
196
+ @policies_by_group = policies_by_group
197
+ @active_revisions = nil
198
+ end
199
+
200
+ private
201
+
202
+ def fetch_policy_lists
203
+ policy_list_data = http_client.get("policies")
204
+ set_policies_by_name_from_api(policy_list_data)
205
+
206
+ policy_group_data = http_client.get("policy_groups")
207
+ set_policies_by_group_from_api(policy_group_data)
208
+ end
209
+
210
+ def set_policies_by_name_from_api(policy_list_data)
211
+ @policies_by_name = policy_list_data.inject({}) do |map, (policy_name, policy_info)|
212
+ map[policy_name] = policy_info["revisions"]
213
+ map
214
+ end
215
+ end
216
+
217
+ def set_policies_by_group_from_api(policy_group_data)
218
+ @policies_by_group = policy_group_data.inject({}) do |map, (policy_group, policy_info)|
219
+ map[policy_group] = (policy_info["policies"] || []).inject({}) do |rev_map, (policy_name, rev_info)|
220
+ rev_map[policy_name] = rev_info["revision_id"]; rev_map
221
+ end
222
+
223
+ map
224
+ end
225
+ end
226
+
227
+ end
228
+ end
229
+ end