chef-dk 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +190 -190
  3. data/Gemfile +26 -26
  4. data/LICENSE +201 -201
  5. data/README.md +292 -276
  6. data/Rakefile +18 -18
  7. data/bin/chef +25 -25
  8. data/chef-dk.gemspec +62 -0
  9. data/lib/chef-dk.rb +19 -19
  10. data/lib/chef-dk/authenticated_http.rb +40 -40
  11. data/lib/chef-dk/builtin_commands.rb +60 -60
  12. data/lib/chef-dk/chef_runner.rb +98 -98
  13. data/lib/chef-dk/cli.rb +200 -200
  14. data/lib/chef-dk/command/base.rb +79 -79
  15. data/lib/chef-dk/command/clean_policy_cookbooks.rb +116 -116
  16. data/lib/chef-dk/command/clean_policy_revisions.rb +113 -113
  17. data/lib/chef-dk/command/delete_policy.rb +122 -122
  18. data/lib/chef-dk/command/delete_policy_group.rb +122 -122
  19. data/lib/chef-dk/command/diff.rb +316 -316
  20. data/lib/chef-dk/command/env.rb +90 -90
  21. data/lib/chef-dk/command/exec.rb +45 -45
  22. data/lib/chef-dk/command/export.rb +151 -151
  23. data/lib/chef-dk/command/gem.rb +47 -47
  24. data/lib/chef-dk/command/generate.rb +120 -120
  25. data/lib/chef-dk/command/generator_commands.rb +80 -80
  26. data/lib/chef-dk/command/generator_commands/app.rb +107 -107
  27. data/lib/chef-dk/command/generator_commands/attribute.rb +37 -37
  28. data/lib/chef-dk/command/generator_commands/base.rb +121 -121
  29. data/lib/chef-dk/command/generator_commands/cookbook.rb +153 -119
  30. data/lib/chef-dk/command/generator_commands/cookbook_code_file.rb +100 -100
  31. data/lib/chef-dk/command/generator_commands/cookbook_file.rb +45 -45
  32. data/lib/chef-dk/command/generator_commands/generator_generator.rb +177 -177
  33. data/lib/chef-dk/command/generator_commands/lwrp.rb +36 -36
  34. data/lib/chef-dk/command/generator_commands/policyfile.rb +127 -86
  35. data/lib/chef-dk/command/generator_commands/recipe.rb +36 -36
  36. data/lib/chef-dk/command/generator_commands/repo.rb +125 -96
  37. data/lib/chef-dk/command/generator_commands/template.rb +46 -46
  38. data/lib/chef-dk/command/install.rb +121 -121
  39. data/lib/chef-dk/command/provision.rb +438 -438
  40. data/lib/chef-dk/command/push.rb +118 -118
  41. data/lib/chef-dk/command/push_archive.rb +126 -126
  42. data/lib/chef-dk/command/shell_init.rb +180 -180
  43. data/lib/chef-dk/command/show_policy.rb +165 -165
  44. data/lib/chef-dk/command/undelete.rb +155 -155
  45. data/lib/chef-dk/command/update.rb +129 -129
  46. data/lib/chef-dk/command/verify.rb +534 -490
  47. data/lib/chef-dk/commands_map.rb +115 -115
  48. data/lib/chef-dk/completions/bash.sh.erb +5 -5
  49. data/lib/chef-dk/completions/chef.fish.erb +10 -10
  50. data/lib/chef-dk/completions/zsh.zsh.erb +21 -21
  51. data/lib/chef-dk/component_test.rb +173 -171
  52. data/lib/chef-dk/configurable.rb +57 -57
  53. data/lib/chef-dk/cookbook_metadata.rb +45 -45
  54. data/lib/chef-dk/cookbook_omnifetch.rb +32 -32
  55. data/lib/chef-dk/cookbook_profiler/git.rb +151 -151
  56. data/lib/chef-dk/cookbook_profiler/identifiers.rb +72 -72
  57. data/lib/chef-dk/cookbook_profiler/null_scm.rb +32 -32
  58. data/lib/chef-dk/exceptions.rb +126 -113
  59. data/lib/chef-dk/generator.rb +163 -163
  60. data/lib/chef-dk/helpers.rb +159 -159
  61. data/lib/chef-dk/pager.rb +106 -106
  62. data/lib/chef-dk/policyfile/chef_repo_cookbook_source.rb +138 -122
  63. data/lib/chef-dk/policyfile/chef_server_cookbook_source.rb +54 -54
  64. data/lib/chef-dk/policyfile/community_cookbook_source.rb +97 -82
  65. data/lib/chef-dk/policyfile/comparison_base.rb +124 -124
  66. data/lib/chef-dk/policyfile/cookbook_location_specification.rb +141 -133
  67. data/lib/chef-dk/policyfile/cookbook_locks.rb +466 -466
  68. data/lib/chef-dk/policyfile/cookbook_sources.rb +22 -21
  69. data/lib/chef-dk/policyfile/delivery_supermarket_source.rb +90 -0
  70. data/lib/chef-dk/policyfile/differ.rb +266 -266
  71. data/lib/chef-dk/policyfile/dsl.rb +223 -197
  72. data/lib/chef-dk/policyfile/lister.rb +232 -232
  73. data/lib/chef-dk/policyfile/null_cookbook_source.rb +45 -45
  74. data/lib/chef-dk/policyfile/read_cookbook_for_compat_mode_upload.rb +124 -124
  75. data/lib/chef-dk/policyfile/reports/install.rb +70 -70
  76. data/lib/chef-dk/policyfile/reports/table_printer.rb +58 -58
  77. data/lib/chef-dk/policyfile/reports/upload.rb +70 -70
  78. data/lib/chef-dk/policyfile/solution_dependencies.rb +298 -298
  79. data/lib/chef-dk/policyfile/storage_config.rb +100 -100
  80. data/lib/chef-dk/policyfile/undo_record.rb +142 -142
  81. data/lib/chef-dk/policyfile/undo_stack.rb +130 -130
  82. data/lib/chef-dk/policyfile/uploader.rb +213 -213
  83. data/lib/chef-dk/policyfile_compiler.rb +380 -322
  84. data/lib/chef-dk/policyfile_lock.rb +552 -552
  85. data/lib/chef-dk/policyfile_services/clean_policies.rb +95 -95
  86. data/lib/chef-dk/policyfile_services/clean_policy_cookbooks.rb +125 -125
  87. data/lib/chef-dk/policyfile_services/export_repo.rb +309 -309
  88. data/lib/chef-dk/policyfile_services/install.rb +125 -125
  89. data/lib/chef-dk/policyfile_services/push.rb +114 -114
  90. data/lib/chef-dk/policyfile_services/push_archive.rb +173 -173
  91. data/lib/chef-dk/policyfile_services/rm_policy.rb +142 -142
  92. data/lib/chef-dk/policyfile_services/rm_policy_group.rb +86 -86
  93. data/lib/chef-dk/policyfile_services/show_policy.rb +237 -237
  94. data/lib/chef-dk/policyfile_services/undelete.rb +108 -108
  95. data/lib/chef-dk/policyfile_services/update_attributes.rb +104 -104
  96. data/lib/chef-dk/service_exception_inspectors.rb +25 -25
  97. data/lib/chef-dk/service_exception_inspectors/base.rb +40 -40
  98. data/lib/chef-dk/service_exception_inspectors/http.rb +121 -121
  99. data/lib/chef-dk/service_exceptions.rb +143 -143
  100. data/lib/chef-dk/shell_out.rb +36 -36
  101. data/lib/chef-dk/skeletons/code_generator/files/default/Berksfile +3 -3
  102. data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +100 -100
  103. data/lib/chef-dk/skeletons/code_generator/files/default/cookbook_readmes/README-policy.md +9 -9
  104. data/lib/chef-dk/skeletons/code_generator/files/default/cookbook_readmes/README.md +54 -54
  105. data/lib/chef-dk/skeletons/code_generator/files/default/gitignore +16 -16
  106. data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +28 -28
  107. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/README.md +27 -27
  108. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +7 -7
  109. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/metadata.rb +3 -3
  110. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +8 -8
  111. data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/README.md +58 -58
  112. data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/example/example_item.json +3 -3
  113. data/lib/chef-dk/skeletons/code_generator/files/default/repo/dot-chef-repo.txt +6 -0
  114. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/README.md +9 -9
  115. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/example.json +12 -12
  116. data/lib/chef-dk/skeletons/code_generator/files/default/repo/policies/README.md +24 -0
  117. data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/README.md +9 -9
  118. data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/example.json +12 -12
  119. data/lib/chef-dk/skeletons/code_generator/files/default/serverspec_spec_helper.rb +8 -8
  120. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper.rb +2 -2
  121. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper_policyfile.rb +2 -0
  122. data/lib/chef-dk/skeletons/code_generator/metadata.rb +8 -8
  123. data/lib/chef-dk/skeletons/code_generator/recipes/app.rb +97 -97
  124. data/lib/chef-dk/skeletons/code_generator/recipes/attribute.rb +12 -12
  125. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook.rb +117 -104
  126. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook_file.rb +24 -24
  127. data/lib/chef-dk/skeletons/code_generator/recipes/lwrp.rb +23 -23
  128. data/lib/chef-dk/skeletons/code_generator/recipes/policyfile.rb +8 -8
  129. data/lib/chef-dk/skeletons/code_generator/recipes/recipe.rb +27 -27
  130. data/lib/chef-dk/skeletons/code_generator/recipes/repo.rb +67 -48
  131. data/lib/chef-dk/skeletons/code_generator/recipes/template.rb +32 -32
  132. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.all_rights.erb +3 -3
  133. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.apache2.erb +201 -201
  134. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv2.erb +339 -339
  135. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv3.erb +674 -674
  136. data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.mit.erb +21 -21
  137. data/lib/chef-dk/skeletons/code_generator/templates/default/Policyfile.rb.erb +25 -20
  138. data/lib/chef-dk/skeletons/code_generator/templates/default/README.md.erb +4 -4
  139. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen.yml.erb +21 -16
  140. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen_policyfile.yml.erb +32 -27
  141. data/lib/chef-dk/skeletons/code_generator/templates/default/metadata.rb.erb +7 -7
  142. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe.rb.erb +5 -5
  143. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe_spec.rb.erb +20 -20
  144. data/lib/chef-dk/skeletons/code_generator/templates/default/repo/gitignore.erb +11 -11
  145. data/lib/chef-dk/skeletons/code_generator/templates/default/serverspec_default_spec.rb.erb +9 -9
  146. data/lib/chef-dk/ui.rb +58 -58
  147. data/lib/chef-dk/version.rb +20 -20
  148. data/lib/kitchen/provisioner/policyfile_zero.rb +189 -193
  149. data/spec/shared/a_file_generator.rb +125 -125
  150. data/spec/shared/a_generated_file.rb +12 -12
  151. data/spec/shared/command_with_ui_object.rb +11 -11
  152. data/spec/shared/custom_generator_cookbook.rb +117 -117
  153. data/spec/shared/fixture_cookbook_checksums.rb +47 -47
  154. data/spec/shared/setup_git_cookbooks.rb +53 -53
  155. data/spec/spec_helper.rb +50 -49
  156. data/spec/test_helpers.rb +84 -84
  157. data/spec/unit/chef_runner_spec.rb +111 -111
  158. data/spec/unit/cli_spec.rb +357 -357
  159. data/spec/unit/command/base_spec.rb +169 -169
  160. data/spec/unit/command/clean_policy_cookbooks_spec.rb +181 -181
  161. data/spec/unit/command/clean_policy_revisions_spec.rb +181 -181
  162. data/spec/unit/command/delete_policy_group_spec.rb +207 -207
  163. data/spec/unit/command/delete_policy_spec.rb +207 -207
  164. data/spec/unit/command/diff_spec.rb +312 -312
  165. data/spec/unit/command/env_spec.rb +52 -52
  166. data/spec/unit/command/exec_spec.rb +179 -179
  167. data/spec/unit/command/export_spec.rb +189 -189
  168. data/spec/unit/command/generate_spec.rb +142 -142
  169. data/spec/unit/command/generator_commands/app_spec.rb +169 -169
  170. data/spec/unit/command/generator_commands/attribute_spec.rb +32 -32
  171. data/spec/unit/command/generator_commands/cookbook_file_spec.rb +32 -32
  172. data/spec/unit/command/generator_commands/cookbook_spec.rb +450 -320
  173. data/spec/unit/command/generator_commands/generator_generator_spec.rb +229 -229
  174. data/spec/unit/command/generator_commands/lwrp_spec.rb +32 -32
  175. data/spec/unit/command/generator_commands/policyfile_spec.rb +225 -125
  176. data/spec/unit/command/generator_commands/recipe_spec.rb +34 -34
  177. data/spec/unit/command/generator_commands/repo_spec.rb +367 -283
  178. data/spec/unit/command/generator_commands/template_spec.rb +32 -32
  179. data/spec/unit/command/install_spec.rb +179 -179
  180. data/spec/unit/command/provision_spec.rb +592 -592
  181. data/spec/unit/command/push_archive_spec.rb +153 -153
  182. data/spec/unit/command/push_spec.rb +199 -199
  183. data/spec/unit/command/shell_init_spec.rb +329 -329
  184. data/spec/unit/command/show_policy_spec.rb +235 -235
  185. data/spec/unit/command/undelete_spec.rb +246 -246
  186. data/spec/unit/command/update_spec.rb +251 -251
  187. data/spec/unit/command/verify_spec.rb +325 -323
  188. data/spec/unit/commands_map_spec.rb +57 -57
  189. data/spec/unit/component_test_spec.rb +126 -126
  190. data/spec/unit/cookbook_metadata_spec.rb +98 -98
  191. data/spec/unit/cookbook_profiler/git_spec.rb +176 -176
  192. data/spec/unit/cookbook_profiler/identifiers_spec.rb +83 -83
  193. data/spec/unit/fixtures/chef-runner-cookbooks/test_cookbook/recipes/recipe_one.rb +9 -9
  194. data/spec/unit/fixtures/chef-runner-cookbooks/test_cookbook/recipes/recipe_two.rb +9 -9
  195. data/spec/unit/fixtures/command/cli_test_command.rb +26 -26
  196. data/spec/unit/fixtures/command/explicit_path_example.rb +7 -7
  197. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/.kitchen.yml +16 -16
  198. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/Berksfile +3 -3
  199. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/README.md +4 -4
  200. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/chefignore +96 -96
  201. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/metadata.rb +8 -8
  202. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/recipes/default.rb +8 -8
  203. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/.kitchen.yml +16 -16
  204. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/Berksfile +3 -3
  205. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/README.md +4 -4
  206. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/chefignore +96 -96
  207. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/metadata.rb +8 -8
  208. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/recipes/default.rb +8 -8
  209. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/.kitchen.yml +16 -16
  210. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/Berksfile +3 -3
  211. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/README.md +4 -4
  212. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/chefignore +96 -96
  213. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/metadata.rb +8 -8
  214. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/recipes/default.rb +8 -8
  215. data/spec/unit/fixtures/cookbooks_api/pruned_small_universe.json +1321 -1321
  216. data/spec/unit/fixtures/cookbooks_api/small_universe.json +2987 -2987
  217. data/spec/unit/fixtures/cookbooks_api/universe.json +1 -1
  218. data/spec/unit/fixtures/cookbooks_api/update_fixtures.rb +36 -36
  219. data/spec/unit/fixtures/dev_cookbooks/README.md +16 -16
  220. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/berkshelf/integration_test +2 -2
  221. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/berkshelf/verify_me +5 -5
  222. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/chef/verify_me +3 -3
  223. data/spec/unit/fixtures/eg_omnibus_dir/valid/embedded/apps/test-kitchen/verify_me +2 -2
  224. data/spec/unit/fixtures/example_cookbook/.gitignore +17 -17
  225. data/spec/unit/fixtures/example_cookbook/.kitchen.yml +16 -16
  226. data/spec/unit/fixtures/example_cookbook/Berksfile +3 -3
  227. data/spec/unit/fixtures/example_cookbook/README.md +4 -4
  228. data/spec/unit/fixtures/example_cookbook/chefignore +96 -96
  229. data/spec/unit/fixtures/example_cookbook/metadata.rb +8 -8
  230. data/spec/unit/fixtures/example_cookbook/recipes/default.rb +8 -8
  231. data/spec/unit/fixtures/example_cookbook_metadata_json_only/.gitignore +17 -17
  232. data/spec/unit/fixtures/example_cookbook_metadata_json_only/.kitchen.yml +16 -16
  233. data/spec/unit/fixtures/example_cookbook_metadata_json_only/Berksfile +3 -3
  234. data/spec/unit/fixtures/example_cookbook_metadata_json_only/README.md +4 -4
  235. data/spec/unit/fixtures/example_cookbook_metadata_json_only/chefignore +96 -96
  236. data/spec/unit/fixtures/example_cookbook_metadata_json_only/metadata.json +5 -5
  237. data/spec/unit/fixtures/example_cookbook_metadata_json_only/recipes/default.rb +8 -8
  238. data/spec/unit/fixtures/example_cookbook_no_metadata/.gitignore +17 -17
  239. data/spec/unit/fixtures/example_cookbook_no_metadata/.kitchen.yml +16 -16
  240. data/spec/unit/fixtures/example_cookbook_no_metadata/Berksfile +3 -3
  241. data/spec/unit/fixtures/example_cookbook_no_metadata/README.md +4 -4
  242. data/spec/unit/fixtures/example_cookbook_no_metadata/chefignore +96 -96
  243. data/spec/unit/fixtures/example_cookbook_no_metadata/recipes/default.rb +8 -8
  244. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/README.md +4 -4
  245. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/chefignore +96 -96
  246. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/metadata.rb +8 -8
  247. data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/recipes/default.rb +8 -8
  248. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/Berksfile +3 -3
  249. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/README.md +4 -4
  250. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/chefignore +96 -96
  251. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/metadata.rb +9 -9
  252. data/spec/unit/fixtures/local_path_cookbooks/cookbook-with-a-dep/recipes/default.rb +8 -8
  253. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/.kitchen.yml +16 -16
  254. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/Berksfile +3 -3
  255. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/README.md +4 -4
  256. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/chefignore +96 -96
  257. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/metadata.rb +8 -8
  258. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/recipes/default.rb +8 -8
  259. data/spec/unit/fixtures/local_path_cookbooks/metadata-missing/README.md +2 -2
  260. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/.kitchen.yml +16 -16
  261. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/README.md +4 -4
  262. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/metadata.rb +8 -8
  263. data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/recipes/default.rb +8 -8
  264. data/spec/unit/generator_spec.rb +120 -120
  265. data/spec/unit/helpers_spec.rb +92 -92
  266. data/spec/unit/pager_spec.rb +119 -119
  267. data/spec/unit/policyfile/chef_repo_cookbook_source_spec.rb +93 -66
  268. data/spec/unit/policyfile/chef_server_cookbook_source_spec.rb +34 -34
  269. data/spec/unit/policyfile/community_cookbook_source_spec.rb +84 -51
  270. data/spec/unit/policyfile/comparison_base_spec.rb +343 -343
  271. data/spec/unit/policyfile/cookbook_location_specification_spec.rb +257 -252
  272. data/spec/unit/policyfile/cookbook_locks_spec.rb +529 -529
  273. data/spec/unit/policyfile/delivery_supermarket_source_spec.rb +130 -0
  274. data/spec/unit/policyfile/differ_spec.rb +687 -687
  275. data/spec/unit/policyfile/lister_spec.rb +272 -272
  276. data/spec/unit/policyfile/null_cookbook_source_spec.rb +35 -35
  277. data/spec/unit/policyfile/read_cookbook_for_compat_mode_upload_spec.rb +92 -92
  278. data/spec/unit/policyfile/reports/install_spec.rb +115 -115
  279. data/spec/unit/policyfile/reports/upload_spec.rb +96 -96
  280. data/spec/unit/policyfile/solution_dependencies_spec.rb +145 -145
  281. data/spec/unit/policyfile/storage_config_spec.rb +172 -172
  282. data/spec/unit/policyfile/undo_record_spec.rb +260 -260
  283. data/spec/unit/policyfile/undo_stack_spec.rb +266 -266
  284. data/spec/unit/policyfile/uploader_spec.rb +410 -410
  285. data/spec/unit/policyfile_demands_spec.rb +997 -876
  286. data/spec/unit/policyfile_evaluation_spec.rb +557 -441
  287. data/spec/unit/policyfile_lock_build_spec.rb +1056 -1056
  288. data/spec/unit/policyfile_lock_install_spec.rb +138 -138
  289. data/spec/unit/policyfile_lock_serialization_spec.rb +425 -425
  290. data/spec/unit/policyfile_lock_validation_spec.rb +611 -611
  291. data/spec/unit/policyfile_services/clean_policies_spec.rb +236 -236
  292. data/spec/unit/policyfile_services/clean_policy_cookbooks_spec.rb +275 -275
  293. data/spec/unit/policyfile_services/export_repo_spec.rb +439 -439
  294. data/spec/unit/policyfile_services/install_spec.rb +191 -191
  295. data/spec/unit/policyfile_services/push_archive_spec.rb +345 -345
  296. data/spec/unit/policyfile_services/push_spec.rb +233 -233
  297. data/spec/unit/policyfile_services/rm_policy_group_spec.rb +241 -241
  298. data/spec/unit/policyfile_services/rm_policy_spec.rb +266 -266
  299. data/spec/unit/policyfile_services/show_policy_spec.rb +889 -889
  300. data/spec/unit/policyfile_services/undelete_spec.rb +304 -304
  301. data/spec/unit/policyfile_services/update_attributes_spec.rb +217 -217
  302. data/spec/unit/service_exception_inspectors/base_spec.rb +43 -43
  303. data/spec/unit/service_exception_inspectors/http_spec.rb +140 -140
  304. data/spec/unit/shell_out_spec.rb +34 -34
  305. data/warning.txt +9 -0
  306. metadata +18 -5
