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.
- checksums.yaml +7 -0
- data/.gitattributes +1 -0
- data/.github/pull_request_template.md +1 -0
- data/.github/workflows/docker.yml +56 -0
- data/.github/workflows/release.yml +36 -0
- data/.gitignore +9 -0
- data/.travis.yml +45 -0
- data/CHANGELOG.mkd +1759 -0
- data/CODEOWNERS +2 -0
- data/CONTRIBUTING.mkd +105 -0
- data/Gemfile +15 -0
- data/LICENSE +14 -0
- data/README.mkd +118 -0
- data/Rakefile +3 -0
- data/azure-pipelines.yml +86 -0
- data/bin/r10k +17 -0
- data/doc/common-patterns.mkd +44 -0
- data/doc/dynamic-environments.mkd +31 -0
- data/doc/dynamic-environments/configuration.mkd +669 -0
- data/doc/dynamic-environments/git-environments.mkd +75 -0
- data/doc/dynamic-environments/introduction.mkd +69 -0
- data/doc/dynamic-environments/master-configuration.mkd +40 -0
- data/doc/dynamic-environments/quickstart.mkd +201 -0
- data/doc/dynamic-environments/svn-environments.mkd +45 -0
- data/doc/dynamic-environments/usage.mkd +132 -0
- data/doc/dynamic-environments/workflow-guide.mkd +247 -0
- data/doc/faq.mkd +164 -0
- data/doc/git/cloning-and-mirroring.mkd +60 -0
- data/doc/git/providers.mkd +111 -0
- data/doc/puppetfile.mkd +309 -0
- data/doc/updating-your-puppetfile.mkd +38 -0
- data/docker/.gitignore +1 -0
- data/docker/.rspec +4 -0
- data/docker/Gemfile +11 -0
- data/docker/Makefile +89 -0
- data/docker/README.md +28 -0
- data/docker/r10k/Dockerfile +67 -0
- data/docker/r10k/adduser.sh +13 -0
- data/docker/r10k/docker-entrypoint.d/10-analytics.sh +30 -0
- data/docker/r10k/docker-entrypoint.sh +11 -0
- data/docker/r10k/release.Dockerfile +54 -0
- data/docker/spec/dockerfile_spec.rb +43 -0
- data/docker/spec/fixtures/Puppetfile +2 -0
- data/integration/Gemfile +19 -0
- data/integration/README.mkd +29 -0
- data/integration/Rakefile +77 -0
- data/integration/component/pre-suite/05_install_dev_r10k.rb +12 -0
- data/integration/files/README.mkd +4 -0
- data/integration/files/hiera.yaml +8 -0
- data/integration/files/modules/helloworld/manifests/init.pp +3 -0
- data/integration/files/modules/hieratest/manifests/init.pp +3 -0
- data/integration/files/modules/unicode/files/pretend_unicode +1 -0
- data/integration/files/modules/unicode/manifests/init.pp +6 -0
- data/integration/files/pre-suite/git_config.pp.erb +19 -0
- data/integration/files/pre-suite/prod_env.config +3 -0
- data/integration/files/r10k_conf.yaml.erb +9 -0
- data/integration/lib/README.mkd +4 -0
- data/integration/lib/git_utils.rb +205 -0
- data/integration/lib/master_manipulator.rb +205 -0
- data/integration/lib/r10k_utils.rb +222 -0
- data/integration/manifests/README.mkd +4 -0
- data/integration/pre-suite/00_pe_install.rb +6 -0
- data/integration/pre-suite/10_git_config.rb +48 -0
- data/integration/pre-suite/20_pe_r10k.rb +55 -0
- data/integration/pre-suite/README.mkd +5 -0
- data/integration/tests/Puppetfile/HTTP_PROXY_affects_forge_source.rb +72 -0
- data/integration/tests/Puppetfile/HTTP_PROXY_affects_git_source.rb +70 -0
- data/integration/tests/README.mkd +4 -0
- data/integration/tests/basic_functionality/install_pe_only_module_with_puppetfile.rb +83 -0
- data/integration/tests/basic_functionality/negative/neg_deploy_with_invalid_r10k_yaml.rb +51 -0
- data/integration/tests/basic_functionality/negative/neg_deploy_with_missing_r10k_yaml.rb +28 -0
- data/integration/tests/basic_functionality/negative/neg_invalid_git_provider.rb +45 -0
- data/integration/tests/basic_functionality/negative/negative_bad_proxy.rb +34 -0
- data/integration/tests/basic_functionality/proxy_specified_in_configuration.rb +103 -0
- data/integration/tests/basic_functionality/proxy_with_pe_only_module.rb +128 -0
- data/integration/tests/basic_functionality/proxy_with_puppetfile.rb +61 -0
- data/integration/tests/basic_functionality/rugged_git_provider_with_ssh.rb +109 -0
- data/integration/tests/basic_functionality/rugged_git_provider_without_ssh.rb +108 -0
- data/integration/tests/command_line/deploy_env_without_mod_update.rb +76 -0
- data/integration/tests/command_line/negative/neg_deploy_env_with_module_update.rb +77 -0
- data/integration/tests/command_line/negative/neg_invalid_cmd_line_arg.rb +23 -0
- data/integration/tests/git_source/HTTP_proxy_and_git_source.rb +70 -0
- data/integration/tests/git_source/git_source_git.rb +128 -0
- data/integration/tests/git_source/git_source_ssh.rb +87 -0
- data/integration/tests/git_source/git_source_submodule.rb +70 -0
- data/integration/tests/git_source/negative/neg_git_broken_remote.rb +38 -0
- data/integration/tests/git_source/negative/neg_git_unauthorized_https.rb +46 -0
- data/integration/tests/git_source/negative/neg_git_unauthorized_ssh.rb +73 -0
- data/integration/tests/git_source/negative/neg_git_unicode_branch.rb +35 -0
- data/integration/tests/i18n/deploy_module_with_unicode_in_file_name.rb +64 -0
- data/integration/tests/purging/content_not_purged_at_root.rb +89 -0
- data/integration/tests/purging/default_purging.rb +125 -0
- data/integration/tests/purging/does_not_purge_files_on_white_list.rb +93 -0
- data/integration/tests/purging/invalid_whitelist_types.rb +63 -0
- data/integration/tests/user_scenario/basic_workflow/multi_env_1000_branches.rb +66 -0
- data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module.rb +111 -0
- data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module_static.rb +117 -0
- data/integration/tests/user_scenario/basic_workflow/multi_env_hiera.rb +100 -0
- data/integration/tests/user_scenario/basic_workflow/multi_env_multi_source.rb +133 -0
- data/integration/tests/user_scenario/basic_workflow/multi_source_custom_forge_git_module.rb +161 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_basedir.rb +46 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_forge_module.rb +48 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module.rb +45 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module_ref.rb +43 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_remote.rb +45 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_branch_name_collision.rb +64 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_disk_full.rb +75 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_duplicate_module_names.rb +44 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_inaccessible_forge.rb +58 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_env_name.rb +34 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_puppet_file.rb +36 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_module_specified_at_deleted_release.rb +49 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_read_only.rb +58 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +51 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_10000_files.rb +75 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_git_module.rb +104 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_module.rb +81 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_custom_module.rb +49 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_large_files.rb +75 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_module_already_installed.rb +82 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_module_last_release_deleted.rb +68 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_non-existent_base_dir.rb +94 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +93 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_switch_forge_git_module.rb +117 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_unicode_paths.rb +60 -0
- data/integration/tests/user_scenario/basic_workflow/single_env_upgrade_forge_mod_revert_change.rb +166 -0
- data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +163 -0
- data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +111 -0
- data/integration/tests/user_scenario/complex_workflow/multi_env_unamanaged.rb +78 -0
- data/integration/tests/user_scenario/complex_workflow/single_env_git_module_update.rb +100 -0
- data/lib/r10k.rb +11 -0
- data/lib/r10k/action/base.rb +31 -0
- data/lib/r10k/action/cri_runner.rb +72 -0
- data/lib/r10k/action/deploy.rb +9 -0
- data/lib/r10k/action/deploy/deploy_helpers.rb +34 -0
- data/lib/r10k/action/deploy/display.rb +89 -0
- data/lib/r10k/action/deploy/environment.rb +196 -0
- data/lib/r10k/action/deploy/module.rb +84 -0
- data/lib/r10k/action/puppetfile.rb +10 -0
- data/lib/r10k/action/puppetfile/check.rb +31 -0
- data/lib/r10k/action/puppetfile/cri_runner.rb +26 -0
- data/lib/r10k/action/puppetfile/install.rb +45 -0
- data/lib/r10k/action/puppetfile/purge.rb +28 -0
- data/lib/r10k/action/runner.rb +96 -0
- data/lib/r10k/action/visitor.rb +31 -0
- data/lib/r10k/cli.rb +51 -0
- data/lib/r10k/cli/deploy.rb +114 -0
- data/lib/r10k/cli/ext/logging.rb +15 -0
- data/lib/r10k/cli/help.rb +7 -0
- data/lib/r10k/cli/puppetfile.rb +74 -0
- data/lib/r10k/cli/version.rb +31 -0
- data/lib/r10k/deployment.rb +132 -0
- data/lib/r10k/deployment/config.rb +56 -0
- data/lib/r10k/environment.rb +37 -0
- data/lib/r10k/environment/bare.rb +16 -0
- data/lib/r10k/environment/base.rb +150 -0
- data/lib/r10k/environment/git.rb +81 -0
- data/lib/r10k/environment/name.rb +86 -0
- data/lib/r10k/environment/svn.rb +91 -0
- data/lib/r10k/environment/with_modules.rb +139 -0
- data/lib/r10k/errors.rb +61 -0
- data/lib/r10k/errors/formatting.rb +28 -0
- data/lib/r10k/feature.rb +56 -0
- data/lib/r10k/feature/collection.rb +23 -0
- data/lib/r10k/features.rb +20 -0
- data/lib/r10k/forge/module_release.rb +228 -0
- data/lib/r10k/git.rb +196 -0
- data/lib/r10k/git/alternates.rb +63 -0
- data/lib/r10k/git/cache.rb +108 -0
- data/lib/r10k/git/errors.rb +34 -0
- data/lib/r10k/git/rugged.rb +17 -0
- data/lib/r10k/git/rugged/bare_repository.rb +85 -0
- data/lib/r10k/git/rugged/base_repository.rb +93 -0
- data/lib/r10k/git/rugged/cache.rb +11 -0
- data/lib/r10k/git/rugged/credentials.rb +91 -0
- data/lib/r10k/git/rugged/thin_repository.rb +89 -0
- data/lib/r10k/git/rugged/working_repository.rb +145 -0
- data/lib/r10k/git/shellgit.rb +9 -0
- data/lib/r10k/git/shellgit/bare_repository.rb +43 -0
- data/lib/r10k/git/shellgit/base_repository.rb +137 -0
- data/lib/r10k/git/shellgit/cache.rb +11 -0
- data/lib/r10k/git/shellgit/thin_repository.rb +69 -0
- data/lib/r10k/git/shellgit/working_repository.rb +111 -0
- data/lib/r10k/git/stateful_repository.rb +95 -0
- data/lib/r10k/initializers.rb +67 -0
- data/lib/r10k/instance_cache.rb +32 -0
- data/lib/r10k/keyed_factory.rb +39 -0
- data/lib/r10k/logging.rb +109 -0
- data/lib/r10k/logging/terminaloutputter.rb +36 -0
- data/lib/r10k/module.rb +38 -0
- data/lib/r10k/module/base.rb +113 -0
- data/lib/r10k/module/forge.rb +177 -0
- data/lib/r10k/module/git.rb +109 -0
- data/lib/r10k/module/local.rb +36 -0
- data/lib/r10k/module/metadata_file.rb +31 -0
- data/lib/r10k/module/svn.rb +112 -0
- data/lib/r10k/puppetfile.rb +286 -0
- data/lib/r10k/settings.rb +194 -0
- data/lib/r10k/settings/collection.rb +123 -0
- data/lib/r10k/settings/container.rb +97 -0
- data/lib/r10k/settings/definition.rb +124 -0
- data/lib/r10k/settings/enum_definition.rb +30 -0
- data/lib/r10k/settings/helpers.rb +38 -0
- data/lib/r10k/settings/list.rb +107 -0
- data/lib/r10k/settings/loader.rb +99 -0
- data/lib/r10k/settings/mixin.rb +54 -0
- data/lib/r10k/settings/uri_definition.rb +19 -0
- data/lib/r10k/source.rb +42 -0
- data/lib/r10k/source/base.rb +74 -0
- data/lib/r10k/source/exec.rb +51 -0
- data/lib/r10k/source/git.rb +142 -0
- data/lib/r10k/source/hash.rb +182 -0
- data/lib/r10k/source/svn.rb +136 -0
- data/lib/r10k/source/yaml.rb +20 -0
- data/lib/r10k/source/yamldir.rb +32 -0
- data/lib/r10k/svn.rb +6 -0
- data/lib/r10k/svn/remote.rb +68 -0
- data/lib/r10k/svn/working_dir.rb +125 -0
- data/lib/r10k/util/attempt.rb +84 -0
- data/lib/r10k/util/basedir.rb +65 -0
- data/lib/r10k/util/commands.rb +31 -0
- data/lib/r10k/util/exec_env.rb +36 -0
- data/lib/r10k/util/license.rb +24 -0
- data/lib/r10k/util/platform.rb +42 -0
- data/lib/r10k/util/purgeable.rb +88 -0
- data/lib/r10k/util/setopts.rb +55 -0
- data/lib/r10k/util/subprocess.rb +84 -0
- data/lib/r10k/util/subprocess/result.rb +56 -0
- data/lib/r10k/util/subprocess/runner.rb +26 -0
- data/lib/r10k/util/subprocess/runner/jruby.rb +23 -0
- data/lib/r10k/util/subprocess/runner/posix.rb +103 -0
- data/lib/r10k/util/subprocess/runner/pump.rb +59 -0
- data/lib/r10k/util/subprocess/runner/windows.rb +23 -0
- data/lib/r10k/util/subprocess/subprocess_error.rb +24 -0
- data/lib/r10k/util/symbolize_keys.rb +35 -0
- data/lib/r10k/version.rb +6 -0
- data/locales/config.yaml +21 -0
- data/locales/r10k.pot +545 -0
- data/r10k.gemspec +50 -0
- data/r10k.yaml.example +112 -0
- data/spec/fixtures/empty/.empty +0 -0
- data/spec/fixtures/integration/git/puppet-boolean-bare.tar +0 -0
- data/spec/fixtures/module/forge/bad_module/metadata.json +1 -0
- data/spec/fixtures/module/forge/eight_hundred/Modulefile +8 -0
- data/spec/fixtures/module/forge/eight_hundred/metadata.json +19 -0
- data/spec/fixtures/unit/action/r10k.yaml +5 -0
- data/spec/fixtures/unit/action/r10k_cachedir.yaml +2 -0
- data/spec/fixtures/unit/action/r10k_generate_types.yaml +3 -0
- data/spec/fixtures/unit/action/r10k_puppet_path.yaml +3 -0
- data/spec/fixtures/unit/puppetfile/argument-error/Puppetfile +1 -0
- data/spec/fixtures/unit/puppetfile/default-branch-override/Puppetfile +5 -0
- data/spec/fixtures/unit/puppetfile/duplicate-module-error/Puppetfile +10 -0
- data/spec/fixtures/unit/puppetfile/invalid-syntax/Puppetfile +1 -0
- data/spec/fixtures/unit/puppetfile/load-error/Puppetfile +1 -0
- data/spec/fixtures/unit/puppetfile/name-error/Puppetfile +1 -0
- data/spec/fixtures/unit/puppetfile/valid-forge-with-version/Puppetfile +1 -0
- data/spec/fixtures/unit/puppetfile/valid-forge-without-version/Puppetfile +1 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/expected_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_expected_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_unmanaged_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/unmanaged_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_two/expected_2 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_two/unmanaged_2 +0 -0
- data/spec/fixtures/unit/util/subprocess/runner/no-execute.sh +3 -0
- data/spec/integration/git/rugged/bare_repository_spec.rb +13 -0
- data/spec/integration/git/rugged/thin_repository_spec.rb +14 -0
- data/spec/integration/git/rugged/working_repository_spec.rb +48 -0
- data/spec/integration/git/shellgit/bare_repository_spec.rb +13 -0
- data/spec/integration/git/shellgit/thin_repository_spec.rb +14 -0
- data/spec/integration/git/shellgit/working_repository_spec.rb +13 -0
- data/spec/integration/git/stateful_repository_spec.rb +159 -0
- data/spec/matchers/exit_with.rb +28 -0
- data/spec/matchers/match_realpath.rb +18 -0
- data/spec/r10k-mocks.rb +3 -0
- data/spec/r10k-mocks/mock_config.rb +33 -0
- data/spec/r10k-mocks/mock_env.rb +15 -0
- data/spec/r10k-mocks/mock_source.rb +13 -0
- data/spec/shared-contexts/git-fixtures.rb +55 -0
- data/spec/shared-examples/deploy-actions.rb +69 -0
- data/spec/shared-examples/git-repository.rb +38 -0
- data/spec/shared-examples/git/bare_repository.rb +132 -0
- data/spec/shared-examples/git/thin_repository.rb +26 -0
- data/spec/shared-examples/git/working_repository.rb +207 -0
- data/spec/shared-examples/puppetfile-action.rb +39 -0
- data/spec/shared-examples/settings/ancestry.rb +44 -0
- data/spec/shared-examples/subprocess-runner.rb +83 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/unit/action/cri_runner_spec.rb +72 -0
- data/spec/unit/action/deploy/deploy_helpers_spec.rb +38 -0
- data/spec/unit/action/deploy/display_spec.rb +31 -0
- data/spec/unit/action/deploy/environment_spec.rb +395 -0
- data/spec/unit/action/deploy/module_spec.rb +139 -0
- data/spec/unit/action/puppetfile/check_spec.rb +41 -0
- data/spec/unit/action/puppetfile/cri_runner_spec.rb +47 -0
- data/spec/unit/action/puppetfile/install_spec.rb +84 -0
- data/spec/unit/action/puppetfile/purge_spec.rb +42 -0
- data/spec/unit/action/runner_spec.rb +213 -0
- data/spec/unit/action/visitor_spec.rb +39 -0
- data/spec/unit/cli_spec.rb +9 -0
- data/spec/unit/deployment/config_spec.rb +33 -0
- data/spec/unit/deployment_spec.rb +162 -0
- data/spec/unit/environment/base_spec.rb +109 -0
- data/spec/unit/environment/git_spec.rb +97 -0
- data/spec/unit/environment/name_spec.rb +135 -0
- data/spec/unit/environment/svn_spec.rb +133 -0
- data/spec/unit/errors/formatting_spec.rb +84 -0
- data/spec/unit/feature_spec.rb +50 -0
- data/spec/unit/forge/module_release_spec.rb +213 -0
- data/spec/unit/git/alternates_spec.rb +116 -0
- data/spec/unit/git/cache_spec.rb +55 -0
- data/spec/unit/git/rugged/cache_spec.rb +29 -0
- data/spec/unit/git/rugged/credentials_spec.rb +109 -0
- data/spec/unit/git/shellgit/cache_spec.rb +27 -0
- data/spec/unit/git/stateful_repository_spec.rb +40 -0
- data/spec/unit/git_spec.rb +102 -0
- data/spec/unit/initializers_spec.rb +68 -0
- data/spec/unit/instance_cache_spec.rb +78 -0
- data/spec/unit/keyed_factory_spec.rb +51 -0
- data/spec/unit/logging/terminaloutputter_spec.rb +53 -0
- data/spec/unit/logging_spec.rb +68 -0
- data/spec/unit/module/base_spec.rb +72 -0
- data/spec/unit/module/forge_spec.rb +207 -0
- data/spec/unit/module/git_spec.rb +274 -0
- data/spec/unit/module/metadata_file_spec.rb +68 -0
- data/spec/unit/module/svn_spec.rb +178 -0
- data/spec/unit/module_spec.rb +29 -0
- data/spec/unit/puppetfile_spec.rb +300 -0
- data/spec/unit/settings/collection_spec.rb +123 -0
- data/spec/unit/settings/container_spec.rb +92 -0
- data/spec/unit/settings/definition_spec.rb +79 -0
- data/spec/unit/settings/enum_definition_spec.rb +20 -0
- data/spec/unit/settings/inheritance_spec.rb +38 -0
- data/spec/unit/settings/list_spec.rb +88 -0
- data/spec/unit/settings/loader_spec.rb +110 -0
- data/spec/unit/settings/uri_definition_spec.rb +23 -0
- data/spec/unit/settings_spec.rb +246 -0
- data/spec/unit/source/base_spec.rb +31 -0
- data/spec/unit/source/exec_spec.rb +81 -0
- data/spec/unit/source/git_spec.rb +185 -0
- data/spec/unit/source/hash_spec.rb +54 -0
- data/spec/unit/source/svn_spec.rb +196 -0
- data/spec/unit/source/yaml_spec.rb +42 -0
- data/spec/unit/source_spec.rb +10 -0
- data/spec/unit/svn/remote_spec.rb +21 -0
- data/spec/unit/svn/working_dir_spec.rb +56 -0
- data/spec/unit/util/attempt_spec.rb +82 -0
- data/spec/unit/util/commands_spec.rb +61 -0
- data/spec/unit/util/exec_env_spec.rb +56 -0
- data/spec/unit/util/purgeable_spec.rb +230 -0
- data/spec/unit/util/setopts_spec.rb +59 -0
- data/spec/unit/util/subprocess/result_spec.rb +36 -0
- data/spec/unit/util/subprocess/runner/posix_spec.rb +7 -0
- data/spec/unit/util/subprocess/runner/pump_spec.rb +79 -0
- data/spec/unit/util/subprocess/runner/windows_spec.rb +7 -0
- data/spec/unit/util/subprocess/subprocess_error_spec.rb +26 -0
- data/spec/unit/util/subprocess_spec.rb +65 -0
- data/spec/unit/util/symbolize_keys_spec.rb +67 -0
- 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
|