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,36 @@
1
+ require 'r10k/module'
2
+ require 'r10k/logging'
3
+
4
+ # A dummy module type that can be used to "protect" Puppet modules that exist
5
+ # inside of the Puppetfile "moduledir" location. Local modules will not be
6
+ # modified, and will not be purged when r10k removes unmanaged modules.
7
+ class R10K::Module::Local < R10K::Module::Base
8
+
9
+ R10K::Module.register(self)
10
+
11
+ def self.implement?(name, args)
12
+ args.is_a?(Hash) && args[:local]
13
+ end
14
+
15
+ include R10K::Logging
16
+
17
+ def version
18
+ "0.0.0"
19
+ end
20
+
21
+ def properties
22
+ {
23
+ :expected => "0.0.0 (local)",
24
+ :actual => "0.0.0 (local)",
25
+ :type => :forge,
26
+ }
27
+ end
28
+
29
+ def status
30
+ :insync
31
+ end
32
+
33
+ def sync(opts={})
34
+ logger.debug1 _("Module %{title} is a local module, always indicating synced.") % {title: title}
35
+ end
36
+ end
@@ -0,0 +1,31 @@
1
+ require 'r10k/module'
2
+ require 'r10k/errors'
3
+ require 'puppet_forge'
4
+
5
+ class R10K::Module::MetadataFile
6
+
7
+ # @param metadata_path [Pathname] The file path to the metadata
8
+ def initialize(metadata_file_path)
9
+ @metadata_file_path = metadata_file_path
10
+ end
11
+
12
+ # Does the metadata file itself exist?
13
+ def exist?
14
+ @metadata_file_path.file? and @metadata_file_path.readable?
15
+ end
16
+
17
+ # @return [Puppet::ModuleTool::Metadata ] The metadata object created by the metadatafile
18
+ def read(metadata_file_path = @metadata_file_path)
19
+ if self.exist?
20
+ metadata_file_path.open do |f|
21
+ begin
22
+ metadata = PuppetForge::Metadata.new
23
+ metadata.update(JSON.load(f), false)
24
+ rescue JSON::ParserError => e
25
+ exception = R10K::Error.wrap(e, _("Could not read metadata.json"))
26
+ raise exception
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,112 @@
1
+ require 'r10k/module'
2
+ require 'r10k/svn/working_dir'
3
+ require 'r10k/util/setopts'
4
+
5
+ class R10K::Module::SVN < R10K::Module::Base
6
+
7
+ R10K::Module.register(self)
8
+
9
+ def self.implement?(name, args)
10
+ args.is_a? Hash and args.has_key? :svn
11
+ end
12
+
13
+ # @!attribute [r] expected_revision
14
+ # @return [String] The SVN revision that the repo should have checked out
15
+ attr_reader :expected_revision
16
+ alias expected_version expected_revision
17
+
18
+ # @!attribute [r] full_path
19
+ # @return [Pathname] The filesystem path to the SVN repo
20
+ attr_reader :full_path
21
+
22
+ # @!attribute [r] username
23
+ # @return [String, nil] The SVN username to be passed to the underlying SVN commands
24
+ # @api private
25
+ attr_reader :username
26
+
27
+ # @!attribute [r] password
28
+ # @return [String, nil] The SVN password to be passed to the underlying SVN commands
29
+ # @api private
30
+ attr_reader :password
31
+
32
+ # @!attribute [r] working_dir
33
+ # @return [R10K::SVN::WorkingDir]
34
+ # @api private
35
+ attr_reader :working_dir
36
+
37
+ include R10K::Util::Setopts
38
+
39
+ INITIALIZE_OPTS = {
40
+ :svn => :url,
41
+ :rev => :expected_revision,
42
+ :revision => :expected_revision,
43
+ :username => :self,
44
+ :password => :self
45
+ }
46
+
47
+ def initialize(name, dirname, opts, environment=nil)
48
+ super
49
+
50
+ setopts(opts, INITIALIZE_OPTS)
51
+
52
+ @working_dir = R10K::SVN::WorkingDir.new(@path, :username => @username, :password => @password)
53
+ end
54
+
55
+ def status
56
+ if not self.exist?
57
+ :absent
58
+ elsif not @working_dir.is_svn?
59
+ :mismatched
60
+ elsif not @url == @working_dir.url
61
+ :mismatched
62
+ elsif not @expected_revision == @working_dir.revision
63
+ :outdated
64
+ else
65
+ :insync
66
+ end
67
+ end
68
+
69
+ def sync(opts={})
70
+ case status
71
+ when :absent
72
+ install
73
+ when :mismatched
74
+ reinstall
75
+ when :outdated
76
+ update
77
+ end
78
+ end
79
+
80
+ def exist?
81
+ path.exist?
82
+ end
83
+
84
+ def properties
85
+ {
86
+ :expected => expected_revision,
87
+ :actual => (@working_dir.revision rescue "(unresolvable)"),
88
+ :type => :svn,
89
+ }
90
+ end
91
+
92
+ private
93
+
94
+ def install
95
+ FileUtils.mkdir @dirname unless File.directory? @dirname
96
+
97
+ @working_dir.checkout(@url, @expected_revision)
98
+ end
99
+
100
+ def uninstall
101
+ path.rmtree
102
+ end
103
+
104
+ def reinstall
105
+ uninstall
106
+ install
107
+ end
108
+
109
+ def update
110
+ @working_dir.update(@expected_revision)
111
+ end
112
+ end
@@ -0,0 +1,286 @@
1
+ require 'thread'
2
+ require 'pathname'
3
+ require 'r10k/module'
4
+ require 'r10k/util/purgeable'
5
+ require 'r10k/errors'
6
+
7
+ module R10K
8
+ class Puppetfile
9
+ # Defines the data members of a Puppetfile
10
+
11
+ include R10K::Settings::Mixin
12
+
13
+ def_setting_attr :pool_size, 1
14
+
15
+ include R10K::Logging
16
+
17
+ # @!attribute [r] forge
18
+ # @return [String] The URL to use for the Puppet Forge
19
+ attr_reader :forge
20
+
21
+ # @!attribute [r] modules
22
+ # @return [Array<R10K::Module>]
23
+ attr_reader :modules
24
+
25
+ # @!attribute [r] basedir
26
+ # @return [String] The base directory that contains the Puppetfile
27
+ attr_reader :basedir
28
+
29
+ # @!attribute [r] moduledir
30
+ # @return [String] The directory to install the modules #{basedir}/modules
31
+ attr_reader :moduledir
32
+
33
+ # @!attrbute [r] puppetfile_path
34
+ # @return [String] The path to the Puppetfile
35
+ attr_reader :puppetfile_path
36
+
37
+ # @!attribute [rw] environment
38
+ # @return [R10K::Environment] Optional R10K::Environment that this Puppetfile belongs to.
39
+ attr_accessor :environment
40
+
41
+ # @!attribute [rw] force
42
+ # @return [Boolean] Overwrite any locally made changes
43
+ attr_accessor :force
44
+
45
+ # @param [String] basedir
46
+ # @param [String] moduledir The directory to install the modules, default to #{basedir}/modules
47
+ # @param [String] puppetfile_path The path to the Puppetfile, default to #{basedir}/Puppetfile
48
+ # @param [String] puppetfile_name The name of the Puppetfile, default to 'Puppetfile'
49
+ # @param [Boolean] force Shall we overwrite locally made changes?
50
+ def initialize(basedir, moduledir = nil, puppetfile_path = nil, puppetfile_name = nil, force = nil )
51
+ @basedir = basedir
52
+ @force = force || false
53
+ @moduledir = moduledir || File.join(basedir, 'modules')
54
+ @puppetfile_name = puppetfile_name || 'Puppetfile'
55
+ @puppetfile_path = puppetfile_path || File.join(basedir, @puppetfile_name)
56
+
57
+ logger.info _("Using Puppetfile '%{puppetfile}'") % {puppetfile: @puppetfile_path}
58
+
59
+ @modules = []
60
+ @managed_content = {}
61
+ @forge = 'forgeapi.puppetlabs.com'
62
+
63
+ @loaded = false
64
+ end
65
+
66
+ def load(default_branch_override = nil)
67
+ return true if self.loaded?
68
+ if File.readable? @puppetfile_path
69
+ self.load!(default_branch_override)
70
+ else
71
+ logger.debug _("Puppetfile %{path} missing or unreadable") % {path: @puppetfile_path.inspect}
72
+ end
73
+ end
74
+
75
+ def load!(default_branch_override = nil)
76
+ @default_branch_override = default_branch_override
77
+
78
+ dsl = R10K::Puppetfile::DSL.new(self)
79
+ dsl.instance_eval(puppetfile_contents, @puppetfile_path)
80
+
81
+ validate_no_duplicate_names(@modules)
82
+ @loaded = true
83
+ rescue SyntaxError, LoadError, ArgumentError, NameError => e
84
+ raise R10K::Error.wrap(e, _("Failed to evaluate %{path}") % {path: @puppetfile_path})
85
+ end
86
+
87
+ def loaded?
88
+ @loaded
89
+ end
90
+
91
+ # @param [Array<String>] modules
92
+ def validate_no_duplicate_names(modules)
93
+ dupes = modules
94
+ .group_by { |mod| mod.name }
95
+ .select { |_, v| v.size > 1 }
96
+ .map(&:first)
97
+ unless dupes.empty?
98
+ msg = _('Puppetfiles cannot contain duplicate module names.')
99
+ msg += ' '
100
+ msg += _("Remove the duplicates of the following modules: %{dupes}" % { dupes: dupes.join(' ') })
101
+ raise R10K::Error.new(msg)
102
+ end
103
+ end
104
+
105
+ # @param [String] forge
106
+ def set_forge(forge)
107
+ @forge = forge
108
+ end
109
+
110
+ # @param [String] moduledir
111
+ def set_moduledir(moduledir)
112
+ @moduledir = if Pathname.new(moduledir).absolute?
113
+ moduledir
114
+ else
115
+ File.join(basedir, moduledir)
116
+ end
117
+ end
118
+
119
+ # @param [String] name
120
+ # @param [*Object] args
121
+ def add_module(name, args)
122
+ if args.is_a?(Hash) && install_path = args.delete(:install_path)
123
+ install_path = resolve_install_path(install_path)
124
+ validate_install_path(install_path, name)
125
+ else
126
+ install_path = @moduledir
127
+ end
128
+
129
+ if args.is_a?(Hash) && @default_branch_override != nil
130
+ args[:default_branch] = @default_branch_override
131
+ end
132
+
133
+ # Keep track of all the content this Puppetfile is managing to enable purging.
134
+ @managed_content[install_path] = Array.new unless @managed_content.has_key?(install_path)
135
+
136
+ mod = R10K::Module.new(name, install_path, args, @environment)
137
+ mod.origin = 'Puppetfile'
138
+
139
+ @managed_content[install_path] << mod.name
140
+ @modules << mod
141
+ end
142
+
143
+ include R10K::Util::Purgeable
144
+
145
+ def managed_directories
146
+ self.load unless @loaded
147
+
148
+ @managed_content.keys
149
+ end
150
+
151
+ # Returns an array of the full paths to all the content being managed.
152
+ # @note This implements a required method for the Purgeable mixin
153
+ # @return [Array<String>]
154
+ def desired_contents
155
+ self.load unless @loaded
156
+
157
+ @managed_content.flat_map do |install_path, modnames|
158
+ modnames.collect { |name| File.join(install_path, name) }
159
+ end
160
+ end
161
+
162
+ def purge_exclusions
163
+ exclusions = managed_directories
164
+
165
+ if environment && environment.respond_to?(:desired_contents)
166
+ exclusions += environment.desired_contents
167
+ end
168
+
169
+ exclusions
170
+ end
171
+
172
+ def accept(visitor)
173
+ pool_size = self.settings[:pool_size]
174
+ if pool_size > 1
175
+ concurrent_accept(visitor, pool_size)
176
+ else
177
+ serial_accept(visitor)
178
+ end
179
+ end
180
+
181
+ private
182
+
183
+ def serial_accept(visitor)
184
+ visitor.visit(:puppetfile, self) do
185
+ modules.each do |mod|
186
+ mod.accept(visitor)
187
+ end
188
+ end
189
+ end
190
+
191
+ def concurrent_accept(visitor, pool_size)
192
+ logger.debug _("Updating modules with %{pool_size} threads") % {pool_size: pool_size}
193
+ mods_queue = modules_queue(visitor)
194
+ thread_pool = pool_size.times.map { visitor_thread(visitor, mods_queue) }
195
+ thread_exception = nil
196
+
197
+ # If any threads raise an exception the deployment is considered a failure.
198
+ # In that event clear the queue, wait for other threads to finish their
199
+ # current work, then re-raise the first exception caught.
200
+ begin
201
+ thread_pool.each(&:join)
202
+ rescue => e
203
+ logger.error _("Error during concurrent deploy of a module: %{message}") % {message: e.message}
204
+ mods_queue.clear
205
+ thread_exception ||= e
206
+ retry
207
+ ensure
208
+ raise thread_exception unless thread_exception.nil?
209
+ end
210
+ end
211
+
212
+ def modules_queue(visitor)
213
+ Queue.new.tap do |queue|
214
+ visitor.visit(:puppetfile, self) do
215
+ modules.each { |mod| queue << mod }
216
+ end
217
+ end
218
+ end
219
+
220
+ def visitor_thread(visitor, mods_queue)
221
+ Thread.new do
222
+ begin
223
+ while mod = mods_queue.pop(true) do mod.accept(visitor) end
224
+ rescue ThreadError => e
225
+ logger.debug _("Module thread %{id} exiting: %{message}") % {message: e.message, id: Thread.current.object_id}
226
+ Thread.exit
227
+ rescue => e
228
+ Thread.main.raise(e)
229
+ end
230
+ end
231
+ end
232
+
233
+ def puppetfile_contents
234
+ File.read(@puppetfile_path)
235
+ end
236
+
237
+ def resolve_install_path(path)
238
+ pn = Pathname.new(path)
239
+
240
+ unless pn.absolute?
241
+ pn = Pathname.new(File.join(basedir, path))
242
+ end
243
+
244
+ # .cleanpath is as good as we can do without touching the filesystem.
245
+ # The .realpath methods will also choke if some of the intermediate
246
+ # paths are missing, even though we will create them later as needed.
247
+ pn.cleanpath.to_s
248
+ end
249
+
250
+ def validate_install_path(path, modname)
251
+ real_basedir = Pathname.new(basedir).cleanpath.to_s
252
+
253
+ unless /^#{Regexp.escape(real_basedir)}.*/ =~ path
254
+ raise R10K::Error.new("Puppetfile cannot manage content '#{modname}' outside of containing environment: #{path} is not within #{real_basedir}")
255
+ end
256
+
257
+ true
258
+ end
259
+
260
+ class DSL
261
+ # A barebones implementation of the Puppetfile DSL
262
+ #
263
+ # @api private
264
+
265
+ def initialize(librarian)
266
+ @librarian = librarian
267
+ end
268
+
269
+ def mod(name, args = nil)
270
+ @librarian.add_module(name, args)
271
+ end
272
+
273
+ def forge(location)
274
+ @librarian.set_forge(location)
275
+ end
276
+
277
+ def moduledir(location)
278
+ @librarian.set_moduledir(location)
279
+ end
280
+
281
+ def method_missing(method, *args)
282
+ raise NoMethodError, _("unrecognized declaration '%{method}'") % {method: method}
283
+ end
284
+ end
285
+ end
286
+ end