@@ -1,95 +1,95 @@
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 'chef-dk/exceptions'
19
- require 'chef-dk/service_exceptions'
20
- require 'chef-dk/policyfile/lister'
21
-
22
- module ChefDK
23
- module PolicyfileServices
24
- class CleanPolicies
25
-
26
- Orphan = Struct.new(:policy_name, :revision_id)
27
-
28
- attr_reader :chef_config
29
- attr_reader :ui
30
-
31
- def initialize(config: nil, ui: nil)
32
- @chef_config = config
33
- @ui = ui
34
- end
35
-
36
- def run
37
- revisions_to_remove = orphaned_policies
38
-
39
- if revisions_to_remove.empty?
40
- ui.err("No policy revisions deleted")
41
- return true
42
- end
43
-
44
- results = revisions_to_remove.map do |policy|
45
- [ remove_policy(policy), policy ]
46
- end
47
-
48
- failures = results.select { |result, _policy| result.kind_of?(Exception) }
49
-
50
- unless failures.empty?
51
- details = failures.map do |result, policy|
52
- "- #{policy.policy_name} (#{policy.revision_id}): #{result.class} #{result}"
53
- end
54
-
55
- message = "Failed to delete some policy revisions:\n" + details.join("\n") + "\n"
56
-
57
- raise PolicyfileCleanError.new(message, MultipleErrors.new("multiple errors"))
58
- end
59
-
60
- true
61
- end
62
-
63
- def orphaned_policies
64
- policy_lister.policies_by_name.keys.inject([]) do |orphans, policy_name|
65
- orphans + policy_lister.orphaned_revisions(policy_name).map do |revision_id|
66
- Orphan.new(policy_name, revision_id)
67
- end
68
- end
69
- rescue => e
70
- raise PolicyfileCleanError.new("Failed to list policies for cleaning.", e)
71
- end
72
-
73
- def policy_lister
74
- @policy_lister ||= Policyfile::Lister.new(config: chef_config)
75
- end
76
-
77
- def http_client
78
- @http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
79
- signing_key_filename: chef_config.client_key,
80
- client_name: chef_config.node_name)
81
- end
82
-
83
- private
84
-
85
- def remove_policy(policy)
86
- ui.msg("DELETE #{policy.policy_name} #{policy.revision_id}")
87
- http_client.delete("/policies/#{policy.policy_name}/revisions/#{policy.revision_id}")
88
- :ok
89
- rescue => e
90
- e
91
- end
92
-
93
- end
94
- end
95
- end
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 'chef-dk/exceptions'
19
+ require 'chef-dk/service_exceptions'
20
+ require 'chef-dk/policyfile/lister'
21
+
22
+ module ChefDK
23
+ module PolicyfileServices
24
+ class CleanPolicies
25
+
26
+ Orphan = Struct.new(:policy_name, :revision_id)
27
+
28
+ attr_reader :chef_config
29
+ attr_reader :ui
30
+
31
+ def initialize(config: nil, ui: nil)
32
+ @chef_config = config
33
+ @ui = ui
34
+ end
35
+
36
+ def run
37
+ revisions_to_remove = orphaned_policies
38
+
39
+ if revisions_to_remove.empty?
40
+ ui.err("No policy revisions deleted")
41
+ return true
42
+ end
43
+
44
+ results = revisions_to_remove.map do |policy|
45
+ [ remove_policy(policy), policy ]
46
+ end
47
+
48
+ failures = results.select { |result, _policy| result.kind_of?(Exception) }
49
+
50
+ unless failures.empty?
51
+ details = failures.map do |result, policy|
52
+ "- #{policy.policy_name} (#{policy.revision_id}): #{result.class} #{result}"
53
+ end
54
+
55
+ message = "Failed to delete some policy revisions:\n" + details.join("\n") + "\n"
56
+
57
+ raise PolicyfileCleanError.new(message, MultipleErrors.new("multiple errors"))
58
+ end
59
+
60
+ true
61
+ end
62
+
63
+ def orphaned_policies
64
+ policy_lister.policies_by_name.keys.inject([]) do |orphans, policy_name|
65
+ orphans + policy_lister.orphaned_revisions(policy_name).map do |revision_id|
66
+ Orphan.new(policy_name, revision_id)
67
+ end
68
+ end
69
+ rescue => e
70
+ raise PolicyfileCleanError.new("Failed to list policies for cleaning.", e)
71
+ end
72
+
73
+ def policy_lister
74
+ @policy_lister ||= Policyfile::Lister.new(config: chef_config)
75
+ end
76
+
77
+ def http_client
78
+ @http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
79
+ signing_key_filename: chef_config.client_key,
80
+ client_name: chef_config.node_name)
81
+ end
82
+
83
+ private
84
+
85
+ def remove_policy(policy)
86
+ ui.msg("DELETE #{policy.policy_name} #{policy.revision_id}")
87
+ http_client.delete("/policies/#{policy.policy_name}/revisions/#{policy.revision_id}")
88
+ :ok
89
+ rescue => e
90
+ e
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -1,125 +1,125 @@
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'
19
-
20
- require 'chef-dk/authenticated_http'
21
- require 'chef-dk/service_exceptions'
22
-
23
- module ChefDK
24
- module PolicyfileServices
25
-
26
- class CleanPolicyCookbooks
27
-
28
- attr_reader :chef_config
29
-
30
- attr_reader :ui
31
-
32
- def initialize(config: nil, ui: nil)
33
- @chef_config = config
34
- @ui = ui
35
-
36
- @all_cookbooks = nil
37
- @active_cookbooks = nil
38
- @all_policies = nil
39
- end
40
-
41
- def run
42
- gc_cookbooks
43
- rescue => e
44
- raise PolicyCookbookCleanError.new("Failed to cleanup policy cookbooks", e)
45
- end
46
-
47
- def gc_cookbooks
48
- cookbooks = cookbooks_to_clean
49
-
50
- if cookbooks.empty?
51
- ui.msg("No cookbooks deleted.")
52
- end
53
-
54
- cookbooks.each do |name, identifiers|
55
- identifiers.each do |identifier|
56
- http_client.delete("/cookbook_artifacts/#{name}/#{identifier}")
57
- ui.msg("DELETE #{name} #{identifier}")
58
- end
59
- end
60
- end
61
-
62
-
63
- def all_cookbooks
64
- cookbook_list = http_client.get("/cookbook_artifacts")
65
- cookbook_list.inject({}) do |cb_map, (name, cb_info)|
66
- cb_map[name] = cb_info["versions"].map { |v| v["identifier"] }
67
- cb_map
68
- end
69
- end
70
-
71
- def active_cookbooks
72
- policy_revisions_by_name.inject({}) do |cb_map, (policy_name, revision_ids)|
73
- revision_ids.each do |revision_id|
74
- cookbook_revisions_in_policy(policy_name, revision_id).each do |cb_name, identifier|
75
- cb_map[cb_name] ||= Set.new
76
- cb_map[cb_name] << identifier
77
- end
78
- end
79
- cb_map
80
- end
81
- end
82
-
83
- def cookbooks_to_clean
84
- active_cbs = active_cookbooks
85
-
86
- all_cookbooks.inject({}) do |cb_map, (cb_name, revisions)|
87
- active_revs = active_cbs[cb_name] || Set.new
88
- inactive_revs = Set.new(revisions) - active_revs
89
- cb_map[cb_name] = inactive_revs unless inactive_revs.empty?
90
-
91
- cb_map
92
- end
93
- end
94
-
95
- # @api private
96
- def policy_revisions_by_name
97
- policies_list = http_client.get("/policies")
98
- policies_list.inject({}) do |policies_map, (name, policy_info)|
99
- policies_map[name] = policy_info["revisions"].keys
100
- policies_map
101
- end
102
- end
103
-
104
- # @api private
105
- def cookbook_revisions_in_policy(name, revision_id)
106
- policy_revision_data = http_client.get("/policies/#{name}/revisions/#{revision_id}")
107
-
108
- policy_revision_data["cookbook_locks"].inject({}) do |cb_map, (cb_name, lock_info)|
109
- cb_map[cb_name] = lock_info["identifier"]
110
- cb_map
111
- end
112
- end
113
-
114
- # @api private
115
- # An instance of ChefDK::AuthenticatedHTTP configured with the user's
116
- # server URL and credentials.
117
- def http_client
118
- @http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
119
- signing_key_filename: chef_config.client_key,
120
- client_name: chef_config.node_name)
121
- end
122
- end
123
- end
124
- end
125
-
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'
19
+
20
+ require 'chef-dk/authenticated_http'
21
+ require 'chef-dk/service_exceptions'
22
+
23
+ module ChefDK
24
+ module PolicyfileServices
25
+
26
+ class CleanPolicyCookbooks
27
+
28
+ attr_reader :chef_config
29
+
30
+ attr_reader :ui
31
+
32
+ def initialize(config: nil, ui: nil)
33
+ @chef_config = config
34
+ @ui = ui
35
+
36
+ @all_cookbooks = nil
37
+ @active_cookbooks = nil
38
+ @all_policies = nil
39
+ end
40
+
41
+ def run
42
+ gc_cookbooks
43
+ rescue => e
44
+ raise PolicyCookbookCleanError.new("Failed to cleanup policy cookbooks", e)
45
+ end
46
+
47
+ def gc_cookbooks
48
+ cookbooks = cookbooks_to_clean
49
+
50
+ if cookbooks.empty?
51
+ ui.msg("No cookbooks deleted.")
52
+ end
53
+
54
+ cookbooks.each do |name, identifiers|
55
+ identifiers.each do |identifier|
56
+ http_client.delete("/cookbook_artifacts/#{name}/#{identifier}")
57
+ ui.msg("DELETE #{name} #{identifier}")
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ def all_cookbooks
64
+ cookbook_list = http_client.get("/cookbook_artifacts")
65
+ cookbook_list.inject({}) do |cb_map, (name, cb_info)|
66
+ cb_map[name] = cb_info["versions"].map { |v| v["identifier"] }
67
+ cb_map
68
+ end
69
+ end
70
+
71
+ def active_cookbooks
72
+ policy_revisions_by_name.inject({}) do |cb_map, (policy_name, revision_ids)|
73
+ revision_ids.each do |revision_id|
74
+ cookbook_revisions_in_policy(policy_name, revision_id).each do |cb_name, identifier|
75
+ cb_map[cb_name] ||= Set.new
76
+ cb_map[cb_name] << identifier
77
+ end
78
+ end
79
+ cb_map
80
+ end
81
+ end
82
+
83
+ def cookbooks_to_clean
84
+ active_cbs = active_cookbooks
85
+
86
+ all_cookbooks.inject({}) do |cb_map, (cb_name, revisions)|
87
+ active_revs = active_cbs[cb_name] || Set.new
88
+ inactive_revs = Set.new(revisions) - active_revs
89
+ cb_map[cb_name] = inactive_revs unless inactive_revs.empty?
90
+
91
+ cb_map
92
+ end
93
+ end
94
+
95
+ # @api private
96
+ def policy_revisions_by_name
97
+ policies_list = http_client.get("/policies")
98
+ policies_list.inject({}) do |policies_map, (name, policy_info)|
99
+ policies_map[name] = policy_info["revisions"].keys
100
+ policies_map
101
+ end
102
+ end
103
+
104
+ # @api private
105
+ def cookbook_revisions_in_policy(name, revision_id)
106
+ policy_revision_data = http_client.get("/policies/#{name}/revisions/#{revision_id}")
107
+
108
+ policy_revision_data["cookbook_locks"].inject({}) do |cb_map, (cb_name, lock_info)|
109
+ cb_map[cb_name] = lock_info["identifier"]
110
+ cb_map
111
+ end
112
+ end
113
+
114
+ # @api private
115
+ # An instance of ChefDK::AuthenticatedHTTP configured with the user's
116
+ # server URL and credentials.
117
+ def http_client
118
+ @http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
119
+ signing_key_filename: chef_config.client_key,
120
+ client_name: chef_config.node_name)
121
+ end
122
+ end
123
+ end
124
+ end
125
+
@@ -1,309 +1,309 @@
1
- #
2
- # Copyright:: Copyright (c) 2014 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 'fileutils'
19
- require 'tmpdir'
20
- require 'zlib'
21
-
22
- require 'archive/tar/minitar'
23
-
24
- require 'chef-dk/service_exceptions'
25
- require 'chef-dk/policyfile_lock'
26
- require 'chef-dk/policyfile/storage_config'
27
-
28
- module ChefDK
29
- module PolicyfileServices
30
-
31
- class ExportRepo
32
-
33
- # Policy groups provide namespaces for policies so that a Chef Server can
34
- # have multiple active iterations of a policy at once, but we don't need
35
- # this when serving a single exported policy via Chef Zero, so hardcode
36
- # it to a "well known" value:
37
- POLICY_GROUP = 'local'.freeze
38
-
39
- include Policyfile::StorageConfigDelegation
40
-
41
- attr_reader :storage_config
42
- attr_reader :root_dir
43
- attr_reader :export_dir
44
-
45
- def initialize(policyfile: nil, export_dir: nil, root_dir: nil, archive: false, force: false)
46
- @root_dir = root_dir
47
- @export_dir = File.expand_path(export_dir)
48
- @archive = archive
49
- @force_export = force
50
-
51
- @policy_data = nil
52
- @policyfile_lock = nil
53
-
54
- policyfile_rel_path = policyfile || "Policyfile.rb"
55
- policyfile_full_path = File.expand_path(policyfile_rel_path, root_dir)
56
- @storage_config = Policyfile::StorageConfig.new.use_policyfile(policyfile_full_path)
57
-
58
- @staging_dir = nil
59
- end
60
-
61
- def archive?
62
- @archive
63
- end
64
-
65
- def policy_name
66
- policyfile_lock.name
67
- end
68
-
69
- def run
70
- assert_lockfile_exists!
71
- assert_export_dir_clean!
72
-
73
- validate_lockfile
74
- write_updated_lockfile
75
- export
76
- end
77
-
78
- def policy_data
79
- @policy_data ||= FFI_Yajl::Parser.parse(IO.read(policyfile_lock_expanded_path))
80
- rescue => error
81
- raise PolicyfileExportRepoError.new("Error reading lockfile #{policyfile_lock_expanded_path}", error)
82
- end
83
-
84
- def policyfile_lock
85
- @policyfile_lock || validate_lockfile
86
- end
87
-
88
- def archive_file_location
89
- return nil unless archive?
90
- filename = "#{policyfile_lock.name}-#{policyfile_lock.revision_id}.tgz"
91
- File.join(export_dir, filename)
92
- end
93
-
94
- def export
95
- with_staging_dir do
96
- create_repo_structure
97
- copy_cookbooks
98
- create_policyfile_data_item
99
- copy_policyfile_lock
100
- create_client_rb
101
- if archive?
102
- create_archive
103
- else
104
- mv_staged_repo
105
- end
106
- end
107
- rescue => error
108
- msg = "Failed to export policy (in #{policyfile_filename}) to #{export_dir}"
109
- raise PolicyfileExportRepoError.new(msg, error)
110
- end
111
-
112
- private
113
-
114
- def with_staging_dir
115
- p = Process.pid
116
- t = Time.new.utc.strftime("%Y%m%d%H%M%S")
117
- Dir.mktmpdir("chefdk-export-#{p}-#{t}") do |d|
118
- begin
119
- @staging_dir = d
120
- yield
121
- ensure
122
- @staging_dir = nil
123
- end
124
- end
125
- end
126
-
127
- def create_archive
128
- Zlib::GzipWriter.open(archive_file_location) do |gz_file|
129
- Dir.chdir(staging_dir) do
130
- Archive::Tar::Minitar.pack(".", gz_file)
131
- end
132
- end
133
- end
134
-
135
- def staging_dir
136
- @staging_dir
137
- end
138
-
139
- def create_repo_structure
140
- FileUtils.mkdir_p(export_dir)
141
- FileUtils.mkdir_p(cookbooks_staging_dir)
142
- FileUtils.mkdir_p(policyfiles_data_bag_staging_dir)
143
- end
144
-
145
- def copy_cookbooks
146
- policyfile_lock.cookbook_locks.each do |name, lock|
147
- copy_cookbook(lock)
148
- end
149
- end
150
-
151
- def copy_cookbook(lock)
152
- dirname = "#{lock.name}-#{lock.dotted_decimal_identifier}"
153
- export_path = File.join(staging_dir, "cookbooks", dirname)
154
- metadata_rb_path = File.join(export_path, "metadata.rb")
155
- FileUtils.cp_r(lock.cookbook_path, export_path)
156
- FileUtils.rm_f(metadata_rb_path)
157
- metadata = lock.cookbook_version.metadata
158
- metadata.version(lock.dotted_decimal_identifier)
159
-
160
- metadata_json_path = File.join(export_path, "metadata.json")
161
-
162
- File.open(metadata_json_path, "wb+") do |f|
163
- f.print(FFI_Yajl::Encoder.encode(metadata.to_hash, pretty: true ))
164
- end
165
- end
166
-
167
- def create_policyfile_data_item
168
- lock_data = policyfile_lock.to_lock.dup
169
-
170
- lock_data["id"] = policy_id
171
-
172
- data_item = {
173
- "id" => policy_id,
174
- "name" => "data_bag_item_policyfiles_#{policy_id}",
175
- "data_bag" => "policyfiles",
176
- "raw_data" => lock_data,
177
- # we'd prefer to leave this out, but the "compatibility mode"
178
- # implementation in chef-client relies on magical class inflation
179
- "json_class" => "Chef::DataBagItem"
180
- }
181
-
182
- File.open(item_path, "wb+") do |f|
183
- f.print(FFI_Yajl::Encoder.encode(data_item, pretty: true ))
184
- end
185
- end
186
-
187
- def copy_policyfile_lock
188
- File.open(lockfile_staging_path, "wb+") do |f|
189
- f.print(FFI_Yajl::Encoder.encode(policyfile_lock.to_lock, pretty: true ))
190
- end
191
- end
192
-
193
- def create_client_rb
194
- File.open(client_rb_staging_path, "wb+") do |f|
195
- f.print( <<-CONFIG )
196
- ### Chef Client Configuration ###
197
- # The settings in this file will configure chef to apply the exported policy in
198
- # this directory. To use it, run:
199
- #
200
- # chef-client -c client.rb -z
201
- #
202
-
203
- use_policyfile true
204
-
205
- # compatibility mode settings are used because chef-zero doesn't yet support
206
- # native mode:
207
- deployment_group '#{policy_name}-local'
208
- versioned_cookbooks true
209
- policy_document_native_api false
210
-
211
- CONFIG
212
- end
213
- end
214
-
215
- def mv_staged_repo
216
- # If we got here, either these dirs are empty/don't exist or force is
217
- # set to true.
218
- FileUtils.rm_rf(cookbooks_dir)
219
- FileUtils.rm_rf(policyfiles_data_bag_dir)
220
-
221
- FileUtils.mv(cookbooks_staging_dir, export_dir)
222
- FileUtils.mkdir_p(export_data_bag_dir)
223
- FileUtils.mv(policyfiles_data_bag_staging_dir, export_data_bag_dir)
224
- FileUtils.mv(lockfile_staging_path, export_dir)
225
- FileUtils.mv(client_rb_staging_path, export_dir)
226
- end
227
-
228
- def validate_lockfile
229
- return @policyfile_lock if @policyfile_lock
230
- @policyfile_lock = ChefDK::PolicyfileLock.new(storage_config).build_from_lock_data(policy_data)
231
- # TODO: enumerate any cookbook that have been updated
232
- @policyfile_lock.validate_cookbooks!
233
- @policyfile_lock
234
- rescue PolicyfileExportRepoError
235
- raise
236
- rescue => error
237
- raise PolicyfileExportRepoError.new("Invalid lockfile data", error)
238
- end
239
-
240
- def write_updated_lockfile
241
- File.open(policyfile_lock_expanded_path, "wb+") do |f|
242
- f.print(FFI_Yajl::Encoder.encode(policyfile_lock.to_lock, pretty: true ))
243
- end
244
- end
245
-
246
- def assert_lockfile_exists!
247
- unless File.exist?(policyfile_lock_expanded_path)
248
- raise LockfileNotFound, "No lockfile at #{policyfile_lock_expanded_path} - you need to run `install` before `push`"
249
- end
250
- end
251
-
252
- def assert_export_dir_clean!
253
- if !force_export? && !conflicting_fs_entries.empty? && !archive?
254
- msg = "Export dir (#{export_dir}) not clean. Refusing to export. (Conflicting files: #{conflicting_fs_entries.join(', ')})"
255
- raise ExportDirNotEmpty, msg
256
- end
257
- end
258
-
259
- def force_export?
260
- @force_export
261
- end
262
-
263
- def conflicting_fs_entries
264
- Dir.glob(File.join(cookbooks_dir, "*")) +
265
- Dir.glob(File.join(policyfiles_data_bag_dir, "*")) +
266
- Dir.glob(File.join(export_dir, "Policyfile.lock.json"))
267
- end
268
-
269
- def cookbooks_dir
270
- File.join(export_dir, "cookbooks")
271
- end
272
-
273
- def export_data_bag_dir
274
- File.join(export_dir, "data_bags")
275
- end
276
-
277
- def policyfiles_data_bag_dir
278
- File.join(export_data_bag_dir, "policyfiles")
279
- end
280
-
281
- def policy_id
282
- "#{policyfile_lock.name}-#{POLICY_GROUP}"
283
- end
284
-
285
- def item_path
286
- File.join(staging_dir, "data_bags", "policyfiles", "#{policy_id}.json")
287
- end
288
-
289
- def cookbooks_staging_dir
290
- File.join(staging_dir, "cookbooks")
291
- end
292
-
293
- def policyfiles_data_bag_staging_dir
294
- File.join(staging_dir, "data_bags", "policyfiles")
295
- end
296
-
297
- def lockfile_staging_path
298
- File.join(staging_dir, "Policyfile.lock.json")
299
- end
300
-
301
- def client_rb_staging_path
302
- File.join(staging_dir, "client.rb")
303
- end
304
-
305
- end
306
-
307
- end
308
- end
309
-
1
+ #
2
+ # Copyright:: Copyright (c) 2014 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 'fileutils'
19
+ require 'tmpdir'
20
+ require 'zlib'
21
+
22
+ require 'archive/tar/minitar'
23
+
24
+ require 'chef-dk/service_exceptions'
25
+ require 'chef-dk/policyfile_lock'
26
+ require 'chef-dk/policyfile/storage_config'
27
+
28
+ module ChefDK
29
+ module PolicyfileServices
30
+
31
+ class ExportRepo
32
+
33
+ # Policy groups provide namespaces for policies so that a Chef Server can
34
+ # have multiple active iterations of a policy at once, but we don't need
35
+ # this when serving a single exported policy via Chef Zero, so hardcode
36
+ # it to a "well known" value:
37
+ POLICY_GROUP = 'local'.freeze
38
+
39
+ include Policyfile::StorageConfigDelegation
40
+
41
+ attr_reader :storage_config
42
+ attr_reader :root_dir
43
+ attr_reader :export_dir
44
+
45
+ def initialize(policyfile: nil, export_dir: nil, root_dir: nil, archive: false, force: false)
46
+ @root_dir = root_dir
47
+ @export_dir = File.expand_path(export_dir)
48
+ @archive = archive
49
+ @force_export = force
50
+
51
+ @policy_data = nil
52
+ @policyfile_lock = nil
53
+
54
+ policyfile_rel_path = policyfile || "Policyfile.rb"
55
+ policyfile_full_path = File.expand_path(policyfile_rel_path, root_dir)
56
+ @storage_config = Policyfile::StorageConfig.new.use_policyfile(policyfile_full_path)
57
+
58
+ @staging_dir = nil
59
+ end
60
+
61
+ def archive?
62
+ @archive
63
+ end
64
+
65
+ def policy_name
66
+ policyfile_lock.name
67
+ end
68
+
69
+ def run
70
+ assert_lockfile_exists!
71
+ assert_export_dir_clean!
72
+
73
+ validate_lockfile
74
+ write_updated_lockfile
75
+ export
76
+ end
77
+
78
+ def policy_data
79
+ @policy_data ||= FFI_Yajl::Parser.parse(IO.read(policyfile_lock_expanded_path))
80
+ rescue => error
81
+ raise PolicyfileExportRepoError.new("Error reading lockfile #{policyfile_lock_expanded_path}", error)
82
+ end
83
+
84
+ def policyfile_lock
85
+ @policyfile_lock || validate_lockfile
86
+ end
87
+
88
+ def archive_file_location
89
+ return nil unless archive?
90
+ filename = "#{policyfile_lock.name}-#{policyfile_lock.revision_id}.tgz"
91
+ File.join(export_dir, filename)
92
+ end
93
+
94
+ def export
95
+ with_staging_dir do
96
+ create_repo_structure
97
+ copy_cookbooks
98
+ create_policyfile_data_item
99
+ copy_policyfile_lock
100
+ create_client_rb
101
+ if archive?
102
+ create_archive
103
+ else
104
+ mv_staged_repo
105
+ end
106
+ end
107
+ rescue => error
108
+ msg = "Failed to export policy (in #{policyfile_filename}) to #{export_dir}"
109
+ raise PolicyfileExportRepoError.new(msg, error)
110
+ end
111
+
112
+ private
113
+
114
+ def with_staging_dir
115
+ p = Process.pid
116
+ t = Time.new.utc.strftime("%Y%m%d%H%M%S")
117
+ Dir.mktmpdir("chefdk-export-#{p}-#{t}") do |d|
118
+ begin
119
+ @staging_dir = d
120
+ yield
121
+ ensure
122
+ @staging_dir = nil
123
+ end
124
+ end
125
+ end
126
+
127
+ def create_archive
128
+ Zlib::GzipWriter.open(archive_file_location) do |gz_file|
129
+ Dir.chdir(staging_dir) do
130
+ Archive::Tar::Minitar.pack(".", gz_file)
131
+ end
132
+ end
133
+ end
134
+
135
+ def staging_dir
136
+ @staging_dir
137
+ end
138
+
139
+ def create_repo_structure
140
+ FileUtils.mkdir_p(export_dir)
141
+ FileUtils.mkdir_p(cookbooks_staging_dir)
142
+ FileUtils.mkdir_p(policyfiles_data_bag_staging_dir)
143
+ end
144
+
145
+ def copy_cookbooks
146
+ policyfile_lock.cookbook_locks.each do |name, lock|
147
+ copy_cookbook(lock)
148
+ end
149
+ end
150
+
151
+ def copy_cookbook(lock)
152
+ dirname = "#{lock.name}-#{lock.dotted_decimal_identifier}"
153
+ export_path = File.join(staging_dir, "cookbooks", dirname)
154
+ metadata_rb_path = File.join(export_path, "metadata.rb")
155
+ FileUtils.cp_r(lock.cookbook_path, export_path)
156
+ FileUtils.rm_f(metadata_rb_path)
157
+ metadata = lock.cookbook_version.metadata
158
+ metadata.version(lock.dotted_decimal_identifier)
159
+
160
+ metadata_json_path = File.join(export_path, "metadata.json")
161
+
162
+ File.open(metadata_json_path, "wb+") do |f|
163
+ f.print(FFI_Yajl::Encoder.encode(metadata.to_hash, pretty: true ))
164
+ end
165
+ end
166
+
167
+ def create_policyfile_data_item
168
+ lock_data = policyfile_lock.to_lock.dup
169
+
170
+ lock_data["id"] = policy_id
171
+
172
+ data_item = {
173
+ "id" => policy_id,
174
+ "name" => "data_bag_item_policyfiles_#{policy_id}",
175
+ "data_bag" => "policyfiles",
176
+ "raw_data" => lock_data,
177
+ # we'd prefer to leave this out, but the "compatibility mode"
178
+ # implementation in chef-client relies on magical class inflation
179
+ "json_class" => "Chef::DataBagItem"
180
+ }
181
+
182
+ File.open(item_path, "wb+") do |f|
183
+ f.print(FFI_Yajl::Encoder.encode(data_item, pretty: true ))
184
+ end
185
+ end
186
+
187
+ def copy_policyfile_lock
188
+ File.open(lockfile_staging_path, "wb+") do |f|
189
+ f.print(FFI_Yajl::Encoder.encode(policyfile_lock.to_lock, pretty: true ))
190
+ end
191
+ end
192
+
193
+ def create_client_rb
194
+ File.open(client_rb_staging_path, "wb+") do |f|
195
+ f.print( <<-CONFIG )
196
+ ### Chef Client Configuration ###
197
+ # The settings in this file will configure chef to apply the exported policy in
198
+ # this directory. To use it, run:
199
+ #
200
+ # chef-client -c client.rb -z
201
+ #
202
+
203
+ use_policyfile true
204
+
205
+ # compatibility mode settings are used because chef-zero doesn't yet support
206
+ # native mode:
207
+ deployment_group '#{policy_name}-local'
208
+ versioned_cookbooks true
209
+ policy_document_native_api false
210
+
211
+ CONFIG
212
+ end
213
+ end
214
+
215
+ def mv_staged_repo
216
+ # If we got here, either these dirs are empty/don't exist or force is
217
+ # set to true.
218
+ FileUtils.rm_rf(cookbooks_dir)
219
+ FileUtils.rm_rf(policyfiles_data_bag_dir)
220
+
221
+ FileUtils.mv(cookbooks_staging_dir, export_dir)
222
+ FileUtils.mkdir_p(export_data_bag_dir)
223
+ FileUtils.mv(policyfiles_data_bag_staging_dir, export_data_bag_dir)
224
+ FileUtils.mv(lockfile_staging_path, export_dir)
225
+ FileUtils.mv(client_rb_staging_path, export_dir)
226
+ end
227
+
228
+ def validate_lockfile
229
+ return @policyfile_lock if @policyfile_lock
230
+ @policyfile_lock = ChefDK::PolicyfileLock.new(storage_config).build_from_lock_data(policy_data)
231
+ # TODO: enumerate any cookbook that have been updated
232
+ @policyfile_lock.validate_cookbooks!
233
+ @policyfile_lock
234
+ rescue PolicyfileExportRepoError
235
+ raise
236
+ rescue => error
237
+ raise PolicyfileExportRepoError.new("Invalid lockfile data", error)
238
+ end
239
+
240
+ def write_updated_lockfile
241
+ File.open(policyfile_lock_expanded_path, "wb+") do |f|
242
+ f.print(FFI_Yajl::Encoder.encode(policyfile_lock.to_lock, pretty: true ))
243
+ end
244
+ end
245
+
246
+ def assert_lockfile_exists!
247
+ unless File.exist?(policyfile_lock_expanded_path)
248
+ raise LockfileNotFound, "No lockfile at #{policyfile_lock_expanded_path} - you need to run `install` before `push`"
249
+ end
250
+ end
251
+
252
+ def assert_export_dir_clean!
253
+ if !force_export? && !conflicting_fs_entries.empty? && !archive?
254
+ msg = "Export dir (#{export_dir}) not clean. Refusing to export. (Conflicting files: #{conflicting_fs_entries.join(', ')})"
255
+ raise ExportDirNotEmpty, msg
256
+ end
257
+ end
258
+
259
+ def force_export?
260
+ @force_export
261
+ end
262
+
263
+ def conflicting_fs_entries
264
+ Dir.glob(File.join(cookbooks_dir, "*")) +
265
+ Dir.glob(File.join(policyfiles_data_bag_dir, "*")) +
266
+ Dir.glob(File.join(export_dir, "Policyfile.lock.json"))
267
+ end
268
+
269
+ def cookbooks_dir
270
+ File.join(export_dir, "cookbooks")
271
+ end
272
+
273
+ def export_data_bag_dir
274
+ File.join(export_dir, "data_bags")
275
+ end
276
+
277
+ def policyfiles_data_bag_dir
278
+ File.join(export_data_bag_dir, "policyfiles")
279
+ end
280
+
281
+ def policy_id
282
+ "#{policyfile_lock.name}-#{POLICY_GROUP}"
283
+ end
284
+
285
+ def item_path
286
+ File.join(staging_dir, "data_bags", "policyfiles", "#{policy_id}.json")
287
+ end
288
+
289
+ def cookbooks_staging_dir
290
+ File.join(staging_dir, "cookbooks")
291
+ end
292
+
293
+ def policyfiles_data_bag_staging_dir
294
+ File.join(staging_dir, "data_bags", "policyfiles")
295
+ end
296
+
297
+ def lockfile_staging_path
298
+ File.join(staging_dir, "Policyfile.lock.json")
299
+ end
300
+
301
+ def client_rb_staging_path
302
+ File.join(staging_dir, "client.rb")
303
+ end
304
+
305
+ end
306
+
307
+ end
308
+ end
309
+