r10k 3.5.2

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 (358) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/pull_request_template.md +1 -0
  4. data/.github/workflows/docker.yml +56 -0
  5. data/.github/workflows/release.yml +36 -0
  6. data/.gitignore +9 -0
  7. data/.travis.yml +45 -0
  8. data/CHANGELOG.mkd +1759 -0
  9. data/CODEOWNERS +2 -0
  10. data/CONTRIBUTING.mkd +105 -0
  11. data/Gemfile +15 -0
  12. data/LICENSE +14 -0
  13. data/README.mkd +118 -0
  14. data/Rakefile +3 -0
  15. data/azure-pipelines.yml +86 -0
  16. data/bin/r10k +17 -0
  17. data/doc/common-patterns.mkd +44 -0
  18. data/doc/dynamic-environments.mkd +31 -0
  19. data/doc/dynamic-environments/configuration.mkd +669 -0
  20. data/doc/dynamic-environments/git-environments.mkd +75 -0
  21. data/doc/dynamic-environments/introduction.mkd +69 -0
  22. data/doc/dynamic-environments/master-configuration.mkd +40 -0
  23. data/doc/dynamic-environments/quickstart.mkd +201 -0
  24. data/doc/dynamic-environments/svn-environments.mkd +45 -0
  25. data/doc/dynamic-environments/usage.mkd +132 -0
  26. data/doc/dynamic-environments/workflow-guide.mkd +247 -0
  27. data/doc/faq.mkd +164 -0
  28. data/doc/git/cloning-and-mirroring.mkd +60 -0
  29. data/doc/git/providers.mkd +111 -0
  30. data/doc/puppetfile.mkd +309 -0
  31. data/doc/updating-your-puppetfile.mkd +38 -0
  32. data/docker/.gitignore +1 -0
  33. data/docker/.rspec +4 -0
  34. data/docker/Gemfile +11 -0
  35. data/docker/Makefile +89 -0
  36. data/docker/README.md +28 -0
  37. data/docker/r10k/Dockerfile +67 -0
  38. data/docker/r10k/adduser.sh +13 -0
  39. data/docker/r10k/docker-entrypoint.d/10-analytics.sh +30 -0
  40. data/docker/r10k/docker-entrypoint.sh +11 -0
  41. data/docker/r10k/release.Dockerfile +54 -0
  42. data/docker/spec/dockerfile_spec.rb +43 -0
  43. data/docker/spec/fixtures/Puppetfile +2 -0
  44. data/integration/Gemfile +19 -0
  45. data/integration/README.mkd +29 -0
  46. data/integration/Rakefile +77 -0
  47. data/integration/component/pre-suite/05_install_dev_r10k.rb +12 -0
  48. data/integration/files/README.mkd +4 -0
  49. data/integration/files/hiera.yaml +8 -0
  50. data/integration/files/modules/helloworld/manifests/init.pp +3 -0
  51. data/integration/files/modules/hieratest/manifests/init.pp +3 -0
  52. data/integration/files/modules/unicode/files/pretend_unicode +1 -0
  53. data/integration/files/modules/unicode/manifests/init.pp +6 -0
  54. data/integration/files/pre-suite/git_config.pp.erb +19 -0
  55. data/integration/files/pre-suite/prod_env.config +3 -0
  56. data/integration/files/r10k_conf.yaml.erb +9 -0
  57. data/integration/lib/README.mkd +4 -0
  58. data/integration/lib/git_utils.rb +205 -0
  59. data/integration/lib/master_manipulator.rb +205 -0
  60. data/integration/lib/r10k_utils.rb +222 -0
  61. data/integration/manifests/README.mkd +4 -0
  62. data/integration/pre-suite/00_pe_install.rb +6 -0
  63. data/integration/pre-suite/10_git_config.rb +48 -0
  64. data/integration/pre-suite/20_pe_r10k.rb +55 -0
  65. data/integration/pre-suite/README.mkd +5 -0
  66. data/integration/tests/Puppetfile/HTTP_PROXY_affects_forge_source.rb +72 -0
  67. data/integration/tests/Puppetfile/HTTP_PROXY_affects_git_source.rb +70 -0
  68. data/integration/tests/README.mkd +4 -0
  69. data/integration/tests/basic_functionality/install_pe_only_module_with_puppetfile.rb +83 -0
  70. data/integration/tests/basic_functionality/negative/neg_deploy_with_invalid_r10k_yaml.rb +51 -0
  71. data/integration/tests/basic_functionality/negative/neg_deploy_with_missing_r10k_yaml.rb +28 -0
  72. data/integration/tests/basic_functionality/negative/neg_invalid_git_provider.rb +45 -0
  73. data/integration/tests/basic_functionality/negative/negative_bad_proxy.rb +34 -0
  74. data/integration/tests/basic_functionality/proxy_specified_in_configuration.rb +103 -0
  75. data/integration/tests/basic_functionality/proxy_with_pe_only_module.rb +128 -0
  76. data/integration/tests/basic_functionality/proxy_with_puppetfile.rb +61 -0
  77. data/integration/tests/basic_functionality/rugged_git_provider_with_ssh.rb +109 -0
  78. data/integration/tests/basic_functionality/rugged_git_provider_without_ssh.rb +108 -0
  79. data/integration/tests/command_line/deploy_env_without_mod_update.rb +76 -0
  80. data/integration/tests/command_line/negative/neg_deploy_env_with_module_update.rb +77 -0
  81. data/integration/tests/command_line/negative/neg_invalid_cmd_line_arg.rb +23 -0
  82. data/integration/tests/git_source/HTTP_proxy_and_git_source.rb +70 -0
  83. data/integration/tests/git_source/git_source_git.rb +128 -0
  84. data/integration/tests/git_source/git_source_ssh.rb +87 -0
  85. data/integration/tests/git_source/git_source_submodule.rb +70 -0
  86. data/integration/tests/git_source/negative/neg_git_broken_remote.rb +38 -0
  87. data/integration/tests/git_source/negative/neg_git_unauthorized_https.rb +46 -0
  88. data/integration/tests/git_source/negative/neg_git_unauthorized_ssh.rb +73 -0
  89. data/integration/tests/git_source/negative/neg_git_unicode_branch.rb +35 -0
  90. data/integration/tests/i18n/deploy_module_with_unicode_in_file_name.rb +64 -0
  91. data/integration/tests/purging/content_not_purged_at_root.rb +89 -0
  92. data/integration/tests/purging/default_purging.rb +125 -0
  93. data/integration/tests/purging/does_not_purge_files_on_white_list.rb +93 -0
  94. data/integration/tests/purging/invalid_whitelist_types.rb +63 -0
  95. data/integration/tests/user_scenario/basic_workflow/multi_env_1000_branches.rb +66 -0
  96. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module.rb +111 -0
  97. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module_static.rb +117 -0
  98. data/integration/tests/user_scenario/basic_workflow/multi_env_hiera.rb +100 -0
  99. data/integration/tests/user_scenario/basic_workflow/multi_env_multi_source.rb +133 -0
  100. data/integration/tests/user_scenario/basic_workflow/multi_source_custom_forge_git_module.rb +161 -0
  101. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_basedir.rb +46 -0
  102. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_forge_module.rb +48 -0
  103. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module.rb +45 -0
  104. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module_ref.rb +43 -0
  105. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_remote.rb +45 -0
  106. data/integration/tests/user_scenario/basic_workflow/negative/neg_branch_name_collision.rb +64 -0
  107. data/integration/tests/user_scenario/basic_workflow/negative/neg_disk_full.rb +75 -0
  108. data/integration/tests/user_scenario/basic_workflow/negative/neg_duplicate_module_names.rb +44 -0
  109. data/integration/tests/user_scenario/basic_workflow/negative/neg_inaccessible_forge.rb +58 -0
  110. data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_env_name.rb +34 -0
  111. data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_puppet_file.rb +36 -0
  112. data/integration/tests/user_scenario/basic_workflow/negative/neg_module_specified_at_deleted_release.rb +49 -0
  113. data/integration/tests/user_scenario/basic_workflow/negative/neg_read_only.rb +58 -0
  114. data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +51 -0
  115. data/integration/tests/user_scenario/basic_workflow/single_env_10000_files.rb +75 -0
  116. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_git_module.rb +104 -0
  117. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_module.rb +81 -0
  118. data/integration/tests/user_scenario/basic_workflow/single_env_custom_module.rb +49 -0
  119. data/integration/tests/user_scenario/basic_workflow/single_env_large_files.rb +75 -0
  120. data/integration/tests/user_scenario/basic_workflow/single_env_module_already_installed.rb +82 -0
  121. data/integration/tests/user_scenario/basic_workflow/single_env_module_last_release_deleted.rb +68 -0
  122. data/integration/tests/user_scenario/basic_workflow/single_env_non-existent_base_dir.rb +94 -0
  123. data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +93 -0
  124. data/integration/tests/user_scenario/basic_workflow/single_env_switch_forge_git_module.rb +117 -0
  125. data/integration/tests/user_scenario/basic_workflow/single_env_unicode_paths.rb +60 -0
  126. data/integration/tests/user_scenario/basic_workflow/single_env_upgrade_forge_mod_revert_change.rb +166 -0
  127. data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +163 -0
  128. data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +111 -0
  129. data/integration/tests/user_scenario/complex_workflow/multi_env_unamanaged.rb +78 -0
  130. data/integration/tests/user_scenario/complex_workflow/single_env_git_module_update.rb +100 -0
  131. data/lib/r10k.rb +11 -0
  132. data/lib/r10k/action/base.rb +31 -0
  133. data/lib/r10k/action/cri_runner.rb +72 -0
  134. data/lib/r10k/action/deploy.rb +9 -0
  135. data/lib/r10k/action/deploy/deploy_helpers.rb +34 -0
  136. data/lib/r10k/action/deploy/display.rb +89 -0
  137. data/lib/r10k/action/deploy/environment.rb +196 -0
  138. data/lib/r10k/action/deploy/module.rb +84 -0
  139. data/lib/r10k/action/puppetfile.rb +10 -0
  140. data/lib/r10k/action/puppetfile/check.rb +31 -0
  141. data/lib/r10k/action/puppetfile/cri_runner.rb +26 -0
  142. data/lib/r10k/action/puppetfile/install.rb +45 -0
  143. data/lib/r10k/action/puppetfile/purge.rb +28 -0
  144. data/lib/r10k/action/runner.rb +96 -0
  145. data/lib/r10k/action/visitor.rb +31 -0
  146. data/lib/r10k/cli.rb +51 -0
  147. data/lib/r10k/cli/deploy.rb +114 -0
  148. data/lib/r10k/cli/ext/logging.rb +15 -0
  149. data/lib/r10k/cli/help.rb +7 -0
  150. data/lib/r10k/cli/puppetfile.rb +74 -0
  151. data/lib/r10k/cli/version.rb +31 -0
  152. data/lib/r10k/deployment.rb +132 -0
  153. data/lib/r10k/deployment/config.rb +56 -0
  154. data/lib/r10k/environment.rb +37 -0
  155. data/lib/r10k/environment/bare.rb +16 -0
  156. data/lib/r10k/environment/base.rb +150 -0
  157. data/lib/r10k/environment/git.rb +81 -0
  158. data/lib/r10k/environment/name.rb +86 -0
  159. data/lib/r10k/environment/svn.rb +91 -0
  160. data/lib/r10k/environment/with_modules.rb +139 -0
  161. data/lib/r10k/errors.rb +61 -0
  162. data/lib/r10k/errors/formatting.rb +28 -0
  163. data/lib/r10k/feature.rb +56 -0
  164. data/lib/r10k/feature/collection.rb +23 -0
  165. data/lib/r10k/features.rb +20 -0
  166. data/lib/r10k/forge/module_release.rb +228 -0
  167. data/lib/r10k/git.rb +196 -0
  168. data/lib/r10k/git/alternates.rb +63 -0
  169. data/lib/r10k/git/cache.rb +108 -0
  170. data/lib/r10k/git/errors.rb +34 -0
  171. data/lib/r10k/git/rugged.rb +17 -0
  172. data/lib/r10k/git/rugged/bare_repository.rb +85 -0
  173. data/lib/r10k/git/rugged/base_repository.rb +93 -0
  174. data/lib/r10k/git/rugged/cache.rb +11 -0
  175. data/lib/r10k/git/rugged/credentials.rb +91 -0
  176. data/lib/r10k/git/rugged/thin_repository.rb +89 -0
  177. data/lib/r10k/git/rugged/working_repository.rb +145 -0
  178. data/lib/r10k/git/shellgit.rb +9 -0
  179. data/lib/r10k/git/shellgit/bare_repository.rb +43 -0
  180. data/lib/r10k/git/shellgit/base_repository.rb +137 -0
  181. data/lib/r10k/git/shellgit/cache.rb +11 -0
  182. data/lib/r10k/git/shellgit/thin_repository.rb +69 -0
  183. data/lib/r10k/git/shellgit/working_repository.rb +111 -0
  184. data/lib/r10k/git/stateful_repository.rb +95 -0
  185. data/lib/r10k/initializers.rb +67 -0
  186. data/lib/r10k/instance_cache.rb +32 -0
  187. data/lib/r10k/keyed_factory.rb +39 -0
  188. data/lib/r10k/logging.rb +109 -0
  189. data/lib/r10k/logging/terminaloutputter.rb +36 -0
  190. data/lib/r10k/module.rb +38 -0
  191. data/lib/r10k/module/base.rb +113 -0
  192. data/lib/r10k/module/forge.rb +177 -0
  193. data/lib/r10k/module/git.rb +109 -0
  194. data/lib/r10k/module/local.rb +36 -0
  195. data/lib/r10k/module/metadata_file.rb +31 -0
  196. data/lib/r10k/module/svn.rb +112 -0
  197. data/lib/r10k/puppetfile.rb +286 -0
  198. data/lib/r10k/settings.rb +194 -0
  199. data/lib/r10k/settings/collection.rb +123 -0
  200. data/lib/r10k/settings/container.rb +97 -0
  201. data/lib/r10k/settings/definition.rb +124 -0
  202. data/lib/r10k/settings/enum_definition.rb +30 -0
  203. data/lib/r10k/settings/helpers.rb +38 -0
  204. data/lib/r10k/settings/list.rb +107 -0
  205. data/lib/r10k/settings/loader.rb +99 -0
  206. data/lib/r10k/settings/mixin.rb +54 -0
  207. data/lib/r10k/settings/uri_definition.rb +19 -0
  208. data/lib/r10k/source.rb +42 -0
  209. data/lib/r10k/source/base.rb +74 -0
  210. data/lib/r10k/source/exec.rb +51 -0
  211. data/lib/r10k/source/git.rb +142 -0
  212. data/lib/r10k/source/hash.rb +182 -0
  213. data/lib/r10k/source/svn.rb +136 -0
  214. data/lib/r10k/source/yaml.rb +20 -0
  215. data/lib/r10k/source/yamldir.rb +32 -0
  216. data/lib/r10k/svn.rb +6 -0
  217. data/lib/r10k/svn/remote.rb +68 -0
  218. data/lib/r10k/svn/working_dir.rb +125 -0
  219. data/lib/r10k/util/attempt.rb +84 -0
  220. data/lib/r10k/util/basedir.rb +65 -0
  221. data/lib/r10k/util/commands.rb +31 -0
  222. data/lib/r10k/util/exec_env.rb +36 -0
  223. data/lib/r10k/util/license.rb +24 -0
  224. data/lib/r10k/util/platform.rb +42 -0
  225. data/lib/r10k/util/purgeable.rb +88 -0
  226. data/lib/r10k/util/setopts.rb +55 -0
  227. data/lib/r10k/util/subprocess.rb +84 -0
  228. data/lib/r10k/util/subprocess/result.rb +56 -0
  229. data/lib/r10k/util/subprocess/runner.rb +26 -0
  230. data/lib/r10k/util/subprocess/runner/jruby.rb +23 -0
  231. data/lib/r10k/util/subprocess/runner/posix.rb +103 -0
  232. data/lib/r10k/util/subprocess/runner/pump.rb +59 -0
  233. data/lib/r10k/util/subprocess/runner/windows.rb +23 -0
  234. data/lib/r10k/util/subprocess/subprocess_error.rb +24 -0
  235. data/lib/r10k/util/symbolize_keys.rb +35 -0
  236. data/lib/r10k/version.rb +6 -0
  237. data/locales/config.yaml +21 -0
  238. data/locales/r10k.pot +545 -0
  239. data/r10k.gemspec +50 -0
  240. data/r10k.yaml.example +112 -0
  241. data/spec/fixtures/empty/.empty +0 -0
  242. data/spec/fixtures/integration/git/puppet-boolean-bare.tar +0 -0
  243. data/spec/fixtures/module/forge/bad_module/metadata.json +1 -0
  244. data/spec/fixtures/module/forge/eight_hundred/Modulefile +8 -0
  245. data/spec/fixtures/module/forge/eight_hundred/metadata.json +19 -0
  246. data/spec/fixtures/unit/action/r10k.yaml +5 -0
  247. data/spec/fixtures/unit/action/r10k_cachedir.yaml +2 -0
  248. data/spec/fixtures/unit/action/r10k_generate_types.yaml +3 -0
  249. data/spec/fixtures/unit/action/r10k_puppet_path.yaml +3 -0
  250. data/spec/fixtures/unit/puppetfile/argument-error/Puppetfile +1 -0
  251. data/spec/fixtures/unit/puppetfile/default-branch-override/Puppetfile +5 -0
  252. data/spec/fixtures/unit/puppetfile/duplicate-module-error/Puppetfile +10 -0
  253. data/spec/fixtures/unit/puppetfile/invalid-syntax/Puppetfile +1 -0
  254. data/spec/fixtures/unit/puppetfile/load-error/Puppetfile +1 -0
  255. data/spec/fixtures/unit/puppetfile/name-error/Puppetfile +1 -0
  256. data/spec/fixtures/unit/puppetfile/valid-forge-with-version/Puppetfile +1 -0
  257. data/spec/fixtures/unit/puppetfile/valid-forge-without-version/Puppetfile +1 -0
  258. data/spec/fixtures/unit/util/purgeable/managed_one/expected_1 +0 -0
  259. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_expected_1 +0 -0
  260. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_unmanaged_1 +0 -0
  261. data/spec/fixtures/unit/util/purgeable/managed_one/unmanaged_1 +0 -0
  262. data/spec/fixtures/unit/util/purgeable/managed_two/expected_2 +0 -0
  263. data/spec/fixtures/unit/util/purgeable/managed_two/unmanaged_2 +0 -0
  264. data/spec/fixtures/unit/util/subprocess/runner/no-execute.sh +3 -0
  265. data/spec/integration/git/rugged/bare_repository_spec.rb +13 -0
  266. data/spec/integration/git/rugged/thin_repository_spec.rb +14 -0
  267. data/spec/integration/git/rugged/working_repository_spec.rb +48 -0
  268. data/spec/integration/git/shellgit/bare_repository_spec.rb +13 -0
  269. data/spec/integration/git/shellgit/thin_repository_spec.rb +14 -0
  270. data/spec/integration/git/shellgit/working_repository_spec.rb +13 -0
  271. data/spec/integration/git/stateful_repository_spec.rb +159 -0
  272. data/spec/matchers/exit_with.rb +28 -0
  273. data/spec/matchers/match_realpath.rb +18 -0
  274. data/spec/r10k-mocks.rb +3 -0
  275. data/spec/r10k-mocks/mock_config.rb +33 -0
  276. data/spec/r10k-mocks/mock_env.rb +15 -0
  277. data/spec/r10k-mocks/mock_source.rb +13 -0
  278. data/spec/shared-contexts/git-fixtures.rb +55 -0
  279. data/spec/shared-examples/deploy-actions.rb +69 -0
  280. data/spec/shared-examples/git-repository.rb +38 -0
  281. data/spec/shared-examples/git/bare_repository.rb +132 -0
  282. data/spec/shared-examples/git/thin_repository.rb +26 -0
  283. data/spec/shared-examples/git/working_repository.rb +207 -0
  284. data/spec/shared-examples/puppetfile-action.rb +39 -0
  285. data/spec/shared-examples/settings/ancestry.rb +44 -0
  286. data/spec/shared-examples/subprocess-runner.rb +83 -0
  287. data/spec/spec_helper.rb +40 -0
  288. data/spec/unit/action/cri_runner_spec.rb +72 -0
  289. data/spec/unit/action/deploy/deploy_helpers_spec.rb +38 -0
  290. data/spec/unit/action/deploy/display_spec.rb +31 -0
  291. data/spec/unit/action/deploy/environment_spec.rb +395 -0
  292. data/spec/unit/action/deploy/module_spec.rb +139 -0
  293. data/spec/unit/action/puppetfile/check_spec.rb +41 -0
  294. data/spec/unit/action/puppetfile/cri_runner_spec.rb +47 -0
  295. data/spec/unit/action/puppetfile/install_spec.rb +84 -0
  296. data/spec/unit/action/puppetfile/purge_spec.rb +42 -0
  297. data/spec/unit/action/runner_spec.rb +213 -0
  298. data/spec/unit/action/visitor_spec.rb +39 -0
  299. data/spec/unit/cli_spec.rb +9 -0
  300. data/spec/unit/deployment/config_spec.rb +33 -0
  301. data/spec/unit/deployment_spec.rb +162 -0
  302. data/spec/unit/environment/base_spec.rb +109 -0
  303. data/spec/unit/environment/git_spec.rb +97 -0
  304. data/spec/unit/environment/name_spec.rb +135 -0
  305. data/spec/unit/environment/svn_spec.rb +133 -0
  306. data/spec/unit/errors/formatting_spec.rb +84 -0
  307. data/spec/unit/feature_spec.rb +50 -0
  308. data/spec/unit/forge/module_release_spec.rb +213 -0
  309. data/spec/unit/git/alternates_spec.rb +116 -0
  310. data/spec/unit/git/cache_spec.rb +55 -0
  311. data/spec/unit/git/rugged/cache_spec.rb +29 -0
  312. data/spec/unit/git/rugged/credentials_spec.rb +109 -0
  313. data/spec/unit/git/shellgit/cache_spec.rb +27 -0
  314. data/spec/unit/git/stateful_repository_spec.rb +40 -0
  315. data/spec/unit/git_spec.rb +102 -0
  316. data/spec/unit/initializers_spec.rb +68 -0
  317. data/spec/unit/instance_cache_spec.rb +78 -0
  318. data/spec/unit/keyed_factory_spec.rb +51 -0
  319. data/spec/unit/logging/terminaloutputter_spec.rb +53 -0
  320. data/spec/unit/logging_spec.rb +68 -0
  321. data/spec/unit/module/base_spec.rb +72 -0
  322. data/spec/unit/module/forge_spec.rb +207 -0
  323. data/spec/unit/module/git_spec.rb +274 -0
  324. data/spec/unit/module/metadata_file_spec.rb +68 -0
  325. data/spec/unit/module/svn_spec.rb +178 -0
  326. data/spec/unit/module_spec.rb +29 -0
  327. data/spec/unit/puppetfile_spec.rb +300 -0
  328. data/spec/unit/settings/collection_spec.rb +123 -0
  329. data/spec/unit/settings/container_spec.rb +92 -0
  330. data/spec/unit/settings/definition_spec.rb +79 -0
  331. data/spec/unit/settings/enum_definition_spec.rb +20 -0
  332. data/spec/unit/settings/inheritance_spec.rb +38 -0
  333. data/spec/unit/settings/list_spec.rb +88 -0
  334. data/spec/unit/settings/loader_spec.rb +110 -0
  335. data/spec/unit/settings/uri_definition_spec.rb +23 -0
  336. data/spec/unit/settings_spec.rb +246 -0
  337. data/spec/unit/source/base_spec.rb +31 -0
  338. data/spec/unit/source/exec_spec.rb +81 -0
  339. data/spec/unit/source/git_spec.rb +185 -0
  340. data/spec/unit/source/hash_spec.rb +54 -0
  341. data/spec/unit/source/svn_spec.rb +196 -0
  342. data/spec/unit/source/yaml_spec.rb +42 -0
  343. data/spec/unit/source_spec.rb +10 -0
  344. data/spec/unit/svn/remote_spec.rb +21 -0
  345. data/spec/unit/svn/working_dir_spec.rb +56 -0
  346. data/spec/unit/util/attempt_spec.rb +82 -0
  347. data/spec/unit/util/commands_spec.rb +61 -0
  348. data/spec/unit/util/exec_env_spec.rb +56 -0
  349. data/spec/unit/util/purgeable_spec.rb +230 -0
  350. data/spec/unit/util/setopts_spec.rb +59 -0
  351. data/spec/unit/util/subprocess/result_spec.rb +36 -0
  352. data/spec/unit/util/subprocess/runner/posix_spec.rb +7 -0
  353. data/spec/unit/util/subprocess/runner/pump_spec.rb +79 -0
  354. data/spec/unit/util/subprocess/runner/windows_spec.rb +7 -0
  355. data/spec/unit/util/subprocess/subprocess_error_spec.rb +26 -0
  356. data/spec/unit/util/subprocess_spec.rb +65 -0
  357. data/spec/unit/util/symbolize_keys_spec.rb +67 -0
  358. metadata +582 -0
