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,24 @@
1
+ require 'r10k/errors'
2
+ require 'r10k/features'
3
+
4
+ module R10K
5
+ module Util
6
+ module License
7
+ extend R10K::Logging
8
+
9
+ def self.load
10
+ if R10K::Features.available?(:pe_license)
11
+ logger.debug2 _("pe_license feature is available, loading PE license key")
12
+ begin
13
+ return PELicense.load_license_key
14
+ rescue PELicense::InvalidLicenseError => e
15
+ raise R10K::Error.wrap(e, _("Invalid PE license detected: %{error_msg}") % {error_msg: e.message} )
16
+ end
17
+ else
18
+ logger.debug2 _("pe_license feature is not available, PE only Puppet modules will not be downloadable.")
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ require 'rbconfig'
2
+
3
+ module R10K
4
+ module Util
5
+ module Platform
6
+ FIPS_FILE = "/proc/sys/crypto/fips_enabled"
7
+
8
+ def self.platform
9
+ # Test JRuby first to handle JRuby on Windows as well.
10
+ if self.jruby?
11
+ :jruby
12
+ elsif self.windows?
13
+ :windows
14
+ else
15
+ :posix
16
+ end
17
+ end
18
+
19
+ # We currently only suport FIPS mode on redhat 7, where it is
20
+ # toggled via a file.
21
+ def self.fips?
22
+ if File.exist?(FIPS_FILE)
23
+ File.read(FIPS_FILE).chomp == "1"
24
+ else
25
+ false
26
+ end
27
+ end
28
+
29
+ def self.windows?
30
+ RbConfig::CONFIG['host_os'] =~ /mswin|win32|dos|mingw|cygwin/i
31
+ end
32
+
33
+ def self.jruby?
34
+ RUBY_PLATFORM == "java"
35
+ end
36
+
37
+ def self.posix?
38
+ !windows? && !jruby?
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,88 @@
1
+ require 'fileutils'
2
+
3
+ module R10K
4
+ module Util
5
+
6
+ # Mixin for purging stale directory contents.
7
+ #
8
+ # @abstract Classes using this mixin need to implement {#managed_directory} and
9
+ # {#desired_contents}
10
+ module Purgeable
11
+
12
+ # @!method logger
13
+ # @abstract Including classes must provide a logger method
14
+ # @return [Log4r::Logger]
15
+
16
+ # @!method desired_contents
17
+ # @abstract Including classes must implement this method to list the
18
+ # expected filenames of managed_directories
19
+ # @return [Array<String>] The full paths to all the content this object is managing
20
+
21
+ # @!method managed_directories
22
+ # @abstract Including classes must implement this method to return an array of
23
+ # paths that can be purged
24
+ # @return [Array<String>] The paths to the directories to be purged
25
+
26
+ # @return [Array<String>] The present directory entries in `self.managed_directories`
27
+ def current_contents(recurse)
28
+ dirs = self.managed_directories
29
+
30
+ dirs.flat_map do |dir|
31
+ if recurse
32
+ glob_exp = File.join(dir, '**', '{*,.[^.]*}')
33
+ else
34
+ glob_exp = File.join(dir, '*')
35
+ end
36
+
37
+ Dir.glob(glob_exp)
38
+ end
39
+ end
40
+
41
+ # @return [Array<String>] Directory contents that are expected but not present
42
+ def pending_contents(recurse)
43
+ desired_contents - current_contents(recurse)
44
+ end
45
+
46
+ # @return [Array<String>] Directory contents that are present but not expected
47
+ def stale_contents(recurse, exclusions, whitelist)
48
+ fn_match_opts = File::FNM_PATHNAME | File::FNM_DOTMATCH
49
+
50
+ (current_contents(recurse) - desired_contents).reject do |item|
51
+ if exclusion_match = exclusions.find { |ex_item| (ex_item == item) || File.fnmatch?(ex_item, item, fn_match_opts) }
52
+ logger.debug2 _("Not purging %{item} due to internal exclusion match: %{exclusion_match}") % {item: item, exclusion_match: exclusion_match}
53
+ elsif whitelist_match = whitelist.find { |wl_item| (wl_item == item) || File.fnmatch?(wl_item, item, fn_match_opts) }
54
+ logger.debug _("Not purging %{item} due to whitelist match: %{whitelist_match}") % {item: item, whitelist_match: whitelist_match}
55
+ end
56
+
57
+ !!exclusion_match || !!whitelist_match
58
+ end
59
+ end
60
+
61
+ # Forcibly remove all unmanaged content in `self.managed_directories`
62
+ def purge!(opts={})
63
+ recurse = opts[:recurse] || false
64
+ whitelist = opts[:whitelist] || []
65
+
66
+ exclusions = self.respond_to?(:purge_exclusions) ? purge_exclusions : []
67
+
68
+ stale = stale_contents(recurse, exclusions, whitelist)
69
+
70
+ if stale.empty?
71
+ logger.debug1 _("No unmanaged contents in %{managed_dirs}, nothing to purge") % {managed_dirs: managed_directories.join(', ')}
72
+ else
73
+ stale.each do |fpath|
74
+ begin
75
+ FileUtils.rm_r(fpath, :secure => true)
76
+ logger.info _("Removing unmanaged path %{path}") % {path: fpath}
77
+ rescue Errno::ENOENT
78
+ # Don't log on ENOENT since we may encounter that from recursively deleting
79
+ # this item's parent earlier in the purge.
80
+ rescue
81
+ logger.debug1 _("Unable to remove unmanaged path: %{path}") % {path: fpath}
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,55 @@
1
+ module R10K
2
+ module Util
3
+
4
+ # Allow for easy setting of instance options based on a hash
5
+ #
6
+ # This emulates the behavior of Ruby 2.0 named arguments, but since r10k
7
+ # supports Ruby 1.8.7+ we cannot use that functionality.
8
+ module Setopts
9
+
10
+ private
11
+
12
+ # @param opts [Hash]
13
+ # @param allowed [Hash<Symbol, Symbol>]
14
+ #
15
+ # @example
16
+ # opts = {:one => "one value"}
17
+ # allowed => {:one => :self}
18
+ # setopts(opts, allowed)
19
+ # @one # => "one value"
20
+ #
21
+ # @example
22
+ # opts = {:uno => "one value"}
23
+ # allowed => {:one => :one, :uno => :one}
24
+ # setopts(opts, allowed)
25
+ # @one # => "one value"
26
+ #
27
+ # @example
28
+ #
29
+ # opts = {:trace => "something"}
30
+ # allowed = {:trace => nil}
31
+ # setopts(opts, allowed)
32
+ # @trace # => nil
33
+ #
34
+ def setopts(opts, allowed)
35
+ opts.each_pair do |key, value|
36
+ if allowed.key?(key)
37
+ rhs = allowed[key]
38
+ case rhs
39
+ when NilClass, FalseClass
40
+ # Ignore nil options
41
+ when :self, TrueClass
42
+ # tr here is because instance variables cannot have hyphens in their names.
43
+ instance_variable_set("@#{key}".tr('-','_').to_sym, value)
44
+ else
45
+ # tr here same as previous
46
+ instance_variable_set("@#{rhs}".tr('-','_').to_sym, value)
47
+ end
48
+ else
49
+ raise ArgumentError, _("%{class_name} cannot handle option '%{key}'") % {class_name: self.class.name, key: key}
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,84 @@
1
+ require 'r10k/util/platform'
2
+
3
+ module R10K
4
+ module Util
5
+
6
+ # The subprocess namespace implements an interface similar to childprocess.
7
+ # The interface has been simplified to make it easier to use and does not
8
+ # depend on native code.
9
+ #
10
+ # @api private
11
+ class Subprocess
12
+
13
+ require 'r10k/util/subprocess/runner'
14
+ require 'r10k/util/subprocess/result'
15
+ require 'r10k/util/subprocess/subprocess_error'
16
+
17
+ # @return [Class < R10K::Util::Subprocess::Runner]
18
+ def self.runner
19
+ if R10K::Util::Platform.windows?
20
+ R10K::Util::Subprocess::Runner::Windows
21
+ elsif R10K::Util::Platform.jruby?
22
+ R10K::Util::Subprocess::Runner::JRuby
23
+ else
24
+ R10K::Util::Subprocess::Runner::POSIX
25
+ end
26
+ end
27
+
28
+ include R10K::Logging
29
+
30
+ # @!attribute [r] argv
31
+ # @return [Array<String>] The command to be executed
32
+ attr_reader :argv
33
+
34
+ # @!attribute [rw] raise_on_fail
35
+ # Determine whether #execute raises an error when the command exits
36
+ # with a non-zero exit status.
37
+ # @return [true, false]
38
+ attr_accessor :raise_on_fail
39
+
40
+ # @!attribute [rw] cwd
41
+ # @return [String] The directory to be used as the cwd when executing
42
+ # the command.
43
+ attr_accessor :cwd
44
+
45
+ # @!attribute [w] logger
46
+ # Allow calling processes to take ownership of execution logs by passing
47
+ # their own logger to the command being executed.
48
+ attr_writer :logger
49
+
50
+ # Prepare the subprocess invocation.
51
+ #
52
+ # @param argv [Array<String>] The argument vector to execute
53
+ def initialize(argv)
54
+ @argv = argv
55
+
56
+ @raise_on_fail = false
57
+ end
58
+
59
+ # Execute the given command and return the result of evaluation.
60
+ #
61
+ # @api public
62
+ # @raise [R10K::Util::Subprocess::SubprocessError] if raise_on_fail is
63
+ # true and the command exited with a non-zero status.
64
+ # @return [R10K::Util::Subprocess::Result]
65
+ def execute
66
+ subprocess = self.class.runner.new(@argv)
67
+ subprocess.cwd = @cwd if @cwd
68
+
69
+ logmsg = _("Starting process: %{args}") % {args: @argv.inspect}
70
+ logmsg << "(cwd: #{@cwd})" if @cwd
71
+ logger.debug2(logmsg)
72
+
73
+ result = subprocess.run
74
+ logger.debug2(_("Finished process:\n%{result}") % {result: result.format})
75
+
76
+ if @raise_on_fail && result.failed?
77
+ raise SubprocessError.new(_("Command exited with non-zero exit code"), :result => result)
78
+ end
79
+
80
+ result
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,56 @@
1
+ # @api private
2
+ class R10K::Util::Subprocess::Result
3
+
4
+ # @!attribute [r] argv
5
+ # @return [Array<String>]
6
+ attr_reader :argv
7
+
8
+ # @!attribute [r] cmd
9
+ # @return [String]
10
+ attr_reader :cmd
11
+
12
+ # @!attribute [r] stdout
13
+ # @return [String]
14
+ attr_reader :stdout
15
+
16
+ # @!attribute [r] stderr
17
+ # @return [String]
18
+ attr_reader :stderr
19
+
20
+ # @!attribute [r] exit_code
21
+ # @return [Integer]
22
+ attr_reader :exit_code
23
+
24
+ def initialize(argv, stdout, stderr, exit_code)
25
+ @argv = argv
26
+ @cmd = argv.join(' ')
27
+ @stdout = stdout.chomp
28
+ @stderr = stderr.chomp
29
+ @exit_code = exit_code
30
+ end
31
+
32
+ def format(with_cmd = true)
33
+ msg = []
34
+ if with_cmd
35
+ msg << "Command: #{@cmd}"
36
+ end
37
+ if !@stdout.empty?
38
+ msg << "Stdout:"
39
+ msg << @stdout
40
+ end
41
+ if !@stderr.empty?
42
+ msg << "Stderr:"
43
+ msg << @stderr
44
+ end
45
+ msg << "Exit code: #{@exit_code}"
46
+ msg.join("\n")
47
+ end
48
+
49
+ def failed?
50
+ exit_code != 0
51
+ end
52
+
53
+ def success?
54
+ exit_code == 0
55
+ end
56
+ end
@@ -0,0 +1,26 @@
1
+ # Define an abstract interface for external command runners.
2
+ #
3
+ # @api private
4
+ class R10K::Util::Subprocess::Runner
5
+
6
+ require 'r10k/util/subprocess/runner/windows'
7
+ require 'r10k/util/subprocess/runner/posix'
8
+ require 'r10k/util/subprocess/runner/jruby'
9
+
10
+ # @!attribute [rw] cwd
11
+ # @return [String] The directory to be used as the cwd when executing
12
+ # the command.
13
+ attr_accessor :cwd
14
+
15
+ # @!attribute [r] result
16
+ # @return [R10K::Util::Subprocess::Result]
17
+ attr_reader :result
18
+
19
+ def initialize(argv)
20
+ raise NotImplementedError
21
+ end
22
+
23
+ def run
24
+ raise NotImplementedError
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ require 'open3'
2
+ require 'r10k/util/subprocess/runner'
3
+
4
+ # Run processes under JRuby.
5
+ #
6
+ # This implementation relies on Open3.capture3 to run commands and capture
7
+ # results. In contrast to the POSIX runner this cannot be used in an
8
+ # asynchronous manner as-is; implementing that will probably mean launching a
9
+ # thread and invoking #capture3 in that thread.
10
+ class R10K::Util::Subprocess::Runner::JRuby < R10K::Util::Subprocess::Runner
11
+
12
+ def initialize(argv)
13
+ @argv = argv
14
+ end
15
+
16
+ def run
17
+ spawn_opts = @cwd ? {:chdir => @cwd} : {}
18
+ stdout, stderr, status = Open3.capture3(*@argv, spawn_opts)
19
+ @result = R10K::Util::Subprocess::Result.new(@argv, stdout, stderr, status.exitstatus)
20
+ rescue Errno::ENOENT, Errno::EACCES => e
21
+ @result = R10K::Util::Subprocess::Result.new(@argv, '', e.message, 255)
22
+ end
23
+ end
@@ -0,0 +1,103 @@
1
+ require 'r10k/util/subprocess/runner'
2
+ require 'r10k/util/subprocess/runner/pump'
3
+ require 'fcntl'
4
+
5
+ # Implement a POSIX command runner by using fork/exec.
6
+ #
7
+ # This implementation is optimized to run commands in the background, and has
8
+ # a few noteworthy implementation details.
9
+ #
10
+ # First off, when the child process is forked, it calls setsid() to detach from
11
+ # the controlling TTY. This has two main ramifications: sending signals will
12
+ # never be send to the forked process, and the forked process does not have
13
+ # access to stdin.
14
+ #
15
+ # @api private
16
+ class R10K::Util::Subprocess::Runner::POSIX < R10K::Util::Subprocess::Runner
17
+
18
+ def initialize(argv)
19
+ @argv = argv
20
+ mkpipes
21
+ end
22
+
23
+ def run
24
+ # Create a pipe so that the parent can verify that the child process
25
+ # successfully executed. The pipe will be closed on a successful exec(),
26
+ # and will contain an error message on failure.
27
+ exec_r, exec_w = pipe
28
+
29
+ @stdout_pump = R10K::Util::Subprocess::Runner::Pump.new(@stdout_r)
30
+ @stderr_pump = R10K::Util::Subprocess::Runner::Pump.new(@stderr_r)
31
+ pid = fork do
32
+ exec_r.close
33
+ execute_child(exec_w)
34
+ end
35
+
36
+ exec_w.close
37
+ @stdout_pump.start
38
+ @stderr_pump.start
39
+
40
+ execute_parent(exec_r, pid)
41
+
42
+ @result
43
+ end
44
+
45
+ private
46
+
47
+ def execute_child(exec_w)
48
+ if @cwd
49
+ Dir.chdir @cwd
50
+ end
51
+
52
+ # Create a new session for the forked child. This prevents children from
53
+ # ever being the foreground process on a TTY, which is almost always what
54
+ # we want in r10k.
55
+ Process.setsid
56
+
57
+ # Reopen file descriptors
58
+ STDOUT.reopen(@stdout_w)
59
+ STDERR.reopen(@stderr_w)
60
+
61
+ executable = @argv.shift
62
+ exec([executable, executable], *@argv)
63
+ rescue SystemCallError => e
64
+ exec_w.write("#{e.class}: #{e.message}")
65
+ exit(254)
66
+ end
67
+
68
+ def execute_parent(exec_r, pid)
69
+ @stdout_w.close
70
+ @stderr_w.close
71
+
72
+ stdout = ''
73
+ stderr = ''
74
+
75
+ if !exec_r.eof?
76
+ stderr = exec_r.read || "exec() failed"
77
+ _, @status = Process.waitpid2(pid)
78
+ else
79
+ _, @status = Process.waitpid2(pid)
80
+ @stdout_pump.wait
81
+ @stderr_pump.wait
82
+ stdout = @stdout_pump.string
83
+ stderr = @stderr_pump.string
84
+ end
85
+ exec_r.close
86
+
87
+ @stdout_r.close
88
+ @stderr_r.close
89
+
90
+ @result = R10K::Util::Subprocess::Result.new(@argv, stdout, stderr, @status.exitstatus)
91
+ end
92
+
93
+ def mkpipes
94
+ @stdout_r, @stdout_w = pipe
95
+ @stderr_r, @stderr_w = pipe
96
+ end
97
+
98
+ def pipe
99
+ ::IO.pipe.tap do |pair|
100
+ pair.each { |p| p.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) }
101
+ end
102
+ end
103
+ end