@@ -0,0 +1,28 @@
1
+ require 'r10k/errors'
2
+
3
+ module R10K
4
+ module Errors
5
+ module Formatting
6
+ module_function
7
+
8
+ # Format this exception for displaying to the user
9
+ #
10
+ # @param exc [Exception] The exception to format
11
+ # @param with_backtrace [true, false] Whether the backtrace should be
12
+ # included with this exception
13
+ # @return [String]
14
+ def format_exception(exc, with_backtrace = false)
15
+ lines = []
16
+ lines << exc.message
17
+ if with_backtrace
18
+ lines.concat(exc.backtrace)
19
+ end
20
+ if exc.respond_to?(:original) && exc.original
21
+ lines << "Original exception:"
22
+ lines<< format_exception(exc.original, with_backtrace)
23
+ end
24
+ lines.join("\n")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,56 @@
1
+ require 'r10k/logging'
2
+
3
+ module R10K
4
+ # Detect whether a given feature is present or absent
5
+ class Feature
6
+
7
+ include R10K::Logging
8
+
9
+ # @attribute [r] name
10
+ # @return [Symbol] The name of this feature
11
+ attr_reader :name
12
+
13
+ # @param name [Symbol] The name of this feature
14
+ # @param opts [Hash]
15
+ # @param block [Proc] An optional block to detect if this feature is available
16
+ #
17
+ # @option opts [String, Array<String>] :libraries One or more libraries to
18
+ # require to make sure this feature is present.
19
+ def initialize(name, opts = {}, &block)
20
+ @name = name
21
+ @libraries = Array(opts.delete(:libraries))
22
+ @block = block
23
+ end
24
+
25
+ # @return [true, false] Is this feature available?
26
+ def available?
27
+ logger.debug1 { _("Testing to see if feature %{name} is available.") % {name: @name} }
28
+ rv = @libraries.all? { |lib| library_available?(lib) } && proc_available?
29
+ msg = rv ? "is" : "is not"
30
+ logger.debug1 { _("Feature %{name} %{message} available.") % {name: @name, message: msg} }
31
+ rv
32
+ end
33
+
34
+ private
35
+
36
+ def library_available?(lib)
37
+ logger.debug2 { _("Attempting to load library '%{lib}' for feature %{name}") % {lib: lib, name: @name} }
38
+ require lib
39
+ true
40
+ rescue ScriptError => e
41
+ logger.debug2 { _("Error while loading library %{lib} for feature %{name}: %{error_msg}") % {lib: lib, name: @name, error_msg: e.message} }
42
+ false
43
+ end
44
+
45
+ def proc_available?
46
+ if @block
47
+ logger.debug2 { _("Evaluating proc %{block} to test for feature %{name}") % {block: @block.inspect, name: @name} }
48
+ output = @block.call
49
+ logger.debug2 { _("Proc %{block} for feature %{name} returned %{output}") % {block: @block.inspect, name: @name, output: output.inspect } }
50
+ !!output
51
+ else
52
+ true
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,23 @@
1
+ require 'r10k/feature'
2
+
3
+ # Store all features and indicate if they're available.
4
+ class R10K::Feature::Collection
5
+ def initialize
6
+ @features = {}
7
+ end
8
+
9
+ # @param name [Symbol] The feature to add
10
+ # @param opts [Hash] Additional options for the feature, see {R10K::Feature}
11
+ # @param block [Proc] An optional block to detect if this feature is present
12
+ # @return [void]
13
+ def add(name, opts = {}, &block)
14
+ @features[name] = R10K::Feature.new(name, opts, &block)
15
+ end
16
+
17
+ # @return [true, false] Does a feature by this name exist and is it available?
18
+ def available?(name)
19
+ if @features.key?(name)
20
+ @features[name].available?
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ require 'r10k/feature/collection'
2
+ require 'forwardable'
3
+ require 'r10k/util/commands'
4
+
5
+ module R10K
6
+ module Features
7
+ @features = R10K::Feature::Collection.new
8
+
9
+ class << self
10
+ extend Forwardable
11
+ def_delegators :@features, :add, :available?
12
+ end
13
+ end
14
+ end
15
+
16
+ R10K::Features.add(:shellgit) { R10K::Util::Commands.which('git') }
17
+
18
+ R10K::Features.add(:rugged, :libraries => 'rugged')
19
+
20
+ R10K::Features.add(:pe_license, :libraries => 'pe_license')
@@ -0,0 +1,228 @@
1
+ require 'r10k/logging'
2
+ require 'r10k/settings/mixin'
3
+ require 'fileutils'
4
+ require 'tmpdir'
5
+ require 'puppet_forge'
6
+
7
+ module R10K
8
+ module Forge
9
+ # Download, unpack, and install modules from the Puppet Forge
10
+ class ModuleRelease
11
+
12
+ include R10K::Settings::Mixin
13
+
14
+ def_setting_attr :proxy
15
+ def_setting_attr :baseurl
16
+ def_setting_attr :cache_root, File.expand_path(ENV['HOME'] ? '~/.r10k/cache': '/root/.r10k/cache')
17
+
18
+ include R10K::Logging
19
+
20
+ # @!attribute [r] forge_release
21
+ # @api private
22
+ # @return [PuppetForge::V3::ModuleRelease] The Forge V3 API module
23
+ # release object used for downloading and verifying the module
24
+ # release.
25
+ attr_reader :forge_release
26
+
27
+ # @!attribute [rw] download_path
28
+ # @return [Pathname] Where the module tarball will be downloaded to.
29
+ attr_accessor :download_path
30
+
31
+ # @!attribute [rw] tarball_cache_path
32
+ # @return [Pathname] Where the module tarball will be cached to.
33
+ attr_accessor :tarball_cache_path
34
+
35
+ # @!attribute [rw] tarball_cache_root
36
+ # @return [Pathname] Directory where the module tarball will be cached to.
37
+ attr_accessor :tarball_cache_root
38
+
39
+ # @!attribute [rw] md5_file_path
40
+ # @return [Pathname] Where the md5 of the cached tarball is stored.
41
+ attr_accessor :md5_file_path
42
+
43
+ # @!attribute [rw] sha256_file_path
44
+ # @return [Pathname] Where the SHA256 of the cached tarball is stored.
45
+ attr_accessor :sha256_file_path
46
+
47
+ # @!attribute [rw] unpack_path
48
+ # @return [Pathname] Where the module will be unpacked to.
49
+ attr_accessor :unpack_path
50
+
51
+ # @param full_name [String] The hyphen separated name of the module
52
+ # @param version [String] The version of the module
53
+ def initialize(full_name, version)
54
+ @full_name = PuppetForge::V3.normalize_name(full_name)
55
+ @version = version
56
+
57
+ # Copy the PuppetForge base connection to the release class; the connection
58
+ # objects are created in the class instances and thus are not shared with
59
+ # subclasses.
60
+ PuppetForge::V3::Release.conn = PuppetForge::V3::Base.conn
61
+
62
+ @forge_release = PuppetForge::V3::Release.new({ :name => @full_name, :version => @version, :slug => "#{@full_name}-#{@version}" })
63
+
64
+ tarball_name = @forge_release.slug + '.tar.gz'
65
+ @download_path = Pathname.new(Dir.mktmpdir) + (tarball_name)
66
+ @tarball_cache_root = Pathname.new(settings[:cache_root]) + (@forge_release.slug + "/tarball/")
67
+ @tarball_cache_path = @tarball_cache_root + tarball_name
68
+
69
+ md5_filename = @forge_release.slug + '.md5'
70
+ @md5_file_path = @tarball_cache_root + md5_filename
71
+
72
+ sha256_filename = @forge_release.slug + '.sha256'
73
+ @sha256_file_path = @tarball_cache_root + sha256_filename
74
+
75
+ @unpack_path = Pathname.new(Dir.mktmpdir) + @forge_release.slug
76
+ end
77
+
78
+ # Download, unpack, and install this module release to the target directory.
79
+ #
80
+ # @example
81
+ # environment_path = Pathname.new('/etc/puppetlabs/puppet/environments/production')
82
+ # target_dir = environment_path + 'eight_hundred'
83
+ # mod = R10K::Forge::ModuleRelease.new('branan-eight_hundred', '8.0.0')
84
+ # mod.install(target_dir)
85
+ #
86
+ # @param target_dir [Pathname] The full path to where the module should be installed.
87
+ # @return [void]
88
+ def install(target_dir)
89
+ download
90
+ verify
91
+ unpack(target_dir)
92
+ ensure
93
+ cleanup
94
+ end
95
+
96
+ # Download the module release to {#download_path} and cache to {#tarball_cache_path}
97
+ #
98
+ # @return [void]
99
+ def download
100
+ if @tarball_cache_path.exist?
101
+ logger.debug1 "Using cached copy of #{@forge_release.slug} tarball"
102
+ else
103
+ logger.debug1 "Downloading #{@forge_release.slug} from #{PuppetForge::Release.conn.url_prefix} to #{@download_path}"
104
+ @forge_release.download(download_path)
105
+ FileUtils::mkdir_p(@tarball_cache_root)
106
+ FileUtils::mv(@download_path, @tarball_cache_path)
107
+ end
108
+ end
109
+
110
+ # Verify the module release cached in {#tarball_cache_path} against the
111
+ # module release checksum given by the Puppet Forge. On mismatch, remove
112
+ # the cached copy.
113
+ #
114
+ # @raise [R10K::Error] when no SHA256 is available and FIPS mode is on
115
+ # @return [void]
116
+ def verify
117
+ logger.debug1 "Verifying that #{@tarball_cache_path} matches checksum"
118
+
119
+ sha256_of_tarball = Digest(:SHA256).file(@tarball_cache_path).hexdigest
120
+
121
+ if @sha256_file_path.exist?
122
+ verify_from_file(sha256_of_tarball, @sha256_file_path)
123
+ else
124
+ if @forge_release.respond_to?(:file_sha256) && !@forge_release.file_sha256.nil? && !@forge_release.file_sha256.size.zero?
125
+ forge_256_checksum = @forge_release.file_sha256
126
+ verify_from_forge(sha256_of_tarball, forge_256_checksum, @sha256_file_path)
127
+ else
128
+ if R10K::Util::Platform.fips?
129
+ raise R10K::Error, "Could not verify module, no SHA256 checksum available, and MD5 checksums not allowed in FIPS mode"
130
+ end
131
+
132
+ logger.debug1 "No SHA256 checksum available, falling back to MD5"
133
+ md5_of_tarball = Digest(:MD5).file(@tarball_cache_path).hexdigest
134
+ if @md5_file_path.exist?
135
+ verify_from_file(md5_of_tarball, @md5_file_path)
136
+ else
137
+ verify_from_forge(md5_of_tarball, @forge_release.file_md5, @md5_file_path)
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ # Verify the checksum of the cached tarball against the
144
+ # module release checksum stored in the cache as well.
145
+ # On mismatch, remove the cached copy of both files.
146
+ # @param tarball_checksum [String] the checksum (either md5 or SHA256)
147
+ # of the downloaded module tarball
148
+ # @param file [Pathname] the file containing the checksum as downloaded
149
+ # previously from the forge
150
+ # @param digest_class [Digest::SHA256, Digest::MD5] which checksum type
151
+ # to verify with
152
+ #
153
+ # @raise [PuppetForge::V3::Release::ChecksumMismatch] The
154
+ # cached module release checksum doesn't match the cached checksum.
155
+ #
156
+ # @return [void]
157
+ def verify_from_file(tarball_checksum, checksum_file_path)
158
+ checksum_from_file = File.read(checksum_file_path).strip
159
+ if tarball_checksum != checksum_from_file
160
+ logger.error "Checksum of #{@tarball_cache_path} (#{tarball_checksum}) does not match checksum #{checksum_from_file} in #{checksum_file_path}. Removing both files."
161
+ @tarball_cache_path.delete
162
+ checksum_file_path.delete
163
+ raise PuppetForge::V3::Release::ChecksumMismatch.new
164
+ end
165
+ end
166
+
167
+ # Verify the checksum of the cached tarball against the
168
+ # module release checksum from the forge.
169
+ # On mismatch, remove the cached copy of the tarball.
170
+ # @param tarball_checksum [String] the checksum (either md5 or SHA256)
171
+ # of the downloaded module tarball
172
+ # @param forge_checksum [String] the checksum downloaded from the Forge
173
+ # @param checksum_file_path [Pathname] the path to write the verified
174
+ # checksum to
175
+ #
176
+ # @raise [PuppetForge::V3::Release::ChecksumMismatch] The
177
+ # cached module release checksum doesn't match the forge checksum.
178
+ #
179
+ # @return [void]
180
+ def verify_from_forge(tarball_checksum, forge_checksum, checksum_file_path)
181
+ if tarball_checksum != forge_checksum
182
+ logger.debug1 "Checksum of #{@tarball_cache_path} (#{tarball_checksum}) does not match checksum #{forge_checksum} found on the forge. Removing tarball."
183
+ @tarball_cache_path.delete
184
+ raise PuppetForge::V3::Release::ChecksumMismatch.new
185
+ else
186
+ File.write(checksum_file_path, forge_checksum)
187
+ end
188
+ end
189
+
190
+ # Unpack the module release at {#tarball_cache_path} into the given target_dir
191
+ #
192
+ # @param target_dir [Pathname] The final path where the module release
193
+ # should be unpacked/installed into.
194
+ # @return [void]
195
+ def unpack(target_dir)
196
+ logger.debug1 _("Unpacking %{tarball_cache_path} to %{target_dir} (with tmpdir %{tmp_path})") % {tarball_cache_path: tarball_cache_path, target_dir: target_dir, tmp_path: unpack_path}
197
+ file_lists = PuppetForge::Unpacker.unpack(tarball_cache_path.to_s, target_dir.to_s, unpack_path.to_s)
198
+ logger.debug2 _("Valid files unpacked: %{valid_files}") % {valid_files: file_lists[:valid]}
199
+ if !file_lists[:invalid].empty?
200
+ logger.debug1 _("These files existed in the module's tar file, but are invalid filetypes and were not unpacked: %{invalid_files}") % {invalid_files: file_lists[:invalid]}
201
+ end
202
+ if !file_lists[:symlinks].empty?
203
+ logger.warn _("Symlinks are unsupported and were not unpacked from the module tarball. %{release_slug} contained these ignored symlinks: %{symlinks}") % {release_slug: @forge_release.slug, symlinks: file_lists[:symlinks]}
204
+ end
205
+ end
206
+
207
+ # Remove all files created while downloading and unpacking the module.
208
+ def cleanup
209
+ cleanup_unpack_path
210
+ cleanup_download_path
211
+ end
212
+
213
+ # Remove the temporary directory used for unpacking the module.
214
+ def cleanup_unpack_path
215
+ if unpack_path.parent.exist?
216
+ unpack_path.parent.rmtree
217
+ end
218
+ end
219
+
220
+ # Remove the downloaded module release.
221
+ def cleanup_download_path
222
+ if download_path.parent.exist?
223
+ download_path.parent.rmtree
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,196 @@
1
+ require 'uri'
2
+ require 'r10k/features'
3
+ require 'r10k/errors'
4
+ require 'r10k/settings'
5
+ require 'r10k/logging'
6
+ require 'r10k/util/platform'
7
+
8
+ module R10K
9
+ module Git
10
+ require 'r10k/git/shellgit'
11
+ require 'r10k/git/rugged'
12
+
13
+ extend R10K::Logging
14
+
15
+ # A list of Git providers, sorted by priority. Providers have features that
16
+ # must be available for them to be used, and a module which is the namespace
17
+ # containing the implementation.
18
+ @providers = [
19
+ [ :shellgit,
20
+ {
21
+ :feature => :shellgit,
22
+ :module => R10K::Git::ShellGit,
23
+ }
24
+ ],
25
+ [ :rugged,
26
+ {
27
+ :feature => :rugged,
28
+ :module => R10K::Git::Rugged,
29
+ :on_set => proc do
30
+ [:ssh, :https].each do |transport|
31
+ if !::Rugged.features.include?(transport)
32
+ logger.warn _("Rugged has been compiled without support for %{transport}; Git repositories will not be reachable via %{transport}.") % {transport: transport}
33
+ end
34
+ end
35
+ end
36
+ }
37
+ ],
38
+ ]
39
+
40
+ # Mark the current provider as invalid.
41
+ #
42
+ # If a provider is set to an invalid provider, we need to make sure that
43
+ # the provider doesn't fall back to the default value, thereby ignoring the
44
+ # explicit value and silently continuing. If the current provider is
45
+ # assigned to this value, no provider will be used until the provider is
46
+ # either reset or assigned a valid provider.
47
+ #
48
+ # @api private
49
+ NULL_PROVIDER = Object.new
50
+
51
+ # Mark the current provider as unset.
52
+ #
53
+ # If the provider has never been set we need to indicate that there is no
54
+ # current value but the default value can be used. If the current provider
55
+ # is assigned to this value and the provider is looked up, the default
56
+ # provider will be looked up and used.
57
+ #
58
+ # @api private
59
+ UNSET_PROVIDER = Object.new
60
+
61
+ # Return the first available Git provider.
62
+ #
63
+ # @raise [R10K::Error] if no Git providers are functional.
64
+ # @return [String] The name of the first available Git implementation.
65
+ def self.default_name
66
+ name, _ = @providers.find { |(_, hash)| R10K::Features.available?(hash[:feature]) }
67
+ if name.nil?
68
+ raise R10K::Error, _("No Git providers are functional.")
69
+ end
70
+ name
71
+ end
72
+
73
+ extend R10K::Logging
74
+
75
+ # Manually set the Git provider by name.
76
+ #
77
+ # @param name [Symbol] The name of the Git provider to use.
78
+ # @raise [R10K::Error] if the requested Git provider doesn't exist.
79
+ # @raise [R10K::Error] if the requested Git provider isn't functional.
80
+ # @return [void]
81
+ def self.provider=(name)
82
+ _, attrs = @providers.find { |(providername, _)| name == providername }
83
+ if attrs.nil?
84
+ @provider = NULL_PROVIDER
85
+ raise R10K::Error, _("No Git provider named '%{name}'.") % {name: name}
86
+ end
87
+ if !R10K::Features.available?(attrs[:feature])
88
+ @provider = NULL_PROVIDER
89
+ raise R10K::Error, _("Git provider '%{name}' is not functional.") % {name: name}
90
+ end
91
+ if attrs[:on_set]
92
+ attrs[:on_set].call
93
+ end
94
+
95
+ @provider = attrs[:module]
96
+ logger.debug1 { _("Setting Git provider to %{provider}") % {provider: @provider.name} }
97
+ end
98
+
99
+ # @return [Module] The namespace of the first available Git implementation.
100
+ # Implementation classes should be looked up against this returned Module.
101
+ def self.provider
102
+ case @provider
103
+ when NULL_PROVIDER
104
+ raise R10K::Error, _("No Git provider set.")
105
+ when UNSET_PROVIDER
106
+ self.provider = default_name
107
+ logger.debug1 { _("Setting Git provider to default provider %{name}") % {name: default_name} }
108
+ end
109
+
110
+ @provider
111
+ end
112
+
113
+ def self.cache
114
+ provider::Cache
115
+ end
116
+
117
+ def self.bare_repository
118
+ provider::BareRepository
119
+ end
120
+
121
+ def self.thin_repository
122
+ provider::ThinRepository
123
+ end
124
+
125
+ # Clear the currently set provider.
126
+ #
127
+ # @api private
128
+ def self.reset!
129
+ @provider = UNSET_PROVIDER
130
+ end
131
+
132
+ @provider = UNSET_PROVIDER
133
+
134
+ extend R10K::Settings::Mixin::ClassMethods
135
+
136
+ def_setting_attr :private_key
137
+ def_setting_attr :proxy
138
+ def_setting_attr :username
139
+ def_setting_attr :repositories, {}
140
+
141
+ def self.get_repo_settings(remote)
142
+ self.settings[:repositories].find {|r| r[:remote] == remote }
143
+ end
144
+
145
+ def self.get_proxy_for_remote(remote)
146
+ # We only support proxy for HTTP(S) transport
147
+ return nil unless remote =~ /^http(s)?/i
148
+
149
+ repo_settings = self.get_repo_settings(remote)
150
+
151
+ if repo_settings && repo_settings.has_key?(:proxy)
152
+ proxy = repo_settings[:proxy] unless repo_settings[:proxy].nil? || repo_settings[:proxy].empty?
153
+ else
154
+ proxy = self.settings[:proxy]
155
+ end
156
+
157
+ R10K::Git.log_proxy_for_remote(proxy, remote) if proxy
158
+
159
+ proxy
160
+ end
161
+
162
+ def self.log_proxy_for_remote(proxy, remote)
163
+ # Sanitize passwords out of the proxy URI for loggging.
164
+ proxy_uri = URI.parse(proxy)
165
+ proxy_str = "#{proxy_uri.scheme}://"
166
+ proxy_str << "#{proxy_uri.userinfo.gsub(/:(.*)$/, ':<FILTERED>')}@" if proxy_uri.userinfo
167
+ proxy_str << "#{proxy_uri.host}:#{proxy_uri.port}"
168
+
169
+ logger.debug { "Using HTTP proxy '#{proxy_str}' for '#{remote}'." }
170
+
171
+ nil
172
+ end
173
+
174
+ # Execute block with given proxy configured in ENV
175
+ def self.with_proxy(new_proxy)
176
+ unless new_proxy.nil?
177
+ old_proxy = Hash[
178
+ ['HTTPS_PROXY', 'HTTP_PROXY', 'https_proxy', 'http_proxy'].collect do |var|
179
+ old_value = ENV[var]
180
+ ENV[var] = new_proxy
181
+
182
+ [var, old_value]
183
+ end
184
+ ]
185
+ end
186
+
187
+ begin
188
+ yield
189
+ ensure
190
+ ENV.update(old_proxy) if old_proxy
191
+ end
192
+
193
+ nil
194
+ end
195
+ end
196
+ end