pax_global_header00006660000000000000000000000064152724162400014515gustar00rootroot0000000000000052 comment=f4c12d4a9e8f333ff82f87659961a0fa49e0d2aa OpenVoxProject-openvox-ebcec1e/000077500000000000000000000000001527241624000167675ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/.gitattributes000066400000000000000000000010141527241624000216560ustar00rootroot00000000000000# Disable NL -> CRNL translation on Windows. This is necessary because the files on disk must # match the checksums in metadata.json. spec/fixtures/integration/application/module/environments/direnv/modules/nginx/README -text spec/fixtures/integration/application/module/environments/direnv/modules/nginx/metadata.json -text spec/fixtures/integration/application/module/environments/direnv/modules/nginx/Modulefile -text spec/fixtures/integration/application/module/environments/direnv/modules/nginx/manifests/init.pp -text OpenVoxProject-openvox-ebcec1e/.github/000077500000000000000000000000001527241624000203275ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/.github/dependabot.yml000066400000000000000000000014261527241624000231620ustar00rootroot00000000000000version: 2 updates: # raise PRs for gem updates - package-ecosystem: bundler directory: "/" schedule: interval: daily time: "13:00" open-pull-requests-limit: 10 # Maintain dependencies for GitHub Actions - package-ecosystem: github-actions directory: "/" schedule: interval: daily time: "13:00" open-pull-requests-limit: 10 # raise PRs for gem updates - package-ecosystem: bundler directory: "/" schedule: interval: daily time: "13:00" open-pull-requests-limit: 10 target-branch: "8.x" # Maintain dependencies for GitHub Actions - package-ecosystem: github-actions directory: "/" schedule: interval: daily time: "13:00" open-pull-requests-limit: 10 target-branch: "8.x" OpenVoxProject-openvox-ebcec1e/.github/release.yml000066400000000000000000000013521527241624000224730ustar00rootroot00000000000000--- # https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes changelog: exclude: labels: - duplicate - invalid - modulesync - question - skip-changelog - wont-fix - wontfix - github_actions categories: - title: Breaking Changes 🛠 labels: - backwards-incompatible - title: New Features 🎉 labels: - enhancement - title: Bug Fixes ðŸ�› labels: - bug - title: Documentation Updates 📚 labels: - documentation - docs - title: Dependency Updates ⬆ï¸� labels: - dependencies - title: Other Changes labels: - "*" OpenVoxProject-openvox-ebcec1e/.github/workflows/000077500000000000000000000000001527241624000223645ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/.github/workflows/acceptance.yml000066400000000000000000000104711527241624000252000ustar00rootroot00000000000000--- name: Beaker OpenVox Acceptance Tests run-name: |- Beaker acceptance tests of openvox on ${{ inputs.guest-arch }} runners for ${{ inputs.pre-release-build && 'pre-release' || 'release' }} packages of openvox-agent ${{ (inputs.pre-release-build && inputs.openvox-agent-version) || format(' collection: "{0}", version: "{1}" ', inputs.collection, ((inputs.openvox-agent-version == '') && 'latest') || inputs.openvox-agent-version) }} and openvox-server ${{ (inputs.pre-release-build && inputs.openvox-server-version) || format(' collection: "{0}", version: "{1}" ', inputs.collection, ((inputs.openvox-server-version == '') && 'latest') || inputs.openvox-server-version) }} on: workflow_dispatch: inputs: ref: description: |- (Ref) The git ref of openvox to run the Beaker test suite from. If testing something from openvox9, this should be a ref off of main. If testing something from openvox8, this should be a ref off of the 8.x branch. required: true type: string default: main fork: description: |- (Fork) The fork of openvox to run the Beaker test suite from. required: true type: string default: openvoxproject pre-release-build: description: |- (Pre-release Build) Whether to test unreleased version packages from the artifacts server, or released packages from the given collection. If this is true, versions must be valid version numbers, not latest, and collection is ignored. The workflow will download and install the matching openvox package files from the artifacts-url server. If this is false, version and collection must match, and the workflow will install the given openvox collection package and then let the system package manager install the latest or version packages from the collection repository. default: true type: boolean openvox-agent-version: description: |- (OpenVox Agent Version) The openvox-agent package version to test. (required if Pre-release Build is true) type: string openvox-server-version: description: |- (OpenVox Server Version) The openvox-server package version to test. (required if Pre-release Build is true) type: string collection: description: |- (Collection) OpenVox collection to use. (ignored if Pre-release Build is true) If testing something from main, this should be openvox9. If testing something from 8.x, this should be openvox8. default: 'openvox9' type: string artifacts-url: description: |- URL to the artifacts server. (used if Pre-release Build is true) default: 'https://s3.osuosl.org/openvox-artifacts' type: string guest-arch: description: |- The architecture of the guest VMs to run the acceptance tests on. This is used by the nested_vms action to determine which VM images to use. If not provided, the default is x86_64. NOTE: Currently only x86_64 *runners* support nested virtualization, so if guest-arch is set to arm64, the nested_vms will run under qemu and be quite a bit slower (5x-20x). type: string default: 'x86_64' permissions: contents: read jobs: acceptance: strategy: fail-fast: false matrix: suite-name: - openvox - openvox-agent uses: 'OpenVoxProject/shared-actions/.github/workflows/beaker_acceptance.yml@main' with: suite-name: ${{ matrix.suite-name }} ref: ${{ inputs.ref }} fork: ${{ inputs.fork }} openvox-collection: ${{ inputs.collection }} openvox-agent-version: ${{ inputs.openvox-agent-version }} openvox-agent-pre-release-build: ${{ inputs.pre-release-build }} openvox-server-version: ${{ inputs.openvox-server-version }} openvox-server-pre-release-build: ${{ inputs.pre-release-build }} artifacts-url: ${{ inputs.artifacts-url }} guest-arch: ${{ inputs.guest-arch }} OpenVoxProject-openvox-ebcec1e/.github/workflows/acceptance_aio.yml000066400000000000000000000065151527241624000260340ustar00rootroot00000000000000--- name: Beaker AIO Package Acceptance Tests run-name: |- Beaker acceptance tests of openvox-agent AIO package for ${{ inputs.pre-release-build && 'pre-release' || 'release' }} package ${{ (inputs.pre-release-build && inputs.version) || format(' collection: "{0}", version: "{1}" ', inputs.collection, ((inputs.version == '') && 'latest') || inputs.version) }} on: workflow_dispatch: inputs: ref: description: |- (Ref) The git ref of openvox-agent to run the Beaker test suite from. If testing something from openvox9, this should be a ref off of main. If testing something from openvox8, this should be a ref off of the 8.x branch. required: true type: string default: main pre-release-build: description: |- (Pre-release Build) Whether to test unreleased version packages from the artifacts server, or released packages from the given collection. If this is true, version must be a valid version, not latest, and collection is ignored. The workflow will download and install the matching openvox-agent package file from the artifacts-url server. If this is false, version and collection must match, and the workflow will install the given openvox collection package and then let the system package manager install the latest or version package from the collection repository. default: true type: boolean version: description: |- (Version) Package version to test. (required if Pre-release Build is true) type: string collection: description: |- (Collection) OpenVox collection to use. (ignored if Pre-release Build is true) If testing something from main, this should be openvox9. If testing something from 8.x, this should be openvox8. default: 'openvox9' type: string artifacts-url: description: |- URL to the artifacts server. (used if Pre-release Build is true) default: 'https://s3.osuosl.org/openvox-artifacts' type: string permissions: contents: read jobs: acceptance: uses: 'OpenVoxProject/shared-actions/.github/workflows/beaker_acceptance.yml@main' with: ref: ${{ inputs.ref }} project-name: openvox-agent os-add: |- [ ["debian", "13", "amd64", "daily-latest"] ] install-openvox: true openvox-collection: ${{ inputs.collection }} openvox-agent-version: ${{ inputs.version }} openvox-agent-pre-release-build: ${{ inputs.pre-release-build }} install-openvox-server: false install-openvoxdb: false artifacts-url: ${{ inputs.artifacts-url }} acceptance-working-dir: 'packaging/acceptance' acceptance-pre-suite: |- [ "pre-suite/configure_type_defaults.rb" ] acceptance-tests: |- [ "tests" ] beaker-options: |- { "helper": "lib/helper.rb" } vms: |- [ { "role": "agent", "count": 1, "cpus": 2, "mem_mb": 4096, "cpu_mode": "host-model" } ] OpenVoxProject-openvox-ebcec1e/.github/workflows/backport.yml000066400000000000000000000012611527241624000247140ustar00rootroot00000000000000--- name: Backport merged pull request on: pull_request_target: types: [labeled] permissions: {} jobs: backport: name: Backport merged pull request # For security reasons, we don't want to checkout and run arbitrary code when # using the pull_request_target trigger. So restrict this to cases where the # backport label is applied to an already merged PR. if: github.event.pull_request.merged && startsWith(github.event.label.name, 'backport ') uses: OpenVoxProject/shared-actions/.github/workflows/backport.yml@main secrets: github_pat: ${{ secrets.OPENVOXBOT_COMMIT_AND_PRS }} ssh_private_key: ${{ secrets.OPENVOXBOT_SSH_PRIVATE_KEY }} OpenVoxProject-openvox-ebcec1e/.github/workflows/build.yml000066400000000000000000000055151527241624000242140ustar00rootroot00000000000000--- name: Build openvox-agent permissions: contents: read on: workflow_dispatch: inputs: ref: description: 'Tag to build for a release, or branch to build for a pre-release' required: true project_name: description: 'The vanagon project to build' required: false default: 'openvox-agent' branch: description: >- The default platform list to build for. Use `main` for 9.x builds and `8.x` for 8.x builds. type: choice options: - main - '8.x' default: 'main' platform_list: description: >- Comma-separated list of platforms to build for. Do not include spaces. If not provided, will use the default platform list chosen above. required: false type: string vanagon_branch: description: 'The branch of the vanagon repository to use' required: false type: string default: 'main' upload_to_s3: description: 'Whether to upload the built artifacts to S3. If false, the artifacts will only be uploaded as workflow artifacts.' required: false type: boolean default: true use_dev: description: 'Use the "dev" branch of the shared-actions repo' required: false type: boolean default: false workflow_call: inputs: ref: type: string required: true project_name: type: string required: false default: 'openvox-agent' branch: type: string required: false default: 'main' platform_list: type: string required: false vanagon_branch: type: string required: false default: 'main' upload_to_s3: type: boolean required: false default: true use_dev: type: boolean required: false default: false jobs: build: if: ${{ !inputs.use_dev }} uses: 'openvoxproject/shared-actions/.github/workflows/build_vanagon.yml@main' with: ref: ${{ inputs.ref }} project_name: ${{ inputs.project_name }} platform_list: ${{ inputs.platform_list }} vanagon_branch: ${{ inputs.vanagon_branch }} upload_to_s3: ${{ inputs.upload_to_s3 }} working_directory: 'packaging' branch: ${{ inputs.branch }} secrets: inherit build_dev: if: ${{ inputs.use_dev }} uses: 'openvoxproject/shared-actions/.github/workflows/build_vanagon.yml@dev' with: ref: ${{ inputs.ref }} project_name: ${{ inputs.project_name }} platform_list: ${{ inputs.platform_list }} vanagon_branch: ${{ inputs.vanagon_branch }} upload_to_s3: ${{ inputs.upload_to_s3 }} working_directory: 'packaging' branch: ${{ inputs.branch }} secrets: inherit OpenVoxProject-openvox-ebcec1e/.github/workflows/gem_release.yaml000066400000000000000000000110251527241624000255170ustar00rootroot00000000000000--- name: Gem Release on: push: tags: - '*' workflow_dispatch: inputs: tag: description: 'Existing tag to release.' required: true type: string permissions: {} env: RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} jobs: build-release: # Prevent releases from forked repositories if: github.repository_owner == 'OpenVoxProject' name: Build the gem runs-on: ubuntu-24.04 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_TAG }} - name: Install Ruby uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0 with: ruby-version: 'ruby' bundler-cache: true - name: Build gem shell: bash run: bundle exec rake ci:gem_build - name: Upload gem to GitHub cache uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: gem-artifact path: '*.gem' retention-days: 1 compression-level: 0 create-github-release: needs: build-release name: Create GitHub release runs-on: ubuntu-24.04 permissions: contents: write # clone repo and create release steps: - name: Download gem from GitHub cache uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: gem-artifact - name: Create Release shell: bash env: GH_TOKEN: ${{ github.token }} # gh supports wildcards for release assets, so we can just upload all gem files in one command run: gh release create --repo ${{ github.repository }} ${{ env.RELEASE_TAG }} --generate-notes ./*.gem release-to-github: needs: build-release name: Release to GitHub runs-on: ubuntu-24.04 permissions: packages: write # publish to rubygems.pkg.github.com steps: - name: Download gem from GitHub cache uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: gem-artifact - name: Publish gem to GitHub packages env: GEM_HOST_API_KEY: ${{ secrets.GITHUB_TOKEN }} # gem push does not support wildcards, so we have to loop through all gem files # each combination of gem name, platform and version is a unique artifact, so we can have multiple gem files with the same name, version but different platforms run: | for gem_file in *.gem; do gem push --host "https://rubygems.pkg.github.com/${{ github.repository_owner }}" "$gem_file" done release-to-rubygems: needs: build-release name: Release gem to rubygems.org runs-on: ubuntu-24.04 environment: release # recommended by rubygems.org permissions: id-token: write # rubygems.org authentication steps: - name: Download gem from GitHub cache uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: gem-artifact - uses: rubygems/configure-rubygems-credentials@dc5a8d8553e6ee01fc26761a49e99e733d17954a # v2.1.0 - name: Publish gem to rubygems.org shell: bash # gem push does not support wildcards, so we have to loop through all gem files # each combination of gem name, platform and version is a unique artifact, so we can have multiple gem files with the same name, version but different platforms run: | for gem_file in *.gem; do gem push "$gem_file" done release-verification: name: Check that all releases are done runs-on: ubuntu-24.04 permissions: contents: read # minimal permissions that we have to grant needs: - create-github-release - release-to-github - release-to-rubygems steps: - name: Download gem from GitHub cache uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: gem-artifact - name: Install Ruby uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0 with: ruby-version: 'ruby' - name: Wait for release to propagate shell: bash # we upload different gem files for different platforms, so we have to wait for all of them to be available. run: | gem install rubygems-await for gem_file in *.gem; do gem await "$gem_file" done OpenVoxProject-openvox-ebcec1e/.github/workflows/prepare_release.yml000066400000000000000000000013001527241624000262370ustar00rootroot00000000000000name: 'Prepare Release' on: workflow_dispatch: inputs: version: description: 'Version to be released (e.g., 8.24.0)' required: true type: string base-branch: description: 'The branch to release from.' type: choice options: - main - '8.x' default: 'main' permissions: {} jobs: prepare_release: uses: OpenVoxProject/shared-actions/.github/workflows/prepare_release.yml@main with: version: ${{ inputs.version }} base-branch: ${{ inputs.base-branch }} secrets: github_pat: ${{ secrets.OPENVOXBOT_COMMIT_AND_PRS }} ssh_private_key: ${{ secrets.OPENVOXBOT_SSH_PRIVATE_KEY }} OpenVoxProject-openvox-ebcec1e/.github/workflows/promote.yml000066400000000000000000000075631527241624000246070ustar00rootroot00000000000000name: Promote Component on: workflow_dispatch: inputs: component: description: 'Component name to promote' required: true type: string ref: description: 'Git ref/tag to promote. For puppet-runtime, use the tag that has been built and uploaded to openvox-artifacts.' required: true type: string branch: description: 'Branch to promote to (defaults to main)' required: false default: 'main' type: choice options: - main - '8.x' permissions: {} jobs: promote: runs-on: ubuntu-26.04 steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ inputs.branch }} token: ${{ secrets.OPENVOXBOT_COMMIT_AND_PRS }} fetch-depth: 0 # required for vanagon below to determine the openvox version - name: Setup git and SSH signing id: git_identity uses: OpenVoxProject/shared-actions/.github/actions/setup-git-ssh-signing@main with: ssh_private_key: ${{ secrets.OPENVOXBOT_SSH_PRIVATE_KEY }} - name: Validate component exists run: | component="${{ inputs.component }}" if [[ ! -f "packaging/configs/components/${component}.json" ]]; then echo "::error::Could not find packaging/configs/components/${component}.json" exit 1 fi - name: Generate component JSON id: generate run: | component="${{ inputs.component }}" ref="${{ inputs.ref }}" if [[ "${component}" =~ ^(puppet-runtime|openssl-fips)$ ]]; then # Munge the ref: replace - with . munged="${ref//-/.}" json="{\"location\":\"https://s3.osuosl.org/openvox-artifacts/${component}/${ref}/\",\"version\":\"${munged}\"}" else json="{\"url\":\"https://github.com/openvoxproject/${component}.git\",\"ref\":\"${ref}\"}" fi echo "json=${json}" >> "$GITHUB_OUTPUT" echo "Generated JSON: ${json}" - name: Write component JSON run: | component="${{ inputs.component }}" echo '${{ steps.generate.outputs.json }}' > "packaging/configs/components/${component}.json" echo "Wrote packaging/configs/components/${component}.json:" cat "packaging/configs/components/${component}.json" - name: Install Ruby uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0 with: ruby-version: ruby bundler-cache: true # downloads all required components and fails if one isn't available # basically ensures our inputs.ref doesn't contain typos - name: Validate Vanagon render working-directory: packaging/ run: bundle exec vanagon render openvox-agent el-10-x86_64 - name: Create Pull Request uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: commit-message: "Promote ${{ inputs.component }} ${{ inputs.ref }} into ${{ inputs.branch }}" branch: "promote/${{ inputs.branch }}/${{ inputs.component }}/${{ inputs.ref }}" delete-branch: true title: "Promote ${{ inputs.component }} ${{ inputs.ref }} into ${{ inputs.branch }}" token: ${{ secrets.OPENVOXBOT_COMMIT_AND_PRS }} assignees: '${{ github.triggering_actor }}' author: '${{ steps.git_identity.outputs.git_author_name }} <${{ steps.git_identity.outputs.git_author_email }}>' committer: '${{ steps.git_identity.outputs.git_committer_name }} <${{ steps.git_identity.outputs.git_committer_email }}>' signoff: true base: ${{ inputs.branch }} body: | Automated promotion of ${{ inputs.component }} to ref ${{ inputs.ref }} in ${{ inputs.branch }}. OpenVoxProject-openvox-ebcec1e/.github/workflows/release.yml000066400000000000000000000032661527241624000245360ustar00rootroot00000000000000name: 'Release' on: workflow_dispatch: inputs: version: description: 'Version to be released' required: true type: string base-branch: description: 'The branch to release from.' type: choice options: - main - '8.x' default: 'main' permissions: {} jobs: verify-version: name: 'Verify prepare_release PR was merged' runs-on: ubuntu-24.04 steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ inputs.base-branch }} - name: Verify PUPPETVERSION matches release version env: RELEASE_VERSION: ${{ inputs.version }} run: | puppetversion=$(ruby -e "require_relative 'lib/puppet/version'; puts Puppet::PUPPETVERSION") if [ "$puppetversion" != "$RELEASE_VERSION" ]; then echo "::error::PUPPETVERSION is '$puppetversion' but expected '$RELEASE_VERSION'. Has the prepare_release PR been merged?" exit 1 fi echo "PUPPETVERSION '$puppetversion' matches release version" release: needs: verify-version uses: OpenVoxProject/shared-actions/.github/workflows/release.yml@main with: version: ${{ inputs.version }} base-branch: ${{ inputs.base-branch }} secrets: github_pat: ${{ secrets.OPENVOXBOT_COMMIT_AND_PRS }} ssh_private_key: ${{ secrets.OPENVOXBOT_SSH_PRIVATE_KEY }} build: needs: release uses: $/.github/workflows/build.yml permissions: contents: read with: ref: ${{ inputs.version }} branch: ${{ inputs.base-branch }} secrets: inherit OpenVoxProject-openvox-ebcec1e/.github/workflows/tests.yaml000066400000000000000000000244321527241624000244170ustar00rootroot00000000000000--- name: RSpec tests on: pull_request: branches: - main push: branches: - main permissions: contents: read env: BUNDLE_SET: "without packaging documentation release" concurrency: group: rspec-tests-${{ github.ref }} cancel-in-progress: true jobs: validate_manpages: name: Validate man pages runs-on: ubuntu-24.04 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # `man` exits 0 even when groff reports problems, so treat any stderr # output as a failure. Unlike the equivalent check in openfact, this only # inspects stderr (some pages legitimately contain the word "warning") # and uses a wide MANWIDTH (some pages contain unbreakable tokens longer # than 80 columns, such as long URLs and the `ciphers` default value, # which trigger unfixable "cannot break line" warnings at narrower widths). - name: Validate man pages with groff run: | status=0 for f in man/man5/*.5 man/man8/*.8; do errors=$(LC_ALL=C.UTF-8 MANROFFSEQ='' MANWIDTH=1000 man --warnings -E UTF-8 -l -Tutf8 -Z "$f" 2>&1 >/dev/null) if [ -n "$errors" ]; then echo "$f:" echo "$errors" status=1 fi done exit $status checks: name: ${{ matrix.cfg.check }} strategy: matrix: cfg: - {check: rubocop, os: ubuntu-latest, ruby: '3.3'} - {check: warnings, os: ubuntu-latest, ruby: '3.3'} runs-on: ${{ matrix.cfg.os }} steps: - name: Checkout current PR uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install ruby version ${{ matrix.cfg.ruby }} uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0 with: ruby-version: ${{ matrix.cfg.ruby }} bundler-cache: true - name: Run ${{ matrix.cfg.check }} check run: bundle exec rake ${{ matrix.cfg.check }} rspec_tests: name: ${{ matrix.cfg.os }}(ruby ${{ matrix.cfg.ruby }}) strategy: fail-fast: false matrix: cfg: - {os: ubuntu-24.04, ruby: '3.2'} - {os: ubuntu-24.04, ruby: '3.3'} - {os: ubuntu-24.04, ruby: '3.4'} - {os: ubuntu-24.04, ruby: '4.0'} - {os: ubuntu-24.04, ruby: 'jruby-10.0.6.0'} - {os: ubuntu-24.04, ruby: 'jruby-10.1.1.0'} - {os: windows-2025, ruby: '3.2'} - {os: windows-2025, ruby: '3.3'} - {os: windows-2025, ruby: '3.4'} - {os: windows-2025, ruby: '4.0'} runs-on: ${{ matrix.cfg.os }} steps: - name: Checkout current PR uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install ruby version ${{ matrix.cfg.ruby }} uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0 with: ruby-version: ${{ matrix.cfg.ruby }} bundler-cache: true - name: Output Ruby Environment run: bundle env - name: Run tests on Windows if: runner.os == 'Windows' run: | # Exclude the workspace and temp dirs from Windows Defender realtime # scanning; the specs create thousands of short-lived tmpfiles and # scanning each one slows the suite considerably. Add-MpPreference -ExclusionPath $Env:GITHUB_WORKSPACE, $Env:RUNNER_TEMP # https://github.com/ruby/ruby/pull/2791/files#diff-ff5ff976e81bebd977f0834e60416abbR97-R100 # Actions uses UTF8, causes test failures, similar to normal OS setup $PSDefaultParameterValues['*:Encoding'] = 'utf8' [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") [Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") $Env:LOG_SPEC_ORDER = 'true' # debug information chcp Get-WinSystemLocale Get-ChildItem Env: | % { Write-Output "$($_.Key): $($_.Value)" } # Enable Windows filesystem 8.3 support, see https://github.com/OpenVoxProject/openvox/pull/180 reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem /t REG_DWORD /v NtfsDisable8dot3NameCreation /d 0 /f # list current OpenSSL install gem list openssl ruby -ropenssl -e 'puts "OpenSSL Version - #{OpenSSL::OPENSSL_VERSION}"; puts "OpenSSL Library Version - #{OpenSSL::OPENSSL_LIBRARY_VERSION}"' # Run tests # Note: keep the default spec grouping here. Consolidating groups # changes which specs share a process, and the Windows registry # integration specs are order/state sensitive (14 failures in # spec/integration/util/windows/registry_spec.rb when run in # larger groups). bundle exec rake parallel:spec - name: Run tests on Linux if: runner.os == 'Linux' run: | # debug information ruby -ropenssl -e 'puts "OpenSSL Version - #{OpenSSL::OPENSSL_VERSION}"; puts "OpenSSL Library Version - #{OpenSSL::OPENSSL_LIBRARY_VERSION}"' if [[ ${{ matrix.cfg.ruby }} =~ "jruby" ]]; then export _JAVA_OPTIONS='-Xmx1024m -Xms512m' # Favor fast startup over peak JIT optimization: the suite runs in # many short-lived processes, so cold-JIT time dominates. Note the # trade-off: less-optimized JIT could in principle behave # differently, but these jobs exist to test openvox under JRuby, # not to exercise JRuby's optimizer. export JRUBY_OPTS='--dev' # workaround for PUP-10683 sudo apt remove rpm # Larger spec groups mean fewer JVM boots (23 -> ~4), each of # which costs startup plus ~19s of requires. bundle exec rake "parallel:spec[$(nproc),6000]" else bundle exec rake parallel:spec fi rake_checks: name: AIO Package Rake Checks runs-on: ubuntu-24.04 steps: # needs fetch-depth because the packaging dem reads old git tags - name: Checkout current PR uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - name: Install Ruby version 3.3 uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0 with: ruby-version: 3.3 bundler-cache: true - name: Validate code run: | bundle exec rake rubocop bundle exec rake -T | grep vox:build bundle exec rake -T | grep vox:upload working-directory: packaging test_gem_build: name: Test gem build runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Ruby uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0 with: ruby-version: ruby bundler-cache: true - name: Build gem for all platforms run: bundle exec rake ci:gem_build - name: Upload gem to GitHub cache uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: gem-artifact path: '*.gem' retention-days: 1 compression-level: 0 test_install: name: Test gem install needs: test_gem_build strategy: matrix: include: - os: ubuntu-24.04 gem-platform: ruby - os: macos-15 gem-platform: universal-darwin - os: windows-2025 gem-platform: x64-mingw-ucrt runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download gem from GitHub cache uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: gem-artifact - name: Determine gem file id: gem shell: bash env: GEM_PLATFORM: ${{ matrix.gem-platform }} run: | gem_file="$( ruby -rrubygems -e ' spec = Gem::Specification.load("openvox.gemspec") abort "Could not load openvox.gemspec" unless spec spec.platform = ENV.fetch("GEM_PLATFORM") unless ENV["GEM_PLATFORM"] == "ruby" puts spec.file_name ' )" test -f "$gem_file" echo "file=$gem_file" >> "$GITHUB_OUTPUT" - name: Install Ruby uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0 with: ruby-version: ruby bundler-cache: true - name: Install gem run: gem install "${{ steps.gem.outputs.file }}" --verbose - name: Smoke test shell: bash run: | puppet --version ruby -rpuppet -e 'puts Puppet.version' # Distro packages and newer Rubies pair puppet with the newest json gem # rather than the one bundled with this Ruby, which is how json 3 broke # every deserialization in #654. Install the newest json and exercise # the JSON load and dump paths against it. - name: Smoke test with newest json gem shell: bash run: | gem install json --no-document ruby -rjson -e 'puts "json #{JSON::VERSION}"' # Util::Json.dump with the pretty generator options puppet facts show > facts.json # JSON.pretty_generate in the parser face puppet parser dump --format json --pretty -e 'notify { "x": }' # Catalog serialized to JSON, then loaded back through Util::Json.load certname="$(puppet config print certname)" puppet catalog compile "$certname" --code 'notify { "json ok": }' \ --render-as json --log_level warning > catalog.json puppet apply --catalog catalog.json tests: if: always() needs: - checks - rake_checks - rspec_tests - test_gem_build - test_install - validate_manpages runs-on: ubuntu-24.04 name: Test suite steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0 with: jobs: ${{ toJSON(needs) }} OpenVoxProject-openvox-ebcec1e/.gitignore000066400000000000000000000020511527241624000207550ustar00rootroot00000000000000.rspec results tags .*.sw[op] test.pp # YARD generated documentation .yardoc /doc # Now that there is a gemfile, RVM ignores rvmrc in parent directories, so a local one is required # to work around that. Which we don't want committed, so we can ignore it here. /.rvmrc .bundle/ .byebug_history /ext/packaging/ /pkg/ Gemfile.lock Gemfile.local Guardfile puppet-acceptance/ /.project .ruby-version .ruby-gemset /acceptance/junit /acceptance/log /acceptance/.beaker /acceptance/.vendor /packaging/acceptance/junit /packaging/acceptance/log /packaging/acceptance/.beaker /packaging/.bundle /packaging/ext/build_metadata.* /packaging/output /packaging/vendor/* /packaging/.vendor/* /packaging/*.log /packaging/pkg/* /packaging/acceptance/junit/* /packaging/acceptance/log/* /packaging/acceptance/tmp/* /packaging/acceptance/merged_options.rb /packaging/acceptance/.beaker/* /packaging/ext/smoke/*output.txt # emacs backup files *~ /*.samples coverage/ # Files and directory added by RubyMine IDE *.iml .rakeTasks .idea/ spec_order.txt /vendor /.vendor /*.gem .DS_Store OpenVoxProject-openvox-ebcec1e/.gitmodules000066400000000000000000000003321527241624000211420ustar00rootroot00000000000000[submodule "benchmarks/full_catalog/puppetlabs-puppetserver_perf_control"] path = benchmarks/full_catalog/puppetlabs-puppetserver_perf_control url = https://github.com/puppetlabs/puppetlabs-puppetserver_perf_control OpenVoxProject-openvox-ebcec1e/.mailmap000066400000000000000000000164771527241624000204270ustar00rootroot00000000000000Adrien Thebo Adrien Thebo Adrien Thebo adrienthebo Allen Ballman ballman Andrew Shafer Andrew Shafer Andrew Shafer Andrew Shafer Andrew Shafer shafer Anselm Strauss Anselm Strauss Anselm Strauss Anselm Strauss Ben Hengst ben hengst Ben Hughes Ben H Ben Hughes Ben Hughes Blake Barnett shadoi Brice Figureau Brice Figureau Bryan Kearney Bryan Kearney Cameron Thomas Cameron Thomas Carl Caum Carl Caum Chris Price Chris Price Chris Price cprice Christian Hofstaedtler Christian Hofstaedtler Dan Bode Dan Bode Dan Bode Dan Bode Dan Bode Dan Bode Daniel Pittman Daniel Pittman David Lutterkort David Lutterkort David Lutterkort lutter David Lutterkort lutter David Schmitt David Schmitt Deepak Giridharagopal Deepak Giridharagopal Dominic Maraglia Donavan Miller donavan Eric Sorenson Eric Sorenson Eric Sorenson Eric Sorenson Eric Sorenson Eric Sorenson Francois Deppierraz Francois Deppierraz Garrett Honeycutt Garrett Honeycutt Gary Larizza Gary Larizza Greg Sutcliffe Greg Sutcliffe James Turnbull James Turnbull James Turnbull James Turnbull James Turnbull James Turnbull James Turnbull root Jeff McCune Jeff McCune Jeffrey J McCune Jeff McCune Jeffrey McCune Jeff McCune mccune Jeff McCune mccune Jeff Weiss Jeff Weiss Jesse Wolfe Jesse Wolfe Jos Boumans josb Josh Cooper Josh Cooper Josh Cooper joshcooper Joshua Harlan Lifton lifton Justin Stoller Justin Stoller Kelsey Hightower Kelsey Hightower Kelsey Hightower Kelsey Hightower Ken Barber Ken Barber Luke Kanies Luke Kanies Luke Kaines Luke Kanies Luke Kanies Luke Kanies Luke Kanies Luke Kanies luke Markus Roberts Markus Roberts Markus Roberts Markus Roberts Markus Roberts markus Martin Englund Martin Englund Matt Palmer mpalmer Matt Robinson Matt Robinson Matthaus Owens Matthaus Litteken Matthaus Owens Matthaus Litteken Matthaus Owens Matthaus Owens Michael Stahnke stahnma Moses Mendoza MosesMendoza Nan Liu Nan Liu Nick Fagerlund nfagerlund Nick Fagerlund nfagerlund Nigel Kersten Nigel Kersten Nigel Kersten Nigel Kersten Ohad Levy Ohad Levy Patrick Carlisle Patrick Patrick Carlisle pcarlisle Paul Lathrop Paul Lathrop Paul Lathrop Paul Lathrop Peter Meier duritong Peter Meier mh Peter Mørch peter Pieter van de Bruggen Pieter van de Bruggen Rahul Gopinath rahul Rahul Gopinath rahul Rahul Gopinath rahul Rahul Gopinath vrthra <9@vrtra.net> Rein Henrichs Rein Henrichs Rudy Gevaert rgevaert Rudy Gevaert rgevaert Russ Allbery Russ Allbery Sean E. Millichamp Sean Millichamp Sean E. Millichamp Sean Millichamp Steve McIintosh steve mcintosh Thom May Thom May Thom May Thom May OpenVoxProject-openvox-ebcec1e/.noexec.yaml000066400000000000000000000000461527241624000212120ustar00rootroot00000000000000--- exclude: - gem - rake - rspec OpenVoxProject-openvox-ebcec1e/.rubocop.yml000066400000000000000000000205531527241624000212460ustar00rootroot00000000000000--- inherit_from: .rubocop_todo.yml plugins: - rubocop-i18n - rubocop-performance - rubocop-rake - rubocop-rspec # without excluding the vendor dirs below, rubocop will load all rubocop config files from installed gems ¯\_(ツ)_/¯ AllCops: TargetRubyVersion: 3.2 Include: - 'lib/**/*.rb' - 'ext/**/*.rb' Exclude: - '**/*.erb' - 'acceptance/**/*' - 'spec/**/*' - 'tasks/**/*' - 'ext/suse/puppet.spec' - 'lib/puppet/vendor/**/*' - 'lib/puppet/pops/model/ast.rb' - 'lib/puppet/pops/parser/eparser.rb' - 'vendor/**/*' - '.vendor/**/*' - 'packaging/resources/files/execution_wrapper' # The formatting of defaults is unusual, so let's skip layout cops. Layout: Exclude: - 'lib/puppet/defaults.rb' # We don't mind when module and class keywords are aligned. Layout/IndentationWidth: AllowedPatterns: ['^\s*module'] Layout/LineEndStringConcatenationIndentation: Enabled: true # Enabling this cop will remove raising RuntimeErrors and cause spec test # failures Style/RedundantException: Exclude: - 'lib/puppet/file_bucket/dipper.rb' - 'lib/puppet/forge.rb' - 'lib/puppet/module_tool/applications/unpacker.rb' - 'lib/puppet/module_tool/local_tarball.rb' - 'lib/puppet/module_tool/tar.rb' - 'lib/puppet/pops/types/class_loader.rb' # Enabling this cop causes a plethora of failed rspec tests, mostly # Errno::ENAMETOOLONG and Puppet::Context::UndefinedBindingError: Unable to # lookup 'environments' errors Style/RedundantSelfAssignment: Exclude: - 'lib/puppet/context.rb' # Enabling this cop causes failures in rb_tree_map_spec relating to important # function slike being unable to delete nodes and returning nil when the key # cannot be found Style/PreferredHashMethods: Enabled: false # Explicitly enables this cop new in 1.7 Layout/SpaceBeforeBrackets: Enabled: true # puppet uses symbol booleans in types and providers to work around long standing # bugs when trying to manage falsey pararameters and properties Lint/BooleanSymbol: Enabled: true Exclude: - 'lib/puppet/type.rb' - 'lib/puppet/type/**/*.rb' - 'lib/puppet/provider/**/*.rb' - 'lib/puppet/reference/providers.rb' - 'lib/puppet/parameter/value.rb' Metrics/AbcSize: Enabled: false Metrics/BlockLength: Enabled: false Metrics/BlockNesting: Enabled: false Metrics/ClassLength: Enabled: false Metrics/CyclomaticComplexity: Enabled: false Metrics/MethodLength: Enabled: false Metrics/ModuleLength: Enabled: false Metrics/ParameterLists: Enabled: false Metrics/PerceivedComplexity: Enabled: false Naming/AccessorMethodName: Enabled: false Naming/BinaryOperatorParameterName: Enabled: false Naming/BlockParameterName: Exclude: - 'lib/puppet/util/windows/daemon.rb' - 'lib/puppet/util/windows/user.rb' Naming/ClassAndModuleCamelCase: Exclude: - 'lib/puppet/ffi/windows/structs.rb' - 'lib/puppet/pops/validation/checker4_0.rb' - 'lib/puppet/pops/validation/validator_factory_4_0.rb' - 'lib/puppet/util/windows/root_certs.rb' - 'lib/puppet/util/windows/security.rb' - 'lib/puppet/util/windows/user.rb' Naming/ConstantName: Exclude: - 'lib/puppet/graph/relationship_graph.rb' - 'lib/puppet/indirector/hiera.rb' - 'lib/puppet/provider/package/sun.rb' - 'lib/puppet/resource/type.rb' - 'lib/puppet/type/schedule.rb' - 'lib/puppet/type/tidy.rb' - 'lib/puppet/util.rb' - 'lib/puppet/util/colors.rb' - 'lib/puppet/util/execution.rb' - 'lib/puppet/util/symbolic_file_mode.rb' - 'lib/puppet/util/tagging.rb' - 'lib/puppet/util/windows/adsi.rb' - 'lib/puppet/util/windows/sid.rb' - 'lib/puppet/util/yaml.rb' Naming/HeredocDelimiterNaming: Enabled: false # Exclude existing violations to avoid breaking changes Naming/MemoizedInstanceVariableName: Exclude: - 'lib/puppet/module_tool/applications/installer.rb' - 'lib/puppet/pops/types/type_factory.rb' - 'lib/puppet/provider/package/portage.rb' - 'lib/puppet/resource.rb' Naming/MethodName: Exclude: - 'lib/puppet/functions/**/*' - 'lib/puppet/parser/ast/pops_bridge.rb' - 'lib/puppet/pops/**/*' - 'lib/puppet/util/windows/**/*' Naming/MethodParameterName: Enabled: false Naming/PredicatePrefix: ForbiddenPrefixes: [] Naming/RescuedExceptionsVariableName: Enabled: false Naming/VariableName: Exclude: - 'ext/windows/service/daemon.rb' - 'lib/puppet/agent.rb' - 'lib/puppet/application/describe.rb' - 'lib/puppet/pops/lookup/hiera_config.rb' - 'lib/puppet/pops/validation/checker4_0.rb' - 'lib/puppet/provider/package/pip.rb' - 'lib/puppet/provider/package/windows/exe_package.rb' - 'lib/puppet/provider/package/windows/msi_package.rb' - 'lib/puppet/ssl/ssl_provider.rb' - 'lib/puppet/util/windows/adsi.rb' - 'lib/puppet/util/windows/daemon.rb' - 'lib/puppet/util/windows/error.rb' - 'lib/puppet/util/windows/user.rb' Naming/VariableNumber: Enabled: false Performance/AncestorsInclude: # new in 1.7 Enabled: true Performance/BigDecimalWithNumericArgument: # new in 1.7 Enabled: true Performance/ConcurrentMonotonicTime: # new in 1.12 Enabled: true Performance/MapCompact: # new in 1.11 Enabled: true Performance/RedundantSortBlock: # new in 1.7 Enabled: true Performance/ReverseFirst: # new in 1.7 Enabled: true RSpec/BeEq: # new in 2.9.0 Enabled: true RSpec/BeNil: # new in 2.9.0 Enabled: true RSpec/ExcessiveDocstringSpacing: # new in 2.5 Enabled: true RSpec/IdenticalEqualityAssertion: # new in 2.4 Enabled: true RSpec/SubjectDeclaration: # new in 2.5 Enabled: true RSpec/VerifiedDoubleReference: # new in 2.10.0 Enabled: true Style/AutoResourceCleanup: Enabled: true Style/CaseEquality: Enabled: true Style/CaseLikeIf: Enabled: true Style/ClassCheck: Enabled: true Style/ClassEqualityComparison: Enabled: true Style/ClassMethods: Enabled: true Style/CollectionCompact: Enabled: true Style/ColonMethodCall: Enabled: true Style/CombinableLoops: Enabled: true Exclude: - 'lib/puppet/graph/relationship_graph.rb' - 'lib/puppet/pops/types/ruby_generator.rb' - 'lib/puppet/provider/service/init.rb' - 'lib/puppet/util/rdoc/generators/puppet_generator.rb' Style/ColonMethodDefinition: Enabled: true Style/DefWithParentheses: Enabled: true Style/Dir: Enabled: true Style/DocumentDynamicEvalDefinition: Enabled: true Style/DoubleCopDisableDirective: Enabled: true Style/EachForSimpleLoop: Enabled: true Style/EachWithObject: Enabled: true Style/EmptyBlockParameter: Enabled: true Style/EmptyCaseCondition: Enabled: true Style/EmptyLambdaParameter: Enabled: true Style/EmptyLiteral: Enabled: true Style/EvalWithLocation: Enabled: true Style/EvenOdd: Enabled: true Style/ExpandPathArguments: Enabled: true Style/FetchEnvVar: Enabled: true Style/FileRead: Enabled: true Style/FileWrite: Enabled: true Style/FloatDivision: Enabled: true Style/For: Enabled: true Style/FrozenStringLiteralComment: Enabled: true Style/GlobalStdStream: Enabled: true Style/GlobalVars: Enabled: true Style/HashAsLastArrayItem: Enabled: true Style/HashConversion: Enabled: true # HashEachMethods does not guarantee the receiver is a Hash, so # this will not work since numerous puppet classes define #value # not #each_value Style/HashEachMethods: Enabled: false Style/HashLikeCase: Enabled: true Exclude: - 'lib/puppet/util/command_line/trollop.rb' Style/HashTransformKeys: Enabled: true Style/HashTransformValues: Enabled: true Style/IdenticalConditionalBranches: Enabled: true Style/IfInsideElse: Enabled: true Style/IfUnlessModifierOfIfUnless: Enabled: true Style/IfWithBooleanLiteralBranches: Enabled: true Style/IfWithSemicolon: Enabled: true Style/InfiniteLoop: Enabled: true Style/InverseMethods: Enabled: true Style/KeywordParametersOrder: Enabled: true Style/Lambda: Enabled: true Style/LambdaCall: Enabled: true Style/LineEndConcatenation: Enabled: true Style/MapToHash: Enabled: true Style/OptionalArguments: Enabled: true Exclude: # Moving optional arguments to the end of the method signature would be # a breaking change. - 'lib/puppet/util/windows/principal.rb' # Interpolated _() strings are all over the codebase. # This would be incredibly noisy, and FastGettext handles interpolation just fine. I18n/GetText/DecorateStringFormattingUsingInterpolation: Enabled: false OpenVoxProject-openvox-ebcec1e/.rubocop_todo.yml000066400000000000000000000621611527241624000222740ustar00rootroot00000000000000# This configuration was generated by # `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp` # using RuboCop version 1.90.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # This cop supports safe autocorrection (--autocorrect). I18n/GetText/DecorateFunctionMessage: Enabled: false # This cop supports safe autocorrection (--autocorrect). I18n/GetText/DecorateString: Enabled: false I18n/GetText/DecorateStringFormattingUsingPercent: Exclude: - 'lib/puppet/provider/user/windows_adsi.rb' - 'lib/puppet/transaction/resource_harness.rb' I18n/RailsI18n/DecorateString: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. Layout/ExtraSpacing: Exclude: - 'lib/puppet/parser/resource.rb' - 'lib/puppet/pops/model/factory.rb' - 'lib/puppet/pops/model/model_label_provider.rb' - 'lib/puppet/pops/parser/lexer_support.rb' - 'lib/puppet/pops/types/types.rb' - 'lib/puppet/provider/service/freebsd.rb' - 'lib/puppet/util/at_fork/solaris.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowForAlignment. Layout/SpaceBeforeFirstArg: Exclude: - 'lib/puppet/pops/types/types.rb' # Configuration parameters: AllowedMethods. # AllowedMethods: enums Lint/ConstantDefinitionInBlock: Exclude: - 'lib/puppet/face/config.rb' - 'lib/puppet/face/help.rb' - 'lib/puppet/face/node/clean.rb' - 'lib/puppet/provider/package/aix.rb' - 'lib/puppet/provider/package/apt.rb' - 'lib/puppet/provider/package/gem.rb' - 'lib/puppet/provider/package/pip.rb' - 'lib/puppet/provider/package/yum.rb' - 'lib/puppet/provider/service/upstart.rb' - 'lib/puppet/provider/user/directoryservice.rb' - 'lib/puppet/type/file.rb' - 'lib/puppet/type/file/source.rb' - 'lib/puppet/type/resources.rb' - 'lib/puppet/type/schedule.rb' - 'lib/puppet/type/tidy.rb' # Configuration parameters: AllowedParentClasses. Lint/MissingSuper: Enabled: false # Configuration parameters: AllowedMethods, AllowedPatterns. Lint/NestedMethodDefinition: Exclude: - 'lib/puppet/pops/types/p_binary_type.rb' - 'lib/puppet/pops/types/p_init_type.rb' - 'lib/puppet/pops/types/p_object_type.rb' - 'lib/puppet/pops/types/p_sem_ver_range_type.rb' - 'lib/puppet/pops/types/p_sem_ver_type.rb' - 'lib/puppet/pops/types/p_sensitive_type.rb' - 'lib/puppet/pops/types/p_timespan_type.rb' - 'lib/puppet/pops/types/p_timestamp_type.rb' - 'lib/puppet/pops/types/p_uri_type.rb' - 'lib/puppet/pops/types/types.rb' - 'lib/puppet/type.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowPercentLiteralArrayArgument. Lint/RedundantSplatExpansion: Exclude: - 'lib/puppet/provider/package/portage.rb' # This cop supports safe autocorrection (--autocorrect). Lint/RedundantStringCoercion: Exclude: - 'lib/puppet/application/agent.rb' Lint/RescueException: Exclude: - 'ext/windows/service/daemon.rb' - 'lib/puppet/configurer/fact_handler.rb' - 'lib/puppet/generate/type.rb' - 'lib/puppet/settings.rb' - 'lib/puppet/transaction/resource_harness.rb' - 'lib/puppet/util.rb' - 'lib/puppet/util/autoload.rb' - 'lib/puppet/util/command_line/trollop.rb' - 'util/rspec_grouper' # Configuration parameters: AllowComments, AllowNil. Lint/SuppressedException: Exclude: - 'lib/puppet/application/face_base.rb' - 'lib/puppet/ffi/windows/functions.rb' - 'lib/puppet/forge/errors.rb' - 'lib/puppet/functions/each.rb' - 'lib/puppet/functions/filter.rb' - 'lib/puppet/functions/map.rb' - 'lib/puppet/functions/slice.rb' - 'lib/puppet/pops/time/timespan.rb' - 'lib/puppet/pops/types/iterable.rb' - 'lib/puppet/pops/types/p_runtime_type.rb' - 'lib/puppet/util/command_line.rb' - 'lib/puppet/util/execution.rb' - 'util/rspec_grouper' # This cop supports safe autocorrection (--autocorrect). Lint/ToJSON: Exclude: - 'lib/puppet/module_tool/metadata.rb' - 'lib/puppet/network/http/error.rb' - 'lib/puppet/pops/serialization/json.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions. # NotImplementedExceptions: NotImplementedError Lint/UnusedMethodArgument: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: CheckForMethodsWithNoSideEffects. Lint/Void: Exclude: - 'lib/puppet/pops/loader/loader_paths.rb' - 'lib/puppet/util/multi_match.rb' # This cop supports unsafe autocorrection (--autocorrect-all). Performance/Count: Exclude: - 'lib/puppet/confine/any.rb' - 'lib/puppet/confine/false.rb' - 'lib/puppet/confine/true.rb' - 'lib/puppet/graph/relationship_graph.rb' - 'lib/puppet/provider.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: IncludeActiveSupportAliases. Performance/DoubleStartEndWith: Exclude: - 'lib/puppet/ssl/certificate_request.rb' # This cop supports unsafe autocorrection (--autocorrect-all). Performance/InefficientHashSearch: Exclude: - 'lib/puppet/face/node/clean.rb' - 'lib/puppet/provider/nameservice/directoryservice.rb' - 'lib/puppet/provider/user/directoryservice.rb' - 'lib/puppet/resource.rb' - 'lib/puppet/util/windows/adsi.rb' # This cop supports safe autocorrection (--autocorrect). Performance/RedundantBlockCall: Exclude: - 'lib/puppet/application.rb' - 'lib/puppet/context.rb' - 'lib/puppet/file_bucket/file.rb' - 'lib/puppet/functions/max.rb' - 'lib/puppet/functions/min.rb' - 'lib/puppet/gettext/stubs.rb' - 'lib/puppet/network/http/api/server/v3.rb' - 'lib/puppet/pal/pal_impl.rb' - 'lib/puppet/pops/adaptable.rb' - 'lib/puppet/pops/lookup/invocation.rb' - 'lib/puppet/pops/model/factory.rb' - 'lib/puppet/util.rb' # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: MaxKeyValuePairs. Performance/RedundantMerge: Exclude: - 'lib/puppet/x509/cert_provider.rb' # This cop supports safe autocorrection (--autocorrect). Performance/RegexpMatch: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). Performance/UnfreezeString: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols, AllowModifiersOnAttrs, AllowModifiersOnAliasMethod. # SupportedStyles: inline, group Style/AccessModifierDeclarations: Exclude: - 'lib/puppet/util/suidmanager.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: separated, grouped Style/AccessorGrouping: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: prefer_alias, prefer_alias_method Style/Alias: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: always, conditionals Style/AndOr: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: percent_q, bare_percent Style/BarePercentLiterals: Exclude: - 'lib/puppet/module_tool/metadata.rb' - 'lib/puppet/node/environment.rb' - 'lib/puppet/parameter/package_options.rb' - 'lib/puppet/provider/package/gem.rb' - 'lib/puppet/provider/package/windows/package.rb' - 'lib/puppet/settings.rb' - 'lib/puppet/settings/base_setting.rb' - 'lib/puppet/transaction/event.rb' - 'lib/puppet/util/execution.rb' # This cop supports safe autocorrection (--autocorrect). Style/BisectedAttrAccessor: Exclude: - 'lib/puppet/module.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object # FunctionalMethods: let, let!, subject, watch # AllowedMethods: lambda, proc, it Style/BlockDelimiters: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowOnConstant, AllowOnSelfClass. Style/CaseEquality: Exclude: - 'lib/puppet/indirector/terminus.rb' - 'lib/puppet/interface/face_collection.rb' - 'lib/puppet/module_tool/installed_modules.rb' - 'lib/puppet/module_tool/shared_behaviors.rb' - 'lib/puppet/util/log/destination.rb' - 'lib/puppet/util/multi_match.rb' # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules. # SupportedStyles: nested, compact # SupportedStylesForClasses: ~, nested, compact # SupportedStylesForModules: ~, nested, compact Style/ClassAndModuleChildren: Enabled: false Style/ClassVars: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, AllowInnerBackticks. # SupportedStyles: backticks, percent_x, mixed Style/CommandLiteral: Exclude: - 'ext/windows/service/daemon.rb' - 'lib/puppet/provider/nameservice/directoryservice.rb' - 'lib/puppet/util/terminal.rb' - 'lib/puppet/util/windows/process.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: Keywords, RequireColon. # Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE Style/CommentAnnotation: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). Style/CommentedKeyword: Exclude: - 'lib/puppet/util/command_line/trollop.rb' - 'lib/puppet/util/rpm_compare.rb' - 'lib/puppet/util/windows/service.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. # SupportedStyles: assign_to_condition, assign_inside_condition Style/ConditionalAssignment: Enabled: false # Configuration parameters: AllowedConstants. Style/Documentation: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: allowed_in_returns, forbidden Style/DoubleNegation: Exclude: - 'lib/puppet/application/lookup.rb' - 'lib/puppet/confine/boolean.rb' - 'lib/puppet/http/service/compiler.rb' - 'lib/puppet/parser/functions/fqdn_rand.rb' - 'lib/puppet/pops/evaluator/evaluator_impl.rb' - 'lib/puppet/pops/issue_reporter.rb' - 'lib/puppet/provider/package/apt.rb' - 'lib/puppet/type.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, AllowComments. # SupportedStyles: empty, nil, both Style/EmptyElse: Exclude: - 'lib/puppet/pal/plan_signature.rb' - 'lib/puppet/pops/loader/dependency_loader.rb' - 'lib/puppet/pops/types/iterable.rb' - 'lib/puppet/pops/types/p_sem_ver_range_type.rb' - 'lib/puppet/pops/types/type_calculator.rb' - 'lib/puppet/pops/types/types.rb' - 'lib/puppet/ssl/state_machine.rb' # This cop supports safe autocorrection (--autocorrect). Style/Encoding: Exclude: - 'lib/puppet/face/module/install.rb' - 'lib/puppet/face/module/list.rb' - 'lib/puppet/face/module/upgrade.rb' - 'lib/puppet/ffi/windows/structs.rb' - 'lib/puppet/interface/action.rb' - 'lib/puppet/module_tool.rb' - 'lib/puppet/type.rb' - 'lib/puppet/type/file.rb' - 'lib/puppet/type/package.rb' - 'lib/puppet/util/windows/service.rb' # This cop supports safe autocorrection (--autocorrect). Style/ExplicitBlockArgument: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: format, sprintf, percent Style/FormatString: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns. # SupportedStyles: annotated, template, unannotated Style/FormatStringToken: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). Style/GlobalStdStream: Exclude: - 'lib/puppet/application/apply.rb' - 'lib/puppet/application/script.rb' - 'lib/puppet/face/epp.rb' - 'lib/puppet/face/parser.rb' - 'lib/puppet/util.rb' - 'lib/puppet/util/command_line.rb' - 'lib/puppet/util/windows/daemon.rb' # Configuration parameters: AllowedVariables. Style/GlobalVars: Exclude: - 'lib/puppet/external/dot.rb' - 'lib/puppet/test/test_helper.rb' - 'lib/puppet/util/logging.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. Style/GuardClause: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys # SupportedShorthandSyntax: always, never, either, consistent, either_consistent Style/HashSyntax: Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/IfUnlessModifier: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: InverseMethods, InverseBlocks. Style/InverseMethods: Exclude: - 'lib/puppet/face/catalog/select.rb' - 'lib/puppet/graph/relationship_graph.rb' - 'lib/puppet/parser/compiler.rb' - 'lib/puppet/pops/loader/loader_paths.rb' - 'lib/puppet/pops/types/ruby_generator.rb' - 'lib/puppet/pops/validation.rb' - 'lib/puppet/pops/validation/checker4_0.rb' - 'lib/puppet/provider/package/pkg.rb' - 'lib/puppet/provider/user/user_role_add.rb' - 'lib/puppet/reference/providers.rb' - 'lib/puppet/type/file.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowedMethods, AllowedPatterns. Style/MethodCallWithoutArgsParentheses: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: require_parentheses, require_no_parentheses, require_no_parentheses_except_multiline Style/MethodDefParentheses: Exclude: - 'lib/puppet/pops/evaluator/evaluator_impl.rb' - 'lib/puppet/pops/evaluator/relationship_operator.rb' - 'lib/puppet/pops/label_provider.rb' - 'lib/puppet/pops/model/factory.rb' - 'lib/puppet/pops/model/model_label_provider.rb' - 'lib/puppet/pops/model/model_tree_dumper.rb' - 'lib/puppet/pops/model/tree_dumper.rb' - 'lib/puppet/pops/parser/interpolation_support.rb' - 'lib/puppet/pops/parser/parser_support.rb' - 'lib/puppet/pops/utils.rb' - 'lib/puppet/pops/validation.rb' - 'lib/puppet/pops/validation/validator_factory_4_0.rb' - 'lib/puppet/util/command_line/trollop.rb' Style/MissingRespondToMissing: Exclude: - 'lib/puppet/module_tool/metadata.rb' - 'lib/puppet/parser/scope.rb' - 'lib/puppet/settings/alias_setting.rb' - 'lib/puppet/util/command_line/trollop.rb' - 'lib/puppet/util/feature.rb' Style/MultilineBlockChain: Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/MultilineIfModifier: Exclude: - 'lib/puppet/face/config.rb' - 'lib/puppet/module_tool/applications/installer.rb' - 'lib/puppet/module_tool/shared_behaviors.rb' - 'lib/puppet/pops/evaluator/access_operator.rb' - 'lib/puppet/pops/loader/task_instantiator.rb' - 'lib/puppet/pops/model/model_tree_dumper.rb' - 'lib/puppet/provider/package/windows.rb' - 'lib/puppet/provider/service/upstart.rb' - 'lib/puppet/resource/catalog.rb' - 'lib/puppet/type/user.rb' - 'lib/puppet/util/execution.rb' - 'lib/puppet/util/windows/com.rb' # This cop supports safe autocorrection (--autocorrect). Style/MultilineIfThen: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: keyword, braces Style/MultilineMemoization: Exclude: - 'lib/puppet/application.rb' - 'lib/puppet/pops/types/types.rb' # This cop supports safe autocorrection (--autocorrect). Style/MultilineTernaryOperator: Exclude: - 'lib/puppet/application/apply.rb' - 'lib/puppet/application/resource.rb' - 'lib/puppet/application/script.rb' - 'lib/puppet/defaults.rb' - 'lib/puppet/environments.rb' - 'lib/puppet/external/dot.rb' - 'lib/puppet/indirector/catalog/compiler.rb' - 'lib/puppet/node/environment.rb' - 'lib/puppet/pal/pal_impl.rb' - 'lib/puppet/pops/lookup/lookup_key.rb' - 'lib/puppet/resource/catalog.rb' - 'lib/puppet/settings/environment_conf.rb' - 'lib/puppet/util.rb' - 'lib/puppet/util/windows/security.rb' # This cop supports safe autocorrection (--autocorrect). Style/MultilineWhenThen: Exclude: - 'lib/puppet/graph/simple_graph.rb' - 'lib/puppet/interface/documentation.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowMethodComparison, ComparisonsThreshold. Style/MultipleComparison: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, Recursive. # SupportedStyles: literals, strict Style/MutableConstant: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. # SupportedStyles: predicate, comparison Style/NumericPredicate: Enabled: false # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowedMethods. # AllowedMethods: infinite?, nonzero? Style/RedundantCondition: Exclude: - 'lib/puppet/face/epp.rb' - 'lib/puppet/functions/tree_each.rb' - 'lib/puppet/pops/evaluator/evaluator_impl.rb' - 'lib/puppet/pops/issue_reporter.rb' - 'lib/puppet/pops/types/types.rb' - 'lib/puppet/provider/package/apt.rb' # This cop supports safe autocorrection (--autocorrect). Style/RedundantParentheses: Exclude: - 'lib/puppet/application/agent.rb' - 'lib/puppet/application/face_base.rb' - 'lib/puppet/graph/rb_tree_map.rb' - 'lib/puppet/module_tool/shared_behaviors.rb' - 'lib/puppet/pops/parser/lexer_support.rb' - 'lib/puppet/provider/package/aix.rb' - 'lib/puppet/provider/package/pip.rb' - 'lib/puppet/provider/package/portage.rb' - 'lib/puppet/provider/package/rpm.rb' - 'lib/puppet/provider/service/launchd.rb' - 'lib/puppet/settings/base_setting.rb' - 'lib/puppet/type/package.rb' - 'lib/puppet/type/tidy.rb' - 'lib/puppet/util/windows/com.rb' # This cop supports unsafe autocorrection (--autocorrect-all). Style/RedundantSort: Exclude: - 'lib/puppet/provider/package/nim.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: implicit, explicit Style/RescueStandardError: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. # AllowedMethods: present?, blank?, presence, try, try! Style/SafeNavigation: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowAsExpressionSeparator. Style/Semicolon: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: only_raise, only_fail, semantic Style/SignalException: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowIfMethodIsEmpty. Style/SingleLineMethods: Exclude: - 'lib/puppet/ffi/windows/api_types.rb' - 'lib/puppet/file_system/memory_file.rb' - 'lib/puppet/graph/simple_graph.rb' - 'lib/puppet/interface/action.rb' - 'lib/puppet/parser/resource.rb' - 'lib/puppet/pops/model/factory.rb' - 'lib/puppet/pops/model/model_label_provider.rb' - 'lib/puppet/pops/types/type_formatter.rb' - 'lib/puppet/provider/nameservice/directoryservice.rb' - 'lib/puppet/provider/service/freebsd.rb' - 'lib/puppet/type.rb' - 'lib/puppet/util/command_line/trollop.rb' - 'lib/puppet/util/metaid.rb' - 'lib/puppet/util/windows/com.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowModifier. Style/SoleNestedConditional: Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/StderrPuts: Exclude: - 'bin/puppet' - 'lib/puppet/application/agent.rb' - 'lib/puppet/application/apply.rb' - 'lib/puppet/application/describe.rb' - 'lib/puppet/application/device.rb' - 'lib/puppet/application/face_base.rb' - 'lib/puppet/application/filebucket.rb' - 'lib/puppet/application/script.rb' - 'lib/puppet/face/config.rb' - 'lib/puppet/reference/type.rb' - 'lib/puppet/util.rb' - 'lib/puppet/util/command_line/trollop.rb' # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: Mode. Style/StringConcatenation: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes Style/StringLiterals: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, MinSize. # SupportedStyles: percent, brackets Style/SymbolArray: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. # AllowedMethods: define_method Style/SymbolProc: Exclude: - 'lib/puppet/provider/aix_object.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, AllowSafeAssignment. # SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex Style/TernaryParentheses: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma Style/TrailingCommaInArguments: Exclude: - 'lib/puppet/util/windows/user.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma Style/TrailingCommaInHashLiteral: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowNamedUnderscoreVariables. Style/TrailingUnderscoreVariable: Exclude: - 'lib/puppet/indirector/file_server.rb' - 'lib/puppet/module/plan.rb' - 'lib/puppet/pops/evaluator/closure.rb' - 'lib/puppet/pops/parser/parser_support.rb' - 'lib/puppet/provider/group/windows_adsi.rb' - 'lib/puppet/provider/package/zypper.rb' - 'lib/puppet/provider/service/launchd.rb' - 'lib/puppet/provider/user/pw.rb' - 'lib/puppet/provider/user/windows_adsi.rb' - 'lib/puppet/resource/type.rb' - 'lib/puppet/util/windows/registry.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, AllowedMethods. # AllowedMethods: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym Style/TrivialAccessors: Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/WhenThen: Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/WhileUntilModifier: Exclude: - 'lib/puppet/parser/scope.rb' - 'lib/puppet/pops/parser/interpolation_support.rb' - 'lib/puppet/pops/parser/locator.rb' - 'lib/puppet/pops/parser/pn_parser.rb' - 'lib/puppet/pops/types/p_object_type.rb' - 'lib/puppet/util/windows/process.rb' # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: forbid_for_all_comparison_operators, forbid_for_equality_operators_only, require_for_all_comparison_operators, require_for_equality_operators_only Style/YodaCondition: Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). Style/ZeroLengthPredicate: Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings. # URISchemes: http, https Layout/LineLength: Max: 582 OpenVoxProject-openvox-ebcec1e/.yardopts000066400000000000000000000005061527241624000206360ustar00rootroot00000000000000--protected --private --verbose --markup markdown --readme README.md --tag status --transitive-tag status --tag comment --hide-tag comment --tag dsl:"DSL" --no-transitive-tag api --template-path yardoc/templates --files CO*.md,api/**/*.md --api public --api private --hide-void-return --exclude lib/puppet/vendor/ lib/**/*.rb OpenVoxProject-openvox-ebcec1e/CHANGELOG.md000066400000000000000000001235751527241624000206150ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. ## [9.3.0](https://github.com/openvoxproject/openvox/tree/9.3.0) (2026-11-03) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.2.1...9.3.0) **Security fixes:** - Read event data hashes with the stringifying converter [\#765](https://github.com/OpenVoxProject/openvox/pull/765) ([nmburgan](https://github.com/nmburgan)) ## [9.2.1](https://github.com/openvoxproject/openvox/tree/9.2.1) (2026-10-23) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.2.0...9.2.1) **Security fixes:** - Promote puppet-runtime 2026.10.23.1 into main [\#746](https://github.com/OpenVoxProject/openvox/pull/746) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) ## [9.2.0](https://github.com/openvoxproject/openvox/tree/9.2.0) (2026-10-22) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.1.1...9.2.0) **Security fixes:** - Promote puppet-runtime 2026.10.22.1 into main [\#743](https://github.com/OpenVoxProject/openvox/pull/743) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) ## [9.1.1](https://github.com/openvoxproject/openvox/tree/9.1.1) (2026-10-21) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.1.0...9.1.1) **Security fixes:** - Promote puppet-runtime 2026.10.21.1 into main [\#734](https://github.com/OpenVoxProject/openvox/pull/734) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) ## [9.1.0](https://github.com/openvoxproject/openvox/tree/9.1.0) (2026-10-13) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.0.0...9.1.0) **Implemented enhancements:** - Port Puppet::Util::Json to the json 3 API [\#706](https://github.com/OpenVoxProject/openvox/pull/706) ([miharp](https://github.com/miharp)) **Closed issues:** - json 3.0.0 breaks Puppet::Util::Json and the test suite [\#654](https://github.com/OpenVoxProject/openvox/issues/654) **Merged pull requests:** - Promote puppet-runtime 2026.10.12.2 into main [\#722](https://github.com/OpenVoxProject/openvox/pull/722) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Add redhatfips-10-x86\_64 platform and remove outdated comments [\#707](https://github.com/OpenVoxProject/openvox/pull/707) ([nmburgan](https://github.com/nmburgan)) - Fix documentation for default disabled reports [\#701](https://github.com/OpenVoxProject/openvox/pull/701) ([ekohl](https://github.com/ekohl)) ## [9.0.0](https://github.com/openvoxproject/openvox/tree/9.0.0) (2026-10-02) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.0.0-rc4...9.0.0) **Fixed bugs:** - \[Bug\]: Ruby crashes on child side of fork pre-exec macOS 26 \(Tahoe\) [\#538](https://github.com/OpenVoxProject/openvox/issues/538) **Merged pull requests:** - Skip the tests that need jruby-openssl in FIPS mode [\#696](https://github.com/OpenVoxProject/openvox/pull/696) ([nmburgan](https://github.com/nmburgan)) ## [9.0.0-rc4](https://github.com/openvoxproject/openvox/tree/9.0.0-rc4) (2026-09-29) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.0.0-rc3...9.0.0-rc4) **Fixed bugs:** - openfact: Update 6.2.0 -\> 6.2.1 [\#692](https://github.com/OpenVoxProject/openvox/pull/692) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) **Merged pull requests:** - Promote puppet-runtime 2026.09.29.1 into main [\#694](https://github.com/OpenVoxProject/openvox/pull/694) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) ## [9.0.0-rc3](https://github.com/openvoxproject/openvox/tree/9.0.0-rc3) (2026-09-25) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.0.0-rc2...9.0.0-rc3) **Fixed bugs:** - packaging: ensure every systemd-distro get a service file [\#688](https://github.com/OpenVoxProject/openvox/pull/688) ([bastelfreak](https://github.com/bastelfreak)) ## [9.0.0-rc2](https://github.com/openvoxproject/openvox/tree/9.0.0-rc2) (2026-09-25) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.0.0-rc1...9.0.0-rc2) **Implemented enhancements:** - openfact: update 6.1.0 -\> 6.2.0 [\#677](https://github.com/OpenVoxProject/openvox/pull/677) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Promote openfact 6.1.0 into main [\#668](https://github.com/OpenVoxProject/openvox/pull/668) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) **Fixed bugs:** - \[Bug\]: use of "server\_list" \(instead of server\) throws an error [\#658](https://github.com/OpenVoxProject/openvox/issues/658) - Wait for certificates in the forked child, not in the daemon [\#683](https://github.com/OpenVoxProject/openvox/pull/683) ([silug](https://github.com/silug)) - Only require the server setting when no explicit server is given [\#659](https://github.com/OpenVoxProject/openvox/pull/659) ([silug](https://github.com/silug)) - print "Loading facts" just once [\#656](https://github.com/OpenVoxProject/openvox/pull/656) ([bastelfreak](https://github.com/bastelfreak)) - Pin json below 3 to unblock CI [\#655](https://github.com/OpenVoxProject/openvox/pull/655) ([miharp](https://github.com/miharp)) - Install the service defaults file on Debian [\#645](https://github.com/OpenVoxProject/openvox/pull/645) ([jcharaoui](https://github.com/jcharaoui)) - Do not swallow RunTimeoutError while collecting facts [\#643](https://github.com/OpenVoxProject/openvox/pull/643) ([silug](https://github.com/silug)) - Kill the forked agent run if it outlives runtimeout [\#642](https://github.com/OpenVoxProject/openvox/pull/642) ([silug](https://github.com/silug)) **Merged pull requests:** - puppet-runtime: Update 2026.09.02.1 -\> 2026.09.24.1 [\#684](https://github.com/OpenVoxProject/openvox/pull/684) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Accept ca\_server and report\_server without server when running as root [\#661](https://github.com/OpenVoxProject/openvox/pull/661) ([silug](https://github.com/silug)) - Document --environment in puppet agent help [\#653](https://github.com/OpenVoxProject/openvox/pull/653) ([miharp](https://github.com/miharp)) - Fix systemd unreferenced variable warning on Debian [\#644](https://github.com/OpenVoxProject/openvox/pull/644) ([jcharaoui](https://github.com/jcharaoui)) - Increase delay affordance in waitforlock test [\#641](https://github.com/OpenVoxProject/openvox/pull/641) ([jcharaoui](https://github.com/jcharaoui)) ## [9.0.0-rc1](https://github.com/openvoxproject/openvox/tree/9.0.0-rc1) (2026-09-04) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.0.0-beta2...9.0.0-rc1) **Breaking changes:** - raise ArgumentError for root when server is unset [\#623](https://github.com/OpenVoxProject/openvox/pull/623) ([corporate-gadfly](https://github.com/corporate-gadfly)) - refactor\(service/systemd\): remove Debian SysVInit compatibility fallback [\#562](https://github.com/OpenVoxProject/openvox/pull/562) ([TheMeier](https://github.com/TheMeier)) **Implemented enhancements:** - feat: add multi platform builds [\#607](https://github.com/OpenVoxProject/openvox/pull/607) ([rwaffen](https://github.com/rwaffen)) - rubocop: cleanup formatting and whitespace [\#594](https://github.com/OpenVoxProject/openvox/pull/594) ([bastelfreak](https://github.com/bastelfreak)) **Fixed bugs:** - \[Bug\]: Sometimes Error "This 'if' statement has no effect", sometimes not [\#542](https://github.com/OpenVoxProject/openvox/issues/542) - Fix excessive reads of /proc/mounts [\#620](https://github.com/OpenVoxProject/openvox/pull/620) ([jenxie](https://github.com/jenxie)) - puppet generate: print module directory when types are missing [\#617](https://github.com/OpenVoxProject/openvox/pull/617) ([Sharpie](https://github.com/Sharpie)) - Report errors when renewing a certificate fails [\#610](https://github.com/OpenVoxProject/openvox/pull/610) ([jay7x](https://github.com/jay7x)) **Security fixes:** - Promote puppet-runtime 2026.09.02.1 into main [\#628](https://github.com/OpenVoxProject/openvox/pull/628) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) **Merged pull requests:** - puppet node: redeclare to identical values is a `notice` not a warning. [\#626](https://github.com/OpenVoxProject/openvox/pull/626) ([jcpunk](https://github.com/jcpunk)) - fix links to point to docs.openvoxproject.org [\#609](https://github.com/OpenVoxProject/openvox/pull/609) ([corporate-gadfly](https://github.com/corporate-gadfly)) - Fix a small typo in the markdown docs \(redux\) [\#603](https://github.com/OpenVoxProject/openvox/pull/603) ([jcharaoui](https://github.com/jcharaoui)) - Update filebucket content acceptance tests for literal checksum semantics [\#602](https://github.com/OpenVoxProject/openvox/pull/602) ([silug](https://github.com/silug)) - Request report storage explicitly in cached-catalog drift test [\#598](https://github.com/OpenVoxProject/openvox/pull/598) ([silug](https://github.com/silug)) - Compare facterversion against installed facter in acceptance test [\#597](https://github.com/OpenVoxProject/openvox/pull/597) ([silug](https://github.com/silug)) - Migrate lookup acceptance tests to Hiera 5 data providers [\#596](https://github.com/OpenVoxProject/openvox/pull/596) ([silug](https://github.com/silug)) ## [9.0.0-beta2](https://github.com/openvoxproject/openvox/tree/9.0.0-beta2) (2026-08-05) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.0.0-beta1...9.0.0-beta2) **Breaking changes:** - puppet-runtime: update 2026.07.16.1-\>2026.08.04.1 / removed java keystores [\#593](https://github.com/OpenVoxProject/openvox/pull/593) ([bastelfreak](https://github.com/bastelfreak)) - Remove zone\_core module [\#592](https://github.com/OpenVoxProject/openvox/pull/592) ([bastelfreak](https://github.com/bastelfreak)) - Update vendored modules to latest versions [\#589](https://github.com/OpenVoxProject/openvox/pull/589) ([bastelfreak](https://github.com/bastelfreak)) - Change reports default from "store" to "none" [\#583](https://github.com/OpenVoxProject/openvox/pull/583) ([Sharpie](https://github.com/Sharpie)) - openfact: Require 6.x [\#577](https://github.com/OpenVoxProject/openvox/pull/577) ([bastelfreak](https://github.com/bastelfreak)) - Promote openfact 6.0.0 into main [\#575](https://github.com/OpenVoxProject/openvox/pull/575) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Remove data-binding settings [\#385](https://github.com/OpenVoxProject/openvox/pull/385) ([silug](https://github.com/silug)) - Remove hiera indirector [\#384](https://github.com/OpenVoxProject/openvox/pull/384) ([silug](https://github.com/silug)) - Allow file content that looks like a checksum. [\#170](https://github.com/OpenVoxProject/openvox/pull/170) ([jeremie-pierson](https://github.com/jeremie-pierson)) **Implemented enhancements:** - Replace deprecated `--force-yes` `apt-get` option [\#560](https://github.com/OpenVoxProject/openvox/pull/560) ([jay7x](https://github.com/jay7x)) - Update CFPropertyList requirement from \>= 3.0.6, \< 4 to ~\> 4.0 [\#509](https://github.com/OpenVoxProject/openvox/pull/509) ([dependabot[bot]](https://github.com/apps/dependabot)) **Fixed bugs:** - \[Bug\]: Centralized filebucket not working properly [\#367](https://github.com/OpenVoxProject/openvox/issues/367) - \[Bug\]: lines in file resource content looking like a checksum throws an error [\#169](https://github.com/OpenVoxProject/openvox/issues/169) - fix: Pacman provider uses unrecognized option '--update' [\#451](https://github.com/OpenVoxProject/openvox/pull/451) ([fmichea](https://github.com/fmichea)) - Fix filebucket REST terminus to support request.server [\#368](https://github.com/OpenVoxProject/openvox/pull/368) ([mdechiaro](https://github.com/mdechiaro)) - fix: `Deferred` resolution of Puppet-language functions \(e.g. mocks in tests\) failing due to lack of `:global_scope` [\#350](https://github.com/OpenVoxProject/openvox/pull/350) ([griggi-ws](https://github.com/griggi-ws)) **Closed issues:** - \[Deprecation\] Replace `puppet master` Terminology in User-Facing Docs/Help [\#347](https://github.com/OpenVoxProject/openvox/issues/347) - \[Deprecation\] Data-Binding Settings [\#338](https://github.com/OpenVoxProject/openvox/issues/338) - \[Deprecation\] `file { content => }` Filebucket Retrieval Behavior [\#335](https://github.com/OpenVoxProject/openvox/issues/335) - \[Deprecation\] `Puppet::Indirector::Hiera` Terminus [\#332](https://github.com/OpenVoxProject/openvox/issues/332) **Merged pull requests:** - Remove setup.ps1 Cygwin setup script [\#591](https://github.com/OpenVoxProject/openvox/pull/591) ([Sharpie](https://github.com/Sharpie)) - Remove unloadable CC-BY-1.0 RDoc template and generator [\#587](https://github.com/OpenVoxProject/openvox/pull/587) ([silug](https://github.com/silug)) - Document cross-node read exposure of a central filebucket [\#585](https://github.com/OpenVoxProject/openvox/pull/585) ([silug](https://github.com/silug)) - Update JRuby 10.1 test cell to 10.1.1.0 [\#584](https://github.com/OpenVoxProject/openvox/pull/584) ([Sharpie](https://github.com/Sharpie)) - Add man page validation to CI [\#580](https://github.com/OpenVoxProject/openvox/pull/580) ([silug](https://github.com/silug)) - Address review feedback from \#530 [\#579](https://github.com/OpenVoxProject/openvox/pull/579) ([silug](https://github.com/silug)) - Remove bashism from pre/post-install scripts [\#573](https://github.com/OpenVoxProject/openvox/pull/573) ([sideeffect42](https://github.com/sideeffect42)) - Update URLs in default config files [\#572](https://github.com/OpenVoxProject/openvox/pull/572) ([jcharaoui](https://github.com/jcharaoui)) - Improve manpage reproducibility [\#570](https://github.com/OpenVoxProject/openvox/pull/570) ([jcharaoui](https://github.com/jcharaoui)) - Fix a small typo in the markdown docs [\#569](https://github.com/OpenVoxProject/openvox/pull/569) ([jcharaoui](https://github.com/jcharaoui)) - Validate that the catalog is compiled for this node [\#568](https://github.com/OpenVoxProject/openvox/pull/568) ([binford2k](https://github.com/binford2k)) - User resource pw provider: Switches a couple commands to the safer array syntax [\#567](https://github.com/OpenVoxProject/openvox/pull/567) ([binford2k](https://github.com/binford2k)) - Set `PUPPET_EXTRA_OPTS` variable to empty [\#559](https://github.com/OpenVoxProject/openvox/pull/559) ([corporate-gadfly](https://github.com/corporate-gadfly)) - Promote puppet-runtime 2026.07.16.1 into main [\#553](https://github.com/OpenVoxProject/openvox/pull/553) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Rebrand Puppet -\> OpenVox and fix links [\#530](https://github.com/OpenVoxProject/openvox/pull/530) ([silug](https://github.com/silug)) - Fix "translates custom oids to their long name" test [\#488](https://github.com/OpenVoxProject/openvox/pull/488) ([anthonyryan1](https://github.com/anthonyryan1)) - Replace 'master' terminology with 'server' [\#348](https://github.com/OpenVoxProject/openvox/pull/348) ([silug](https://github.com/silug)) ## [9.0.0-beta1](https://github.com/openvoxproject/openvox/tree/9.0.0-beta1) (2026-07-15) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.0.0-alpha2...9.0.0-beta1) **Breaking changes:** - More secure default server setting [\#536](https://github.com/OpenVoxProject/openvox/pull/536) ([corporate-gadfly](https://github.com/corporate-gadfly)) - Raise minimum Ruby version to 3.2.0 [\#442](https://github.com/OpenVoxProject/openvox/pull/442) ([silug](https://github.com/silug)) - Remove legacy PAL script eval APIs [\#393](https://github.com/OpenVoxProject/openvox/pull/393) ([silug](https://github.com/silug)) - Remove regsubst encoding argument [\#391](https://github.com/OpenVoxProject/openvox/pull/391) ([silug](https://github.com/silug)) - Remove pluginsync setting [\#389](https://github.com/OpenVoxProject/openvox/pull/389) ([silug](https://github.com/silug)) - Remove configprint setting [\#374](https://github.com/OpenVoxProject/openvox/pull/374) ([silug](https://github.com/silug)) **Fixed bugs:** - \[Bug\]: ca\_refresh\_interval is not respected — agent refreshes CA on every run when server responds 304 [\#435](https://github.com/OpenVoxProject/openvox/issues/435) - \[Bug\]: Puppet 8 introduced a regex node definition regression [\#14](https://github.com/OpenVoxProject/openvox/issues/14) - Update ca\_last\_update/crl\_last\_update on HTTP 304 [\#524](https://github.com/OpenVoxProject/openvox/pull/524) ([bastelfreak](https://github.com/bastelfreak)) - Copy input mtime to files generated by puppet generate types [\#522](https://github.com/OpenVoxProject/openvox/pull/522) ([silug](https://github.com/silug)) - Tolerate concurrent creation of directories [\#506](https://github.com/OpenVoxProject/openvox/pull/506) ([Sharpie](https://github.com/Sharpie)) - Fix handling of Puppet::Pops serialization issues [\#502](https://github.com/OpenVoxProject/openvox/pull/502) ([seanmil](https://github.com/seanmil)) - Fix regex node lookup regression from PUP-11515 [\#481](https://github.com/OpenVoxProject/openvox/pull/481) ([corporate-gadfly](https://github.com/corporate-gadfly)) **Closed issues:** - \[Deprecation\] Fine-Grained `filetimeout` Control [\#345](https://github.com/OpenVoxProject/openvox/issues/345) - \[Deprecation\] `Puppet::SSL::Certificate` Class [\#344](https://github.com/OpenVoxProject/openvox/issues/344) - \[Deprecation\] PAL Script Evaluation APIs [\#343](https://github.com/OpenVoxProject/openvox/issues/343) - \[Deprecation\] `source_permissions` File Parameter [\#340](https://github.com/OpenVoxProject/openvox/issues/340) - \[Deprecation\] `pluginsync` Setting [\#339](https://github.com/OpenVoxProject/openvox/issues/339) - \[Deprecation\] `configprint` Setting [\#337](https://github.com/OpenVoxProject/openvox/issues/337) - \[Deprecation\] `regsubst()` Encoding Argument [\#336](https://github.com/OpenVoxProject/openvox/issues/336) **Merged pull requests:** - CI: Speed up JRuby and Windows spec runs [\#525](https://github.com/OpenVoxProject/openvox/pull/525) ([silug](https://github.com/silug)) - Add arm64 support to acceptance [\#495](https://github.com/OpenVoxProject/openvox/pull/495) ([jpartlow](https://github.com/jpartlow)) - Remove filetimeout deprecation warning [\#419](https://github.com/OpenVoxProject/openvox/pull/419) ([silug](https://github.com/silug)) - Remove source\_permissions deprecation warning [\#418](https://github.com/OpenVoxProject/openvox/pull/418) ([silug](https://github.com/silug)) - add runtime deprecation warnings to Puppet::Util ENV wrappers [\#417](https://github.com/OpenVoxProject/openvox/pull/417) ([silug](https://github.com/silug)) ## [9.0.0-alpha2](https://github.com/openvoxproject/openvox/tree/9.0.0-alpha2) (2026-06-10) [Full Changelog](https://github.com/openvoxproject/openvox/compare/9.0.0-alpha1...9.0.0-alpha2) **Breaking changes:** - return to preprocessing deferred functions by default [\#462](https://github.com/OpenVoxProject/openvox/pull/462) ([binford2k](https://github.com/binford2k)) - Decouple :posix feature from :syslog library check [\#458](https://github.com/OpenVoxProject/openvox/pull/458) ([silug](https://github.com/silug)) - remove pe\_serverversion fact [\#397](https://github.com/OpenVoxProject/openvox/pull/397) ([corporate-gadfly](https://github.com/corporate-gadfly)) **Implemented enhancements:** - Add windows-msys2-x64 build for OpenVox 9 [\#468](https://github.com/OpenVoxProject/openvox/pull/468) ([Sharpie](https://github.com/Sharpie)) **Fixed bugs:** - Manage group members on EL 10 without libuser [\#476](https://github.com/OpenVoxProject/openvox/pull/476) ([Sharpie](https://github.com/Sharpie)) - Fix File.open Ruby 3.2 regression in FileSystem::Uniquefile [\#450](https://github.com/OpenVoxProject/openvox/pull/450) ([JonasVerhofste](https://github.com/JonasVerhofste)) **Merged pull requests:** - Promote puppet-runtime 2026.06.09.1 into main [\#479](https://github.com/OpenVoxProject/openvox/pull/479) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - CI: Use bot account for backports [\#472](https://github.com/OpenVoxProject/openvox/pull/472) ([bastelfreak](https://github.com/bastelfreak)) - Add JRuby 10.0.5.0 and 10.1.0.0 to test matrix [\#463](https://github.com/OpenVoxProject/openvox/pull/463) ([silug](https://github.com/silug)) ## [8.28.1](https://github.com/openvoxproject/openvox/tree/8.28.1) (2026-07-07) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.28.0...8.28.1) **Fixed bugs:** - \[Bug\]: ca\_refresh\_interval is not respected — agent refreshes CA on every run when server responds 304 [\#435](https://github.com/OpenVoxProject/openvox/issues/435) - \[Bug\]: Puppet 8 introduced a regex node definition regression [\#14](https://github.com/OpenVoxProject/openvox/issues/14) **Closed issues:** - \[Deprecation\] `Puppet::SSL::Certificate` Class [\#344](https://github.com/OpenVoxProject/openvox/issues/344) - \[Deprecation\] PAL Script Evaluation APIs [\#343](https://github.com/OpenVoxProject/openvox/issues/343) - \[Deprecation\] `source_permissions` File Parameter [\#340](https://github.com/OpenVoxProject/openvox/issues/340) - \[Deprecation\] `pluginsync` Setting [\#339](https://github.com/OpenVoxProject/openvox/issues/339) - \[Deprecation\] `configprint` Setting [\#337](https://github.com/OpenVoxProject/openvox/issues/337) - \[Deprecation\] `regsubst()` Encoding Argument [\#336](https://github.com/OpenVoxProject/openvox/issues/336) ## [8.28.0](https://github.com/openvoxproject/openvox/tree/8.28.0) (2026-06-10) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.27.0...8.28.0) **Implemented enhancements:** - Add platform definitions for Fedora 44 [\#455](https://github.com/OpenVoxProject/openvox/pull/455) ([Sharpie](https://github.com/Sharpie)) - Promote openfact 5.6.1 into main [\#436](https://github.com/OpenVoxProject/openvox/pull/436) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) **Fixed bugs:** - avoid badly anchored regular expression [\#414](https://github.com/OpenVoxProject/openvox/pull/414) ([corporate-gadfly](https://github.com/corporate-gadfly)) **Merged pull requests:** - Promote puppet-runtime 2026.05.20.1 into main [\#453](https://github.com/OpenVoxProject/openvox/pull/453) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Switch from puppet-strings to openvox-strings [\#434](https://github.com/OpenVoxProject/openvox/pull/434) ([tuxmea](https://github.com/tuxmea)) - Update acceptance defaults and descriptions for OpenVox 9 [\#431](https://github.com/OpenVoxProject/openvox/pull/431) ([nmburgan](https://github.com/nmburgan)) - Promote puppet-runtime 2026.05.07.1 into main [\#429](https://github.com/OpenVoxProject/openvox/pull/429) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Change branch name in promote workflow [\#428](https://github.com/OpenVoxProject/openvox/pull/428) ([nmburgan](https://github.com/nmburgan)) - Changes to prepare for 8.x branching [\#425](https://github.com/OpenVoxProject/openvox/pull/425) ([nmburgan](https://github.com/nmburgan)) - Add release version check and stop trying to bump to an RC version [\#413](https://github.com/OpenVoxProject/openvox/pull/413) ([nmburgan](https://github.com/nmburgan)) ## [8.27.0](https://github.com/openvoxproject/openvox/tree/8.27.0) (2026-05-15) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.26.2...8.27.0) ## [8.26.2](https://github.com/openvoxproject/openvox/tree/8.26.2) (2026-04-18) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.26.1...8.26.2) **Fixed bugs:** - \[Bug\]: `provides puppet-agent` uses bare major version, breaking `>= x.y.z` dependency constraints \(e.g. foreman-installer\) [\#406](https://github.com/OpenVoxProject/openvox/issues/406) - Revert "Add syslog as a runtime dependency" [\#410](https://github.com/OpenVoxProject/openvox/pull/410) ([nmburgan](https://github.com/nmburgan)) - \(\#406\) packaging: Set Maj.Min.Patch version as `provides` instead of major one [\#407](https://github.com/OpenVoxProject/openvox/pull/407) ([bastelfreak](https://github.com/bastelfreak)) **Merged pull requests:** - Promote puppet-runtime 2026.04.17.1 [\#411](https://github.com/OpenVoxProject/openvox/pull/411) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - .gitignore: Ignore /acceptance/.vendor [\#408](https://github.com/OpenVoxProject/openvox/pull/408) ([bastelfreak](https://github.com/bastelfreak)) ## [8.26.1](https://github.com/openvoxproject/openvox/tree/8.26.1) (2026-04-15) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.26.0...8.26.1) **Merged pull requests:** - Promote puppet-runtime 2026.04.15.1 [\#404](https://github.com/OpenVoxProject/openvox/pull/404) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Add signoff to promote action [\#402](https://github.com/OpenVoxProject/openvox/pull/402) ([nmburgan](https://github.com/nmburgan)) - Add syslog as a runtime dependency [\#400](https://github.com/OpenVoxProject/openvox/pull/400) ([nmburgan](https://github.com/nmburgan)) - acceptance: add hiera-eyaml v5 backend test [\#399](https://github.com/OpenVoxProject/openvox/pull/399) ([nmburgan](https://github.com/nmburgan)) - avoid command injection risk [\#398](https://github.com/OpenVoxProject/openvox/pull/398) ([corporate-gadfly](https://github.com/corporate-gadfly)) ## [8.26.0](https://github.com/openvoxproject/openvox/tree/8.26.0) (2026-04-14) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.25.0...8.26.0) **Implemented enhancements:** - \[Feature request\]: file resource should support etag [\#328](https://github.com/OpenVoxProject/openvox/issues/328) - \[Feature request\]: Provide SLES16 packages [\#246](https://github.com/OpenVoxProject/openvox/issues/246) - Add a renew\_cert subcommand to puppet ssl [\#363](https://github.com/OpenVoxProject/openvox/pull/363) ([jay7x](https://github.com/jay7x)) - Make regsubst\(\) sensitive-aware [\#354](https://github.com/OpenVoxProject/openvox/pull/354) ([cocker-cc](https://github.com/cocker-cc)) - Feature: file etag support [\#329](https://github.com/OpenVoxProject/openvox/pull/329) ([C24-AK](https://github.com/C24-AK)) - Add environment parameter to the package resource type [\#321](https://github.com/OpenVoxProject/openvox/pull/321) ([C24-AK](https://github.com/C24-AK)) **Fixed bugs:** - \[Bug\]: OpenVox Agent on SuSE 15.5 fails with `version 'GLIBC_2.34' not found` [\#226](https://github.com/OpenVoxProject/openvox/issues/226) - fix: puppet module install should honor manage\_file\_permissions=false [\#362](https://github.com/OpenVoxProject/openvox/pull/362) ([dotconfig404](https://github.com/dotconfig404)) - unbreak OpenBSD package handling. [\#316](https://github.com/OpenVoxProject/openvox/pull/316) ([buzzdeee](https://github.com/buzzdeee)) - Use usermod\(8\) on OpenBSD to unbreak password management [\#294](https://github.com/OpenVoxProject/openvox/pull/294) ([klemensn](https://github.com/klemensn)) **Merged pull requests:** - Promote openfact 5.6.0 [\#387](https://github.com/OpenVoxProject/openvox/pull/387) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Promote puppet-runtime 2026.04.09.1 [\#386](https://github.com/OpenVoxProject/openvox/pull/386) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - fix: skip SHA1 CSR signing test when OpenSSL doesn't support it [\#378](https://github.com/OpenVoxProject/openvox/pull/378) ([silug](https://github.com/silug)) - fix: stub SRV DNS in ca\_server session spec [\#377](https://github.com/OpenVoxProject/openvox/pull/377) ([silug](https://github.com/silug)) - Fix acceptance tests for systemd PrivateTmp compatibility [\#376](https://github.com/OpenVoxProject/openvox/pull/376) ([nmburgan](https://github.com/nmburgan)) - Fix acceptance tests for systemd PrivateTmp compatibility [\#375](https://github.com/OpenVoxProject/openvox/pull/375) ([nmburgan](https://github.com/nmburgan)) - Add libffi-devel to Windows setup script [\#373](https://github.com/OpenVoxProject/openvox/pull/373) ([nmburgan](https://github.com/nmburgan)) - Promote puppet-runtime 2026.04.05.1 [\#372](https://github.com/OpenVoxProject/openvox/pull/372) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Restore the legend of help help help help help [\#364](https://github.com/OpenVoxProject/openvox/pull/364) ([nmburgan](https://github.com/nmburgan)) - Fixes for Ruby 4.0 compatibility [\#311](https://github.com/OpenVoxProject/openvox/pull/311) ([silug](https://github.com/silug)) ## [8.25.0](https://github.com/openvoxproject/openvox/tree/8.25.0) (2026-02-17) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.24.2...8.25.0) **Implemented enhancements:** - \[Feature request\]: environment parameter for package resource [\#298](https://github.com/OpenVoxProject/openvox/issues/298) - Add Ubuntu 26.04 support [\#315](https://github.com/OpenVoxProject/openvox/pull/315) ([bastelfreak](https://github.com/bastelfreak)) - Reduce OpenSSL monkey patch to only calling set\_params [\#308](https://github.com/OpenVoxProject/openvox/pull/308) ([ekohl](https://github.com/ekohl)) - Remove monkey patch to remove daemonize [\#307](https://github.com/OpenVoxProject/openvox/pull/307) ([ekohl](https://github.com/ekohl)) - Add SLES 16 ARM64 support [\#306](https://github.com/OpenVoxProject/openvox/pull/306) ([bastelfreak](https://github.com/bastelfreak)) - Add SLES16 [\#302](https://github.com/OpenVoxProject/openvox/pull/302) ([sbernhard](https://github.com/sbernhard)) - Drop multi\_json support [\#293](https://github.com/OpenVoxProject/openvox/pull/293) ([ekohl](https://github.com/ekohl)) - Do not explicitly disable SSLv3 [\#287](https://github.com/OpenVoxProject/openvox/pull/287) ([smortex](https://github.com/smortex)) - feat: add `{debian13,ubuntu24.04,ubuntu25.04}-armhf` platform configs [\#286](https://github.com/OpenVoxProject/openvox/pull/286) ([Gitii](https://github.com/Gitii)) **Fixed bugs:** - \[Bug\]: OpenVox Agent fails/gets deactivated after update with theforeman-puppet [\#279](https://github.com/OpenVoxProject/openvox/issues/279) - Include missing EC2 stub request [\#272](https://github.com/OpenVoxProject/openvox/pull/272) ([eciii](https://github.com/eciii)) **Merged pull requests:** - Promote puppet-runtime 2026.02.16.1 [\#324](https://github.com/OpenVoxProject/openvox/pull/324) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Promote openfact 5.4.0 [\#322](https://github.com/OpenVoxProject/openvox/pull/322) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Promote puppet-runtime 2026.02.06.1 [\#313](https://github.com/OpenVoxProject/openvox/pull/313) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - puppet-runtime: Update 2025.12.05.1-\>2026.01.30.1 [\#305](https://github.com/OpenVoxProject/openvox/pull/305) ([bastelfreak](https://github.com/bastelfreak)) - Promote openssl-fips 2025.12.17.1 [\#284](https://github.com/OpenVoxProject/openvox/pull/284) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Update promotion action [\#283](https://github.com/OpenVoxProject/openvox/pull/283) ([nmburgan](https://github.com/nmburgan)) ## [8.24.2](https://github.com/openvoxproject/openvox/tree/8.24.2) (2025-12-15) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.24.1...8.24.2) **Fixed bugs:** - \[Bug\]: Version 8.24.0 fails with Error: Could not find a suitable provider for augeas [\#262](https://github.com/OpenVoxProject/openvox/issues/262) **Merged pull requests:** - Promote openfact 5.2.1 [\#277](https://github.com/OpenVoxProject/openvox/pull/277) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Relax version requirements for some default gems [\#275](https://github.com/OpenVoxProject/openvox/pull/275) ([nmburgan](https://github.com/nmburgan)) ## [8.24.1](https://github.com/openvoxproject/openvox/tree/8.24.1) (2025-12-05) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.24.0...8.24.1) **Fixed bugs:** - \[Bug\]: sysctl augeas broken after upgrade to Version 8.24.0 [\#264](https://github.com/OpenVoxProject/openvox/issues/264) - \[Bug\]: Augeas broken since openvox 8.24.0, missing augeas/facade [\#263](https://github.com/OpenVoxProject/openvox/issues/263) **Merged pull requests:** - Promote puppet-runtime 2025.12.05.1 [\#266](https://github.com/OpenVoxProject/openvox/pull/266) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Update augeas test to detect provider failure [\#265](https://github.com/OpenVoxProject/openvox/pull/265) ([nmburgan](https://github.com/nmburgan)) - Add dbus feature [\#261](https://github.com/OpenVoxProject/openvox/pull/261) ([ananace](https://github.com/ananace)) ## [8.24.0](https://github.com/openvoxproject/openvox/tree/8.24.0) (2025-12-04) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.23.1...8.24.0) **Implemented enhancements:** - Loosen some gem dependencies for new versions and update minitar usage [\#242](https://github.com/OpenVoxProject/openvox/pull/242) ([nmburgan](https://github.com/nmburgan)) - Create execution\_wrapper.bat to allow Choria to work with Windows [\#222](https://github.com/OpenVoxProject/openvox/pull/222) ([magarvo](https://github.com/magarvo)) - feat: add opkg package management support for TurrisOS [\#221](https://github.com/OpenVoxProject/openvox/pull/221) ([VILJkid](https://github.com/VILJkid)) - Add jruby-9.4.14.0 to CI matrix [\#210](https://github.com/OpenVoxProject/openvox/pull/210) ([bastelfreak](https://github.com/bastelfreak)) **Fixed bugs:** - \[Bug\]: `implementation` is just a local fact [\#220](https://github.com/OpenVoxProject/openvox/issues/220) - \[Bug\]: puppet apply warns about missing client certificates [\#21](https://github.com/OpenVoxProject/openvox/issues/21) **Merged pull requests:** - Promote openfact 5.2.0 [\#258](https://github.com/OpenVoxProject/openvox/pull/258) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Promote openfact 6a26ce51cf65f7cc325330c40922e9556651cf35 [\#257](https://github.com/OpenVoxProject/openvox/pull/257) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Use PR for promotion action [\#255](https://github.com/OpenVoxProject/openvox/pull/255) ([nmburgan](https://github.com/nmburgan)) - Use token when checking out repo [\#254](https://github.com/OpenVoxProject/openvox/pull/254) ([nmburgan](https://github.com/nmburgan)) - Add promote action [\#253](https://github.com/OpenVoxProject/openvox/pull/253) ([nmburgan](https://github.com/nmburgan)) - Update release automation [\#252](https://github.com/OpenVoxProject/openvox/pull/252) ([nmburgan](https://github.com/nmburgan)) - add note about server\_list precedence [\#251](https://github.com/OpenVoxProject/openvox/pull/251) ([binford2k](https://github.com/binford2k)) - Fix description of `source` since `yum` allows it now [\#249](https://github.com/OpenVoxProject/openvox/pull/249) ([binford2k](https://github.com/binford2k)) - include "local" facts in facts output [\#240](https://github.com/OpenVoxProject/openvox/pull/240) ([binford2k](https://github.com/binford2k)) - Correct homepage in gemspec [\#223](https://github.com/OpenVoxProject/openvox/pull/223) ([ekohl](https://github.com/ekohl)) - CI: Build gem for each PR & Move packaging checks to global config & Windows: Run one spec file per CPU core [\#216](https://github.com/OpenVoxProject/openvox/pull/216) ([bastelfreak](https://github.com/bastelfreak)) - Add switch for uploading to S3 [\#212](https://github.com/OpenVoxProject/openvox/pull/212) ([nmburgan](https://github.com/nmburgan)) - Update acceptance workflow for changed beaker acceptance [\#209](https://github.com/OpenVoxProject/openvox/pull/209) ([jpartlow](https://github.com/jpartlow)) - `yum` package provider: add `assumeyes` to `yum check-update` [\#188](https://github.com/OpenVoxProject/openvox/pull/188) ([SvenVD-be](https://github.com/SvenVD-be)) - Prevents spurious clientcert warnings in serverless mode [\#22](https://github.com/OpenVoxProject/openvox/pull/22) ([binford2k](https://github.com/binford2k)) ## [8.23.1](https://github.com/openvoxproject/openvox/tree/8.23.1) (2025-09-08) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.23.0...8.23.1) **Fixed bugs:** - Fix how we find the version library [\#203](https://github.com/OpenVoxProject/openvox/pull/203) ([nmburgan](https://github.com/nmburgan)) **Merged pull requests:** - Promote puppet-runtime 2025.09.08.1 [\#204](https://github.com/OpenVoxProject/openvox/pull/204) ([nmburgan](https://github.com/nmburgan)) - Test for r10k failure condition [\#202](https://github.com/OpenVoxProject/openvox/pull/202) ([nmburgan](https://github.com/nmburgan)) ## [8.23.0](https://github.com/openvoxproject/openvox/tree/8.23.0) (2025-09-07) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.22.0...8.23.0) - This is our first release where MacOS and Windows agents are built entirely in GitHub Actions! - MacOS x86_64 is now supported - The MacOS agents now work on all currently supported MacOS versions (13, 14, and 15). No need for separate packages! - The openvox-agent repo, which was the repo used for building the openvox-agent packages, has now been integrated into this openvox repo under the 'packaging' directory. This will allow us to have fewer steps in the build process and tag changes more cleanly, rather than having to tag two separate repos. Note that for releases prior to this one, the changelog in this file refers only to the changes to openvox itself and not packaging changes. For example, 8.22.1 was released to fix an unintentional service renaming issue and details are in the openvox-agent repo. At some point, we may try to integrate the two changelogs. - This release contains a large number of dependencies bumps. Most are not security related, but many dependencies were lagging for a long time. See [this PR](https://github.com/OpenVoxProject/puppet-runtime/pull/35) for details. - A patch for Augeas to address [CVE-2025-2588](https://github.com/advisories/GHSA-hxwj-c5vw-fwgp) **Implemented enhancements:** - Respect systemd's RUNTIME\_DIRECTORY environment variable [\#165](https://github.com/OpenVoxProject/openvox/pull/165) ([ekohl](https://github.com/ekohl)) **Fixed bugs:** - treat windows service accounts as case insensitive [\#172](https://github.com/OpenVoxProject/openvox/pull/172) ([binford2k](https://github.com/binford2k)) - Ensure confdir exists [\#171](https://github.com/OpenVoxProject/openvox/pull/171) ([binford2k](https://github.com/binford2k)) **Merged pull requests:** - Promote puppet-runtime 2025.09.04.1 [\#191](https://github.com/OpenVoxProject/openvox/pull/191) ([nmburgan](https://github.com/nmburgan)) - Merge openvox-agent vanagon repo [\#186](https://github.com/OpenVoxProject/openvox/pull/186) ([austb](https://github.com/austb)) ## [8.22.0](https://github.com/openvoxproject/openvox/tree/8.22.0) (2025-08-23) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.21.1...8.22.0) ## [8.21.1](https://github.com/openvoxproject/openvox/tree/8.21.1) (2025-07-23) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.21.0...8.21.1) **Fixed bugs:** - Make passing invalid options to install.rb fatal [\#156](https://github.com/OpenVoxProject/openvox/pull/156) ([ekohl](https://github.com/ekohl)) **Merged pull requests:** - Revert "Mark some failing 8.3 Windows tests as pending" [\#159](https://github.com/OpenVoxProject/openvox/pull/159) ([ekohl](https://github.com/ekohl)) - \(maint\) Drop debian-10 from testing matrix [\#152](https://github.com/OpenVoxProject/openvox/pull/152) ([jpartlow](https://github.com/jpartlow)) ## [8.21.0](https://github.com/openvoxproject/openvox/tree/8.21.0) (2025-07-09) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.20.0...8.21.0) **Implemented enhancements:** - Remove facter from install.rb [\#147](https://github.com/OpenVoxProject/openvox/pull/147) ([ekohl](https://github.com/ekohl)) ## [8.20.0](https://github.com/openvoxproject/openvox/tree/8.20.0) (2025-06-27) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.19.2...8.20.0) **Implemented enhancements:** - Switch from facter to openfact [\#142](https://github.com/OpenVoxProject/openvox/pull/142) ([smortex](https://github.com/smortex)) - \(PUP-12083\) Update soft limit warning for fact value & name length [\#137](https://github.com/OpenVoxProject/openvox/pull/137) ([bastelfreak](https://github.com/bastelfreak)) **Fixed bugs:** - Maintain consistent JSON formatting [\#132](https://github.com/OpenVoxProject/openvox/pull/132) ([bastelfreak](https://github.com/bastelfreak)) **Merged pull requests:** - cleanup gem metadata after Perforce-\>OpenVoxProject migration [\#140](https://github.com/OpenVoxProject/openvox/pull/140) ([smortex](https://github.com/smortex)) ## [8.19.2](https://github.com/openvoxproject/openvox/tree/8.19.2) (2025-06-06) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.19.1...8.19.2) **Fixed bugs:** - server\_facts: Switch implementation-\>serverimplementation [\#107](https://github.com/OpenVoxProject/openvox/pull/107) ([binford2k](https://github.com/binford2k)) - Reflect Ruby 3.4 stack trace changes [\#100](https://github.com/OpenVoxProject/openvox/pull/100) ([ekohl](https://github.com/ekohl)) - Add base64 as gem dependencies for Ruby 3.4 [\#98](https://github.com/OpenVoxProject/openvox/pull/98) ([ekohl](https://github.com/ekohl)) - Add racc gem dependency [\#89](https://github.com/OpenVoxProject/openvox/pull/89) ([ekohl](https://github.com/ekohl)) ## [8.19.1](https://github.com/openvoxproject/openvox/tree/8.19.1) (2025-06-03) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.19.0...8.19.1) **Fixed bugs:** - Fix invalid gemspec in AIO package [\#91](https://github.com/OpenVoxProject/openvox/pull/91) ([smortex](https://github.com/smortex)) ## [8.19.0](https://github.com/openvoxproject/openvox/tree/8.19.0) (2025-05-30) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.18.1...8.19.0) **Implemented enhancements:** - Add `implementation` fact to agent and server. [\#63](https://github.com/OpenVoxProject/openvox/pull/63) ([ffrank](https://github.com/ffrank)) **Fixed bugs:** - Replace `erase` with `remove`, since it's no longer supported with DNF5 [\#68](https://github.com/OpenVoxProject/openvox/pull/68) ([Stricken1670](https://github.com/Stricken1670)) \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* OpenVoxProject-openvox-ebcec1e/CODE_OF_CONDUCT.md000066400000000000000000000076021527241624000215730ustar00rootroot00000000000000# Community Guidelines and Code of Conduct We want to keep the OpenVox communities awesome, and we need your help to keep it that way. While we have specific guidelines for various tools (see links below), in general, you should: * **Be nice**: Be courteous, respectful and polite to fellow community members. No offensive comments related to gender, gender identity or expression, sexual orientation, disability, physical appearance, body size, race, religion; no sexual images in public spaces, real or implied violence, intimidation, oppression, stalking, following, harassing photography or recording, sustained disruption of talks or other events, inappropriate physical contact, doxxing, or unwelcome sexual attention will be tolerated. We like nice people way better than mean ones! * **Encourage diversity and participation**: Make everyone in our community feel welcome, regardless of their background, and do everything possible to encourage participation in our community. * **Focus on constructive criticisms**: When offering suggestions, whether in online discussions or as comments on a pull request, you should always use welcoming and inclusive language. Be respectful of differing viewpoints and the fact that others may not have the same experiences you do. Offer suggestions for improvement, rather than focusing on mistakes. When others critique your work or ideas, gracefully accept the criticisms and default to assuming good intentions. * **Keep it legal**: Basically, don't get us in trouble. Share only content that you own, do not share private or sensitive information, and don't break the law. * **Stay on topic**: Keep conversation in a thread on topic, whether that's a pull request or a Slack conversation or anything else. Make sure that you are posting to the correct channel and remember that nobody likes spam. ## Guideline violations --- 3 strikes method The point of this section is not to find opportunities to punish people, but we do need a fair way to deal with people who do harm to our community. Extreme violations of a threatening, abusive, destructive, or illegal nature will be addressed immediately and are not subject to 3 strikes. * First occurrence: We'll give you a friendly, but public, reminder that the behavior is inappropriate according to our guidelines. * Second occurrence: We'll send you a private message with a warning that any additional violations will result in removal from the community. * Third occurrence: Depending on the violation, we might need to delete or ban your account. Notes: * Obvious spammers are banned on first occurrence. If we don’t do this, we’ll have spam all over the place. * Violations are forgiven after 6 months of good behavior, and we won’t hold a grudge. * People who are committing minor formatting / style infractions will get some education, rather than hammering them in the 3 strikes process. Contact conduct@puppet.com to report abuse or appeal violations. This email list goes to Kara Sowles (kara at puppet.com) and Katie Abbott (katie dot abbott at puppet.com). In the case of appeals, we know that mistakes happen, and we’ll work with you to come up with a fair solution if there has been a misunderstanding. ## Full text See our [full community guidelines](https://puppet.com/community/community-guidelines), covering Slack, IRC, events and other forms of community participation. ## Credits Credit to [01.org](https://01.org/community/participation-guidelines) and [meego.com](http://wiki.meego.com/Community_guidelines), since they formed the starting point for many of these guidelines. The Event Code of Conduct is based on the [example policy from the Geek Feminism wiki](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment), created by the Ada Initiative and other volunteers. The [PyCon Code of Conduct](https://github.com/python/pycon-code-of-conduct) also served as inspiration. OpenVoxProject-openvox-ebcec1e/Gemfile000066400000000000000000000105031527241624000202610ustar00rootroot00000000000000source ENV['GEM_SOURCE'] || "https://rubygems.org" gemspec def location_for(place, fake_version = nil) if place.is_a?(String) && place =~ /^((?:git[:@]|https:)[^#]*)#(.*)/ [fake_version, { git: $1, branch: $2, require: false }].compact elsif place.is_a?(String) && place =~ /^file:\/\/(.*)/ ['>= 0', { path: File.expand_path($1), require: false }] else [place, { require: false }] end end # Make sure these gem requirements are in sync with the gemspec. Specifically, # the runtime_dependencies in openvox.gemspec match the runtime dependencies here # (like openfact, semantic_puppet, and puppet-resource_api) gem "openfact", *location_for(ENV['OPENFACT_LOCATION'] || ["~> 6.0"]) gem "semantic_puppet", *location_for(ENV['SEMANTIC_PUPPET_LOCATION'] || ["~> 1.0"]) gem "puppet-resource_api", *location_for(ENV['RESOURCE_API_LOCATION'] || ["~> 2.0"]) # Need to update the openssl gem on MacOS to avoid SSL errors. # https://www.rubyonmac.dev/certificate-verify-failed-unable-to-get-certificate-crl-openssl-ssl-sslerror gem 'openssl', '~> 3' if RUBY_PLATFORM =~ /darwin/ group(:features) do gem 'diff-lcs', '~> 1.3', require: false gem "hiera", *location_for(ENV['HIERA_LOCATION']) if ENV.has_key?('HIERA_LOCATION') gem 'hiera-eyaml', *location_for(ENV['HIERA_EYAML_LOCATION']) gem 'hocon', '~> 1.0', require: false # requires native libshadow headers/libs #gem 'ruby-shadow', '~> 2.5', require: false, platforms: [:ruby] gem 'minitar', '~> 1.0', require: false gem 'msgpack', '~> 1.2', require: false gem 'rdoc', '~> 8.0', require: false, platforms: [:ruby] # requires native augeas headers/libs # gem 'ruby-augeas', require: false, platforms: [:ruby] # requires native ldap headers/libs # gem 'ruby-ldap', '~> 0.9', require: false, platforms: [:ruby] gem 'openvoxserver-ca', '~> 3.0', require: false gem 'syslog', '>= 0.1.1', '< 1', require: false, platforms: [:ruby] gem 'CFPropertyList', '~> 4.0', require: false end group(:test) do # 1.16.0 - 1.16.2 are broken on Windows gem 'ffi', '>= 1.15.5', '< 2', '!= 1.16.0', '!= 1.16.1', '!= 1.16.2', require: false gem "json-schema", '>= 2', '< 7', require: false gem "rake", *location_for(ENV['RAKE_LOCATION'] || '~> 13.0') gem "rspec", "~> 3.1", require: false gem "rspec-expectations", ["~> 3.9", "!= 3.9.3"] gem "rspec-its", "~> 2.0", require: false gem 'rspec-mocks', '< 3.13.3', require: false # breaking change afterwards: https://github.com/rspec/rspec-mocks/pull/1596 gem 'vcr', '~> 6.1', require: false gem 'webmock', '~> 3.0', require: false gem 'webrick', '~> 1.7', require: false gem 'yard', require: false # The source gemspec has the generic ruby platform, so declare this explicitly for Windows development and CI. gem 'win32ole', '>= 1.8', '< 2.0', require: false, platforms: [:windows] gem 'rubocop', '~> 1.92.0', require: false, platforms: [:ruby] gem 'rubocop-i18n', '~> 3.0', require: false, platforms: [:ruby] gem 'rubocop-performance', '~> 1.0', require: false, platforms: [:ruby] gem 'rubocop-rake', '~> 0.6', require: false, platforms: [:ruby] gem 'rubocop-rspec', '~> 3.0', require: false, platforms: [:ruby] end group(:development, optional: true) do gem 'memory_profiler', require: false, platforms: [:mri] gem 'pry', require: false, platforms: [:ruby] if RUBY_PLATFORM != 'java' gem 'ruby-prof', '>= 0.16.0', require: false end end group(:packaging) do gem 'packaging', *location_for(ENV['PACKAGING_LOCATION'] || '~> 0.105') if RUBY_VERSION >= '3.2' gem 'vanagon', *location_for(ENV['VANAGON_LOCATION'] || 'https://github.com/openvoxproject/vanagon#main') end gem 'artifactory' gem 'json', '< 4' gem 'octokit' end group(:documentation, optional: true) do gem 'gettext-setup', '~> 1.0', require: false, platforms: [:ruby] gem 'ronn-ng', '~> 0.10.1', require: false, platforms: [:ruby] gem 'openvox-strings', require: false, platforms: [:ruby] gem 'pandoc-ruby', require: false, platforms: [:ruby] end # exlude the windows platform, faraday doesn't install properly on it # and we only generate the changelog in github linux runners platforms :ruby do group :release, optional: true do gem 'faraday-retry', require: false gem 'github_changelog_generator', '~> 1.18', require: false end end if File.exist? "#{__FILE__}.local" eval(File.read("#{__FILE__}.local"), binding) end # vim:filetype=ruby OpenVoxProject-openvox-ebcec1e/Guardfile.example000066400000000000000000000043421527241624000222510ustar00rootroot00000000000000# More info at https://github.com/guard/guard#readme # You'll need to make sure Guard, and any of its plugins are in your Gemfile.local # # Example: # # Automatically run tests on file changes # gem 'guard', require: false # gem 'guard-rspec', require: false # gem 'guard-bundler', require: false # gem 'terminal-notifier-guard', require: false # # After running `bundle install`, you can run Guard via `bundle exec guard` # from the top of the repository checkout. notification(:terminal_notifier, app_name: "Puppet ::", group: `pwd`.chomp) if `uname` =~ /Darwin/ ## Uncomment and set this to only include directories you want to watch # directories %w(app lib config test spec features) \ # .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")} ## Note: if you are using the `directories` clause above and you are not ## watching the project directory ('.'), then you will want to move ## the Guardfile to a watched dir and symlink it back, e.g. # # $ mkdir config # $ mv Guardfile config/ # $ ln -s config/Guardfile . # # and, you'll have to watch "config/Guardfile" instead of "Guardfile" guard :bundler do require 'guard/bundler' require 'guard/bundler/verify' helper = Guard::Bundler::Verify.new files = ['Gemfile', 'Gemfile.local'] files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) } # Assume files are symlinked from somewhere files.each { |file| watch(helper.real_path(file)) } end def file2specs(match) file = match[0] puts "Lib file changed: #{file.inspect}" %w{spec/unit spec/integration}.collect { |d| file.sub('lib/puppet', d).sub(".rb", "_spec.rb") }.find_all { |f| File.exist?(f) } end rspec_options = { cmd: "bundle exec rspec", run_all: { cmd: "bundle exec parallel_rspec -o '--format progress ", cmd_additional_args: "'" }, all_after_pass: false } guard :rspec, rspec_options do require "guard/rspec/dsl" dsl = Guard::RSpec::Dsl.new(self) # Feel free to open issues for suggestions and improvements # RSpec files rspec = dsl.rspec watch(rspec.spec_helper) { rspec.spec_dir } watch(rspec.spec_support) { rspec.spec_dir } watch(rspec.spec_files) # Ruby files ruby = dsl.ruby watch(ruby.lib_files) { |f| file2specs(f) } end OpenVoxProject-openvox-ebcec1e/HISTORY.md000066400000000000000000000536701527241624000204650ustar00rootroot00000000000000## [8.28.1](https://github.com/openvoxproject/openvox/tree/8.28.1) (2026-07-07) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.28.0...8.28.1) **Fixed bugs:** - \[Bug\]: ca\_refresh\_interval is not respected — agent refreshes CA on every run when server responds 304 [\#435](https://github.com/OpenVoxProject/openvox/issues/435) - \[Bug\]: Puppet 8 introduced a regex node definition regression [\#14](https://github.com/OpenVoxProject/openvox/issues/14) **Closed issues:** - \[Deprecation\] `Puppet::SSL::Certificate` Class [\#344](https://github.com/OpenVoxProject/openvox/issues/344) - \[Deprecation\] PAL Script Evaluation APIs [\#343](https://github.com/OpenVoxProject/openvox/issues/343) - \[Deprecation\] `source_permissions` File Parameter [\#340](https://github.com/OpenVoxProject/openvox/issues/340) - \[Deprecation\] `pluginsync` Setting [\#339](https://github.com/OpenVoxProject/openvox/issues/339) - \[Deprecation\] `configprint` Setting [\#337](https://github.com/OpenVoxProject/openvox/issues/337) - \[Deprecation\] `regsubst()` Encoding Argument [\#336](https://github.com/OpenVoxProject/openvox/issues/336) ## [8.28.0](https://github.com/openvoxproject/openvox/tree/8.28.0) (2026-06-10) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.27.0...8.28.0) **Implemented enhancements:** - Add platform definitions for Fedora 44 [\#455](https://github.com/OpenVoxProject/openvox/pull/455) ([Sharpie](https://github.com/Sharpie)) - Promote openfact 5.6.1 into main [\#436](https://github.com/OpenVoxProject/openvox/pull/436) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) **Fixed bugs:** - avoid badly anchored regular expression [\#414](https://github.com/OpenVoxProject/openvox/pull/414) ([corporate-gadfly](https://github.com/corporate-gadfly)) **Merged pull requests:** - Promote puppet-runtime 2026.05.20.1 into main [\#453](https://github.com/OpenVoxProject/openvox/pull/453) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Switch from puppet-strings to openvox-strings [\#434](https://github.com/OpenVoxProject/openvox/pull/434) ([tuxmea](https://github.com/tuxmea)) - Update acceptance defaults and descriptions for OpenVox 9 [\#431](https://github.com/OpenVoxProject/openvox/pull/431) ([nmburgan](https://github.com/nmburgan)) - Promote puppet-runtime 2026.05.07.1 into main [\#429](https://github.com/OpenVoxProject/openvox/pull/429) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Change branch name in promote workflow [\#428](https://github.com/OpenVoxProject/openvox/pull/428) ([nmburgan](https://github.com/nmburgan)) - Changes to prepare for 8.x branching [\#425](https://github.com/OpenVoxProject/openvox/pull/425) ([nmburgan](https://github.com/nmburgan)) - Add release version check and stop trying to bump to an RC version [\#413](https://github.com/OpenVoxProject/openvox/pull/413) ([nmburgan](https://github.com/nmburgan)) ## [8.27.0](https://github.com/openvoxproject/openvox/tree/8.27.0) (2026-05-15) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.26.2...8.27.0) ## [8.26.2](https://github.com/openvoxproject/openvox/tree/8.26.2) (2026-04-18) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.26.1...8.26.2) **Fixed bugs:** - \[Bug\]: `provides puppet-agent` uses bare major version, breaking `>= x.y.z` dependency constraints \(e.g. foreman-installer\) [\#406](https://github.com/OpenVoxProject/openvox/issues/406) - Revert "Add syslog as a runtime dependency" [\#410](https://github.com/OpenVoxProject/openvox/pull/410) ([nmburgan](https://github.com/nmburgan)) - \(\#406\) packaging: Set Maj.Min.Patch version as `provides` instead of major one [\#407](https://github.com/OpenVoxProject/openvox/pull/407) ([bastelfreak](https://github.com/bastelfreak)) **Merged pull requests:** - Promote puppet-runtime 2026.04.17.1 [\#411](https://github.com/OpenVoxProject/openvox/pull/411) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - .gitignore: Ignore /acceptance/.vendor [\#408](https://github.com/OpenVoxProject/openvox/pull/408) ([bastelfreak](https://github.com/bastelfreak)) ## [8.26.1](https://github.com/openvoxproject/openvox/tree/8.26.1) (2026-04-15) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.26.0...8.26.1) **Merged pull requests:** - Promote puppet-runtime 2026.04.15.1 [\#404](https://github.com/OpenVoxProject/openvox/pull/404) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Add signoff to promote action [\#402](https://github.com/OpenVoxProject/openvox/pull/402) ([nmburgan](https://github.com/nmburgan)) - Add syslog as a runtime dependency [\#400](https://github.com/OpenVoxProject/openvox/pull/400) ([nmburgan](https://github.com/nmburgan)) - acceptance: add hiera-eyaml v5 backend test [\#399](https://github.com/OpenVoxProject/openvox/pull/399) ([nmburgan](https://github.com/nmburgan)) - avoid command injection risk [\#398](https://github.com/OpenVoxProject/openvox/pull/398) ([corporate-gadfly](https://github.com/corporate-gadfly)) ## [8.26.0](https://github.com/openvoxproject/openvox/tree/8.26.0) (2026-04-14) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.25.0...8.26.0) **Implemented enhancements:** - \[Feature request\]: file resource should support etag [\#328](https://github.com/OpenVoxProject/openvox/issues/328) - \[Feature request\]: Provide SLES16 packages [\#246](https://github.com/OpenVoxProject/openvox/issues/246) - Add a renew\_cert subcommand to puppet ssl [\#363](https://github.com/OpenVoxProject/openvox/pull/363) ([jay7x](https://github.com/jay7x)) - Make regsubst\(\) sensitive-aware [\#354](https://github.com/OpenVoxProject/openvox/pull/354) ([cocker-cc](https://github.com/cocker-cc)) - Feature: file etag support [\#329](https://github.com/OpenVoxProject/openvox/pull/329) ([C24-AK](https://github.com/C24-AK)) - Add environment parameter to the package resource type [\#321](https://github.com/OpenVoxProject/openvox/pull/321) ([C24-AK](https://github.com/C24-AK)) **Fixed bugs:** - \[Bug\]: OpenVox Agent on SuSE 15.5 fails with `version 'GLIBC_2.34' not found` [\#226](https://github.com/OpenVoxProject/openvox/issues/226) - fix: puppet module install should honor manage\_file\_permissions=false [\#362](https://github.com/OpenVoxProject/openvox/pull/362) ([dotconfig404](https://github.com/dotconfig404)) - unbreak OpenBSD package handling. [\#316](https://github.com/OpenVoxProject/openvox/pull/316) ([buzzdeee](https://github.com/buzzdeee)) - Use usermod\(8\) on OpenBSD to unbreak password management [\#294](https://github.com/OpenVoxProject/openvox/pull/294) ([klemensn](https://github.com/klemensn)) **Merged pull requests:** - Promote openfact 5.6.0 [\#387](https://github.com/OpenVoxProject/openvox/pull/387) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Promote puppet-runtime 2026.04.09.1 [\#386](https://github.com/OpenVoxProject/openvox/pull/386) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - fix: skip SHA1 CSR signing test when OpenSSL doesn't support it [\#378](https://github.com/OpenVoxProject/openvox/pull/378) ([silug](https://github.com/silug)) - fix: stub SRV DNS in ca\_server session spec [\#377](https://github.com/OpenVoxProject/openvox/pull/377) ([silug](https://github.com/silug)) - Fix acceptance tests for systemd PrivateTmp compatibility [\#376](https://github.com/OpenVoxProject/openvox/pull/376) ([nmburgan](https://github.com/nmburgan)) - Fix acceptance tests for systemd PrivateTmp compatibility [\#375](https://github.com/OpenVoxProject/openvox/pull/375) ([nmburgan](https://github.com/nmburgan)) - Add libffi-devel to Windows setup script [\#373](https://github.com/OpenVoxProject/openvox/pull/373) ([nmburgan](https://github.com/nmburgan)) - Promote puppet-runtime 2026.04.05.1 [\#372](https://github.com/OpenVoxProject/openvox/pull/372) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Restore the legend of help help help help help [\#364](https://github.com/OpenVoxProject/openvox/pull/364) ([nmburgan](https://github.com/nmburgan)) - Fixes for Ruby 4.0 compatibility [\#311](https://github.com/OpenVoxProject/openvox/pull/311) ([silug](https://github.com/silug)) ## [8.25.0](https://github.com/openvoxproject/openvox/tree/8.25.0) (2026-02-17) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.24.2...8.25.0) **Implemented enhancements:** - \[Feature request\]: environment parameter for package resource [\#298](https://github.com/OpenVoxProject/openvox/issues/298) - Add Ubuntu 26.04 support [\#315](https://github.com/OpenVoxProject/openvox/pull/315) ([bastelfreak](https://github.com/bastelfreak)) - Reduce OpenSSL monkey patch to only calling set\_params [\#308](https://github.com/OpenVoxProject/openvox/pull/308) ([ekohl](https://github.com/ekohl)) - Remove monkey patch to remove daemonize [\#307](https://github.com/OpenVoxProject/openvox/pull/307) ([ekohl](https://github.com/ekohl)) - Add SLES 16 ARM64 support [\#306](https://github.com/OpenVoxProject/openvox/pull/306) ([bastelfreak](https://github.com/bastelfreak)) - Add SLES16 [\#302](https://github.com/OpenVoxProject/openvox/pull/302) ([sbernhard](https://github.com/sbernhard)) - Drop multi\_json support [\#293](https://github.com/OpenVoxProject/openvox/pull/293) ([ekohl](https://github.com/ekohl)) - Do not explicitly disable SSLv3 [\#287](https://github.com/OpenVoxProject/openvox/pull/287) ([smortex](https://github.com/smortex)) - feat: add `{debian13,ubuntu24.04,ubuntu25.04}-armhf` platform configs [\#286](https://github.com/OpenVoxProject/openvox/pull/286) ([Gitii](https://github.com/Gitii)) **Fixed bugs:** - \[Bug\]: OpenVox Agent fails/gets deactivated after update with theforeman-puppet [\#279](https://github.com/OpenVoxProject/openvox/issues/279) - Include missing EC2 stub request [\#272](https://github.com/OpenVoxProject/openvox/pull/272) ([eciii](https://github.com/eciii)) **Merged pull requests:** - Promote puppet-runtime 2026.02.16.1 [\#324](https://github.com/OpenVoxProject/openvox/pull/324) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Promote openfact 5.4.0 [\#322](https://github.com/OpenVoxProject/openvox/pull/322) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Promote puppet-runtime 2026.02.06.1 [\#313](https://github.com/OpenVoxProject/openvox/pull/313) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - puppet-runtime: Update 2025.12.05.1-\>2026.01.30.1 [\#305](https://github.com/OpenVoxProject/openvox/pull/305) ([bastelfreak](https://github.com/bastelfreak)) - Promote openssl-fips 2025.12.17.1 [\#284](https://github.com/OpenVoxProject/openvox/pull/284) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Update promotion action [\#283](https://github.com/OpenVoxProject/openvox/pull/283) ([nmburgan](https://github.com/nmburgan)) ## [8.24.2](https://github.com/openvoxproject/openvox/tree/8.24.2) (2025-12-15) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.24.1...8.24.2) **Fixed bugs:** - \[Bug\]: Version 8.24.0 fails with Error: Could not find a suitable provider for augeas [\#262](https://github.com/OpenVoxProject/openvox/issues/262) **Merged pull requests:** - Promote openfact 5.2.1 [\#277](https://github.com/OpenVoxProject/openvox/pull/277) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Relax version requirements for some default gems [\#275](https://github.com/OpenVoxProject/openvox/pull/275) ([nmburgan](https://github.com/nmburgan)) ## [8.24.1](https://github.com/openvoxproject/openvox/tree/8.24.1) (2025-12-05) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.24.0...8.24.1) **Fixed bugs:** - \[Bug\]: sysctl augeas broken after upgrade to Version 8.24.0 [\#264](https://github.com/OpenVoxProject/openvox/issues/264) - \[Bug\]: Augeas broken since openvox 8.24.0, missing augeas/facade [\#263](https://github.com/OpenVoxProject/openvox/issues/263) **Merged pull requests:** - Promote puppet-runtime 2025.12.05.1 [\#266](https://github.com/OpenVoxProject/openvox/pull/266) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Update augeas test to detect provider failure [\#265](https://github.com/OpenVoxProject/openvox/pull/265) ([nmburgan](https://github.com/nmburgan)) - Add dbus feature [\#261](https://github.com/OpenVoxProject/openvox/pull/261) ([ananace](https://github.com/ananace)) ## [8.24.0](https://github.com/openvoxproject/openvox/tree/8.24.0) (2025-12-04) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.23.1...8.24.0) **Implemented enhancements:** - Loosen some gem dependencies for new versions and update minitar usage [\#242](https://github.com/OpenVoxProject/openvox/pull/242) ([nmburgan](https://github.com/nmburgan)) - Create execution\_wrapper.bat to allow Choria to work with Windows [\#222](https://github.com/OpenVoxProject/openvox/pull/222) ([magarvo](https://github.com/magarvo)) - feat: add opkg package management support for TurrisOS [\#221](https://github.com/OpenVoxProject/openvox/pull/221) ([VILJkid](https://github.com/VILJkid)) - Add jruby-9.4.14.0 to CI matrix [\#210](https://github.com/OpenVoxProject/openvox/pull/210) ([bastelfreak](https://github.com/bastelfreak)) **Fixed bugs:** - \[Bug\]: `implementation` is just a local fact [\#220](https://github.com/OpenVoxProject/openvox/issues/220) - \[Bug\]: puppet apply warns about missing client certificates [\#21](https://github.com/OpenVoxProject/openvox/issues/21) **Merged pull requests:** - Promote openfact 5.2.0 [\#258](https://github.com/OpenVoxProject/openvox/pull/258) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Promote openfact 6a26ce51cf65f7cc325330c40922e9556651cf35 [\#257](https://github.com/OpenVoxProject/openvox/pull/257) ([OpenVoxProjectBot](https://github.com/OpenVoxProjectBot)) - Use PR for promotion action [\#255](https://github.com/OpenVoxProject/openvox/pull/255) ([nmburgan](https://github.com/nmburgan)) - Use token when checking out repo [\#254](https://github.com/OpenVoxProject/openvox/pull/254) ([nmburgan](https://github.com/nmburgan)) - Add promote action [\#253](https://github.com/OpenVoxProject/openvox/pull/253) ([nmburgan](https://github.com/nmburgan)) - Update release automation [\#252](https://github.com/OpenVoxProject/openvox/pull/252) ([nmburgan](https://github.com/nmburgan)) - add note about server\_list precedence [\#251](https://github.com/OpenVoxProject/openvox/pull/251) ([binford2k](https://github.com/binford2k)) - Fix description of `source` since `yum` allows it now [\#249](https://github.com/OpenVoxProject/openvox/pull/249) ([binford2k](https://github.com/binford2k)) - include "local" facts in facts output [\#240](https://github.com/OpenVoxProject/openvox/pull/240) ([binford2k](https://github.com/binford2k)) - Correct homepage in gemspec [\#223](https://github.com/OpenVoxProject/openvox/pull/223) ([ekohl](https://github.com/ekohl)) - CI: Build gem for each PR & Move packaging checks to global config & Windows: Run one spec file per CPU core [\#216](https://github.com/OpenVoxProject/openvox/pull/216) ([bastelfreak](https://github.com/bastelfreak)) - Add switch for uploading to S3 [\#212](https://github.com/OpenVoxProject/openvox/pull/212) ([nmburgan](https://github.com/nmburgan)) - Update acceptance workflow for changed beaker acceptance [\#209](https://github.com/OpenVoxProject/openvox/pull/209) ([jpartlow](https://github.com/jpartlow)) - `yum` package provider: add `assumeyes` to `yum check-update` [\#188](https://github.com/OpenVoxProject/openvox/pull/188) ([SvenVD-be](https://github.com/SvenVD-be)) - Prevents spurious clientcert warnings in serverless mode [\#22](https://github.com/OpenVoxProject/openvox/pull/22) ([binford2k](https://github.com/binford2k)) ## [8.23.1](https://github.com/openvoxproject/openvox/tree/8.23.1) (2025-09-08) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.23.0...8.23.1) **Fixed bugs:** - Fix how we find the version library [\#203](https://github.com/OpenVoxProject/openvox/pull/203) ([nmburgan](https://github.com/nmburgan)) **Merged pull requests:** - Promote puppet-runtime 2025.09.08.1 [\#204](https://github.com/OpenVoxProject/openvox/pull/204) ([nmburgan](https://github.com/nmburgan)) - Test for r10k failure condition [\#202](https://github.com/OpenVoxProject/openvox/pull/202) ([nmburgan](https://github.com/nmburgan)) ## [8.23.0](https://github.com/openvoxproject/openvox/tree/8.23.0) (2025-09-07) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.22.0...8.23.0) - This is our first release where MacOS and Windows agents are built entirely in GitHub Actions! - MacOS x86_64 is now supported - The MacOS agents now work on all currently supported MacOS versions (13, 14, and 15). No need for separate packages! - The openvox-agent repo, which was the repo used for building the openvox-agent packages, has now been integrated into this openvox repo under the 'packaging' directory. This will allow us to have fewer steps in the build process and tag changes more cleanly, rather than having to tag two separate repos. Note that for releases prior to this one, the changelog in this file refers only to the changes to openvox itself and not packaging changes. For example, 8.22.1 was released to fix an unintentional service renaming issue and details are in the openvox-agent repo. At some point, we may try to integrate the two changelogs. - This release contains a large number of dependencies bumps. Most are not security related, but many dependencies were lagging for a long time. See [this PR](https://github.com/OpenVoxProject/puppet-runtime/pull/35) for details. - A patch for Augeas to address [CVE-2025-2588](https://github.com/advisories/GHSA-hxwj-c5vw-fwgp) **Implemented enhancements:** - Respect systemd's RUNTIME\_DIRECTORY environment variable [\#165](https://github.com/OpenVoxProject/openvox/pull/165) ([ekohl](https://github.com/ekohl)) **Fixed bugs:** - treat windows service accounts as case insensitive [\#172](https://github.com/OpenVoxProject/openvox/pull/172) ([binford2k](https://github.com/binford2k)) - Ensure confdir exists [\#171](https://github.com/OpenVoxProject/openvox/pull/171) ([binford2k](https://github.com/binford2k)) **Merged pull requests:** - Promote puppet-runtime 2025.09.04.1 [\#191](https://github.com/OpenVoxProject/openvox/pull/191) ([nmburgan](https://github.com/nmburgan)) - Merge openvox-agent vanagon repo [\#186](https://github.com/OpenVoxProject/openvox/pull/186) ([austb](https://github.com/austb)) ## [8.22.0](https://github.com/openvoxproject/openvox/tree/8.22.0) (2025-08-23) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.21.1...8.22.0) ## [8.21.1](https://github.com/openvoxproject/openvox/tree/8.21.1) (2025-07-23) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.21.0...8.21.1) **Fixed bugs:** - Make passing invalid options to install.rb fatal [\#156](https://github.com/OpenVoxProject/openvox/pull/156) ([ekohl](https://github.com/ekohl)) **Merged pull requests:** - Revert "Mark some failing 8.3 Windows tests as pending" [\#159](https://github.com/OpenVoxProject/openvox/pull/159) ([ekohl](https://github.com/ekohl)) - \(maint\) Drop debian-10 from testing matrix [\#152](https://github.com/OpenVoxProject/openvox/pull/152) ([jpartlow](https://github.com/jpartlow)) ## [8.21.0](https://github.com/openvoxproject/openvox/tree/8.21.0) (2025-07-09) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.20.0...8.21.0) **Implemented enhancements:** - Remove facter from install.rb [\#147](https://github.com/OpenVoxProject/openvox/pull/147) ([ekohl](https://github.com/ekohl)) ## [8.20.0](https://github.com/openvoxproject/openvox/tree/8.20.0) (2025-06-27) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.19.2...8.20.0) **Implemented enhancements:** - Switch from facter to openfact [\#142](https://github.com/OpenVoxProject/openvox/pull/142) ([smortex](https://github.com/smortex)) - \(PUP-12083\) Update soft limit warning for fact value & name length [\#137](https://github.com/OpenVoxProject/openvox/pull/137) ([bastelfreak](https://github.com/bastelfreak)) **Fixed bugs:** - Maintain consistent JSON formatting [\#132](https://github.com/OpenVoxProject/openvox/pull/132) ([bastelfreak](https://github.com/bastelfreak)) **Merged pull requests:** - cleanup gem metadata after Perforce-\>OpenVoxProject migration [\#140](https://github.com/OpenVoxProject/openvox/pull/140) ([smortex](https://github.com/smortex)) ## [8.19.2](https://github.com/openvoxproject/openvox/tree/8.19.2) (2025-06-06) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.19.1...8.19.2) **Fixed bugs:** - server\_facts: Switch implementation-\>serverimplementation [\#107](https://github.com/OpenVoxProject/openvox/pull/107) ([binford2k](https://github.com/binford2k)) - Reflect Ruby 3.4 stack trace changes [\#100](https://github.com/OpenVoxProject/openvox/pull/100) ([ekohl](https://github.com/ekohl)) - Add base64 as gem dependencies for Ruby 3.4 [\#98](https://github.com/OpenVoxProject/openvox/pull/98) ([ekohl](https://github.com/ekohl)) - Add racc gem dependency [\#89](https://github.com/OpenVoxProject/openvox/pull/89) ([ekohl](https://github.com/ekohl)) ## [8.19.1](https://github.com/openvoxproject/openvox/tree/8.19.1) (2025-06-03) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.19.0...8.19.1) **Fixed bugs:** - Fix invalid gemspec in AIO package [\#91](https://github.com/OpenVoxProject/openvox/pull/91) ([smortex](https://github.com/smortex)) ## [8.19.0](https://github.com/openvoxproject/openvox/tree/8.19.0) (2025-05-30) [Full Changelog](https://github.com/openvoxproject/openvox/compare/8.18.1...8.19.0) **Implemented enhancements:** - Add `implementation` fact to agent and server. [\#63](https://github.com/OpenVoxProject/openvox/pull/63) ([ffrank](https://github.com/ffrank)) **Fixed bugs:** - Replace `erase` with `remove`, since it's no longer supported with DNF5 [\#68](https://github.com/OpenVoxProject/openvox/pull/68) ([Stricken1670](https://github.com/Stricken1670)) \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* OpenVoxProject-openvox-ebcec1e/LICENSE000066400000000000000000000261361527241624000200040ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. OpenVoxProject-openvox-ebcec1e/README.md000066400000000000000000000057471527241624000202630ustar00rootroot00000000000000# OpenVox OpenVox is a community implementation of Puppet, an automated administrative engine for your Linux, Unix, and Windows systems, designed to perform administrative tasks (such as adding users, installing packages, and updating server configurations) based on a centralized specification. ## Documentation As of now, OpenVox is effectively the same as the original Puppetâ„¢ï¸� packages, aside from some minor build pipeline changes and package renaming. This means that aside from the installation, most existing Puppetâ„¢ï¸� docs and tutorials will still be applicable. As the OpenVox project matures, we will create more documentation, guides, and tutorials. Documentation is available at [the OpenVox documentation site](https://docs.openvoxproject.org/). ### HTTP API [HTTP API Index](https://docs.openvoxproject.org/openvox/latest/http_api/http_api_index.html) ## Installation To install OpenVox, [see our installation guide.](https://voxpupuli.org/openvox/install/) and [quickstart page](https://voxpupuli.org/openvox/quickstart/). If you need to run OpenVox from source as a tester or developer, see the [Quick Start to Developing on OpenVox](docs/quickstart.md) guide. ## Developing and Contributing We'd love to get contributions from you! For a quick guide to getting your system setup for developing, take a look at our [Quickstart Guide](docs/quickstart.md). Once you are up and running, take a look at the [Contribution Documents](https://github.com/OpenVoxProject/.github/blob/main/CONTRIBUTING.md) to see how to get your changes merged in. For more complete docs on developing with OpenVox, take a look at the rest of the [developer documents](docs/index.md). ## Licensing See [LICENSE](LICENSE) file. OpenVox is licensed by the OpenVox Project as a community maintained implementation of Puppet. The OpenVox Project can be contacted at: openvox@voxpupuli.org. Puppet itself is licensed by Puppet, Inc. under the Apache license. Puppet, Inc. can be contacted at: info@puppet.com. ## Support Please log issues in this project's [GitHub Issues](https://github.com/OpenVoxProject/puppet/issues). Other channels for getting help can be found at our [support page](https://voxpupuli.org/openvox/support/), including the mailing list and other community spaces available for asking questions and getting help from others. We use semantic version numbers for our releases and recommend that users stay as up-to-date as possible by upgrading to patch releases and minor releases as they become available. Bug fixes and ongoing development will occur in minor releases for the current major version. Security fixes will be backported to a previous major version on a best-effort basis, until the previous major version is no longer maintained. For example: If a security vulnerability is discovered in OpenVox 8.1.1, we would fix it in the 8 series, most likely as 8.1.2. Maintainers would then make a best effort to backport that fix onto earlier releases that haven't reached their respective end-of-life dates. OpenVoxProject-openvox-ebcec1e/Rakefile000066400000000000000000000124621527241624000204410ustar00rootroot00000000000000# frozen_string_literal: true require 'open3' require 'rake' require 'rubygems' require 'rubygems/package_task' RED = "\033[31m" GREEN = "\033[32m" RESET = "\033[0m" def run_command(cmd, silent: true, print_command: false, report_status: false) puts "#{GREEN}Running #{cmd}#{RESET}" if print_command output = '' Open3.popen2e(cmd) do |_stdin, stdout_stderr, thread| stdout_stderr.each do |line| puts line unless silent output += line end exitcode = thread.value.exitstatus unless exitcode.zero? err = "#{RED}Command failed! Command: #{cmd}, Exit code: #{exitcode}" # Print details if we were running silent err += "\nOutput:\n#{output}" if silent err += RESET abort err end puts "#{GREEN}Command finished with status #{exitcode}#{RESET}" if report_status end output.chomp end Dir.glob(File.join('tasks/**/*.rake')).each { |file| load file } ### Packaging stuff ### if Rake.application.top_level_tasks.grep(/^(pl:|package:)/).any? begin require 'packaging' Pkg::Util::RakeUtils.load_packaging_tasks rescue LoadError => e puts "Error loading packaging rake tasks: #{e}" end end namespace :package do task :bootstrap do puts 'Bootstrap is no longer needed, using packaging-as-a-gem' end task :implode do puts 'Implode is no longer needed, using packaging-as-a-gem' end end task :default do sh %{rake -T} end namespace :ci do desc 'Build openvox gems' task :gem_build, [:gemspec] do |t, args| args.with_defaults(gemspec: 'openvox.gemspec') stdout, stderr, status = Open3.capture3(<<~END) gem build #{args.gemspec} --verbose --strict --platform x64-mingw-ucrt && \ gem build #{args.gemspec} --verbose --strict --platform universal-darwin && \ gem build #{args.gemspec} --verbose --strict END if !status.exitstatus.zero? puts "Error building #{args.gemspec}\n#{stdout} \n#{stderr}" exit(1) else puts stdout end end desc 'build the nightly openvox gems' task :nightly_gem_build do # this is taken from `rake package:nightly_gem` extended_dot_version = %x{git describe --tags --dirty --abbrev=7}.chomp.tr('-', '.') # we must create tempfile in the same directory as openvox.gemspec, since # it uses __dir__ to determine which files to include require 'tempfile' Tempfile.create('gemspec', __dir__) do |dst| File.open('openvox.gemspec', 'r') do |src| src.readlines.each do |line| if line.match?(/version\s*=\s*['"][0-9.]+['"]/) line = "spec.version = '#{extended_dot_version}'" end dst.puts line end end dst.flush Rake::Task['ci:gem_build'].invoke(dst.path) end end end task :spec do ENV["LOG_SPEC_ORDER"] = "true" sh %{rspec #{ENV['TEST'] || ENV['TESTS'] || ENV['SPEC'] || 'spec'}} end begin require 'rubocop/rake_task' RuboCop::RakeTask.new(:rubocop) do |task| # These make the rubocop experience maybe slightly less terrible task.options = ['--display-cop-names', '--display-style-guide', '--extra-details'] # Use Rubocop's Github Actions formatter if possible task.formatters << 'github' if ENV['GITHUB_ACTIONS'] == 'true' end rescue LoadError # the gem is only used on MRI Ruby end desc "verify that changed files are clean of Ruby warnings" task(:warnings) do # This rake task looks at all files modified in this branch. commit_range = 'HEAD^..HEAD' ruby_files_ok = true puts "Checking modified files #{commit_range}" %x{git diff --diff-filter=ACM --name-only #{commit_range}}.each_line do |modified_file| modified_file.chomp! # Skip racc generated file as it can have many warnings that cannot be manually fixed next if modified_file.end_with?("pops/parser/eparser.rb") next if modified_file.start_with?('spec/fixtures/', 'acceptance/fixtures/') || File.extname(modified_file) != '.rb' puts modified_file stdout, stderr, _ = Open3.capture3("ruby -wc \"#{modified_file}\"") unless stderr.empty? ruby_files_ok = false puts stderr end puts stdout end raise "One or more ruby files contain warnings." unless ruby_files_ok end if Rake.application.top_level_tasks.grep(/^gettext:/).any? begin spec = Gem::Specification.find_by_name 'gettext-setup' load "#{spec.gem_dir}/lib/tasks/gettext.rake" GettextSetup.initialize(File.absolute_path('locales', File.dirname(__FILE__))) rescue LoadError abort("Run `bundle install --with documentation` to install the `gettext-setup` gem.") end end begin require "github_changelog_generator/task" require_relative "lib/puppet/version" GitHubChangelogGenerator::RakeTask.new :changelog do |config| config.header = <<~HEADER.chomp # Changelog All notable changes to this project will be documented in this file. HEADER config.user = "openvoxproject" config.project = "openvox" config.exclude_labels = %w[dependencies duplicate question invalid wontfix wont-fix modulesync skip-changelog] config.since_tag = "9.0.0-alpha1" config.future_release = Puppet::PUPPETVERSION config.exclude_tags_regex = /\A[7,8]\./ end rescue LoadError task :changelog do abort("Run `bundle install --with release` to install the `github_changelog_generator` gem.") end end desc 'Prepare for a release' task 'release:prepare' => [:changelog] OpenVoxProject-openvox-ebcec1e/acceptance/000077500000000000000000000000001527241624000210555ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/.beaker.yml000066400000000000000000000006331527241624000231110ustar00rootroot00000000000000--- ssh: keys: - id_rsa_acceptance - ~/.ssh/id_rsa-acceptance xml: true timesync: false repo_proxy: true add_el_extras: false 'master-start-curl-retries': 30 log_level: debug preserve_hosts: onfail helper: ./lib/helper.rb options_file: ./config/aio/options.rb OpenVoxProject-openvox-ebcec1e/acceptance/.gitignore000066400000000000000000000002621527241624000230450ustar00rootroot00000000000000.vagrant local_options.rb pl-puppet-build.repo pl-puppet-repos.rpm repos.tar repo-configs log id_rsa-acceptance id_rsa-acceptance.pub preserved_config.yaml merged_options.rb tmp OpenVoxProject-openvox-ebcec1e/acceptance/Gemfile000066400000000000000000000022601527241624000223500ustar00rootroot00000000000000# Specifies a gem mirror; duplicated in acceptance setup # to ensure a similar environment on acceptance hosts. source ENV['GEM_SOURCE'] || 'https://rubygems.org' def location_for(place, fake_version = nil) if place.is_a?(String) && place =~ /^((?:git[:@]|https:)[^#]*)#(.*)/ [fake_version, { :git => $1, :branch => $2, :require => false }].compact elsif place.is_a?(String) && place =~ /^file:\/\/(.*)/ ['>= 0', { :path => File.expand_path($1), :require => false }] else [place, { :require => false }] end end gem "beaker", *location_for(ENV['BEAKER_VERSION'] || '~> 7.6') gem "beaker-puppet", *location_for(ENV['BEAKER_PUPPET_VERSION' || "~> 4.4"]) gem "beaker-vagrant", *location_for(ENV['BEAKER_VAGRANT_VERSION'] || "~> 2.1") gem "beaker-vcloud", *location_for(ENV['BEAKER_VCLOUD_VERSION'] || "~> 2.2") gem "beaker-docker", *location_for(ENV['BEAKER_DOCKER_VERSION'] || "~> 3.1") gem "rake", ">= 12.3.3" gem "httparty", :require => false gem 'uuidtools', :require => false group(:test) do gem "rspec", "~> 2.14.0", :require => false gem "mocha", "~> 0.10.5", :require => false end if File.exist? "#{__FILE__}.local" eval(File.read("#{__FILE__}.local"), binding) end OpenVoxProject-openvox-ebcec1e/acceptance/README.md000066400000000000000000000522451527241624000223440ustar00rootroot00000000000000# Running Puppet Acceptance Tests ## Table of Contents * [Setup](#setup) * [Quick Start](#quick-start) * [Configuration](#configuration) * [Running Tests](#running-tests) * [Writing Tests](#writing-tests) * [Getting Help](#getting-help) ------------- An important aside: Currently running acceptance tests that contain a specific change is challenging unless you have access to infrastructure internal to the Puppet, Inc. network. This is a known issue, and we are working to make this a better experience for our community. ------------- ## Setup ### Prerequisites * git * ruby * [bundler][] * a local clone of the puppet repo All command examples in this readme assume you are working in the same directory this README is in, `puppet/acceptance`. ### Installation All of the dependencies you need to run and develop tests are defined in `Gemfile`. To install them, run `bundle install --path .bundle/gems`. This command, as well all the command examples in this README, assume you are working in the acceptance directory. If you ever have issues with your runtime dependencies, you can update them with `bundle update` or start over fresh with `rm -rf .bundle/gems; bundle install --path .bundle/gems`. To ensure installation was successful, you can run `bundle exec rake -T`. This should return something along these lines: ``` $ bundle exec rake -T rake ci:help # Print usage information rake ci:test:aio # Run the acceptance tests using puppet-agent (AI... rake ci:test:gem # Run the acceptance tests against puppet gem on ... rake ci:test:git # Run the acceptance tests against a git checkout rake ci:test:quick # Run a limited but representative subset of acce... rake clean # Remove any temporary products rake clobber # Remove any generated files ``` To get a detailed description of all of these tasks, run `bundle exec rake -D`. ------------- ## Quick Start ### For community members Currently, there isn't a good way for community members to run acceptance tests. This is a known problem. We currently have multiple avenues we are exploring to make running puppet acceptance tests easier for our community. In the meantime, we apologize for the inconvenience. ### For Puppet, Inc. employees If you have access to infrastructure internal to the Puppet, Inc. network, then the quickest way to get acceptance tests running is with vmpooler. To test changes that are available on a branch on github.com: ``` bundle exec rake ci:test:git OPTIONS='--preserve-hosts=always' SHA=ticket/6.0.x/ticketed-work-description RUNTIME_BRANCH=6.0.x FORK=melissa TESTS='tests/path/to/test.rb,tests/other/test.rb' ``` Where `SHA` is the branch name, `RUNTIME_BRANCH` is the agent version stream, and `FORK` is the github fork where the branch lives. To test changes that are available in a puppet-agent package on builds.delivery.puppetlabs.net: ``` bundle exec rake ci:test:aio OPTIONS='--preserve-hosts=always' SHA=9124b4e81ec0ac6394d3edc67d4ab71866869fd7 TESTS='tests/path/to/test.rb,tests/other/test.rb' ``` `SHA` is a sha or tag that exists on builds.delivery.puppetlabs.net/puppet-agent To rerun a test on the hosts that have already been provisioned, use beaker subcommands: ``` bundle exec beaker exec tests/path/to/test.rb,tests/other/test.rb ``` Always clean up after yourself when you are done: ``` bundle exec beaker destroy ``` This will remove any provisioned hosts. Only run this once you are done with the hosts that have been checked out and provisioned for a given run. ------------- ## Configuration ### Environment Variables A detailed description of the available environment variables can be found by running `bundle exec rake ci:help`. This will print a list of both required and optional environment variables with short descriptions on how they are used. Please review all of these options as they will impact how your test servers are provisioned. This rake task is the most up to date source for this information. Please read through the available variables, their defaults, and what they do. They may impact your acceptance run in ways you do not expect. ### Customizing Test Targets If you are using the vmpooler hypervisor internal to Puppet, Inc. infrastructure, you can customize the platforms to test on using the `HOSTS` environment variable. You'll set the `HOSTS` environment variable to the host string you want to test, such as `HOSTS=redhat7-64ma-windows2012r2-64a`. For a list of available `HOSTS` platforms and their exact naming structures, check the keys listed in [beaker hostgenerator](https://github.com/puppetlabs/beaker-hostgenerator/blob/master/lib/beaker-hostgenerator/data.rb). Generally, this string will be in the format `{platform}{version}-{architecture}{role/s}`. You will most often use either the agent (a) or master (m) role, but you can find a list of available roles in [beaker hostgenerator](https://github.com/puppetlabs/beaker-hostgenerator/blob/master/lib/beaker-hostgenerator/roles.rb). Multiple hosts in the string are separated with a dash(`-`). You must have at least one agent and at least one master. Be careful not to confuse the different host string formats. We have different tools that expect the host string to be in different forms. For example, `packaging_platform` is specific to how [Vanagon](https://github.com/puppetlabs/vanagon) parses that string. ### The Hosts File The rake tasks that run acceptance will by default create a hosts file and populate it using [beaker-hostgenerator][] using either the `HOSTS` environment variable or the default host string (currently `redhat7-64ma-windows2012r2-64a`). The automation assumes you are using the vmpooler hypervisor and a vmpooler instance that is only available to Puppet, Inc. employees. If you want to customize the hypervisor or the vmpooler instance, you'll need to generate your own hosts file. You must pass in a valid host string to the `beaker-hostgenerator` command. See [Customizing Test Targets](#customizing-test-targets) for more information on how to construct a valid host string. To customize the hypervisor, pass in `--hypervisor {hypervisor name}`. To set the vmpooler instance, use `--global-config pooling_api={vmpooler uri}`. Only the vmpooler hypervisor uses the pooling_api key. The host string that is passed in is the same that you would use with the `HOSTS` environment variable. See [Customizing Test Targets](#customizing-test-targets) on how to format this string. To have the automation recognize and use your custom hosts file, you'll need to set the `HOSTS` environment variable to the hosts file. In the above example, we called this file `hosts.yaml`, so we will set `HOSTS` to `hosts.yaml` when running all future beaker commands or rake tasks to run acceptance tests. For example, if you were to run this command: ``` bundle exec beaker-hostgenerator redhat7-64ma-windows2012r2-64a --disable-default-role --osinfo-version 1 --hypervisor vmpooler --global-config pooling_api=http://customvmpooler/ > hosts.yaml ``` You would generate a file called `hosts.yaml` that contains something like this: ``` --- HOSTS: redhat7-64-1: platform: el-7-x86_64 packaging_platform: el-7-x86_64 template: redhat-7-x86_64 hypervisor: vmpooler roles: - master - agent windows2012r2-64-1: platform: windows-2012r2-64 packaging_platform: windows-2012-x64 ruby_arch: x64 template: win-2012r2-x86_64 hypervisor: vmpooler roles: - agent CONFIG: nfs_server: none consoleport: 443 pooling_api: http://customvmpooler/ ``` We can then run the acceptance tests with: `bundle exec rake ci:test:aio HOSTS=hosts.yaml SHA={sha}` ### Hypervisor Options The hypervisor dictates where you will be running the acceptance tests. The beaker hypervisors take care of basic host setup so that you will have a consistent host environment across every test run. You can find more details on the different hypervisor options in [the beaker repo](https://github.com/puppetlabs/beaker/blob/master/docs/how_to/hypervisors/README.md). Here, we will focus on vmpooler and docker, as those are the two we use most often internally. If you use a hypervisor other than abs, vagrant, vmpooler, or docker, you'll have to add the gem to that hypervisor to `Gemfile.local` and run `bundle update` to install the new gems. You also have the ability to run tests on a static host. #### VMPooler [VMPooler](https://github.com/puppetlabs/vmpooler) is the default hypervisor we use. This is only available to Puppet, Inc. employees as it uses internal infrastructure. If you have access to a similar setup, then you are welcome to use this option with a few values changed. If you are using the Puppet internal vmpooler, then you can simply run the acceptance rake tasks. See [Customizing Test Targets](#customizing-test-targets) about how to use the `HOSTS` environment variable to customize the platforms you are running tests on. To use a different vmpooler instance, use `--global-config pooling_api=http://customvmpooler/` when you use `beaker-hostgenerator` to generate `hosts.yaml`. Make sure you set `HOSTS` to the hosts file you just generated so the automation can find that file. See [The Hosts File](#the-hosts-file) for more detail on the hosts file. #### Docker To test with [the docker hypervisor](https://github.com/puppetlabs/beaker-docker), you will want to generate a custom hosts file. You will also mostly likely need to manually edit the file. See [The Hosts File](#the-hosts-file) for more detail on the hosts file. To create a hosts file with a centos 7 master and a centos 7 agent, we can use the following beaker-hostgenerator command `bundle exec beaker-hostgenerator centos7-64m-centos7-64a --disable-default-role --osinfo-version 1 --hypervisor docker > hosts.yaml` Which will produce a file called `hosts.yaml` that contains the following: ``` --- HOSTS: centos7-64-1: docker_cmd: - "/sbin/init" image: centos:7 platform: centos-7-x86_64 packaging_platform: el-7-x86_64 docker_image_commands: - cp /bin/true /sbin/agetty - yum install -y crontabs initscripts iproute openssl sysvinit-tools tar wget which ss hypervisor: docker roles: - master centos7-64-2: docker_cmd: - "/sbin/init" image: centos:7 platform: centos-7-x86_64 packaging_platform: el-7-x86_64 docker_image_commands: - cp /bin/true /sbin/agetty - yum install -y crontabs initscripts iproute openssl sysvinit-tools tar wget which ss hypervisor: docker roles: - agent CONFIG: nfs_server: none consoleport: 443 ``` Run acceptance tests against pre-built puppet-agent packages with `bundle exec rake ci:test:aio SHA={sha|tag} TESTS=path/to/test.rb HOSTS=hosts.yaml` Note that if you are not running tests against the master branch and you are installing the latest puppetserver package, you will likely need to set `RELEASE_STREAM` to pick up the correct server version. Please see the section on [environment variables](#environment-variables) for more information. When you generate your [hosts file](#the-hosts-file), [beaker-hostgenerator][] does its best to populate the values as logically as possible. You will likely want to update or modify them to suite your needs. With `image`, [beaker-hostgenerator][] does its best to guess the most logical image string based on the platform you are building. For the most part, this should work without interference, but if you are using a custom docker image or do not want the default, then you will have to manually update this string. Not every string beaker-hostgenerator uses to populate this variable will be valid. `docker_image_commands` is automatically populated when generating the hosts file with [beaker-hostgenerator][]. This has already been set for a handful of host types, but may not be set for all. * TODO I only tried this once using a docker image that already had puppetserver installed as the master host. The image I used took forever to provision, so I gave up. If we want to continue down this route, we need to make sure the setup steps can check if puppetserver has already been installed so that we don't try to install it agian. * TODO There's something odd with `docker_mage_entrypoint` versus `docker_cmd`. We should clarify the difference between these two values. I don't quite understand what the difference is between them. * TODO These docker containers have to run in privileged mode (or systemd, among possibly other things, won't function as we need them to). This is not ideal if you're testing code that affects your OS (ie running docker on linux without a docker machine in between the container and your laptop). BE CAREFUL #### Static Hosts This is not recommended unless you are familiar with how beaker and beaker-puppet provision hosts. To test on a server that's already been spun up or doesn't require a hypervisor, you should set the name of the host to the FQDN of the server you want to use, then remove the hypervisor and template settings. This is not recommended, and you may run into issues with failures or overwritten configuration due to either beaker provision steps or test provisioning steps. ``` --- HOSTS: azeqdqmk14mvu3g.delivery.puppetlabs.net: platform: el-7-x86_64 packaging_platform: el-7-x86_64 roles: - master ``` ------------- ## Running Tests ### Testing with pre-built packages ``` bundle exec rake ci:test: SHA={sha|tag} ``` This is the primary method that we use to run puppet acceptance tests. It requires puppet-agent packages that have been built with the version of the puppet code that you want to test. As building packages usually takes quite a bit of time, this method requires some patience. You are required to set `SHA` when running acceptance tests against pre-built packages. #### Testing a specific version If you are testing a specific version, `SHA` must be set to a value that exists on the path `#{ENV['DEV_BUILDS_URL']}/puppet-agent/#{ENV['SHA']}`. Note that this value corresponds to the puppet-agent package, not to puppet. `DEV_BUILDS_URL` defaults to the internal build server that is only accessible to Puppet, Inc. employees. The method called here depends on information written to a yaml file in that directory. Though you can override DEV_BUILDS_URL, the automation here is very specific and likely will not work as you are expecting it to. ``` bundle exec rake ci:test:aio SHA=3cfbac6857c10efc5b1e02262cfd7b849bb9c4b2 ``` ``` bundle exec rake ci:test:aio SHA=6.0.5 ``` #### Testing Nightlies If you do not have access to internal infrastructure, you can test against packages that have been made available on nightlies.puppet.com. Currently, you cannot specify a specific version. Instead, you have to use the latest shipped package for the release stream you are interested in. To do this, `SHA` must be set to `latest`. If you want to modify the release stream you are testing, `RELEASE_STREAM` can be modified. It defaults to `puppet` which should correspond to the latest stream available. If you want to modify `RELEASE_STREAM`, set it to an available repo, such as `puppet5`. ``` bundle exec rake ci:test:aio SHA=latest RELEASE_STREAM=puppet5 ``` ### Testing with Git ``` bundle exec rake ci:test:git SHA={sha|tag|branch} ``` #### From a repo on a git server Though we primarily run acceptance tests against a built package, it is possible to run these tests with a git checkout. This is most useful when testing locally to speed up the feedback cycle. When testing from a github repo we need to unpack the appropriate [runtime archive](https://github.com/puppetlabs/puppet-runtime) for the platform we are testing on. These pre-built archives are stored on an internal server, and are currently only available to Puppet, Inc. employees. With these archives, we get all of the runtime dependencies that are usually provided as a part of the puppet agent package. This allows us to replicate the runtime environment produced via a package install for the purpose of running acceptance tests. When testing with git, `SHA` can be set to any git artifact: a long sha, a short sha, a tag, a branch name, etc. What happens is that we write a gemfile with the details of the puppet repo, pointing to the artifact referenced with `SHA`. Then when we run `bundle install` on the testing host, bundler grabs puppet from wherever the gemfile points. If the git artifact referenced is not from the puppetlabs repo, you can use `FORK` to point to a different github namespace. Likewise, if the artifact you want to access is not available on `github.com` but a custom git server, you can set `SERVER` to customize the git uri bundler pulls from. For more details on these environment variables, run `bundle exec rake ci:help`. As an example, if I have a development branch (`developent/master/major-feature`) that I'm working on and it only exists in my fork of puppet (`github.com/joeschmoe/puppet`), then I will run ``` bundle exec rake ci:test:git SHA=developent/master/major-feature FORK=joeschmoe ``` Please note that any changes you want to test must be pushed up to your github server. This is how we access the code to be tested. #### From a local repo If you are testing with git and using the docker hypervisor, you can run tests against the puppet checkout on your local system. You need to update your hosts file to add `mount_folders` to the docker host where you want the checkout of puppet to be available. Here, `host_path` is the path to puppet on your local machine. The `container_path` is where puppet will end up on the docker image, so you can leave it as `/build/puppet`. Note that although `SHA` is required, it is never used in this workflow. For consistency, I would recommend setting `SHA` to your working branch name. We still need access to our runtime dependencies when testing against a local git checkout. When we are testing with the docker hypervisor, we assume that the docker image you are using will have this. As of this writing (Jan. 2019), the docker image you'll want to use for these tests is not public. The image is called `agent-runtime-{branch}`, where `{branch}` is the branch of puppet you are testing. This image includes everything we build as a part of [the runtime archive](https://github.com/puppetlabs/puppet-runtime). These components are normally provided as a part of the puppet agent package. ``` --- HOSTS: debian8-64-1: hypervisor: docker docker_image_entrypoint: "/sbin/init" image: pcr-internal.puppet.net/pe-and-platform/agent-runtime-master:201810110.17.gb5afc66 platform: debian-8-amd64 packaging_platform: debian-8-amd64 docker_image_commands: - rm -f /usr/sbin/policy-rc.d - systemctl mask getty@tty1.service getty-static.service - apt-get update && apt-get install -y cron locales-all net-tools wget mount_folders: puppet: host_path: ~/puppet container_path: /build/puppet roles: - agent ``` For more details on testing with docker, see [the docker section](#docker). Remember that `HOSTS` must be set to your hosts file for the automation to honor it. ### Testing with Gems Currently, running acceptance tests with gems is not working. ``` bundle exec rake ci:test:gem ``` ### Rerunning Failed Tests The rake tasks we use here take advantage of a newer feature in beaker that gives us quite a bit of flexibility. We take advantage of beaker subcommands. Subcommands are individual beaker invocations that are used to run the different stages of running tests: provisioning, pre-suite setup, tests, etc. We do this by writing state to the file `.beaker/subcommand_options.yaml`. With each new invocation of a subcommand, beaker will check for this file and load the contents if the file exists. The important thing about this feature is that you can rerun tests without going through the entire provisioning process every time. To ensure your hosts aren't cleaned up after a run, set `OPTIONS='--preserve-hosts=always'`. With this set, we can rerun a failed test using the infrastructure beaker has already provisioned. ``` bundle exec rake ci:test:aio OPTIONS='--preserve-hosts=always' SHA=6.0.5 ``` If this run fails because a small handful of tests fail, you can rerun only those tests that failed. For example, assume that `tests/resource/package/yum.rb` and `tests/node/check_woy_cache_works.rb` both had failing tests. you can run ``` bundle exec beaker exec tests/resource/package/yum.rb,tests/node/check_woy_cache_works.rb ``` This should work regardless of which hypervisor or testing method you are using. ------------- ## Writing Tests Read more about writing beaker tests in beaker. Check out the [tutorials section](https://github.com/puppetlabs/beaker/tree/master/docs/tutorials) and [how to write a quick test](https://github.com/puppetlabs/beaker/blob/master/docs/tutorials/lets_write_a_test.md) ------------- ## Getting Help ### On the web * [Puppet help messageboard](http://puppet.com/community/get-help) * [General GitHub documentation](http://help.github.com/) ### On chat * Slack (slack.puppet.com) #testing, #puppet-dev, #windows [bundler]: https://rubygems.org/gems/bundler [rspec-puppet]: http://rspec-puppet.com/ [rspec-puppet_docs]: http://rspec-puppet.com/documentation/ [beaker]: https://github.com/puppetlabs/beaker [beaker-puppet]: https://github.com/puppetlabs/beaker-puppet [beaker-hostgenerator]: https://github.com/puppetlabs/beaker-hostgenerator OpenVoxProject-openvox-ebcec1e/acceptance/Rakefile000066400000000000000000000110321527241624000225170ustar00rootroot00000000000000require 'beaker-puppet' Beaker::DSL::Helpers::RakeHelpers.load_tasks namespace :ci do namespace :test do desc <<-EOS Run a limited but representative subset of acceptance tests against puppet-agent (AIO) packages. This task is intended to reduce testing time on a per-commit basis. $ SHA= bundle exec rake ci:test:quick SHA should be the full SHA for the puppet-agent package. EOS task :quick => ['ci:check_env', 'ci:gen_hosts'] do ENV['TESTS'] = get_test_sample.join(",") Rake::Task["ci:test:aio"].invoke end desc <<-EOS Run tests on docker quickly and easily. The docker container is set up to mount your puppet directory in the container. This means you can edit code or test files and rerun tests without reconfiguring your test environment. Defaults to running all tests unless TESTS is set. TESTS is a comma seperated list of test files to run. $ bundle exec rake ci:test:docker TESTS='path/to/test.rb,path/to/another/test.rb' By default, tests are run on a centos 7 host. To change the host, set HOSTS to a valid host string according to beaker-hostgenerator requirements. All tests marked with a server tag will be skipped. This task skips all cleanup. Please be sure to run `bundle exec beaker destroy` to clean up docker containers used for testing. EOS task :docker do begin ENV['HOSTS'] ||= 'centos7-64a' ENV['SHA'] ||= `git rev-parse HEAD`.chomp ENV['OPTIONS'] ||= '--preserve-hosts=always' ENV['OPTIONS'] += ' --test-tag-exclude=server' Rake::Task["ci:gen_hosts"].invoke('docker') hosts_file_content = YAML.load_file ENV['HOSTS'] hosts_file_content['HOSTS'].each do |host| host[1]['mount_folders'] = { 'puppet' => { 'host_path' => "#{File.dirname(__dir__)}" , 'container_path' => '/build/puppet' } } host[1]['tag'] = 'acceptance_test_host' end File.open(ENV['HOSTS'], "w") { |f| f.write(YAML.dump(hosts_file_content)) } Rake::Task["ci:test:git"].invoke ensure puts <<-EOF ************************ You can modify puppet code or tests and rerun tests without modifying your test environment. To rerun a test or set of tests, pass a comma seperated list of tests to: $ bundle exec beaker exec path/to/test.rb or $ bundle exec beaker exec path/to/test.rb,path/to/another/test.rb ************************ This task skips all clean up so you can rerun tests. Don't forget to clean up after yourself! To clean up the docker containers used to run tests, run: $ bundle exec beaker destroy ************************ EOF end end end namespace :sync do task :windows do raise 'WIN_MACHINE environment variable is required' unless ENV['WIN_MACHINE'] win_machine = ENV['WIN_MACHINE'] + '.delivery.puppetlabs.net' path = ENV['LIB_DIR'] || 'type' # 'lib/puppet' prefix is implicit. dest_path = path.split('/')[0...-1].join system("scp -r #{File.dirname(__FILE__)}/../lib/puppet/#{path} Administrator@#{win_machine}:'C:/Program\\ Files/Puppet\\ Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/#{dest_path}'") end end end def get_test_sample # This set represents a reasonable sample of puppet acceptance tests, # covering a wide range of features and code susceptible to regressions. tests = [ 'tests/direct_puppet/cached_catalog_remediate_local_drift.rb', 'tests/resource/file/content_attribute.rb', 'tests/face/loadable_from_modules.rb', 'tests/language/functions_in_puppet_language.rb', 'tests/parser_functions/calling_all_functions.rb', 'tests/ticket_4622_filebucket_diff_test.rb', 'tests/pluginsync/4420_pluginfacts_should_be_resolvable_on_agent.rb', 'tests/ssl/puppet_cert_generate_and_autosign.rb', 'tests/resource/package/yum.rb', 'tests/resource/service/ticket_5024_systemd_enabling_masked_service.rb', 'tests/resource/service/puppet_service_management.rb' ] # Add any tests modified within the last two weeks to the list, excluding # deleted ones. We can't rely on --diff-filter, because an acceptance # test may be modified and then deleted in the same time range. modified = `git log --name-only --pretty="format:" --since 2.weeks ./tests` tests += modified.split("\n").reject do |s| s.empty? end.collect do |s| s.sub('acceptance/', '') end.select do |s| s =~ /\.rb$/ end.find_all do |s| File.exist?(s) end tests.uniq.sort end OpenVoxProject-openvox-ebcec1e/acceptance/config/000077500000000000000000000000001527241624000223225ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/config/aio/000077500000000000000000000000001527241624000230725ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/config/aio/options.rb000066400000000000000000000005751527241624000251210ustar00rootroot00000000000000{ :type => 'aio', 'is_puppetserver' => true, 'use-service' => true, # use service scripts to start/stop stuff 'puppetservice' => 'puppetserver', 'puppetserver-confdir' => '/etc/puppetlabs/puppetserver/conf.d', 'puppetserver-config' => '/etc/puppetlabs/puppetserver/conf.d/puppetserver.conf', } OpenVoxProject-openvox-ebcec1e/acceptance/config/gem/000077500000000000000000000000001527241624000230725ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/config/gem/options.rb000066400000000000000000000001141527241624000251060ustar00rootroot00000000000000{ # Use `git` so that we have a sane ruby environment :type => 'git', } OpenVoxProject-openvox-ebcec1e/acceptance/config/git/000077500000000000000000000000001527241624000231055ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/config/git/options.rb000066400000000000000000000006641527241624000251330ustar00rootroot00000000000000{ :type => 'git', :install => [ 'puppet', ], 'is_puppetserver' => false, 'use-service' => true, # use service scripts to start/stop stuff 'puppetservice' => 'puppetserver', 'puppetserver-confdir' => '/etc/puppetlabs/puppetserver/conf.d', 'puppetserver-config' => '/etc/puppetlabs/puppetserver/conf.d/puppetserver.conf' } OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/000077500000000000000000000000001527241624000227265ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/MockInstaller.cs000066400000000000000000000025531527241624000260310ustar00rootroot00000000000000/* The MockInstaller is a C# class representing a stubbed exe installer. We will compile this class into an installable .exe file. A MockInstaller _MUST_ come alongside a MockUninstaller, so we can uninstall the fake package from the system */ using System; public class MockInstaller { public static void Main() { try { %{install_commands} } catch { Environment.Exit(1003); } string keyName = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; Microsoft.Win32.RegistryKey key; key = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(keyName + "\\%{package_display_name}"); /* Puppet deems an exe package 'installable' by identifying whether or not the following registry values exist in the Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\PackageName key: * DisplayName * DisplayVersion * UninstallString So we must set those values in the registry for this to be an 'installable package' manageable by puppet. */ key.SetValue("DisplayName", "%{package_display_name}"); key.SetValue("DisplayVersion", "1.0.0"); key.SetValue("UninstallString", @"%{uninstaller_location}"); key.Close(); Console.WriteLine("Installing..."); } } OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/MockService.cs000066400000000000000000000055601527241624000254750ustar00rootroot00000000000000/* The MockService is a C# class representing a stubbed service. We will compile this class into the service's .exe file. Here, we implement four methods: * OnStart -- called when SCM starts the service * OnPause -- called when SCM pauses the service * OnContinue -- called when SCM resumes a paused service * OnStop -- called when SCM stops a service Before calling one of these 'On' methods, the ServiceBase class sets the service state to the corresponding PENDING state. The service state is in this PENDING state until the 'On' method is finished, whereby it is then transitioned into the corresponding final state. Thus if we sleep for a few seconds in the 'On' method, then note that SCM will report our service state as being in the PENDING state while we're asleep. For example, if the 'On' method is 'OnStart', the service state is set to START_PENDING before calling 'OnStart', is START_PENDING while executing 'OnStart', and then is set to RUNNING after exiting 'OnStart'. When testing the Windows service provider, we really want to test to ensure that it handles the state transitions correctly. For example, we want to check that: * It waits for the appropriate PENDING state to finish * It sets the service state to the appropriate final state The reason we want to do this is because our service provider is communicating with SCM directly, which does not care how the service implements these transitions so long as it implements them. C#'s ServiceBase class implements these state transitions for us. Thus by going to sleep in all of our 'On' methods, we simulate transitioning to the corresponding PENDING state. When we wake-up and exit the 'On' method, we will transition to the appropriate final state. NOTE: Normally, you're supposed to have the service thread in a separate process. The 'On' methods in this class would send signals to the service thread and then wait for those signals to be processed. Sending and waiting for these signals is quite hard and unnecessary for our use-case, which is why our MockService does not have the service thread. */ using System; using System.ServiceProcess; public class MockService : ServiceBase { public static void Main() { System.ServiceProcess.ServiceBase.Run(new MockService()); } public MockService() { ServiceName = "%{service_name}"; CanStop = true; CanPauseAndContinue = true; } private void StubPendingTransition(int seconds) { RequestAdditionalTime(2000); System.Threading.Thread.Sleep(seconds * 1000); } protected override void OnStart(string [] args) { StubPendingTransition(%{start_sleep}); } protected override void OnPause() { StubPendingTransition(%{pause_sleep}); } protected override void OnContinue() { StubPendingTransition(%{continue_sleep}); } protected override void OnStop() { StubPendingTransition(%{stop_sleep}); } } OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/MockUninstaller.cs000066400000000000000000000015601527241624000263710ustar00rootroot00000000000000/* The MockUninstaller is a C# class representing a stubbed exe uninstaller. We will compile this class into an usable .exe file. A MockInstaller _MUST_ come alongside a MockUninstaller, so we can uninstall the fake package from the system */ using System; public class MockInstaller { public static void Main() { try { %{uninstall_commands} } catch { Environment.Exit(1003); } string keyName = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; Console.WriteLine("Uninstalling..."); /* Remove the entire registry key created by the installer exe */ using (Microsoft.Win32.RegistryKey _key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(keyName, true)) { _key.DeleteSubKeyTree("%{package_display_name}"); } } } OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/debian-repo/000077500000000000000000000000001527241624000251135ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/debian-repo/Packages.gz000066400000000000000000000010251527241624000271710ustar00rootroot00000000000000‹��p^ÍÓÍŽÔ0 à{Ÿ"/À;ÿB,¬Ð^ViWNì°ÝiÕé€àéÉÌÀ,âÀq…Ô\§NüÉ[*_è³ôêAÆqú6-#weÙÓ®W°Ñ/ »ZÊðJYKË£qìniØ­mÉÒ«wü ´So‰e_êU96ùx3æYÖM™_wï‡QvôØ~³yùTðþTgÃ’»»áGÛŒÑv·×nxìU° 9»ä‰wìb®!p) 3�!ìîn® WÖX­É[ ˜XgpZ§Éd‡ÕEò“÷Ó1�ï•�B•Äyª5H ÌEkO^´‹Ž�ƒñ)·CÂU 2…P3Z2˜ `»jëÈ©K™öÒm—aZ†õ{¯¦ù¦±»nÏ_†ùœts|­útê¯úð0ìUûH­²_Õ|6PuZÔöÔ­Kh^¦¯7�®Ûþ[ Ò3Q ýa ^¬ $½ÆAA*ÀšŒ5ÂAÜo«`™ê]MA×Ö鑵·±¸&Ç>%ÊÁ:-+ÍäAlÍM)24]9c 9Õj0'+ .ÇäB†`Ú¶‘ìþ/+|¦©Â¿¦* ¿H±µb<ÛB. Z@@J(Eª¿¤ ²�Ql¶d9�¢ ]4¤‘ debian-binary 1584434776 0 0 100644 4 ` 2.0 control.tar.gz 1584434776 0 0 100644 471 ` ‹íÔÍjÛ@`�÷)¦·EòJviH½´Zz\KSk[iWÌ®Z|é³wd�K mzqJ`>,d�V«ÃLz™œ\ÆÖey8³ßχÿ¹^ée¡×EYp|½^ ”É#C4��÷ñoëºÿD¥—µw‘|wâú¯Šâ�õ׺¼_ÿ<×:K “úŸÜÆÔ_Í+h±ëüwO]£n‘‚õ®‚<Í.rõëx¸Üš€jCÖ“�û ü0…M§^RÝÚÈ«Fâ�LשwƺÈR¯í@Ö8xe õWõH·sàf‡cZûþZ½áÙa~ßÛ)%¸;ä[€"†Ü7|ö›ÃÇÐ@þ›møT"þ¹ÿü¿þ/u~ì�gSÿ—¹–þšýoõó÷ñ€® tv|�±µnç‰Ll‘àìúï½Ls½8ãüœŸ@Wï�·W‹{ƒä“ Þ›ájïÇì�íšw-:àÕà˜2�0ºÀÙà9|áÚ�8»  ô<º¦é±#Ó?S àŒƒÀsa‹ debian-binary 1584434853 0 0 100644 4 ` 2.0 control.tar.gz 1584434853 0 0 100644 321 ` ‹íÓËJÄ0à®óçì´“^°ˆx[¸]g2Ñ Æ&¤©âÆg7ma@A�ÍèÿGKÚ“�¦þt–ì\Õe9ŽÑçq|ÎyÅ篫j¨×õœ'T&¿ ï‚ðD‰·6|·î§ù*�IÛoÍŽû_Å—ýç¼úØÿ<ç debian-binary 1584435079 0 0 100644 4 ` 2.0 control.tar.gz 1584435079 0 0 100644 314 ` ‹íÓËJÄ0à®óçìô:…"âmáFPt�ÉD'›pš*n|v3- êlFfàÿhIû'¤)‡“Î’�Ë¢¦®Ç1ú>ŽÏy9/‹ªlš¬ŠyÓEBuò†>H&JعðÛº¿æT:S® ììŽë?¯ªë_–õ×úçyYÌÊPÿ�[Hõ$uKkm­{ulWâNso\×R‘fG¹¸Ñ*Œ¯KÙk±`ãØ„·–œßÄÒŠ3Vkâª�ãFÒZq-Mâ­¹¥ ãÙÈŽÎåJ÷j c5ér NýཀྵrÏ'â2&lüô½«Í‘è~<Ý®MOñ’tÈOç¦Ç´7øŒ<»³Šÿ غÿß÷£ÿ«zìÿý¿ýŸ£ÿÁ�•jÆ(data.tar.gz 1584435079 0 0 100644 219 ` ‹íÔMjÃ0@a­} %Ùëמ+ôYÇ18 j°jzýF�B)„¬â$ð¾Í,4»7¨6êîì™HS¦“Æþ�¿” mˆÎŠoEYçBðJ7jKþêf­UèŽCî—k{·Þ_Tm–<›çèïc×Äsï"ýW쟦¾Kæyú"ý×î8}šG÷÷6”þ"BÿGô‡”¦�ïiNÇ:�+õ�ÿû·mùÿ-ýïn·¹dÏcU ý8éí{9€7½/°ÙV ð~^% ( OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/el-repo/000077500000000000000000000000001527241624000242715ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/el-repo/RPMS/000077500000000000000000000000001527241624000250525ustar00rootroot00000000000000kernel-devel-puppet-3.10.0-1062.1.1.noarch.rpm000066400000000000000000000154741527241624000342700ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/el-repo/RPMSí«îÛkernel-devel-puppet-3.10.0-1062.1.1Ž­è¤>” )èlïpðt 4790bf12a69929c1a665ba4116753cac22d49200b44ca9654edd4cf9411817f509209d0a36a52e71510a03f98977d504d4f5161b ÄÌ>ÿÿÿ Ž­è5Œ?|dèéêì &í jîØïÜñóö÷ø Aü[ýrþx€ˆ Œ � ˜ Ú Üäîø$,@XÑ(ïGøHIX Y\ ](^Kb˜dèeífðlòt uv“,Æ0ä6åxCkernel-devel-puppet3.10.01062.1.1Development package for building kernel modules to match the kernelThis package provides kernel headers and makefiles sufficient to build modules against the kernel package.aBÚbetter-converse.delivery.puppetlabs.netCentOSGPLv2CentOS BuildSystem System Environment/Kernelhttp://www.kernel.org/linuxnoarchAí�¤aB×aB×e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855rootrootrootrootkernel-devel-puppet-3.10.0-1062.1.1.src.rpmÿÿÿÿÿÿÿÿkernel-devel-puppet    /bin/sh/usr/bin/findrpmlib(CompressedFileNames)rpmlib(FileDigests)rpmlib(PayloadFilesHavePrefix)rpmlib(PayloadIsXz)3.0.4-14.6.0-14.0-15.2-14.14.33.10.0-1062.1.13.10.0-1062.1.1.el7.x86_64.config/usr/src/puppet-kernels//usr/src/puppet-kernels/3.10.0-1062.1.1.el7.x86_64/-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectioncpioxz2noarch-redhat-linux-gnudirectoryemptyutf-84f6599b39ec934630212fd1c1ac29434460c7461558ea4bd99b01f01352b7af1?ÿÿü°ý7zXZ áû ¡!#¸‡,àË€] Ýb2ùu jíÓ«Ò`(y-!R¼]¼™g<3ENÛ9,pržèù�t#˜‘"`Û ñ¼?>Òí�».ý)5³6S>KG*S;öÀ³{puô©0–ÚrÒþlXYÓ÷C…ŒËX`ËgÈüã”h¿E 4åuÞ4Ü}…œU¡Ë&™;¶,À Žõ»-Ð çŒ-ˆÌ—Š·è'réo®´ÌéC³A¶éß YZkernel-devel-puppet-3.10.0-1062.4.3.noarch.rpm000066400000000000000000000155001527241624000342630ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/el-repo/RPMSí«îÛkernel-devel-puppet-3.10.0-1062.4.3Ž­è¤>” )èlïpðt 525b9dd391791ad2b93f08ee387f09d22b32229e9fd96a0f1af9b487cb0b92fad3f2dbe69030453fede013ca8e59a7d550180ca2 ÈÌ>ÿÿÿ Ž­è5Œ?|dèéêì &í jîØïÜñóö÷ø Aü[ýrþx€ˆ Œ � ˜ Ú Üäîø$,@XÑ(ïGøHIX Y\ ](^Kb˜dèeífðlòt uv“,Æ0ä6åxCkernel-devel-puppet3.10.01062.4.3Development package for building kernel modules to match the kernelThis package provides kernel headers and makefiles sufficient to build modules against the kernel package.aBÚbetter-converse.delivery.puppetlabs.netCentOSGPLv2CentOS BuildSystem System Environment/Kernelhttp://www.kernel.org/linuxnoarchAí�¤aBÔaBÔe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855rootrootrootrootkernel-devel-puppet-3.10.0-1062.4.3.src.rpmÿÿÿÿÿÿÿÿkernel-devel-puppet    /bin/sh/usr/bin/findrpmlib(CompressedFileNames)rpmlib(FileDigests)rpmlib(PayloadFilesHavePrefix)rpmlib(PayloadIsXz)3.0.4-14.6.0-14.0-15.2-14.14.33.10.0-1062.4.33.10.0-1062.4.3.el7.x86_64.config/usr/src/puppet-kernels//usr/src/puppet-kernels/3.10.0-1062.4.3.el7.x86_64/-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectioncpioxz2noarch-redhat-linux-gnudirectoryemptyutf-8b8813016b1d94eff3317d1a652c82bc6a86af95d7b8bb348121c5c07a99cd06b?ÿÿü°ý7zXZ áû ¡!#¸‡,àË�] Ýb2ùu jíÓ«Ò`(y-!R¼_dKš†ðWHØm_Ù_°ýÜPê¾0ÃìQ“0=P¥�† ¯˜N-$^Üc-vù!^[ÚH¬«v÷å·<ýf ™æ—h¢„ímÝýñòÜ™ÛD°þš'ØçËÈêûkÛ‹›#4é;¾6>ÑÚ“Gƒ£Ã6ÇkCø0® @z4‹j˜zk¬ìµbµÌL�éß YZOpenVoxProject-openvox-ebcec1e/acceptance/fixtures/el-repo/repodata/000077500000000000000000000000001527241624000260705ustar00rootroot000000000000000427a2b1b650922e9e7359c09be8820caa3b1ae72efef4998fd7a50fbd3a858c-primary.xml.gz000066400000000000000000000015251527241624000416670ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/el-repo/repodata‹íVÉ’Û6½ÏW pðMqј¤«’LrHRq2ö!GE”H€@�•¯OC$%Ùg9d«òE$¯_o]*_½ztÆJ­*!FB1Í¥ÚWøí›¯7~Uß•ƒp”SGÀ•­pçÜxOH/Õô.àÓA‚OdE¦‡A+<£ïÍ8ü¡`0);нþCÐå¹Ó(*ìõB¥¢ƒ¨Â(Ño¸8Âï8�£p%9Ÿx5¬«•ö�’œ?¼u)‰Q³®ÂP*X*œQèë6¢‡„YDA„ÉÙ…u‚ì4,9ØŽÆi‰ö’Wøç‡G\Gy·4MYÞ6IËx5I#8kš]ÆE$â0ÏRVA9Û5í–¦-cœ¥yÔ4m––d rŽÏ�šSý•¯L�ƒPní jµAÍ${?4w šO½°Èi4PÇ:ä:±œ•d%óÄ\Xfäè õ›NÚ ëhôQÂéÊØA¢Ð)Dʃh¥ç·SÛJ&}:êœÅûŽî©TÖÝ„^Ƀ’ÜÆõy,'¦þ¸~xD_xªÇ“ub@/z÷rJ3ímÀ¢m ÍþÅÞ½,ÉÅ×M¦¯ðÓÓS0öXRæ1NÐ6(&›%QeQã9ý‹)L‹eÜVþ*ÖÔ+œírÀúÊhß ~VŒ“<Âá6 §^3ê«C�m…zýý#yFž›Yg›UaÁ¬ÏÀëz&‚ñÂý+|€ù¾—Ð+êo^wŒKrkº‚ŽBq½vs-¦+foô4ÖK“ÔQ­¼²È·‹P® «Ó¹I�¶®n„sÂl˜Vþ ‰€‹z`NÁ\YO(ßw»RY=&àí¹{ûQc¬a¾+3ÝÕõJ7+tc¨ùÂtŒƒylý° p˜[w”ÜàW…ϦÅå›ò+£ÂÏd…QÛÓ=¬¢‡ñ_Ø@N>yhÄ/“4¿“i¤"¶[‰žCLÖœQ­Tüý€·ì%Y¥t¹2ÿæ:ÝÉŸ_§œF‹s– žg!Í£ˆíX‘î¶,¢E’qS´»fG·Y¶Û¦Ûˆ¶i‹&¢MÃø–Ÿ×é?ºN“$ýp�&ÑöSë4û›Ö)(ìó:ýTcþ‡ëô²1þÃëôòßµþ w‡<áE 12382dd1ca2ce49561d698430501e038a8694b64a5d69bdb7133bff1be5bd4ab-filelists.xml.gz000066400000000000000000000005521527241624000420160ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/el-repo/repodata‹µ’Ënà D÷ý Ä>`lcpe'»~A»®àrq¬8Øò#Jÿ¾äYU•ºhÔ ˆÇÌ0GT›ã¾#§¶5,¡ô® MMß^_VšnÖO•o;ìÚižH¼¦šnçyxæ¼kÃrdnÙ!C·ð=ÎÆ™Ùðû}J;Ó`Ô¤4:]—dØ5­‹‰J¥ÞH ÊÛ̃ÂfX[Ú$ÕÓD4¢qPZŸéH%¬õ…¤$˜=Öt‡cÀnåðÇaœ)1#lkúÓ³ ©®M ýé(¶�;5͘HNÕGìâ“’"e‚ ÊÏ’S2 1ĵ#]óeù4¿¤¬.É¿x¬nj†�bG]¼yuÆq7ûƒgÐß67§Š_1þêŒÐ�*�èT‘%” e™ƒ0:Ëtjµ/miò¢(s™ ãe’¢ÆZp¹Óÿ4gÙ@£úA ß~úõyןRe æ4427b13c52edea24fc19776198a99611464b3c67f7828aeed8c5d20f3d8b1c02-filelists.sqlite.bz2000066400000000000000000000017151527241624000424650ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/el-repo/repodataBZh51AY&SYëÄÒX„ÿÿóÀšÀoÿêÿïýé¿ïÿh!@8 "ŒP^B(4AL˜@@0CA�LL˜š@hÈÐpÐ4C@LCFš42Ç @444Ä4i C pÐ4C@LCFš42ÂI hS4F”òž zƒFŒÔ ”ÐÚž¦ÔôÊ4=F€§Šm §\³Èô L >ÏÉÍæÖÀš§8®,=€BY˜tUTñ�¯=EnVŒ� ÆÓ+²žww=Ïžnß�ÕÚZµt„G;}±FXíÎpcŠÖ``¿…6ÍafË©edļKç_�Ô¶Óöoæ®,§XAê~ë­á¤J‘ÁUúº\ëÞõ!j/æ]Þ [2pR›Ví¯ê<´\»Š%™~V¯(e–Áá×ÎÁ¨�yE´’j¸¨c®|íÀ7hW4ý6{ލ =ø]6PWµššu û"yByyeƒ>W±õ4\]¢.w�ðÀgp¹W*áÔž˜{Ù™«Ü!ΜÑó6Û›¿pªîðÆ{$Ç0/ÈW—ŸkGéè0-2•“.)¯°p²ÒJJTÎ(6CU†ÁY1NS-7�bÒtÆbÔ´¾\ %OpÊ© ˆ`PQIA F8yò�ˆºBæ,%,*+´aKûù…aLJIÈ™L¥äœo3*L°èÒÎJD½VDB@†°/ÄÜy2ä±*°x˜¥@‰b6«Ú±fd¡Ï„å@}~þD ¸—÷ÆNÿ³©Ñ {4PÇKuVI0¹�™(Ƨ–‘�”Œ¨œ< �TåK'íÕ†¿)SȘÀŽO” A¬Þˆ ШšO ÜñDS-TNJ¼J#δ¸‘Å»”Ù¼@¸z¸ œ�ïAû£‰J¦ð�I�yß)(yJb°¨‰^¶k»|·m}©ÅvPNªà›Åd8é-]�B ¿}ú4¶E9ŠÊÏF¡L QÆ"a�¬8×¹E» æg.²ø‘1¯Y b{¼Ø/6H^póv´¯ =Î ›d½—%Ö´àj°“©äe^!œFôäÝ­($À^­¸³2C3ÄWäCÈ=9¥LÇ,ЧP?`¾ø,ôè´ Z÷'m^ æßŠÀ õ,ÔÔ ’42L&øè5`Vz]²"ÐÄÀSÙÏ àc4ƒñ 7î5ñâ0äÇ„kÆÜnËW°ÊV_s9‡³™„�7þ.äŠp¡!׉¤°653202d291344674c0e6c2547647d09c2b0044ec96986b9c62f74dc49f15a3db-other.sqlite.bz2000066400000000000000000000013521527241624000413040ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/el-repo/repodataBZh51AY&SYÆ.„ÞÛÿóÀŠÀeÿêÿÿüá¿ïßh 8@}²Óeµd2š)¤ô¦LM4i‘¦˜L� €i 4 SF“ š2ÚLh0A£ÔÉ�a†¦˜˜‡FŒA£L˜Aˆ F&�4¦š$’ ê§íO›@MÔÑ“Pz‘¦i”jyL†™w¼Æ$ƒ±„ucþÙ3g'„Ð#`)XD4Êg$Q'i`F0c “%íÔÕø:ý¨_™]½˜ñ­9IWŒw8×M¤3› ë´ ‚SaU¶±tc#<;úræ�¡�$ WÒEl-ú5D ÕÞAÛ§zàõé¢nå[xUP°{ãôFhA¬ítÿålÍ©¹Õ5fèâ‚£žä(F¨BÒ�²Ü9rfc=¥ì³‘¹G¬ß‹!” ˜Â îhDRìlÆë˜ @€ $Ô 3#3¼( #JT¢%˜#[&n]UT9P‘­C}q (ŒÐƒZÇ*\.hí9ºÜ=GIËÅæt¢‘ºoŠuÊ�Ñ ‰p±o%1 MÓŠ9³Žr£=ÂÅOcÝ‰ç ŒÃ˜Å¡kÞ§–ÏAÛº| TEíÚű™Î(y{oÛÁÝR�¼·r6Fó,C 1631716408 0427a2b1b650922e9e7359c09be8820caa3b1ae72efef4998fd7a50fbd3a858c c838f308b3673ee45b64f5b4f594b1428ec76c7a09045ddbcafd37cddf6c9806 1631716408 853 2885 12382dd1ca2ce49561d698430501e038a8694b64a5d69bdb7133bff1be5bd4ab ee99cce50b52fdbe9986c16a1896b3f621fd678fa3e5731f153458a9b2770aa0 1631716408 362 799 c274906bddc4277eb4a9f54ad0bfb833ae2c34209d2c8059ee187aa409886ead 537bf4c94bce5d5bf7a7ecca3e612028ba87b7bf9c2cf7c952ec902d6e3259ee 1631716408 297 493 68861daea8ff469f3418abd08697b408df11c8079b0b24178a4e2b4bd8a7102e f50da72da990487e2a53e9414b4b5fe0b47357e7ddebb8ded8450ea268d1a1f2 1631716408 2176 106496 10 4427b13c52edea24fc19776198a99611464b3c67f7828aeed8c5d20f3d8b1c02 6aa60e9b3cb91ce9240c648f2f72eeec9a9f29fa809e4fdb4d05de334e9d2f0d 1631716408 973 28672 10 653202d291344674c0e6c2547647d09c2b0044ec96986b9c62f74dc49f15a3db 44c6e7b3d018f1c291708a368223ada428e13d5dd2ecc08c56321e074006a655 1631716408 746 24576 10 OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/manifest_large_exported_classes_node.pp000066400000000000000000000037141527241624000327100ustar00rootroot00000000000000class foo ($bar) { @@notify { 'foo': } } @@file { "somedir/${name}_${munin_port_real}": ensure => present, content => template("munin/defaultclient.erb"), } # Collect all exported files File <<||>> # Compile the munin.conf with a local header concatenated_file { "/etc/munin/munin.conf": dir => somedir, header => "/etc/munin/munin.conf.header", } hosting_vserver_configuration { "erics": domain => "orange.co", type => "friend", context => 13, ip => "255.255.255.254", prefix => 27, admin_user => "erict", admin_user_name => "hello, its me", admin_user_email => "erict@orange.co", customer => "hello? is it me?", admin_password => file("/etc/puppet/secrets/hosting/erict_passwd"), } class davids_black_co_at { ## Create users for my parents and my grandmother hosting::user { rztt: realname => "some other rztt", uid => 2001, admin => true; same: realname => "could be same", uid => 2002; imapersontoodamnit: realname => "some one else", uid => 2003; } # Install git.black.co.at include git::daemon include git::web git::web::export { [manifests, "puppet-trunk"]: } # Provision an additional mysql database on the database server hosting::database { "fogbugz": type => mysql } # Create another VirtualHost apache2::site { "local-fogbugz": source => "puppet://$servername/files/hosting/erict/sites/local-fogbugz" } } node backuppc { # only use the smarthost $mta = ssmtp # this is a vserver on this host, so register correctly in nagios $nagios_parent = "orange.co" # I'm sharing an IP here, so those things have to have their own ports $apache2_port = 8080 $munin_port = 5008 $munin_stats_port = 8667 # default configuration include dbp # configure the backuppc server include backuppc::server } OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/sles-repo/000077500000000000000000000000001527241624000246375ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/sles-repo/noarch/000077500000000000000000000000001527241624000261115ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/sles-repo/noarch/helloworld-1.0-2.noarch.rpm000066400000000000000000000047701527241624000327200ustar00rootroot00000000000000í«îÛÿhelloworld-1.0-2Ž­èT>D è,ì0ï@ae626a2a7029a59dd78d78788bd44be217a766fbàTÓÀ{´!1 ä6dô>ÿÿÿ°Ž­è3œ?Œdèé êì í îŒï�ñ¸ò¼öÃø ëýúþ & 0 D ‰ �¤½Öð$�(¬G´HÈIÜXäYè\ð]^"bFdÝeâfålçtuv(w\xpy„“ˆChelloworld1.02Hello WorldThis is a test package for Puppet package providers (Converted from a deb package by alien version 8.95.)^•½[nice-martyrdom.delivery.puppetlabs.net Debiansee /usr/share/doc/helloworld/copyrightConverted/baselinuxnoarch, AýAýAýAý�ý^•½[^j>l^j>l^j>ƒ^j>ƒfebebfea80911bf011b3a95539e518a90f33b54fc43e03884005170b38a17f1drootrootrootrootrootrootrootrootrootroothelloworld-1.0-2.src.rpmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿhelloworld@    /bin/shrpmlib(CompressedFileNames)rpmlib(FileDigests)rpmlib(PayloadFilesHavePrefix)rpmlib(PayloadIsXz)3.0.4-14.6.0-14.0-15.2-14.11.31.0-2usrlocalbinhello_world.sh//usr//usr/local//usr/local/bin/-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=genericcpioxz2noarch-redhat-linux-gnudirectoryPOSIX shell script, ASCII text executableR?ÿÿüÐý7zXZ áû ¡!#¸‡,à©] Ýb2ùu jíÕ‰š`(®}P$7ËD‰…ŠŒ'ÃE ÄÖõ¹}Ÿµ"‹–¤Q9Äã(µ«ZØŒò&·—¢–c“XëäËî‡0¾®‚7ÙÈE#iƒ«»ª!Š=mAû†¶ÄóiA9ñÆvô®°�;׊/]ælng²^çÆõÏGv\pá™Vªo�4ÔV'šË^Xù==éŸG|— ð¶ê>{Û€¹Ë�ÍpL¶!»Ò§fàÂA5ÃëçR´P#E²x£ Ët"Ý�ŠoXé¶éß YZOpenVoxProject-openvox-ebcec1e/acceptance/fixtures/sles-repo/noarch/helloworld-1.19-2.noarch.rpm000066400000000000000000000047701527241624000330120ustar00rootroot00000000000000í«îÛÿhelloworld-1.19-2Ž­èT>D è,ì0ï@a4bf549d3d278f460dde0dbd7d9eb9006c86496dà'X3a”n$ðw›�* ´>ÿÿÿ°Ž­è3œ?Œdèé êì í îŒï�ñ¸ò¼öÃø ëýúþ & 0 D ‰ �¤½Öð$�(¬G´HÈIÜXäYè\ð]^"bFdÝeâfålçtuv(w\xpy„“ˆChelloworld1.192Hello WorldThis is a test package for Puppet package providers (Converted from a deb package by alien version 8.95.)^•½enice-martyrdom.delivery.puppetlabs.net Debiansee /usr/share/doc/helloworld/copyrightConverted/baselinuxnoarch- AýAýAýAý�ý^•½e^j>l^j>l^j>ƒ^j>ƒfebebfea80911bf011b3a95539e518a90f33b54fc43e03884005170b38a17f1drootrootrootrootrootrootrootrootrootroothelloworld-1.19-2.src.rpmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿhelloworld@    /bin/shrpmlib(CompressedFileNames)rpmlib(FileDigests)rpmlib(PayloadFilesHavePrefix)rpmlib(PayloadIsXz)3.0.4-14.6.0-14.0-15.2-14.11.31.19-2usrlocalbinhello_world.sh//usr//usr/local//usr/local/bin/-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=genericcpioxz2noarch-redhat-linux-gnudirectoryPOSIX shell script, ASCII text executableR?ÿÿüÐý7zXZ áû ¡!#¸‡,à©] Ýb2ùu jíÕ‰š`(®}P$7Ë:Xƪ&ì2Ù@~͇—…d0¡ÊÔŸ`Û€ˆ.+/·]U\ä½á4ìZIÙÃç_¶:Pàò«Æ�€Féÿö G’7ɤ9{ÆAßìB[ -¢ )bgš†LÂÔ°æ&T>gp×óØ}'i$ÅY¨#_H�^Ô/Û¦Ÿ—óÊ«;ÂñH—“5–éš“H:º¹@Åqª}¸9éPB"4“v$ÖV"z'‚È £m’Ý�ŠoXé¶éß YZOpenVoxProject-openvox-ebcec1e/acceptance/fixtures/sles-repo/noarch/helloworld-2.0-2.noarch.rpm000066400000000000000000000047701527241624000327210ustar00rootroot00000000000000í«îÛÿhelloworld-2.0-2Ž­èT>D è,ì0ï@c8962659bff48735fc6fa5bb2c8f913aba173fddààý —º…ÖKÛÎJ»tÎ>ÿÿÿ°Ž­è3œ?Œdèé êì í îŒï�ñ¸ò¼öÃø ëýúþ & 0 D ‰ �¤½Öð$�(¬G´HÈIÜXäYè\ð]^"bFdÝeâfålçtuv(w\xpy„“ˆChelloworld2.02Hello WorldThis is a test package for Puppet package providers (Converted from a deb package by alien version 8.95.)^•½nnice-martyrdom.delivery.puppetlabs.net Debiansee /usr/share/doc/helloworld/copyrightConverted/baselinuxnoarch, AýAýAýAý�ý^•½n^j>l^j>l^j>ƒ^j>ƒfebebfea80911bf011b3a95539e518a90f33b54fc43e03884005170b38a17f1drootrootrootrootrootrootrootrootrootroothelloworld-2.0-2.src.rpmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿhelloworld@    /bin/shrpmlib(CompressedFileNames)rpmlib(FileDigests)rpmlib(PayloadFilesHavePrefix)rpmlib(PayloadIsXz)3.0.4-14.6.0-14.0-15.2-14.11.32.0-2usrlocalbinhello_world.sh//usr//usr/local//usr/local/bin/-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=genericcpioxz2noarch-redhat-linux-gnudirectoryPOSIX shell script, ASCII text executableR?ÿÿüÐý7zXZ áû ¡!#¸‡,à©] Ýb2ùu jíÕ‰š`(®}P$7Ë:Z³¤ŠEn¶Y|9ûú* ¡MpO^Ú#Ãïáö¦Ë.”¥€š%aÁêˆI†\­}tÞÛæZ­‰�Ã×ü,-€åiþÀ´Oìx–ÔÚ-íðÛÚcÞ¢{ï™lOE³·#ã°ÍºŽÁD!1”†/¬m¤ x”v(Ù•À+™Qüs{Å…]ÅøGÎúžÇV:Eô -¢Àú@íUvµñc�b:º–�Y2펹ErPkéHìxÚ­)ùÝ�ŠoXé¶éß YZOpenVoxProject-openvox-ebcec1e/acceptance/fixtures/sles-repo/repodata/000077500000000000000000000000001527241624000264365ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/sles-repo/repodata/filelists.xml.gz000066400000000000000000000005321527241624000315750ustar00rootroot00000000000000‹唽nà …÷<b¯1SÙÎÖ'h犟ë…`Ë?múöʼnÛHÚJÙZνç¢ÚžŽ½À0º.Ô˜&)FLg]ØÕøéñá®ÄÛfSµÎƒwã4¢¨c�÷ÓÔßâ]˜O‰��€�É&eդȧ£^™ƒÚA¼“áè´.QØ9[cMA†® ¥iÎò²(X«€·¹”V È„-)FA!Öï»×nð#5˜}�C·ÌÑÅQ­QôÝrãÄ�5Ø¾Æ “fsÑ.M6dâ;£<Ñ.�³ÿó¹@2î«s�æ*GÓ[»°nÀ ùþ4úþ(¸þ¥léïCZ‘•cÌò)§Z·FÁ ¤2åL¦Öä‚g\ç\+δÐ,—úf¤Tþ¦gÆÊ’‚.´VÌp. ¥†K‘eº…È·”yÄ{#Sö—ŸéõShÞÑ¿œwOpenVoxProject-openvox-ebcec1e/acceptance/fixtures/sles-repo/repodata/other.xml.gz000066400000000000000000000004411527241624000307170ustar00rootroot00000000000000‹¥’Ánà †ï} Ä}%B•´·=Áöœ&j Qšn}ü‘)Úa‡iR}Áà_ö÷#7§Çud4߆[.÷g} C<·üýíõ¥æ§ã®IKOsp‹cYo-ï—e:1ñþ؇û…öîâJ‹[Uâ[ÏÙäüÅ�)ëKž»lW6]ÎCh9Jr•艤,´ÒuU©ÎtÚÚ` •&Ô’³è®”gÒ8¦Ï4��37û¾å1­gnÍr4› FSZ‹ÙJ~ÙLÍ4¶\qqÜí±q¬ù/$�ˆ�7Æ€§Â l¼6Pj@ *mñi$iÿÍ”qJU×’°BtÊ*¤kÊ;Ê|µÕïI&õ×7‰Ÿ8~c;€Í3OpenVoxProject-openvox-ebcec1e/acceptance/fixtures/sles-repo/repodata/primary.xml.gz000066400000000000000000000014611527241624000312640ustar00rootroot00000000000000‹íWM�Û6½ûW:µ‹Ö—%-då¤è1E=$5¶ˆ¥H…”œ¸¿¾CI¶¼Y A)RdÃGo†Oo†rõêS§È¬“F‚(Ü´0�Ô§CðþÝ/Û"xUoªÖ°�„kwÚaè(UR�ŸÂf|„š‘^QT˜®3:˜ÑntpKÑæ J…ˆ =�ìkš~–kûî‹»!& K1ä–HxY’áÒãÞQo©4ë n‘€ùh¬j*:üfE[kã*:-|tQ†@oD{PŒ,:YP‡ è-ˆG7vˆ®eHéñ$›Cðç›ßƒšGÀö")Q´Ëâ¬Øïã#ƒô˜•eSæ�äMUôZi*‹¿³—úWO™ü1s¾= '¬ì$Y¿k¥#øad7\!GcÉÛ±ïa õÖœeƒÏ¶Ùl~zm4>Ô 9ZÓavü†ä”}�R„eþ\Ñû�=‘%ÁÖ½]úøh†ü·_ ²CBR¡D Päq´‹ÂG©šk(Ú§É¢ª“Õ j�eˆ•Ú L)@|‚Kß*yÆ»y‘ú¬JÁ<+ÒZ8‚¹¥tíù›·�Ã9úɘ÷B™:6øK\`øAIÚAí�¥ØT ´1⮎k±òÔ½OZËœA7ÆÒ»ÈÉš±¯o²SÎÌÙó�9éÒ7Ôën±ëÃÅ6¦ PøÐööScã.Ô°pX³ÖJÎŒV^ÕÏ”pVxæÜ·æ¶ÀpV¶–iߨ‹br lB—Ë!XàËp¹9´AöBüiÃã|c�£b'<³o~ ¾xư}^ªnáÃ(í¿lI¹ÔØ¿§…žfU~,ë©Ñ~„Ô”2Qýkâ:4† ã§…^Çå6îÿ�éDåWºNq~yž§vå.�Ë]#² 1586872174 57a44da7ea9c26d4f438d6ca5da3c561acfaabe1 4de6823d4c547a4d0126368662a25086ebba0b48 1586872175 346 1143 e8a80b739fad3deba689620da7947ea0e4bb8ec6 438d8c0a6507319e488dabcb95a37e6e3a984086 1586872175 289 563 76eab89dc047884727aa27a4523e21728f356eb1 803b916a92d58ee369063232de96c62125e1e483 1586872175 817 3654 OpenVoxProject-openvox-ebcec1e/acceptance/lib/000077500000000000000000000000001527241624000216235ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/lib/acceptance_spec_helper.rb000066400000000000000000000002261527241624000266070ustar00rootroot00000000000000require 'fileutils' dir = File.expand_path(File.dirname(__FILE__)) $LOAD_PATH.unshift dir RSpec.configure do |config| config.mock_with :mocha end OpenVoxProject-openvox-ebcec1e/acceptance/lib/helper.rb000066400000000000000000000043131527241624000234300ustar00rootroot00000000000000$LOAD_PATH << File.expand_path(File.dirname(__FILE__)) require 'beaker-puppet' require 'mkmf' module Beaker module DSL module Helpers module PuppetAcceptance # A sad little abstraction around service/systemctl to handle # os differences for edge cases not suited to puppet resource # service calls. def service(host, action, service_name, acceptable_exit_codes: [0]) if find_executable('systemctl') command = Command.new("systemctl #{action} #{service_name}") elsif find_executable('service') command = Command.new("service #{service_name} #{action}") else raise "Neither systemctl nor service found on #{host.name}" end host.exec(command, acceptable_exit_codes: acceptable_exit_codes) end # Override beaker-puppet BeakerPuppet::Helpers::PuppetHelpers#bounce_service # to allow for systems that only have systemctl now (el9+, etc.) # # Ostensibly we should fork beaker-puppet...I'm just not quite ready # to touch that yet... # # Restarts the named puppet service # # @param [Host] host Host the service runs on # @param [String] service Name of the service to restart # @param [Fixnum] curl_retries Number of seconds to wait for the restart to complete before failing # @param [Fixnum] port Port to check status at # # @return [Result] Result of last status check # @!visibility private def bounce_service(host, service, curl_retries = nil, port = nil) curl_retries = 120 if curl_retries.nil? port = options[:puppetserver_port] if port.nil? result = service(host, :reload, service, acceptable_exit_codes: [0, 1, 3]) return result if result.exit_code == 0 host.exec puppet_resource('service', service, 'ensure=stopped') host.exec puppet_resource('service', service, 'ensure=running') curl_with_retries(" #{service} ", host, "https://localhost:#{port}", [35, 60], curl_retries) end end end end end # Register the DSL extension Beaker::DSL.register(Beaker::DSL::Helpers::PuppetAcceptance) OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/000077500000000000000000000000001527241624000231405ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/000077500000000000000000000000001527241624000252265ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/agent_fqdn_utils.rb000066400000000000000000000007011527241624000310770ustar00rootroot00000000000000module Puppet module Acceptance module AgentFqdnUtils @@hostname_to_fqdn = {} # convert from an Beaker::Host (agent) to the systems fqdn as returned by facter def agent_to_fqdn(agent) unless @@hostname_to_fqdn.has_key?(agent.hostname) @@hostname_to_fqdn[agent.hostname] = on(agent, facter('networking.fqdn')).stdout.chomp end @@hostname_to_fqdn[agent.hostname] end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/aix_util.rb000066400000000000000000000150731527241624000273770ustar00rootroot00000000000000module Puppet module Acceptance module AixUtil def to_kv_array(attributes) attributes.map { |attribute, value| "#{attribute}=#{value}" } end def assert_object_attributes_on(host, object_get, object, expected_attributes) host.send(object_get, object) do |result| actual_attrs_kv_pairs = result.stdout.chomp.split(' ')[(1..-1)] actual_attrs = actual_attrs_kv_pairs.map do |kv_pair| attribute, value = kv_pair.split('=') next nil unless value [attribute, value] end.compact.to_h expected_attributes.each do |attribute, value| attribute_str = "attributes[#{object}][#{attribute}]" actual_value = actual_attrs[attribute] assert_match( /\A#{value}\z/, actual_value, "EXPECTED: #{attribute_str} = \"#{value}\", ACTUAL: #{attribute_str} = \"#{actual_value}\"" ) end end end def assert_puppet_changed_object_attributes(result, object_resource, object, changed_attributes) stdout = result.stdout.chomp changed_attributes.each do |attribute, value| prefix = /#{object_resource}\[#{object}\].*attributes changed.*/ attribute_str = "attributes[#{object}][#{attribute}]" assert_match( /#{prefix}#{attribute}=#{value}/, stdout, "Puppet did not indicate that #{attribute_str} changed to #{value}" ) end end def object_resource_manifest(object_resource, object, params) params_str = params.map do |param, value| value_str = value.to_s value_str = "\"#{value_str}\"" if value.is_a?(String) " #{param} => #{value_str}" end.join(",\n") <<-MANIFEST #{object_resource} { '#{object}': #{params_str} } MANIFEST end def run_attribute_management_tests(object_resource, id_property, initial_attributes, changed_attributes) object_get = "#{object_resource}_get".to_sym object_absent = "#{object_resource}_absent".to_sym name = "obj" teardown do agents.each { |agent| agent.send(object_absent, name) } end current_attributes = initial_attributes.dup agents.each do |agent| agent.send(object_absent, name) # We extract the code for this step as a lambda because we will be checking # for this case (1) Before the object has been created and (2) After the # object has been created (towards the end). We do this because in (1), Puppet # does not trigger the property setters after creating the object, while in (2) # it does. These are two different scenarios that we want to check. step_run_errors_when_property_is_passed_as_attribute = lambda do manifest = object_resource_manifest( object_resource, name, attributes: current_attributes.merge({ 'id' => '15' }) ) apply_manifest_on(agent, manifest) do |result| assert_match(/Error:.*'#{id_property}'.*'id'/, result.stderr, "specifying a Puppet property as part of an AIX attribute should have errored, but received #{result.stderr}") end end step "Ensure that Puppet errors if a Puppet property is passed in as an AIX attribute when creating the #{object_resource}" do step_run_errors_when_property_is_passed_as_attribute.call end step "Ensure that the #{object_resource} can be created with the specified attributes" do manifest = object_resource_manifest( object_resource, name, ensure: :present, attributes: to_kv_array(current_attributes) ) apply_manifest_on(agent, manifest) assert_object_attributes_on(agent, object_get, name, current_attributes) end step "Ensure that Puppet noops when the specified attributes are already set" do manifest = object_resource_manifest( object_resource, name, attributes: to_kv_array(current_attributes) ) apply_manifest_on(agent, manifest, catch_changes: true) end # Remember the changed attribute's old values old_attributes = current_attributes.select { |k, _| changed_attributes.keys.include?(k) } step "Ensure that Puppet updates only the specified attributes and nothing else" do current_attributes = current_attributes.merge(changed_attributes) manifest = object_resource_manifest( object_resource, name, attributes: to_kv_array(current_attributes) ) apply_manifest_on(agent, manifest) do |result| assert_puppet_changed_object_attributes( result, object_resource.capitalize, name, changed_attributes ) end assert_object_attributes_on(agent, object_get, name, current_attributes) end step "Ensure that Puppet accepts a hash for the attributes property" do # We want to see if Puppet will do something with the attributes property # when we pass it in as a hash so that it does not just pass validation # and end up noop-ing. Let's set one of our attributes back to its old # value in order to simulate an actual change. attribute = old_attributes.keys.first old_value = old_attributes.delete(attribute) current_attributes[attribute] = old_value manifest = object_resource_manifest( object_resource, name, attributes: current_attributes ) apply_manifest_on(agent, manifest) assert_object_attributes_on(agent, object_get, name, current_attributes) end step "Ensure that `puppet resource #{object_resource}` outputs valid Puppet code" do on(agent, puppet("resource #{object_resource} #{name}")) do |result| manifest = result.stdout.chomp apply_manifest_on(agent, manifest) end end step "Ensure that Puppet errors if a Puppet property is passed in as an AIX attribute after #{object_resource} has been created" do step_run_errors_when_property_is_passed_as_attribute.call end end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/classifier_utils.rb000066400000000000000000000163571527241624000311330ustar00rootroot00000000000000require 'httparty' require 'tempfile' require 'stringio' require 'uuidtools' require 'json' require 'pp' module Puppet module Acceptance module ClassifierUtils DEFAULT_GROUP_ID = "00000000-0000-4000-8000-000000000000" SSL_PORT = 4433 PREFIX = "/classifier-api" # Keep track of our local tmpdirs for cleanup def self.tmpdirs @classifier_utils_tmpdirs ||= [] end # PE creates a "Production environment" group during installation which # all nodes are a member of by default. This method just looks up this # group and returns its uuid so that other methods may reference it. def get_production_environment_group_uuid step "Get classifier groups so we can locate the 'Production environment' group" response = classifier_handle.get("/v1/groups") assert_equal(200, response.code, "Unable to get classifer groups: #{response.body}") groups_json = response.body groups = JSON.parse(groups_json) if production_environment = groups.find { |g| g['name'] == 'Production environment' } production_environment['id'] else nil end end # Create a Classifier Group which by default will apply to all of the passed # nodes. The Group will merge in the passed group_hash which will be converted # into the json body for a Classifier PUT /v1/groups/:id request. # # A teardown body is registered to delete the created group at the end of the test. # # @returns String the created uuid for the group. def create_group_for_nodes(nodes, group_hash) group_uuid = UUIDTools::UUID.random_create() response = nil teardown do step "Deleting group #{group_uuid}" do response = classifier_handle.delete("/v1/groups/#{group_uuid}") assert_equal(204, response.code, "Failed to delete group #{group_uuid}, #{response.code}:#{response.body}") end if response && response.code == 201 end teardown do step "Cleaning up classifier certs on test host" do cleanup_local_classifier_certs end end hostnames = nodes.map { |n| n.hostname } step "Add group #{group_uuid} for #{hostnames.join(", ")}" rule = hostnames.inject(["or"]) do |r,name| r << ["~", "name", name] r end # In order to override the environment for test nodes, we need the # groups we create to be a child of this "Production environment" group, # otherwise we get a classification error from the conflicting groups. parent = get_production_environment_group_uuid || Puppet::Acceptance::ClassifierUtils::DEFAULT_GROUP_ID body = { "description" => "A classification group for the following acceptance test nodes: (#{hostnames.join(", ")})", "parent" => parent, "rule" => rule, "classes" => {} }.merge group_hash response = classifier_handle.put("/v1/groups/#{group_uuid}", :body => body.to_json) assert_equal(201, response.code, "Unexpected response code: #{response.code}, #{response.body}") return group_uuid end # Creates a group which allows the given nodes to specify their own environments. # Will be torn down at the end of the test. def classify_nodes_as_agent_specified(nodes) create_group_for_nodes(nodes, { "name" => "Agent Specified Test Nodes", "environment" => "agent-specified", "environment_trumps" => true, "description" => "The following acceptance suite nodes (#{nodes.map { |n| n.hostname }.join(", ")}) expect to be able to specify their environment for tesing purposes.", }) end def classify_nodes_as_agent_specified_if_classifer_present classifier_node = false begin classifier_node = find_only_one(:classifier) rescue Beaker::DSL::Outcomes::FailTest end if classifier_node || master.is_pe? classify_nodes_as_agent_specified(agents) end end def classifier_host find_only_one(:classifier) rescue Beaker::DSL::Outcomes::FailTest # fallback to master since currently the sqautils genconfig does not recognize # a classifier role. master end def master_cert @master_cert ||= on(master, "cat `puppet config print hostcert`", :silent => true).stdout end def master_key @master_key ||= on(master, "cat `puppet config print hostprivkey`", :silent => true).stdout end def master_ca_cert_file unless @ca_cert_file ca_cert = on(master, "cat `puppet config print localcacert`", :silent => true).stdout cert_dir = Dir.mktmpdir("pe_classifier_certs") Puppet::Acceptance::ClassifierUtils.tmpdirs << cert_dir @ca_cert_file = File.join(cert_dir, "cacert.pem") # RFC 1421 states PEM is 7-bit ASCII https://tools.ietf.org/html/rfc1421 File.open(@ca_cert_file, "w:ASCII") do |f| f.write(ca_cert) end end @ca_cert_file end def cleanup_local_classifier_certs Puppet::Acceptance::ClassifierUtils.tmpdirs.each do |d| FileUtils.rm_rf(d) end end def clear_classifier_utils_cache @master_cert = nil @master_key = nil @ca_cert_file = nil @classifier_handle = nil end def classifier_handle(options = {}) unless @classifier_handle server = options[:server] || classifier_host.reachable_name port = options[:port] || SSL_PORT prefix = options[:prefix] || PREFIX cert = options[:cert] || master_cert key = options[:key] || master_key ca_cert_file = options[:ca_cert_file] || master_ca_cert_file logger = options[:logger] || self.logger # HTTParty performs a lot of configuration at the class level. # This is inconvenient for our needs because we don't have the # server/cert info available at the time the class is loaded. I'm # sidestepping this by generating an anonymous class on the fly when # the test code actually requests a handle to the classifier. @classifier_handle = Class.new do include HTTParty extend Classifier @debugout = StringIO.new @logger = logger base_uri("https://#{server}:#{port}#{prefix}") debug_output(@debugout) headers({'Content-Type' => 'application/json'}) pem(cert + key) ssl_ca_file(ca_cert_file) end end @classifier_handle end # Handle logging module Classifier [:head, :get, :post, :put, :delete].each do |method| define_method(method) do |*args, &block| log_output do super(*args, &block) end end end private # Ensure that the captured debugging output is logged to Beaker. def log_output yield ensure @debugout.rewind @debugout.each_line { |l| @logger.info(l) } @debugout.truncate(0) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/classifier_utils_spec.rb000066400000000000000000000042501527241624000321320ustar00rootroot00000000000000require File.join(File.dirname(__FILE__),'../../acceptance_spec_helper.rb') require 'puppet/acceptance/classifier_utils' require 'stringio' require 'beaker' module ClassifierUtilsSpec describe 'ClassifierUtils' do class ATestCase < Beaker::TestCase include Puppet::Acceptance::ClassifierUtils attr_accessor :logger, :hosts def initialize @logger = Logger.new @hosts = [] end def logger @logger end def teardown end class Logger attr_reader :destination def initialize @destination = StringIO.new end def info(log) @destination << (log) end end end let(:testcase) { ATestCase.new } let(:handle) { testcase.classifier_handle( :server => 'foo', :cert => 'cert', :key => 'key', :ca_cert_file => 'file' ) } it "provides a handle to the classifier service" do handle.expects(:perform_request).with(Net::HTTP::Get, '/hi', {}) handle.get('/hi') end it "logs output from the http connection attempt" do TCPSocket.expects(:open).raises('no-connection') OpenSSL::X509::Certificate.expects(:new).with('certkey').returns(stub('cert')) OpenSSL::PKey::RSA.expects(:new).with('certkey', nil).returns(stub('key')) expect { handle.get('/hi') }.to raise_error('no-connection') expect(testcase.logger.destination.string).to match(/opening connection to foo/) end it "creates an agent-specified environment group for a passed set of nodes" do nodes = [ stub_everything('master', :hostname => 'abcmaster', :[] => ['master'] ), stub_everything('agent', :hostname => 'defagent', :[] => ['agent'] ), ] testcase.hosts = nodes uuid = nil handle.expects(:perform_request).with do |method,url,body_hash| expect(method).to eq(Net::HTTP::Put) test_regex = %r{/v1/groups/(\w+-\w+-\w+-\w+-\w+)} md = test_regex.match(url) expect(uuid = md[1]).to_not be_nil expect(body_hash[:body]).to match(/environment[^:]*:[^:]*agent-specified/) end.returns( stub_everything('response', :code => 201)) expect(testcase.classify_nodes_as_agent_specified(nodes).to_s).to eq(uuid) end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/common_utils.rb000066400000000000000000000034351527241624000302700ustar00rootroot00000000000000module Puppet module Acceptance module BeakerUtils # TODO: This should be added to Beaker def assert_matching_arrays(expected, actual, message = "") assert_equal(expected.sort, actual.sort, message) end end module PackageUtils def package_present(host, package, version = nil) host.install_package(package, '', version) end def package_absent(host, package, cmdline_args = '', opts = {}) host.uninstall_package(package, cmdline_args, opts) end end module CommandUtils def ruby_command(host) "env PATH=\"#{host['privatebindir']}:${PATH}\" ruby" end module_function :ruby_command def gem_command(host, type='aio') if type == 'aio' if host['platform'] =~ /windows/ "env PATH=\"#{host['privatebindir']}:${PATH}\" cmd /c gem" else "env PATH=\"#{host['privatebindir']}:${PATH}\" gem" end else on(host, 'which gem').stdout.chomp end end module_function :gem_command end module ManifestUtils def resource_manifest(resource, title, params = {}) params_str = params.map do |param, value| # This is not quite correct for all parameter values, # but it is good enough for most purposes. value_str = value.to_s value_str = "\"#{value_str}\"" if value.is_a?(String) " #{param} => #{value_str}" end.join(",\n") <<-MANIFEST #{resource} { '#{title}': #{params_str} } MANIFEST end def file_manifest(path, params = {}) resource_manifest('file', path, params) end def user_manifest(username, params = {}) resource_manifest('user', username, params) end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/environment_utils.rb000066400000000000000000000365231527241624000313500ustar00rootroot00000000000000require 'puppet/acceptance/module_utils' module Puppet module Acceptance module EnvironmentUtils include Puppet::Acceptance::ModuleUtils # Generate puppet manifest for the creation of an environment with # the given modulepath and manifest and env_name. The created environment # will have on testing_mod module, and manifest site.pp which includes it. # # @param options [Hash] # @option options [String] :modulepath Modules directory # @option options [String] :manifest Manifest directory # @option options [String] :env_name Environment name # @return [String] Puppet manifest to create the environment files def generate_environment(options) modulepath = options[:modulepath] manifestpath = options[:manifestpath] env_name = options[:env_name] <<-MANIFEST_SNIPPET file { ################################################### # #{env_name} #{generate_module("testing_mod", env_name, modulepath)} "#{manifestpath}":; "#{manifestpath}/site.pp": ensure => file, mode => "0640", content => ' notify { "in #{env_name} site.pp": } include testing_mod ' ; } MANIFEST_SNIPPET end # Generate one module's manifest code. def generate_module(module_name, env_name, modulepath) <<-MANIFEST_SNIPPET "#{modulepath}":; "#{modulepath}/#{module_name}":; "#{modulepath}/#{module_name}/manifests":; "#{modulepath}/#{module_name}/manifests/init.pp": ensure => file, mode => "0640", content => 'class #{module_name} { notify { "include #{env_name} #{module_name}": } }' ; MANIFEST_SNIPPET end # Default, legacy, dynamic and directory environments # using generate_manifest(), all rooted in testdir. # # @param [String] testdir path to the temp directory which will be the confdir all # the environments live in # @return [String] Puppet manifest to generate all of the environment files. def environment_manifest(testdir) <<-MANIFEST File { ensure => directory, owner => #{master.puppet['user']}, group => #{master.puppet['group']}, mode => "0750", } file { "#{testdir}": } #{generate_environment( :modulepath => "#{testdir}/modules", :manifestpath => "#{testdir}/manifests", :env_name => "default environment")} #{generate_environment( :modulepath => "#{testdir}/testing-modules", :manifestpath => "#{testdir}/testing-manifests", :env_name => "legacy testing environment")} file { "#{testdir}/dynamic":; "#{testdir}/dynamic/testing":; } #{generate_environment( :modulepath => "#{testdir}/dynamic/testing/modules", :manifestpath => "#{testdir}/dynamic/testing/manifests", :env_name => "dynamic testing environment")} file { "#{testdir}/environments":; "#{testdir}/environments/testing":; } #{generate_environment( :modulepath => "#{testdir}/environments/testing/modules", :manifestpath => "#{testdir}/environments/testing/manifests", :env_name => "directory testing environment")} file { "#{testdir}/environments/testing_environment_conf":; } #{generate_environment( :modulepath => "#{testdir}/environments/testing_environment_conf/nonstandard-modules", :manifestpath => "#{testdir}/environments/testing_environment_conf/nonstandard-manifests", :env_name => "directory testing with environment.conf")} file { "#{testdir}/environments/testing_environment_conf/environment.conf": ensure => file, mode => "0640", content => ' modulepath = nonstandard-modules:$basemodulepath manifest = nonstandard-manifests config_version = local-version.sh ' } file { "#{testdir}/environments/testing_environment_conf/local-version.sh": ensure => file, mode => "0640", content => '#! /usr/bin/env bash echo "local testing_environment_conf"' ; } ################### # Services file { "#{testdir}/services":; "#{testdir}/services/testing":; #{generate_module('service_mod', "service testing environment", "#{testdir}/services/testing/modules")} } ####################### # Config version script file { "#{testdir}/static-version.sh": ensure => file, mode => "0640", content => '#! /usr/bin/env bash echo "static"' ; } MANIFEST end def get_directory_hash_from(host, path) dir_hash = {} on(host, "ls #{path}") do |result| result.stdout.split.inject(dir_hash) do |hash,f| hash[f] = "#{path}/#{f}" hash end end dir_hash end def safely_shadow_directory_contents_and_yield(host, original_path, new_path, &block) original_files = get_directory_hash_from(host, original_path) new_files = get_directory_hash_from(host, new_path) conflicts = original_files.keys & new_files.keys step "backup original files" do conflicts.each do |c| on(host, "mv #{original_files[c]} #{original_files[c]}.bak") end end step "shadow original files with temporary files" do new_files.each do |name,full_path_name| on(host, "cp -R #{full_path_name} #{original_path}/#{name}") end end new_file_list = new_files.keys.map { |name| "#{original_path}/#{name}" }.join(' ') step "open permissions to 755 on all temporary files copied into working dir and set ownership" do on(host, "chown -R #{host.puppet['user']}:#{host.puppet['group']} #{new_file_list}") on(host, "chmod -R 755 #{new_file_list}") end if host.check_for_command("selinuxenabled") result = on(host, "selinuxenabled", :acceptable_exit_codes => [0,1]) if result.exit_code == 0 step "mirror selinux contexts" do context = on(host, "matchpathcon #{original_path}").stdout.chomp.split(' ')[1] on(host, "chcon -R #{context} #{new_file_list}") end end end yield ensure step "clear out the temporary files" do files_to_delete = new_files.keys.map { |name| "#{original_path}/#{name}" } on(host, "rm -rf #{files_to_delete.join(' ')}") end step "move the shadowed files back to their original places" do conflicts.each do |c| on(host, "mv #{original_files[c]}.bak #{original_files[c]}") end end end # Stand up a puppet master on the master node with the given master_opts # using the passed envdir as the source of the puppet environment files, # and passed confdir as the directory to use for the temporary # puppet.conf. It then runs through a series of environment tests for the # passed environment and returns a hashed structure of the results. # # @return [Hash>] Hash of # Beaker::Hosts for each agent run keyed to a hash of Beaker::Result # objects keyed by each subtest that was performed. def use_an_environment(environment, description, master_opts, envdir, confdir, options = {}) master_puppet_conf = master_opts.dup # shallow clone results = {} safely_shadow_directory_contents_and_yield(master, puppet_config(master, 'codedir', section: 'master'), envdir) do config_print = options[:config_print] directory_environments = options[:directory_environments] with_puppet_running_on(master, master_puppet_conf, confdir) do agents.each do |agent| agent_results = results[agent] = {} step "puppet agent using #{description} environment" args = "-t", "--server", master args << ["--environment", environment] if environment # Test agents configured to use directory environments (affects environment # loading on the agent, especially with regards to requests/node environment) args << "--environmentpath='$confdir/environments'" if directory_environments && agent != master on(agent, puppet("agent", *args), :acceptable_exit_codes => (0..255)) do |result| agent_results[:puppet_agent] = result end args = ["--trace"] args << ["--environment", environment] if environment step "print puppet config for #{description} environment" on(master, puppet(*(["config", "print", "basemodulepath", "modulepath", "manifest", "config_version", config_print] + args)), :acceptable_exit_codes => (0..255)) do |result| agent_results[:puppet_config] = result end step "puppet apply using #{description} environment" on(master, puppet(*(["apply", '-e', '"include testing_mod"'] + args)), :acceptable_exit_codes => (0..255)) do |result| agent_results[:puppet_apply] = result end end end end return results end # For each Beaker::Host in the results Hash, generates a chart, comparing # the expected exit code and regexp matches from expectations to the # Beaker::Result.output for a particular command that was executed in the # environment. Outputs either 'ok' or text highlighting the errors, and # returns false if any errors were found. # # @param [Hash>] results # @param [Hash Integer,Array}>] expectations # @return [Array] Returns an empty array of there were no failures, or an # Array of failed cases. def review_results(results, expectations) failed = [] results.each do |agent, agent_results| divider = "-" * 79 logger.info divider logger.info "For: (#{agent.name}) #{agent}" logger.info divider agent_results.each do |testname, execution_results| expected_exit_code = expectations[testname][:exit_code] match_tests = expectations[testname][:matches] || [] not_match_tests = expectations[testname][:does_not_match] || [] expect_failure = expectations[testname][:expect_failure] notes = expectations[testname][:notes] errors = [] if execution_results.exit_code != expected_exit_code errors << "To exit with an exit code of '#{expected_exit_code}', instead of '#{execution_results.exit_code}'" end match_tests.each do |regexp| if execution_results.output !~ regexp errors << "#{errors.empty? ? "To" : "And"} match: #{regexp}" end end not_match_tests.each do |regexp| if execution_results.output =~ regexp errors << "#{errors.empty? ? "Not to" : "And not"} match: #{regexp}" end end error_msg = "Expected the output:\n#{execution_results.output}\n#{errors.join("\n")}" unless errors.empty? case_failed = case when errors.empty? && expect_failure then 'ok - failed as expected' when errors.empty? && !expect_failure then 'ok' else '*UNEXPECTED FAILURE*' end logger.info "#{testname}: #{case_failed}" if case_failed == 'ok - failed as expected' logger.info divider logger.info "Case is known to fail as follows:\n#{execution_results.output}\n" elsif case_failed == '*UNEXPECTED FAILURE*' failed << "Unexpected failure for #{testname}" logger.info divider logger.info "#{error_msg}" end logger.info("------\nNotes: #{notes}") if notes logger.info divider end end return failed end def assert_review(review) failures = [] review.each do |failed| if !failed.empty? problems = "Problems in the output reported above:\n #{failed}" logger.warn(problems) failures << problems end end assert failures.empty?, "Failed Review:\n\n#{failures.join("\n")}\n" end # generate a random string of 6 letters and numbers. NOT secure def random_string [*('a'..'z'),*('0'..'9')].shuffle[0,8].join end private :random_string # if the first test to call this has changed the environmentpath, this will cause trouble # maybe not the best idea to memoize this? def environmentpath @@memoized_environmentpath ||= master.puppet['environmentpath'] end module_function :environmentpath # use a directory outside /tmp because systemd PrivateTmp isolates /tmp from the service def test_tmpdir '/opt/puppetlabs/test-tmp' end module_function :test_tmpdir # create a temporary environment and symbolically link it into the environmentpath # we can't use the temp_file utils in our own lib because host.tmpdir violates puppet's naming requirements # in rare cases we want to do this on agents when testing things that use the default manifest def mk_tmp_environment_with_teardown(host, environment) # add the tmp_environment to a set to ensure no collisions @@tmp_environment_set ||= Set.new deadman = 100; loop_num = 0 while @@tmp_environment_set.include?(tmp_environment = environment.downcase + '_' + random_string) do break if (loop_num = loop_num + 1) > deadman end @@tmp_environment_set << tmp_environment tmpdir = File.join(test_tmpdir, tmp_environment) on host, "mkdir -p #{tmpdir}/manifests #{tmpdir}/modules; chmod -R 755 #{tmpdir}" teardown do on host, "rm -rf #{File.join(environmentpath, tmp_environment)} #{tmpdir}" end # WARNING: this won't work with filesync (symlinked environments are not supported) on host, "mkdir -p #{environmentpath}; ln -sf #{tmpdir} #{File.join(environmentpath, tmp_environment)}" return tmp_environment end module_function :mk_tmp_environment_with_teardown # create sitepp in a tmp_environment as created by mk_tmp_environment_with_teardown def create_sitepp(host, tmp_environment, file_content) file_path = File.join(test_tmpdir, tmp_environment, 'manifests', 'site.pp') create_remote_file(host, file_path, file_content) on host, "chmod -R 755 #{file_path}" end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/environment_utils_spec.rb000066400000000000000000000134321527241624000323540ustar00rootroot00000000000000require File.join(File.dirname(__FILE__),'../../acceptance_spec_helper.rb') require 'puppet/acceptance/environment_utils' module EnvironmentUtilsSpec describe 'EnvironmentUtils' do class ATestCase include Puppet::Acceptance::EnvironmentUtils def step(str) yield end def on(host, command, options = nil) stdout = host.do(command, options) yield TestResult.new(stdout) if block_given? end end class TestResult attr_accessor :stdout def initialize(stdout) self.stdout = stdout end end class TestHost attr_accessor :did, :directories, :attributes def initialize(directories, attributes = {}) self.directories = directories self.did = [] self.attributes = attributes end def do(command, options) did << (options.nil? ? command : [command, options]) case command when /^ls (.*)/ then directories[$1] end end def [](param) attributes[param] end end let(:testcase) { ATestCase.new } let(:host) { TestHost.new(directory_contents, 'user' => 'root', 'group' => 'puppet') } let(:directory_contents) do { '/etc/puppetlabs/puppet' => 'foo bar baz widget', '/tmp/dir' => 'foo dingo bar thing', } end it "runs the block of code" do ran_code = false testcase.safely_shadow_directory_contents_and_yield(host, '/etc/puppetlabs/puppet', '/tmp/dir') do ran_code = true end expect(ran_code).to be true expect(host.did).to eq([ "ls /etc/puppetlabs/puppet", "ls /tmp/dir", "mv /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/foo.bak", "mv /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/bar.bak", "cp -R /tmp/dir/foo /etc/puppetlabs/puppet/foo", "cp -R /tmp/dir/dingo /etc/puppetlabs/puppet/dingo", "cp -R /tmp/dir/bar /etc/puppetlabs/puppet/bar", "cp -R /tmp/dir/thing /etc/puppetlabs/puppet/thing", "chown -R root:puppet /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/dingo /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/thing", "chmod -R 770 /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/dingo /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/thing", "rm -rf /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/dingo /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/thing", "mv /etc/puppetlabs/puppet/foo.bak /etc/puppetlabs/puppet/foo", "mv /etc/puppetlabs/puppet/bar.bak /etc/puppetlabs/puppet/bar" ]) end it "backs up the original items that are shadowed by tmp items" do testcase.safely_shadow_directory_contents_and_yield(host, '/etc/puppetlabs/puppet', '/tmp/dir') {} expect(host.did.grep(%r{mv /etc/puppetlabs/puppet/\w+ })).to eq([ "mv /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/foo.bak", "mv /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/bar.bak", ]) end it "copies in all the tmp items into the working dir" do testcase.safely_shadow_directory_contents_and_yield(host, '/etc/puppetlabs/puppet', '/tmp/dir') {} expect(host.did.grep(%r{cp})).to eq([ "cp -R /tmp/dir/foo /etc/puppetlabs/puppet/foo", "cp -R /tmp/dir/dingo /etc/puppetlabs/puppet/dingo", "cp -R /tmp/dir/bar /etc/puppetlabs/puppet/bar", "cp -R /tmp/dir/thing /etc/puppetlabs/puppet/thing", ]) end it "opens the permissions on all copied files to 770 and sets ownership based on host settings" do testcase.safely_shadow_directory_contents_and_yield(host, '/etc/puppetlabs/puppet', '/tmp/dir') {} expect(host.did.grep(%r{ch(mod|own)})).to eq([ "chown -R root:puppet /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/dingo /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/thing", "chmod -R 770 /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/dingo /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/thing", ]) end it "deletes all the tmp items from the working dir" do testcase.safely_shadow_directory_contents_and_yield(host, '/etc/puppetlabs/puppet', '/tmp/dir') {} expect(host.did.grep(%r{rm})).to eq([ "rm -rf /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/dingo /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/thing", ]) end it "replaces the original items that had been shadowed into the working dir" do testcase.safely_shadow_directory_contents_and_yield(host, '/etc/puppetlabs/puppet', '/tmp/dir') {} expect(host.did.grep(%r{mv /etc/puppetlabs/puppet/\w+\.bak})).to eq([ "mv /etc/puppetlabs/puppet/foo.bak /etc/puppetlabs/puppet/foo", "mv /etc/puppetlabs/puppet/bar.bak /etc/puppetlabs/puppet/bar" ]) end it "always cleans up, even if the code we yield to raises an error" do expect do testcase.safely_shadow_directory_contents_and_yield(host, '/etc/puppetlabs/puppet', '/tmp/dir') do raise 'oops' end end.to raise_error('oops') expect(host.did).to eq([ "ls /etc/puppetlabs/puppet", "ls /tmp/dir", "mv /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/foo.bak", "mv /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/bar.bak", "cp -R /tmp/dir/foo /etc/puppetlabs/puppet/foo", "cp -R /tmp/dir/dingo /etc/puppetlabs/puppet/dingo", "cp -R /tmp/dir/bar /etc/puppetlabs/puppet/bar", "cp -R /tmp/dir/thing /etc/puppetlabs/puppet/thing", "chown -R root:puppet /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/dingo /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/thing", "chmod -R 770 /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/dingo /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/thing", "rm -rf /etc/puppetlabs/puppet/foo /etc/puppetlabs/puppet/dingo /etc/puppetlabs/puppet/bar /etc/puppetlabs/puppet/thing", "mv /etc/puppetlabs/puppet/foo.bak /etc/puppetlabs/puppet/foo", "mv /etc/puppetlabs/puppet/bar.bak /etc/puppetlabs/puppet/bar" ]) end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/i18n_utils.rb000066400000000000000000000031371527241624000275560ustar00rootroot00000000000000module Puppet module Acceptance module I18nUtils # try to enable the locale's for a given language on the agent and return the preferred language name # # @param agent [string] the agent to check the locale configuration on # @param language [string] the language attempt to configure if needed # @return language [string] the language string to use on the agent node, will return nil if not available def enable_locale_language(agent, language) if agent['platform'] =~ /ubuntu/ on(agent, 'locale -a') do |locale_result| if locale_result.stdout !~ /#{language}/ on(agent, "locale-gen --lang #{language}") end end elsif agent['platform'] =~ /debian/ on(agent, 'locale -a') do |locale_result| if locale_result.stdout !~ /#{language}/ on(agent, "cp /etc/locale.gen /etc/locale.gen.orig ; sed -e 's/# #{language}/#{language}/' /etc/locale.gen.orig > /etc/locale.gen") on(agent, 'locale-gen') end end end return language_name(agent, language) end # figure out the preferred language string for the requested language if the language is configured on the system def language_name(agent, language) step "PLATFORM #{agent['platform']}" on(agent, 'locale -a') do |locale_result| ["#{language}.utf8", "#{language}.UTF-8", language].each do |lang| return lang if locale_result.stdout =~ /#{lang}/ end end return nil end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/i18ndemo_utils.rb000066400000000000000000000051621527241624000304230ustar00rootroot00000000000000module Puppet module Acceptance module I18nDemoUtils require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils I18NDEMO_NAME = "i18ndemo" I18NDEMO_MODULE_NAME = "eputnam-#{I18NDEMO_NAME}" # Returns the command line to set system LANG for the given host. # # Debian-family platforms use update-locale (from the 'locales' package), # which writes /etc/default/locale directly. We avoid localectl there # because it routes through systemd-localed/polkit; starting with Debian 13 # (trixie) that path denies Beaker's non-interactive SSH session with # "Failed to issue method call: Access denied". This change is expected # to filter down to Ubuntu and other Debian-based distros. # # Every other platform keeps using localectl, which works under their # default polkit policy. def set_system_locale_command(host, language) if %w[debian ubuntu].include?(host['platform'].variant) "update-locale LANG=#{language}" else "localectl set-locale LANG=#{language}" end end def configure_master_system_locale(requested_language) language = enable_locale_language(master, requested_language) fail_test("puppet server machine is missing #{requested_language} locale. help...") if language.nil? on(master, set_system_locale_command(master, language)) on(master, puppet_resource('service', master['puppetservice'], 'ensure=stopped')) on(master, puppet_resource('service', master['puppetservice'], 'ensure=running')) end def reset_master_system_locale language = enable_locale_language(master, 'en_US') on(master, set_system_locale_command(master, language)) on(master, puppet_resource('service', master['puppetservice'], 'ensure=stopped')) on(master, puppet_resource('service', master['puppetservice'], 'ensure=running')) end def install_i18n_demo_module(node, environment=nil) env_options = environment.nil? ? '' : "--environment #{environment}" on(node, puppet("module install #{I18NDEMO_MODULE_NAME} #{env_options}")) end def uninstall_i18n_demo_module(node, environment=nil) env_options = environment.nil? ? '' : "--environment #{environment}" [I18NDEMO_MODULE_NAME, 'puppetlabs-stdlib', 'puppetlabs-translate'].each do |module_name| on(node, puppet("module uninstall #{module_name} #{env_options}"), :acceptable_exit_codes => [0,1]) end var_dir = on(node, puppet('config print vardir')).stdout.chomp on(node, "rm -rf '#{File.join(var_dir, 'locales', 'ja')}' '#{File.join(var_dir, 'locales', 'fi')}'") end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/module_utils.rb000066400000000000000000000260741527241624000302710ustar00rootroot00000000000000module Puppet module Acceptance module ModuleUtils # Return an array of module paths for a given host. # # Example return value: # # [ # "/etc/puppetlabs/code/environments/production/modules", # "/etc/puppetlabs/code/modules", # "/opt/puppet/share/puppet/modules", # ] # # @param host [String] hostname # @return [Array] paths for found modulepath def get_modulepaths_for_host(host) environment = on(host, puppet("config print environment")).stdout.chomp on(host, puppet("config print modulepath --environment #{environment}")).stdout.chomp.split(host['pathseparator']) end # Return a string of the default (first) path in modulepath for a given host. # # Example return value: # # "/etc/puppetlabs/code/environments/production/modules" # # @param host [String] hostname # @return [String] first path for found modulepath def get_default_modulepath_for_host(host) get_modulepaths_for_host(host)[0] end # Return an array of paths to installed modules for a given host. # # Example return value: # # [ # "/opt/puppet/share/puppet/modules/apt", # "/opt/puppet/share/puppet/modules/auth_conf", # "/opt/puppet/share/puppet/modules/concat", # ] # # @param host [String] hostname # @return [Array] paths for found modules def get_installed_modules_for_host(host) on(host, puppet('module list --render-as json')) do |result| str = result.stdout.lines.to_a.last pat = /\(([^()]+)\)/ mods = str.scan(pat).flatten return mods end end # Return a hash of array of paths to installed modules for a hosts. # The individual hostnames are the keys of the hash. The only value # for a given key is an array of paths for the found modules. # # Example return value: # # { # "my_master" => # [ # "/opt/puppet/share/puppet/modules/apt", # "/opt/puppet/share/puppet/modules/auth_conf", # "/opt/puppet/share/puppet/modules/concat", # ], # "my_agent01" => # [ # "/opt/puppet/share/puppet/modules/apt", # "/opt/puppet/share/puppet/modules/auth_conf", # "/opt/puppet/share/puppet/modules/concat", # ], # } # # @param hosts [Array] hostnames # @return [Hash] paths for found modules indexed by hostname def get_installed_modules_for_hosts(hosts) mods = {} hosts.each do |host| mods[host] = get_installed_modules_for_host host end return mods end # Compare the module paths in given hashes and remove paths that # are were not present in the first hash. The use case for this # method is to remove any modules that were installed during the # course of a test run. # # Installed module hashes would be gathered using the # `get_+installed_module_for_hosts` command in the setup stage # and teardown stages of a test. These hashes would be passed into # this method in order to find modules installed during the test # and delete them in order to return the SUT environments to their # initial state. # # TODO: Enhance to take versions into account, so that upgrade/ # downgrade events during a test does not persist in the SUT # environment. # # @param beginning_hash [Hash] paths for found modules indexed # by hostname. Taken in the setup stage of a test. # @param ending_hash [Hash] paths for found modules indexed # by hostname. Taken in the teardown stage of a test. def rm_installed_modules_from_hosts(beginning_hash, ending_hash) ending_hash.each do |host, mod_array| mod_array.each do |mod| if ! beginning_hash[host].include? mod on host, "rm -rf '#{mod}'" end end end end # Convert a semantic version number string to an integer. # # Example return value given an input of '1.2.42': # # 10242 # # @param semver [String] semantic version number def semver_to_i( semver ) # semver assumed to be in format .. # calculation assumes that each segment is < 100 tmp = semver.split('.') tmp[0].to_i * 10000 + tmp[1].to_i * 100 + tmp[2].to_i end # Compare two given semantic version numbers. # # Returns an integer indicating the relationship between the two: # 0 indicates that both are equal # a value greater than 0 indicates that the semver1 is greater than semver2 # a value less than 0 indicates that the semver1 is less than semver2 # def semver_cmp( semver1, semver2 ) semver_to_i(semver1) - semver_to_i(semver2) end # Assert that a module was installed according to the UI.. # # This is a wrapper to centralize the validation about how # the UI responded that a module was installed. # It is called after a call # to `on ( host )` and inspects # STDOUT for specific content. # # @param stdout [String] # @param module_author [String] the author portion of a module name # @param module_name [String] the name portion of a module name # @param module_verion [String] the version of the module to compare to # installed version # @param compare_op [String] the operator for comparing the verions of # the installed module def assert_module_installed_ui( stdout, module_author, module_name, module_version = nil, compare_op = nil ) valid_compare_ops = {'==' => 'equal to', '>' => 'greater than', '<' => 'less than'} assert_match(/#{module_author}-#{module_name}/, stdout, "Notice that module '#{module_author}-#{module_name}' was installed was not displayed") if version /#{module_author}-#{module_name} \(.*v(\d+\.\d+\.\d+)/ =~ stdout installed_version = Regexp.last_match[1] if valid_compare_ops.include? compare_op assert_equal( true, semver_cmp(installed_version, module_version).send(compare_op, 0), "Installed version '#{installed_version}' of '#{module_name}' was not #{valid_compare_ops[compare_op]} '#{module_version}'") end end end # Assert that a module is installed on disk. # # @param host [HOST] the host object to make the remote call on # @param module_name [String] the name portion of a module name # @param optional moduledir [String, Array] the path where the module should be, will # iterate over components of the modulepath by default. def assert_module_installed_on_disk(host, module_name, moduledir=nil) moduledir ||= get_modulepaths_for_host(host) modulepath = moduledir.is_a?(Array) ? moduledir : [moduledir] moduledir= nil modulepath.each do |i| # module directory should exist if on(host, %Q{[ -d "#{i}/#{module_name}" ]}, :acceptable_exit_codes => (0..255)).exit_code == 0 moduledir = i end end fail_test('module directory not found') unless moduledir owner = '' group = '' on host, %Q{ls -ld "#{moduledir}"} do listing = stdout.split(' ') owner = listing[2] group = listing[3] end # A module's files should have: # * a mode of 644 (755, if they're a directory) # * owner == owner of moduledir # * group == group of moduledir on host, %Q{ls -alR "#{moduledir}/#{module_name}"} do listings = stdout.split("\n") listings = listings.grep(/^[bcdlsp-]/) listings = listings.reject { |l| l =~ /\.\.$/ } listings.each do |line| fileinfo = parse_ls(line) assert_equal owner, fileinfo[:owner] assert_equal group, fileinfo[:group] if fileinfo[:filetype] == 'd' assert_equal 'rwx', fileinfo[:perms][:user] assert_equal 'r-x', fileinfo[:perms][:group] assert_equal 'r-x', fileinfo[:perms][:other] else assert_equal 'rw-', fileinfo[:perms][:user] assert_equal 'r--', fileinfo[:perms][:group] assert_equal 'r--', fileinfo[:perms][:other] end end end end LS_REGEX = %r[(.)(...)(...)(...).?[[:space:]]+\d+[[:space:]]+([[:word:]]+)[[:space:]]+([[:word:]]+).*[[:space:]]+([[:graph:]]+)$] def parse_ls(line) match = line.match(LS_REGEX) if match.nil? fail_test "#{line.inspect} doesn't match ls output regular expression" end captures = match.captures { :filetype => captures[0], :perms => { :user => captures[1], :group => captures[2], :other => captures[3], }, :owner => captures[4], :group => captures[5], :file => captures[6] } end private :parse_ls # Assert that a module is not installed on disk. # # @param host [HOST] the host object to make the remote call on # @param module_name [String] the name portion of a module name # @param optional moduledir [String, Array] the path where the module should be, will # iterate over components of the modulepath by default. def assert_module_not_installed_on_disk(host, module_name, moduledir=nil) moduledir ||= get_modulepaths_for_host(host) modulepath = moduledir.is_a?(Array) ? moduledir : [moduledir] moduledir= nil modulepath.each do |i| # module directory should not exist on host, %Q{[ ! -d "#{i}/#{module_name}" ]} end end # Create a simple directory environment and puppet.conf at :tmpdir. # # @note Also registers a teardown block to remove generated files. # # @param tmpdir [String] directory to contain all the # generated environment files # @return [String] path to the new puppet configuration file defining the # environments def generate_base_directory_environments(tmpdir) puppet_conf = "#{tmpdir}/puppet2.conf" dir_envs = "#{tmpdir}/environments" step 'Configure a the direnv directory environment' apply_manifest_on master, %Q{ File { ensure => directory, owner => #{master.puppet['user']}, group => #{master.puppet['group']}, mode => "0750", } file { [ '#{dir_envs}', '#{dir_envs}/direnv', ]: } file { '#{puppet_conf}': ensure => file, content => " [main] environmentpath=#{dir_envs} " } } return puppet_conf end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/puppet_type_test_tools.rb000066400000000000000000000100271527241624000324100ustar00rootroot00000000000000require 'puppet/acceptance/environment_utils' module Puppet module Acceptance module PuppetTypeTestTools include Puppet::Acceptance::EnvironmentUtils # for now, just for #random_string # FIXME: yardocs # TODO: create resource class which contains its manifest chunk, and assertions # can be an array or singular, holds the manifest and the assertion_code # has getter for the manifest # has #run_assertions(BeakerResult or string) def generate_manifest(test_resources) manifest = '' test_resources = [test_resources].flatten # ensure it's an array so we enumerate properly test_resources.each do |resource| manifest << resource[:pre_code] + "\n" if resource[:pre_code] namevar = (resource[:parameters][:namevar] if resource[:parameters]) || "#{resource[:type]}_#{random_string}" # ensure these are double quotes around the namevar incase users puppet-interpolate inside it # FIXME: add test ^^ manifest << resource[:type] + '{"' + namevar + '":' if resource[:type] if resource[:parameters] resource[:parameters].each do |key,value| next if key == :namevar manifest << "#{key} => #{value}," end end manifest << "}\n" if resource[:type] end return manifest end def generate_assertions(test_resources) assertion_code = '' test_resources = [test_resources].flatten # ensure it's an array so we enumerate properly test_resources.each do |resource| if resource[:assertions] resource[:assertions] = [resource[:assertions]].flatten # ensure it's an array so we enumerate properly resource[:assertions].each do |assertion_type| expect_failure = false if assertion_type[:expect_failure] expect_failure = true assertion_code << "expect_failure '#{assertion_type[:expect_failure][:message]}' do\n" # delete the message assertion_type[:expect_failure].delete(:message) # promote the hash in expect_failure assertion_type = assertion_type[:expect_failure] assertion_type.delete(:expect_failure) end # ensure all the values are arrays assertion_values = [assertion_type.values].flatten assertion_values.each do |assertion_value| # TODO: non matching asserts? # TODO: non stdout? (support stdout, stderr, exit_code) # TODO: what about checking resource state on host (non agent/apply #on use)? if assertion_type.keys.first =~ /assert_match/ assert_msg = 'found ' elsif assertion_type.keys.first =~ /refute_match/ assert_msg = 'did not find ' else assert_msg = '' end if assertion_value.is_a?(String) matcher = "\"#{assertion_value}\"" elsif assertion_value.is_a?(Regexp) matcher = assertion_value.inspect else matcher = assertion_value end assertion_code << "#{assertion_type.keys.first}(#{matcher}, result.stdout, '#{assert_msg}#{matcher}')\n" end assertion_code << "end\n" if expect_failure end end end return assertion_code end Result = Struct.new(:stdout) def run_assertions(assertions = '', result) result_struct = Result.new if result.respond_to? :stdout result_struct.stdout = result.stdout else # handle results sent in as string result_struct.stdout = result end result = result_struct begin eval(assertions) rescue RuntimeError, SyntaxError => e puts e puts assertions raise end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/puppet_type_test_tools_spec.rb000066400000000000000000000147371527241624000334360ustar00rootroot00000000000000require File.join(File.dirname(__FILE__),'../../acceptance_spec_helper.rb') require 'puppet/acceptance/puppet_type_test_tools.rb' require 'beaker/dsl/assertions' require 'beaker/result' module Puppet module Acceptance describe 'PuppetTypeTestTools' do include PuppetTypeTestTools include Beaker::DSL::Assertions include Beaker context '#generate_manifest' do it 'takes a single hash' do expect(generate_manifest({:type => 'fake'})).to match(/^fake{"fake_\w{8}":}$/) end it 'takes an array' do expect(generate_manifest([{:type => 'fake'}])).to match(/^fake{"fake_\w{8}":}$/) end it 'generates empty puppet code (assertion-only instance)' do expect(generate_manifest({:fake => 'fake'})).to eql('') end it 'puts a namevar in the right place' do expect(generate_manifest({:type => 'fake', :parameters => {:namevar => 'blah'}})).to match(/^fake{"blah":}$/) end it 'retains puppet code in a namevar' do expect(generate_manifest({:type => 'fake', :parameters => {:namevar => "half_${interpolated}_puppet_namevar"}})). to match(/^fake{"half_\${interpolated}_puppet_namevar":}$/) end it 'places pre_code before the type' do expect(generate_manifest({:type => 'fake', :pre_code => '$some = puppet_code'})). to match(/^\$some = puppet_code\nfake{"fake_\w{8}":}$/m) end it 'places multiple, arbitrary parameters' do expect(generate_manifest({:type => 'fake', :parameters => {:someprop => "function(call)", :namevar => "blah", :someparam => 2}})). to match(/^fake{"blah":someprop => function\(call\),someparam => 2,}$/) end end context '#generate_assertions' do it 'takes a single hash' do expect(generate_assertions({:assertions => {:fake => 'matcher'}})) .to match(/^fake\("matcher", result\.stdout, '"matcher"'\)$/) end it 'takes an array' do expect(generate_assertions([{:assertions => {:fake => 'matcher'}}])) .to match(/^fake\("matcher", result\.stdout, '"matcher"'\)$/) end it 'generates empty assertions (puppet-code only instance)' do expect(generate_assertions({:type => 'no assertions'})).to eql('') end it 'generates arbitrary assertions' do expect(generate_assertions({:assertions => [{:fake => 'matcher'}, {:other => 'othermatch'}]})) .to match(/^fake\("matcher", result\.stdout, '"matcher"'\)\nother\("othermatch", result.stdout, '"othermatch"'\)$/m) end it 'can give a regex to assertions' do expect(generate_assertions({:assertions => {:fake => /matcher/}})) .to match(/^fake\(\/matcher\/, result\.stdout, '\/matcher\/'\)$/) end it 'allows multiple of one assertion type' do expect(generate_assertions({:assertions => {:fake => ['matcher','othermatch']}})) .to match(/^fake\("matcher", result\.stdout, '"matcher"'\)\nfake\("othermatch", result.stdout, '"othermatch"'\)$/) end it 'allows multiple assertion_types with multiple values' do expect(generate_assertions({:assertions => [{:fake => ['matcher','othermatch']}, {:fake2 => ['matcher2','othermatch2']}]})) .to match(/^fake\("matcher", result\.stdout, '"matcher"'\)\nfake\("othermatch", result.stdout, '"othermatch"'\)\nfake2\("matcher2", result.stdout, '"matcher2"'\)\nfake2\("othermatch2", result.stdout, '"othermatch2"'\)\n$/) end context 'expect_failure' do it 'generates arbitrary assertion' do expect(generate_assertions({:assertions => {:expect_failure => {:fake => 'matcher'}}})) .to match(/^expect_failure '' do\nfake\(.*\)\nend$/) end it 'allows multiple of one assertion type' do expect(generate_assertions({:assertions => {:expect_failure => {:fake => ['matcher','othermatch']}}})) .to match(/^expect_failure '' do\nfake\(.*\)\nfake\(.*\)\nend$/) end it 'allows multiple assertion_types' do pending 'ack! requires recursion :-(' #expect(generate_assertions({:assertions => {:expect_failure => [{:fake => 'matcher'},{:fake2 => 'matcher2'}]}})) #.to match(/^expect_failure '' do\nfake\(.*\)\nfake2\(.*\)\nend$/) end it 'allows multiple assertion_types with an expect_failure on one' do expect(generate_assertions({:assertions => [{:expect_failure => {:fake => 'matcher'}}, {:fake2 => 'matcher2'}]})) .to match(/^expect_failure '' do\nfake\(.*\)\nend\nfake2\(.*\)$/) end it 'allows custom expect_failure messages' do expect(generate_assertions({:assertions => {:expect_failure => {:fake => 'matcher', :message => 'oh noes, this should fail but pass'}}})) .to match(/^expect_failure 'oh noes, this should fail but pass' do\nfake\(.*\)\nend$/) end end it 'allow custom assertion messages' end context 'run_assertions' do #def run_assertions(assertions = '', result) it 'takes a string result' do expect(run_assertions('assert_match("yes please", result.stdout)', 'yes please')).to be true end let(:result) {Beaker::Result.new('host','command')} it 'takes a beaker "type" Result' do result.stdout = 'yes please' expect(run_assertions('assert_match("yes please", result.stdout)', result)).to be true end it 'runs a bunch of assertions' do result.stdout = 'yes please' expect(run_assertions("assert_match('yes please', result.stdout)\nrefute_match('blah', result.stdout)", result)).to be false end it 'fails assertions' do pending 'why doesnt this work?' result.stdout = 'yes please' expect(run_assertions('assert_match("blah", result.stdout)', result)).to raise_error end context 'exceptions' do #rescue RuntimeError, SyntaxError => e it 'puts the assertion code, raises error' do pending 'why doesnt this work?' expect(run_assertions('assert_match("blah") }', result)).to raise_error end end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/rpm_util.rb000066400000000000000000000076641527241624000274230ustar00rootroot00000000000000module Puppet module Acceptance module RpmUtils # Utilities for creating a basic rpm package and using it in tests @@defaults = {:repo => '/tmp/rpmrepo', :pkg => 'mypkg', :publisher => 'tstpub.lan', :version => '1.0'} @@setup_packages = {} def rpm_provider(agent) has_dnf = on(agent, 'which dnf', :acceptable_exit_codes => [0,1]).exit_code if has_dnf == 0 'dnf' else 'yum' end end def setup(agent) @@setup_packages[agent] ||= {} cmd = rpm_provider(agent) required_packages = ['createrepo', 'curl', 'rpm-build'] required_packages.each do |pkg| pkg_installed = (on agent, "#{cmd} list installed #{pkg}", :acceptable_exit_codes => (0..255)).exit_code == 0 # package not present, so perform a new install if !pkg_installed on agent, "#{cmd} install -y #{pkg}" # package is present, but has not yet attempted an upgrade # note that this may influence YUM cache behavior elsif !@@setup_packages[agent].has_key?(pkg) # first pass, always attempt an upgrade to latest version # fixes Fedora 25 curl compat with python-pycurl for instance on agent, "#{cmd} upgrade -y #{pkg}" end @@setup_packages[agent][pkg] = true end end def clean_rpm(agent, o={}) cmd = rpm_provider(agent) o = @@defaults.merge(o) on agent, "rm -rf #{o[:repo]}", :acceptable_exit_codes => (0..255) on agent, "#{cmd} remove -y #{o[:pkg]}", :acceptable_exit_codes => (0..255) on agent, "rm -f /etc/yum.repos.d/#{o[:publisher]}.repo", :acceptable_exit_codes => (0..255) end def setup_rpm(agent, o={}) setup(agent) o = @@defaults.merge(o) on agent, "mkdir -p #{o[:repo]}/{RPMS,SRPMS,BUILD,SOURCES,SPECS}" on agent, "echo '%_topdir #{o[:repo]}' > ~/.rpmmacros" on agent, "createrepo #{o[:repo]}" on agent, "cat < /etc/yum.repos.d/#{o[:publisher]}.repo [#{o[:publisher]}] name=#{o[:publisher]} baseurl=file://#{o[:repo]}/ enabled=1 gpgcheck=0 EOF " end def send_rpm(agent, o={}) setup(agent) o = @@defaults.merge(o) on agent, "mkdir -p #{o[:repo]}/#{o[:pkg]}-#{o[:version]}/usr/bin" on agent, "cat < #{o[:repo]}/#{o[:pkg]} #!/bin/bash echo Hello World EOF " pkg_name = "#{o[:pkg]}-#{o[:version]}" on agent, "install -m 755 #{o[:repo]}/#{o[:pkg]} #{o[:repo]}/#{pkg_name}/usr/bin" on agent, "tar -zcvf #{o[:repo]}/SOURCES/#{pkg_name}.tar.gz -C #{o[:repo]} #{pkg_name}" on agent, "cat < #{o[:repo]}/SPECS/#{o[:pkg]}.spec # Don't try fancy stuff like debuginfo, which is useless on binary-only packages. Don't strip binary too # Be sure buildpolicy set to do nothing %define __spec_install_post %{nil} %define debug_package %{nil} %define __os_install_post %{_dbpath}/brp-compress Summary: A very simple toy bin rpm package Name: #{o[:pkg]} Version: #{o[:version]} Release: 1 Epoch: #{o[:epoch] || 0} BuildArch: noarch License: GPL+ Group: Development/Tools SOURCE0 : %{name}-%{version}.tar.gz URL: https://www.puppetlabs.com/ BuildRoot: %{_topdir}/BUILD/%{name}-%{version}-%{release}-root %description %{summary} %prep %setup -q %build # Empty section. %install rm -rf %{buildroot} mkdir -p %{buildroot} # in builddir cp -a * %{buildroot} %clean rm -rf %{buildroot} %files %defattr(-,root,root,-) %{_bindir}/* %changelog * Mon Dec 01 2014 Michael Smith #{o[:version]}-1 - First Build EOF " on agent, "rpmbuild -ba #{o[:repo]}/SPECS/#{o[:pkg]}.spec" on agent, "createrepo --update #{o[:repo]}" cmd = rpm_provider(agent) # DNF requires a cache reset to make local repositories accessible. if cmd == 'dnf' on agent, "dnf clean metadata" end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/service_utils.rb000066400000000000000000000161441527241624000304410ustar00rootroot00000000000000require 'puppet/acceptance/common_utils' module Puppet module Acceptance module ServiceUtils # Return whether a host supports the systemd provider. # @param host [String] hostname # @return [Boolean] whether the systemd provider is supported. def supports_systemd?(host) # The Windows MSI doesn't put Puppet in the Ruby vendor or site dir, so loading it fails. return false if host.platform.variant == 'windows' ruby = Puppet::Acceptance::CommandUtils.ruby_command(host) suitable = on(host, "#{ruby} -e \"require 'puppet'; puts Puppet::Type.type(:service).provider(:systemd).suitable?\"" ).stdout.chomp suitable == "true" ? true : false end # Construct manifest ensuring service status. # @param service [String] name of the service # @param status [Hash] properties to set - can include 'ensure' and 'enable' keys. # @return [String] a manifest def service_manifest(service, status) ensure_status = "ensure => '#{status[:ensure]}'," if status[:ensure] enable_status = "enable => '#{status[:enable]}'," if status[:enable] %Q{ service { '#{service}': #{ensure_status} #{enable_status} } } end # Alter the state of a service using puppet apply and assert that a change was logged. # Assumes the starting state is not the desired state. # @param host [String] hostname. # @param service [String] name of the service. # @param status [Hash] properties to set - can include 'ensure' and 'enable' keys. # @return None def ensure_service_change_on_host(host, service, status) # the process of creating the service will also start it # to avoid a flickering test from the race condition, this test will ensure # that the exit code is either # 2 => something changed, or # 0 => no change needed apply_manifest_on(host, service_manifest(service, status), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/Service\[#{service}\]\/ensure: ensure changed '\w+' to '#{status[:ensure]}'/, result.stdout, 'Service status change failed') if status[:ensure] assert_match(/Service\[#{service}\]\/enable: enable changed '\w+' to '#{status[:enable]}'/, result.stdout, 'Service enable change failed') if status[:enable] end end # Ensure the state of a service using puppet apply and assert that no change was logged. # Assumes the starting state is the ensured state. # @param host [String] hostname. # @param service [String] name of the service. # @param status [Hash] properties to set - can include 'ensure' and 'enable' keys. # @return None def ensure_service_idempotent_on_host(host, service, status) # ensure idempotency apply_manifest_on(host, service_manifest(service, status)) do |result| refute_match(/Service\[#{service}\]\/ensure/, result.stdout, 'Service status not idempotent') if status[:ensure] refute_match(/Service\[#{service}\]\/enable/, result.stdout, 'Service enable not idempotent') if status[:enable] end end # Alter the state of a service using puppet apply, assert that it changed and change is idempotent. # Can set 'ensure' and 'enable'. Assumes the starting state is not the desired state. # @param host [String] hostname. # @param service [String] name of the service. # @param status [Hash] properties to set - can include 'ensure' and 'enable' keys. # @param block [Proc] optional: block to verify service state # @return None def ensure_service_on_host(host, service, status, &block) ensure_service_change_on_host(host, service, status) assert_service_status_on_host(host, service, status, &block) ensure_service_idempotent_on_host(host, service, status) assert_service_status_on_host(host, service, status, &block) end # Checks that the ensure and/or enable status of a service are as expected. # @param host [String] hostname. # @param service [String] name of the service. # @param status [Hash] properties to set - can include 'ensure' and 'enable' keys. # @param block [Proc] optional: block to verify service state # @return None def assert_service_status_on_host(host, service, status, &block) ensure_status = "ensure.+=> '#{status[:ensure]}'" if status[:ensure] enable_status = "enable.+=> '#{status[:enable]}'" if status[:enable] on(host, puppet_resource('service', service)) do |result| assert_match(/'#{service}'.+#{ensure_status}.+#{enable_status}/m, result.stdout, "Service status does not match expectation #{status}") end # Verify service state on the system using a custom block if block yield block end end # Refreshes a service. # @param host [String] hostname. # @param service [String] name of the service to refresh. # @return None def refresh_service_on_host(host, service) refresh_manifest = %Q{ service { '#{service}': } notify { 'Refreshing #{service}': notify => Service['#{service}'], } } apply_manifest_on(host, refresh_manifest) end # Runs some common acceptance tests for nonexistent services. # @param service [String] name of the service # @return None def run_nonexistent_service_tests(service) step "Verify that a nonexistent service is considered stopped, disabled and no logonaccount is reported" do on(agent, puppet_resource('service', service)) do |result| { enable: false, ensure: :stopped }.each do |property, value| assert_match(/#{property}.*#{value}.*$/, result.stdout, "Puppet does not report #{property}=#{value} for a non-existent service") end refute_match(/logonaccount\s+=>/, result.stdout, "Puppet reports logonaccount for a non-existent service") end end step "Verify that stopping and disabling a nonexistent service is a no-op" do manifest = service_manifest(service, ensure: :stopped, enable: false) apply_manifest_on(agent, manifest, catch_changes: true) end [ [ :enabling, [ :enable, true ]], [ :starting, [ :ensure, :running ]] ].each do |operation, (property, value)| manifest = service_manifest(service, property => value) step "Verify #{operation} a non-existent service prints an error message but does not fail the run without detailed exit codes" do apply_manifest_on(agent, manifest) do |result| assert_match(/Error:.*#{service}.*$/, result.stderr, "Puppet does not error when #{operation} a non-existent service.") end end step "Verify #{operation} a non-existent service with detailed exit codes correctly returns an error code" do apply_manifest_on(agent, manifest, :acceptable_exit_codes => [4]) end end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/solaris_util.rb000066400000000000000000000133521527241624000302700ustar00rootroot00000000000000module Puppet module Acceptance module IPSUtils def clean(agent, o={}) o = {:repo => '/var/tstrepo', :pkg => 'mypkg', :publisher => 'tstpub.lan'}.merge(o) on agent, "rm -rf %s||:" % o[:repo] on agent, "rm -rf /tst||:" on agent, "pkg uninstall %s||:" % o[:pkg] on agent, "pkg unset-publisher %s ||:" % o[:publisher] end def setup(agent, o={}) o = {:repo => '/var/tstrepo', :publisher => 'tstpub.lan'}.merge(o) on agent, "mkdir -p %s" % o[:repo] on agent, "pkgrepo create %s" % o[:repo] on agent, "pkgrepo set -s %s publisher/prefix=%s" % [o[:repo], o[:publisher]] on agent, "pkgrepo -s %s refresh" % o[:repo] end def setup_fakeroot(agent, o={}) o = {:root=>'/opt/fakeroot'}.merge(o) on agent, "rm -rf %s" % o[:root] on agent, "mkdir -p %s/tst/usr/bin" % o[:root] on agent, "mkdir -p %s/tst/etc" % o[:root] on agent, "echo dummy > %s/tst/usr/bin/x" % o[:root] on agent, "echo val > %s/tst/etc/y" % o[:root] end def setup_fakeroot2(agent, o={}) o = {:root=>'/opt/fakeroot'}.merge(o) on agent, "rm -rf %s" % o[:root] on agent, "mkdir -p %s/tst2/usr/bin" % o[:root] on agent, "mkdir -p %s/tst2/etc" % o[:root] on agent, "echo dummy > %s/tst2/usr/bin/x" % o[:root] on agent, "echo val > %s/tst2/etc/y" % o[:root] end def send_pkg2(agent, o={}) o = {:repo=>'/var/tstrepo', :root=>'/opt/fakeroot', :publisher=>'tstpub.lan', :pkg=>'mypkg2@0.0.1', :pkgdep => 'mypkg@0.0.1'}.merge(o) on agent, "(pkgsend generate %s; echo set name=pkg.fmri value=pkg://%s/%s)> /tmp/%s.p5m" % [o[:root], o[:publisher], o[:pkg], o[:pkg]] on agent, "echo depend type=require fmri=%s >> /tmp/%s.p5m" % [o[:pkgdep], o[:pkg]] on agent, "pkgsend publish -d %s -s %s /tmp/%s.p5m" % [o[:root], o[:repo], o[:pkg]] on agent, "pkgrepo refresh -p %s -s %s" % [o[:publisher], o[:repo]] on agent, "pkg refresh" on agent, "pkg list -g %s" % o[:repo] end def send_pkg(agent, o={}) o = {:repo=>'/var/tstrepo', :root=>'/opt/fakeroot', :publisher=>'tstpub.lan', :pkg=>'mypkg@0.0.1'}.merge(o) on agent, "(pkgsend generate %s; echo set name=pkg.fmri value=pkg://%s/%s)> /tmp/%s.p5m" % [o[:root], o[:publisher], o[:pkg], o[:pkg]] on agent, "pkgsend publish -d %s -s %s /tmp/%s.p5m" % [o[:root], o[:repo], o[:pkg]] on agent, "pkgrepo refresh -p %s -s %s" % [o[:publisher], o[:repo]] on agent, "pkg refresh" end def set_publisher(agent, o={}) o = {:repo=>'/var/tstrepo', :publisher=>'tstpub.lan'}.merge(o) on agent, "pkg set-publisher -g %s %s" % [o[:repo], o[:publisher]] on agent, "pkg refresh" end end module SMFUtils def clean(agent, o={}) o = {:service => 'tstapp'}.merge(o) on(agent, "svcs -l %s" % o[:service], acceptable_exit_codes: [0, 1]) do |result| next if result.stdout =~ /doesn't match/ lines = result.stdout.chomp.lines instances = lines.select { |line| line =~ /^fmri/ }.map { |line| line.split(' ')[1].chomp } instances.each do |instance| on agent, "svcadm disable %s ||:" % instance on agent, "svccfg delete %s ||:" % instance end end on agent, "rm -rf /var/svc/manifest/application/%s.xml ||:" % o[:service] on agent, "rm -f /opt/bin/%s ||:" % o[:service] end def setup(agent, o={}) setup_methodscript(agent, o) end def setup_methodscript(agent, o={}) o = {:service => 'tstapp'}.merge(o) on agent, "mkdir -p /opt/bin" create_remote_file agent, '/lib/svc/method/%s' % o[:service], %[ #!/usr/bin/sh . /lib/svc/share/smf_include.sh case "$1" in start) /opt/bin/%s ;; stop) ctid=`svcprop -p restarter/contract $SMF_FMRI` if [ -n "$ctid" ]; then smf_kill_contract $ctid TERM fi ;; *) echo "Usage: $0 { start | stop }" ; exit 1 ;; esac exit $SMF_EXIT_OK ] % ([o[:service]] * 4) create_remote_file agent, ('/opt/bin/%s' % o[:service]), %[ #!/usr/bin/sh cleanup() { rm -f /tmp/%s.pidfile; exit 0 } trap cleanup INT TERM trap '' HUP (while :; do sleep 1; done) & echo $! > /tmp/%s.pidfile ] % ([o[:service]] * 2) on agent, "chmod 755 /lib/svc/method/%s" % o[:service] on agent, "chmod 755 /opt/bin/%s" % o[:service] on agent, "mkdir -p /var/svc/manifest/application" create_remote_file agent, ('/var/smf-%s.xml' % o[:service]), %[ ] % ([o[:service]] * 4) on agent, "svccfg -v validate /var/smf-%s.xml" % o[:service] on agent, "echo > /var/svc/log/application-%s:default.log" % o[:service] return ("/var/smf-%s.xml" % o[:service]), ("/lib/svc/method/%s" % o[:service]) end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/static_catalog_utils.rb000066400000000000000000000035371527241624000317640ustar00rootroot00000000000000module Puppet module Acceptance module StaticCatalogUtils # Adds code-id-command and code-content-command scripts # to the server and updates puppetserver.conf. This is # necessary for testing static catalogs. # @param master [String] the host running puppetserver. # @param scriptdir [String] the path to the directory where the scripts should be placed. def setup_puppetserver_code_id_scripts(master, scriptdir) code_id_command = < true) file { '#{scriptdir}/code_id.sh': ensure => file, content => "#{code_id_command}", mode => "0755", } file { '#{scriptdir}/code_content.sh': ensure => file, content => "#{code_content_command}", mode => "0755", } MANIFEST puppetserver_config = "#{master['puppetserver-confdir']}/puppetserver.conf" on master, "cp #{puppetserver_config} #{scriptdir}/puppetserver.conf.bak" versioned_code_settings = {"versioned-code" => {"code-id-command" => "#{scriptdir}/code_id.sh", "code-content-command" => "#{scriptdir}/code_content.sh"}} modify_tk_config(master, puppetserver_config, versioned_code_settings) end def cleanup_puppetserver_code_id_scripts(master, scriptdir) # These are -f so we don't bail on the teardown if for some reason they didn't get laid down on master, "rm -f #{scriptdir}/code_id.sh" on master, "rm -f #{scriptdir}/code_content.sh" puppetserver_config = "#{master['puppetserver-confdir']}/puppetserver.conf" on master, "cp #{scriptdir}/puppetserver.conf.bak #{puppetserver_config}" end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/temp_file_utils.rb000066400000000000000000000151311527241624000307400ustar00rootroot00000000000000module Puppet module Acceptance module TempFileUtils RWXR_XR_X = '0755' PUPPET_CODEDIR_PERMISSIONS = RWXR_XR_X # Return the name of the root user, as appropriate for the platform. def root_user(host) case host['platform'] when /windows/ 'Administrator' else 'root' end end # Return the name of the root group, as appropriate for the platform. def root_group(host) case host['platform'] when /windows/ 'Administrators' when /aix/ 'system' when /osx|bsd/ 'wheel' else 'root' end end # Create a file on the host. # Parameters: # [host] the host to create the file on # [file_path] the path to the file to be created # [file_content] a string containing the contents to be written to the file # [options] a hash containing additional behavior options. Currently supported: # * :mkdirs (default false) if true, attempt to create the parent directories on the remote host before writing # the file # * :owner (default 'root') the username of the user that the file should be owned by # * :group (default 'puppet') the name of the group that the file should be owned by # * :mode (default '644') the mode (file permissions) that the file should be created with def create_test_file(host, file_rel_path, file_content, options = {}) # set default options options[:mkdirs] ||= false options[:mode] ||= "755" unless options[:owner] if host['roles'].include?('master') then options[:owner] = host.puppet['user'] else options[:owner] = root_user(host) end end unless options[:group] if host['roles'].include?('master') then options[:group] = host.puppet['group'] else options[:group] = root_group(host) end end file_path = get_test_file_path(host, file_rel_path) mkdirs(host, File.dirname(file_path)) if (options[:mkdirs] == true) create_remote_file(host, file_path, file_content) # # NOTE: we need these chown/chmod calls because the acceptance framework connects to the nodes as "root", but # puppet 'master' runs as user 'puppet'. Therefore, in order for puppet master to be able to read any files # that we've created, we have to carefully set their permissions # chown(host, options[:owner], options[:group], file_path) chmod(host, options[:mode], file_path) end # Given a relative path, returns an absolute path for a test file. Basically, this just prepends the # a unique temp dir path (specific to the current test execution) to your relative path. def get_test_file_path(host, file_rel_path) initialize_temp_dirs unless @host_test_tmp_dirs File.join(@host_test_tmp_dirs[host.name], file_rel_path) end # Check for the existence of a temp file for the current test; basically, this just calls file_exists?(), # but prepends the path to the current test's temp dir onto the file_rel_path parameter. This allows # tests to be written using only a relative path to specify file locations, while still taking advantage # of automatic temp file cleanup at test completion. def test_file_exists?(host, file_rel_path) file_exists?(host, get_test_file_path(host, file_rel_path)) end def file_exists?(host, file_path) host.execute("test -f \"#{file_path}\"", :acceptable_exit_codes => [0, 1]) do |result| return result.exit_code == 0 end end def dir_exists?(host, dir_path) host.execute("test -d \"#{dir_path}\"", :acceptable_exit_codes => [0, 1]) do |result| return result.exit_code == 0 end end def link_exists?(host, link_path) host.execute("test -L \"#{link_path}\"", :acceptable_exit_codes => [0, 1]) do |result| return result.exit_code == 0 end end def file_contents(host, file_path) host.execute("cat \"#{file_path}\"") do |result| return result.stdout end end def tmpdir(host, basename) host_tmpdir = host.tmpdir(basename) # we need to make sure that the puppet user can traverse this directory... chmod(host, "755", host_tmpdir) host_tmpdir end def mkdirs(host, dir_path) on(host, "mkdir -p #{dir_path}") end def chown(host, owner, group, path) on(host, "chown #{owner}:#{group} #{path}") end def chmod(host, mode, path) on(host, "chmod #{mode} #{path}") end # Returns an array containing the owner, group and mode of # the file specified by path. The returned mode is an integer # value containing only the file mode, excluding the type, e.g # S_IFDIR 0040000 def stat(host, path) require File.join(File.dirname(__FILE__),'common_utils.rb') ruby = Puppet::Acceptance::CommandUtils.ruby_command(host) owner = on(host, "#{ruby} -e 'require \"etc\"; puts (Etc.getpwuid(File.stat(\"#{path}\").uid).name)'").stdout.chomp group = on(host, "#{ruby} -e 'require \"etc\"; puts (Etc.getgrgid(File.stat(\"#{path}\").gid).name)'").stdout.chomp mode = on(host, "#{ruby} -e 'puts (File.stat(\"#{path}\").mode & 07777)'").stdout.chomp.to_i [owner, group, mode] end def initialize_temp_dirs() # pluck this out of the test case environment; not sure if there is a better way @cur_test_file = @path @cur_test_file_shortname = File.basename(@cur_test_file, File.extname(@cur_test_file)) # we need one list of all of the hosts, to assist in managing temp dirs. It's possible # that the master is also an agent, so this will consolidate them into a unique set @all_hosts = Set[master, *agents] # now we can create a hash of temp dirs--one per host, and unique to this test--without worrying about # doing it twice on any individual host @host_test_tmp_dirs = Hash[@all_hosts.map do |host| [host.name, tmpdir(host, @cur_test_file_shortname)] end ] end def remove_temp_dirs() @all_hosts.each do |host| on(host, "rm -rf #{@host_test_tmp_dirs[host.name]}") end end # a silly variable for keeping track of whether or not all of the tests passed... @all_tests_passed = false end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/windows_utils.rb000066400000000000000000000034711527241624000304720ustar00rootroot00000000000000require 'puppet/acceptance/common_utils' module Puppet module Acceptance module WindowsUtils require 'puppet/acceptance/windows_utils/service.rb' require 'puppet/acceptance/windows_utils/package_installer.rb' def profile_base(agent) ruby = Puppet::Acceptance::CommandUtils.ruby_command(agent) getbasedir = <<'END' puts ENV['USERPROFILE'].match(/(.*)\\\\[^\\\\]*/)[1] END on(agent, "#{ruby} -e \"#{getbasedir}\"").stdout.chomp end # Checks whether the account with the given username has the given password on a host def assert_password_matches_on(host, username, password, msg = nil) script = <<-PS1 Add-Type -AssemblyName System.DirectoryServices.AccountManagement $ctx = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine, $env:COMPUTERNAME) $ctx.ValidateCredentials("#{username}", "#{password}") PS1 result = execute_powershell_script_on(host, script) assert_match(/True/, result.stdout.strip, msg) end def deny_administrator_access_to(host, filepath) # we need to create a fake directory in the user's tempdir with powershell because the ACL # perms set down by cygwin when making tempdirs makes the ACL unusable. Thus we create a # tempdir using powershell and pull its' ACL as a starting point for the new ACL. script = <<-PS1 mkdir -Force $env:TMP\\fake-dir-for-acl $acl = Get-ACL $env:TMP\\fake-dir-for-acl rm -Force $env:TMP\\fake-dir-for-acl $ar = New-Object system.security.accesscontrol.filesystemaccessrule("Administrator","FullControl","Deny") $acl.SetAccessRule($ar) Set-ACL #{filepath} $acl PS1 execute_powershell_script_on(host, script) end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/windows_utils/000077500000000000000000000000001527241624000301405ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/windows_utils/package_installer.rb000066400000000000000000000056471527241624000341510ustar00rootroot00000000000000module Puppet module Acceptance module WindowsUtils # Sets up a mock installer on the host. def create_mock_package(host, tmpdir, config = {}, installer_file = 'MockInstaller.cs', uninstaller_file = 'MockUninstaller.cs') installer_exe_path = "#{tmpdir}/#{config[:name].gsub(/\s+/, '')}Installer.exe".gsub('/', '\\') uninstaller_exe_path = "#{tmpdir}/#{config[:name].gsub(/\s+/, '')}Uninstaller.exe".gsub('/', '\\') tranformations = { package_display_name: config[:name], uninstaller_location: uninstaller_exe_path, install_commands: config[:install_commands], uninstall_commands: config[:uninstall_commands] } [ { source: installer_file, destination: installer_exe_path }, { source: uninstaller_file, destination: uninstaller_exe_path }, ].each do |exe| fixture_path = File.join( File.dirname(__FILE__), '..', '..', '..', '..', 'fixtures', exe[:source] ) code = File.read(fixture_path) % tranformations build_mock_exe(host, exe[:destination], code) end # If the registry key still exists from a previous package install, then delete it. teardown do if package_installed?(host, config[:name]) on host, powershell("\"Remove-Item HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\#{config[:name]}\"") end end # return the installer path for tests to use as the source: attribute installer_exe_path end def build_mock_exe(host, destination, code) # Make a source file containing the code on the SUT, the source file # will be the same location/name as the destination exe but with the .cs # extension source_path_on_host = destination.gsub(/\.exe$/, '.cs') create_remote_file(host, source_path_on_host.gsub('\\', '/'), code) # Create the installer.exe file by compiling the copied over C# code # with PowerShell create_installer_exe = "\"Add-Type"\ " -TypeDefinition (Get-Content #{source_path_on_host} | Out-String)"\ " -Language CSharp"\ " -OutputAssembly #{destination}"\ " -OutputType ConsoleApplication\"" on host, powershell(create_installer_exe) end def package_installed?(host, name) # A successfully installed mock package will have created a registry key under # HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall. Simply checking # for that key should suffice as an indicator that the installer completed test_key = "\"Test-Path HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\#{name}\"" on(host, powershell(test_key)) do |result| return result.stdout.chomp == 'True' end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/lib/puppet/acceptance/windows_utils/service.rb000066400000000000000000000112471527241624000321320ustar00rootroot00000000000000module Puppet module Acceptance module WindowsUtils # Sets up a mock service on the host. The methodology here is a simplified # version of what's described in https://msdn.microsoft.com/en-us/magazine/mt703436.aspx def setup_service(host, config = {}, service_file = 'MockService.cs') config[:name] ||= "Mock Service" config[:display_name] ||= "#{config[:name]} (Puppet Acceptance Tests)" config[:description] ||= "Service created solely for acceptance testing the Puppet Windows Service provider" # Create a temporary directory to store the service's C# source code + # its .exe file. tmpdir = host.tmpdir("mock_service") # Copy-over the C# code code_fixture_path = File.join( File.dirname(__FILE__), '..', '..', '..', '..', 'fixtures', service_file ) code = File.read(code_fixture_path) % { service_name: config[:name], start_sleep: config[:start_sleep], pause_sleep: config[:pause_sleep], continue_sleep: config[:continue_sleep], stop_sleep: config[:stop_sleep] } code_path_unix = "#{tmpdir}/source.cs" code_path_win = code_path_unix.gsub('/', '\\') create_remote_file(host, code_path_unix, code) # Create the service.exe file by compiling the copied over C# code # with PowerShell service_exe_path_win = "#{tmpdir}/#{config[:name]}.exe".gsub('/', '\\') create_service_exe = "\"Add-Type"\ " -TypeDefinition (Get-Content #{code_path_win} | Out-String)"\ " -Language CSharp"\ " -OutputAssembly #{service_exe_path_win}"\ " -OutputType ConsoleApplication"\ " -ReferencedAssemblies 'System.ServiceProcess'\"" on host, powershell(create_service_exe) # Now register the service with SCM register_service_with_scm = "\"New-Service"\ " #{config[:name]}"\ " #{service_exe_path_win}"\ " -DisplayName '#{config[:display_name]}'"\ " -Description '#{config[:description]}'"\ " -StartupType Automatic\"" on host, powershell(register_service_with_scm) # Ensure that our service is deleted after the tests teardown { delete_service(host, config[:name]) } end def delete_service(host, name) # Check if our service has already been deleted. If so, then we # have nothing else to do. begin on host, powershell("Get-Service #{name}") rescue Beaker::Host::CommandFailure return end # Ensure that our service process is killed. We cannot do a Stop-Service here # b/c there's a chance that our service could be in a pending state (e.g. # "PausePending", "ContinuePending"). If this is the case, then Stop-Service # will fail. on host, powershell("\"Get-Process #{name} -ErrorAction SilentlyContinue | Stop-Process -Force\" | exit 0") # Now remove our service. We use sc.exe because older versions of PowerShell # may not have the Remove-Service commandlet. on agent, "sc.exe delete #{name}" end # Config should be a hash of => def assert_service_properties_on(host, name, properties = {}) properties.each do |property, expected_value| # We need to get the underlying WMI object for the service since that # object contains all of our service properties. The one returned by # Get-Service only has these properties for newer versions of PowerShell. get_property_value = "\"Get-WmiObject -Class Win32_Service"\ " | Where-Object { \\$_.name -eq '#{name}' }"\ " | ForEach-Object { \\$_.#{property} }\"" on(host, powershell(get_property_value)) do |result| actual_value = result.stdout.chomp property_str = "#{name}[#{property}]" assert_match(expected_value, actual_value, "EXPECTED: #{property_str} = #{expected_value}, ACTUAL: #{property_str} = #{actual_value}") end end end def assert_service_startmode_delayed(host, name) get_delayed_service = "\"Get-ChildItem HKLM:\\SYSTEM\\CurrentControlSet\\Services"\ " | Where-Object { \\$_.Property -Contains 'DelayedAutoStart' -And \\$_.PsChildName -Like '#{name}' }"\ " | Select-Object -ExpandProperty PSChildName\"" on(host, powershell(get_delayed_service)) do |result| svc = result.stdout.chomp assert(!svc.empty?, "Service #{name} does not exist or is not a delayed service") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/pending/000077500000000000000000000000001527241624000225015ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/pending/ticket_11860_exec_should_not_override_locale.rb000066400000000000000000000055501527241624000335350ustar00rootroot00000000000000test_name "#11860: exec resources should not override system locale" ####################################################################################### # NOTE ####################################################################################### # # This test won't run properly until the test agent nodes have the Spanish language # pack installed on them. On an ubuntu system, this can be done with the following: # # apt-get install language-pack-es-base # # Also, this test depends on the following pull requests: # # https://github.com/puppetlabs/puppet-acceptance/pull/123 # https://github.com/puppetlabs/facter/pull/159 # ####################################################################################### temp_file_name = "/tmp/11860_exec_should_not_override_locale.txt" locale_string = "es_ES.UTF-8" step "Check value of LANG environment variable" # in this step we are going to run an "exec" block that writes the value of the LANG # environment variable to a file. We need to verify that exec's are no longer # forcefully setting this var to 'C'. test_LANG_manifest = < "/usr/bin/printenv LANG > #{temp_file_name}", } HERE # apply the manifest. # # note that we are passing in an extra :environment argument, which will cause the # framework to temporarily set this variable before executing the puppet command. # this lets us know what value we should be looking for as the output of the exec. apply_manifest_on agents, test_LANG_manifest, :environment => {:LANG => locale_string} # cat the temp file and make sure it contained the correct value. on(agents, "cat #{temp_file_name}").each do |result| assert_equal(locale_string, "#{result.stdout.chomp}", "Unexpected result for host '#{result.host}'") end step "Check for locale-specific output of cat command" # in this step we are going to run an "exec" block that runs the "cat" command. The command # is intentionally invalid, because we are going to run it using a non-standard locale and # we want to confirm that the error message is in the correct language. test_cat_manifest = < "/bin/cat SOME_FILE_THAT_DOESNT_EXIST > #{temp_file_name} 2>&1", returns => 1, } HERE # apply the manifest, again passing in the extra :environment argument to set our locale. apply_manifest_on agents, test_cat_manifest, :environment => {:LANG => locale_string} # cat the output file and ensure that the error message is in spanish on(agents, "cat #{temp_file_name}").each do |result| assert_equal("/bin/cat: SOME_FILE_THAT_DOESNT_EXIST: No existe el fichero o el directorio", "#{result.stdout.chomp}", "Unexpected result for host '#{result.host}'") end step "cleanup" # remove the temp file on agents, "rm -f #{temp_file_name}" OpenVoxProject-openvox-ebcec1e/acceptance/pending/ticket_4149_parseonly_should_not_fail.rb000066400000000000000000000016011527241624000323150ustar00rootroot00000000000000test_name "#4149: parseonly should do the right thing" step "test with a manifest with syntax errors" manifest = 'class someclass { notify { "hello, world" } }' apply_manifest_on(agents, manifest, :parseonly => true, :acceptable_exit_codes => [1]) { stdout =~ /Could not parse for .*: Syntax error/ or fail_test("didn't get a reported systax error") } step "test with a manifest with correct syntax" apply_manifest_on agents,'class someclass { notify("hello, world") }', :parseonly => true # REVISIT: This tests the current behaviour, which is IMO not actually the # correct behaviour. On the other hand, if we change this we might # unexpectedly break things out in the wild, so better to be warned than to be # surprised by it. --daniel 2010-12-22 step "test with a class with an invalid attribute" apply_manifest_on agents, 'file { "/tmp/whatever": fooble => 1 }', :parseonly => true ticket_4151_defined_function_should_not_return_true_for_unrealized_virtual_resources.rb000066400000000000000000000014041527241624000441120ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/pendingtest_name "#4151: defined function should not return true for unrealized virtual resources" # Jeff McCune # 2010-07-06 # # This script is expected to exit non-zero if ticket 4151 has not been # fixed. # # The expected behavior is for defined() to only return true if a virtual # resource has been realized. # # This test creates a virtual resource, does NOT realize it, then calls # the defined() function against it. If defined returns true, there will # be an error since Notify["goodbye"] will require a resource which has # not been realized. manifest1 = %q{ @notify { "hello": } if (defined(Notify["hello"])) { $requires = [ Notify["hello"] ] } notify { "goodbye": require => $requires } } apply_manifest_on(agents, manifest1) OpenVoxProject-openvox-ebcec1e/acceptance/pending/ticket_5027_warn_on_dynamic_scope.rb000066400000000000000000000014131527241624000314050ustar00rootroot00000000000000test_name "#5027: Issue warnings when using dynamic scope" step "Apply dynamic scoping manifest on agents" apply_manifest_on agents, %q{ $foo = 'foo_value' class a { $bar = 'bar_value' include b } class b inherits c { notify { $baz: } # should not generate a warning -- inherited from class c notify { $bar: } # should generate a warning -- uses dynamic scoping notify { $foo: } # should not generate a warning -- comes from top scope } class c { $baz = 'baz_value' } include a } step "Verify deprecation warning" fail_test "Deprecation warning not issued" unless stdout.include? 'warning: Dynamic lookup of $bar will not be supported in future versions. Use a fully-qualified variable name or parameterized classes.' OpenVoxProject-openvox-ebcec1e/acceptance/pending/ticket_5224_exec_should_unset_user_env_vars.rb000066400000000000000000000073521527241624000335350ustar00rootroot00000000000000test_name "#5224: exec resources should unset user-related environment variables" ####################################################################################### # NOTE ####################################################################################### # # This test depends on the following pull requests: # # https://github.com/puppetlabs/puppet-acceptance/pull/123 # # because it needs to be able to set some environment variables for the duration of # the puppet commands. Shouldn't be moved out of 'pending' until after that has been # merged. # ####################################################################################### temp_file_name = "/tmp/5224_exec_should_unset_user_env_vars.txt" sentinel_string = "Abracadabra" # these should match up with the value of Puppet::Util::POSIX_USER_ENV_VARS, # but I don't have access to that from here, so this is unfortunately hard-coded # (cprice 2012-01-27) POSIX_USER_ENV_VARS = ['HOME', 'USER', 'LOGNAME'] step "Check value of user-related environment variables" # in this step we are going to run some "exec" blocks that writes the value of the # user-related environment variables to a file. We need to verify that exec's are # unsetting these vars. test_printenv_manifest = < "/usr/bin/printenv %s > #{temp_file_name}", } HERE # loop over the vars that we care about; these should match up with the value of Puppet::Util::POSIX_USER_ENV_VARS, # but I don't have access to that from here, so this is unfortunately hard-coded (cprice 2012-01-27) POSIX_USER_ENV_VARS.each do |var| # apply the manifest. # # note that we are passing in an extra :environment argument, which will cause the # framework to temporarily set this variable before executing the puppet command. # this lets us know what value we should be looking for as the output of the exec. apply_manifest_on agents, test_printenv_manifest % [var, var], :environment => {var => sentinel_string} # cat the temp file and make sure it contained the correct value. on(agents, "cat #{temp_file_name}").each do |result| assert_equal("", "#{result.stdout.chomp}", "Unexpected result for host '#{result.host}', environment var '#{var}'") end end step "Check value of user-related environment variables when they are provided as part of the exec resource" # in this step we are going to run some "exec" blocks that write the value of the # user-related environment variables to a file. However, this time, the manifest # explicitly overrides these variables in the "environment" section, so we need to # be sure that we are respecting these overrides. test_printenv_with_env_overrides_manifest = < "/usr/bin/printenv %s > #{temp_file_name}", environment => ["%s=#{sentinel_string}", "FOO=bar"] } HERE # loop over the vars that we care about; POSIX_USER_ENV_VARS.each do |var| # apply the manifest. # # note that we are passing in an extra :environment argument, which will cause the # framework to temporarily set this variable before executing the puppet command. # this lets us know what value we should be looking for as the output of the exec. apply_manifest_on agents, test_printenv_with_env_overrides_manifest % [var, var, var], :environment => {var => sentinel_string} # cat the temp file and make sure it contained the correct value. on(agents, "cat #{temp_file_name}").each do |result| assert_equal(sentinel_string, "#{result.stdout.chomp}", "Unexpected result for host '#{result.host}', environment var '#{var}'") end end step "cleanup" # remove the temp file on agents, "rm -f #{temp_file_name}" OpenVoxProject-openvox-ebcec1e/acceptance/pending/ticket_6928_puppet_master_parse_fails.rb000066400000000000000000000033411527241624000323220ustar00rootroot00000000000000test_name "#6928: Puppet --parseonly should return deprication message" # Create good and bad formatted manifests step "Master: create valid, invalid formatted manifests" create_remote_file(master, '/tmp/good.pp', %w{notify{good:}} ) create_remote_file(master, '/tmp/bad.pp', 'notify{bad:') step "Master: use --parseonly on an invalid manifest, should return 1 and issue deprecation warning" on master, puppet_master( %w{--parseonly /tmp/bad.pp} ), :acceptable_exit_codes => [ 1 ] fail_test "Deprecation warning not issued for --parseonly" unless stdout.include? '--parseonly has been removed. Please use \'puppet parser validate \'' step "Agents: create valid, invalid formatted manifests" agents.each do |host| create_remote_file(host, '/tmp/good.pp', %w{notify{good:}} ) create_remote_file(host, '/tmp/bad.pp', 'notify{bad:') end step "Agents: use --parseonly on an invalid manifest, should return 1 and issue deprecation warning" agents.each do |host| on(host, "puppet --parseonly /tmp/bad.pp}", :acceptable_exit_codes => [ 1 ]) do fail_test "Deprecation warning not issued for --parseonly" unless stdout.include? '--parseonly has been removed. Please use \'puppet parser validate \'' end end step "Test Face for ‘parser validate’ with good manifest -- should pass" agents.each do |host| on(host, "puppet parser validate /tmp/good.pp", :acceptable_exit_codes => [ 0 ]) end step "Test Face for ‘parser validate’ with bad manifest -- should fail" agents.each do |host| on(host, "puppet parser validate /tmp/bad.pp", :acceptable_exit_codes => [ 1 ]) do fail_test "Bad manifest detection failed" unless stderr.include? 'Could not run: Could not parse for environment production' end end OpenVoxProject-openvox-ebcec1e/acceptance/pre-suite/000077500000000000000000000000001527241624000227725ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/pre-suite/000_configure_type_defaults.rb000066400000000000000000000005651527241624000306150ustar00rootroot00000000000000# Ensures that the /root/.ssh/environment file is # set up with a path that includes /opt/puppetlabs/bin. # Normally this would be called as part of beaker-puppet # install steps, but we are installing openvox packages outside # of beaker-puppet, since it doesn't handle openvox. test_name('configure root ssh environment path') do configure_type_defaults_on(agents) end OpenVoxProject-openvox-ebcec1e/acceptance/pre-suite/005_set_server_tmpdir.rb000066400000000000000000000007631527241624000274510ustar00rootroot00000000000000# Set TMPDIR on the primary so that mktemp creates directories outside /tmp. # With systemd PrivateTmp=true on the puppetserver service, the server process # gets its own /tmp namespace and can't see directories created there by beaker. test_name('configure TMPDIR for PrivateTmp compatibility') do server_tmpdir = '/opt/puppetlabs/test-tmp' on(master, "mkdir -p #{server_tmpdir} && chown puppet #{server_tmpdir} && chmod 755 #{server_tmpdir}") master.add_env_var('TMPDIR', server_tmpdir) end OpenVoxProject-openvox-ebcec1e/acceptance/pre-suite/010_set_puppetserver_memory_defaults.rb000066400000000000000000000017721527241624000326040ustar00rootroot00000000000000# Tune puppetserver java to half the system memory. test_name 'Set Puppetserver Memory Defaults' do skip_test 'No primary node to configure Puppetserver memory defaults for' unless master mem_in_bytes = on(master, 'facter memory.system.total_bytes').stdout.strip megabytes = 1024 * 1024 half_mem = (mem_in_bytes.to_i / megabytes / 2) defaults_dir = case master.platform when /debian|ubuntu/ then '/etc/default' else '/etc/sysconfig' end if half_mem > 2048 mem_regex = "-Xms[0-9]+[m|g][[:blank:]]+-Xmx[0-9]+[m|g]" mem_replacement = "-Xms#{half_mem}m -Xmx#{half_mem}m" on(master, <<~EOS) sed -i -E \ -e '/^JAVA_ARGS=/ s/#{mem_regex}/#{mem_replacement}/' \ #{defaults_dir}/puppetserver EOS on(master, "cat #{defaults_dir}/puppetserver") else logger.info("System memory on the primary is less than 4GB (#{(mem_in_bytes.to_i / megabytes)}m). Leaving the defult 2GB for Puppetserver memory.") end end OpenVoxProject-openvox-ebcec1e/acceptance/pre-suite/011_set_puppetserver_timeouts.rb000066400000000000000000000025731527241624000312570ustar00rootroot00000000000000test_name 'Set Puppetserver start and reload timeouts' do skip_test 'No primary node to configure Puppetserver timeouts for' unless master start_timeout = options['puppetserver-start-timeout'] reload_timeout = options['puppetserver-reload-timeout'] skip_test 'No timeout options specified, skipping' if (start_timeout.nil? && reload_timeout.nil?) # Update the defaults used internally by the puppetserver # service scripts. defaults_dir = case master.platform when /debian|ubuntu/ then '/etc/default' else '/etc/sysconfig' end exprs = [] exprs << "-e '/^START_TIMEOUT=/ s/=.*$/=#{start_timeout}/'" if !start_timeout.nil? exprs << "-e '/^RELOAD_TIMEOUT=/ s/=.*$/=#{reload_timeout}/'" if !reload_timeout.nil? on(master, "sed -i #{exprs.join(' ')} #{defaults_dir}/puppetserver") on(master, "cat #{defaults_dir}/puppetserver") # And update the defaults used by the systemd service unit. # Puppetserver will effectively timeout a start at whichever # is shorter... if !start_timeout.nil? dropin_dir = '/etc/systemd/system/puppetserver.service.d' on(master, <<~EOS) mkdir -p #{dropin_dir} printf '[Service]\\nTimeoutStartSec=#{start_timeout}\\n' \ > #{dropin_dir}/timeouts.conf EOS on(master, 'systemctl daemon-reload') on(master, 'systemctl cat puppetserver.service') end end OpenVoxProject-openvox-ebcec1e/acceptance/pre-suite/012_disable_dropsonde.rb000066400000000000000000000010641527241624000273620ustar00rootroot00000000000000# Ensure openvox-server telemetry is off, for one because we wouldn't # want false results from test runs, and more specifically because of # reload delays: # https://github.com/OpenVoxProject/openvox-server/issues/24 test_name 'Disable Dropsonde' do skip_test 'not testing with puppetserver' unless @options['is_puppetserver'] puppetserver_opts = { dropsonde: { enabled: false, }, } puppetserver_conf = File.join("#{master['puppetserver-confdir']}", 'puppetserver.conf') modify_tk_config(master, puppetserver_conf, puppetserver_opts) end OpenVoxProject-openvox-ebcec1e/acceptance/pre-suite/015_prep_locales.rb000066400000000000000000000005211527241624000263520ustar00rootroot00000000000000test_name 'Ensure locales are present' do agents.each do |agent| package = case agent.platform when /^el/ then 'glibc-all-langpacks' when /debian/ then 'locales-all' else nil end on(agent, puppet_resource('package', package, 'ensure=present')) if !package.nil? end end OpenVoxProject-openvox-ebcec1e/acceptance/pre-suite/040_ValidateSignCert.rb000066400000000000000000000023771527241624000271030ustar00rootroot00000000000000test_name 'Validate Sign Cert' do need_to_run = false hosts.each do |host| need_to_run ||= !host['use_existing_container'] end skip_test 'No new hosts to create, skipping' unless need_to_run skip_test 'not testing with puppetserver' unless @options['is_puppetserver'] hostname = on(master, 'facter hostname').stdout.strip fqdn = on(master, 'facter fqdn').stdout.strip step 'Ensure puppet is stopped' on(master, puppet('resource', 'service', master['puppetservice'], 'ensure=stopped')) step 'Clear SSL on all hosts' hosts.each do |host| ssldir = host.puppet['ssldir'] # preserve permissions for master's ssldir so puppetserver can read it on(host, "rm -rf '#{ssldir}/'*") end step "Set 'server' setting" hosts.each do |host| on(host, puppet("config set server #{fqdn} --section main")) end step 'Start puppetserver' do master_opts = { main: { dns_alt_names: "puppet,#{hostname},#{fqdn}", server: fqdn, autosign: true, }, } on(master, 'puppetserver ca setup') with_puppet_running_on(master, master_opts) do step 'Agents: Run agent --test with autosigning enabled to get cert' on(agents, puppet('agent --test'), acceptable_exit_codes: [0, 2]) end end end OpenVoxProject-openvox-ebcec1e/acceptance/pre-suite/045_EnsureMasterStarted.rb000066400000000000000000000003331527241624000276520ustar00rootroot00000000000000test_name 'Ensure the master is running' skip_test 'not testing with puppetserver' unless @options['is_puppetserver'] on(master, puppet('resource', 'service', master['puppetservice'], 'ensure=running', 'enable=true')) OpenVoxProject-openvox-ebcec1e/acceptance/teardown/000077500000000000000000000000001527241624000227005ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/teardown/common/000077500000000000000000000000001527241624000241705ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/teardown/common/099_Archive_Logs.rb000066400000000000000000000114101527241624000274600ustar00rootroot00000000000000require 'date' def file_glob(host, path) result = on(host, "ls #{path}", :acceptable_exit_codes => [0, 2]) return [] if result.exit_code != 0 return result.stdout.strip.split("\n") end # This test is prefixed with zzz so it will hopefully run last. test_name 'Backup puppet logs and app data on all hosts' do today = Date.today().to_s # truncate the job name so it only has the name-y part and no parameters job_name = (ENV['JOB_NAME'] || 'unknown_jenkins_job') .sub(/[A-Z0-9_]+=.*$/, '') .gsub(/[\/,.]/, '_')[0..200] archive_name = "#{job_name}__#{ENV['BUILD_ID']}__#{today}__sut-files.tgz" archive_root = "SUT_#{today}" hosts.each do |host| step("Capturing log errors for #{host}") do case host[:platform] when /windows/ # on Windows, all of the desired data (including logs) is in the data dir puppetlabs_data = 'C:/ProgramData/PuppetLabs' archive_file_from(host, puppetlabs_data, {}, archive_root, archive_name) # Note: Windows `ls` uses absolute paths for all matches when an absolute path is supplied. tempdir = 'C:/Windows/TEMP' file_glob(host, File.join(tempdir, 'install-puppet-*.log')).each do |install_log| archive_file_from(host, install_log, {}, archive_root, archive_name) end file_glob(host, File.join(tempdir, 'puppet-*-installer.log')).each do |install_log| archive_file_from(host, install_log, {}, archive_root, archive_name) end else puppetlabs_logdir = '/var/log/puppetlabs' grep_for_alerts = if host[:platform] =~ /solaris/ "egrep -i 'warn|error|fatal'" elsif host[:platform] =~ /aix/ "grep -iE -B5 -A10 'warn|error|fatal'" else "grep -i -B5 -A10 'warn\\|error\\|fatal'" end ## If there are any PL logs, try to echo all warning, error, and fatal ## messages from all PL logs to the job's output on(host, <<-GREP_FOR_ALERTS, :accept_all_exit_codes => true ) if [ -d #{puppetlabs_logdir} ] && [ -n "$(find #{puppetlabs_logdir} -name '*.log*')" ]; then for log in $(find #{puppetlabs_logdir} -name '*.log*'); do # grep /dev/null only to get grep to print filenames, since -H is not in POSIX spec for grep #{grep_for_alerts} $log /dev/null; echo "" done fi GREP_FOR_ALERTS step("Archiving logs for #{host} into #{archive_name} (muzzling everything but :warn or higher beaker logs...)") do ## turn the logger off to avoid getting hundreds of lines of scp progress output previous_level = @logger.log_level @logger.log_level = :warn pxp_cache = '/opt/puppetlabs/pxp-agent/spool' puppetlabs_data = '/etc/puppetlabs' version_lookup_result = on(host, "cat /opt/puppetlabs/puppet/VERSION", :accept_all_exit_codes => true) # If we can't find a VERSION file, chances are puppet wasn't # installed and these paths aren't present. Beaker's # archive_file_from() will fail if it can't find the file, and we # want to proceed... if version_lookup_result.exit_code == 0 agent_version = version_lookup_result.output.strip archive_file_from(host, pxp_cache, {}, archive_root, archive_name) unless version_is_less(agent_version, "1.3.2") archive_file_from(host, puppetlabs_data, {}, archive_root, archive_name) archive_file_from(host, puppetlabs_logdir, {}, archive_root, archive_name) end syslog_dir = '/var/log' syslog_name = 'messages' if host[:platform] =~ /ubuntu|debian/ syslog_name = 'syslog' elsif host[:platform] =~ /solaris/ syslog_dir = '/var/adm' # Next few lines are for debugging POOLER-200, once that is resolved this can be removed @logger.log_level = previous_level on(host, 'egrep -i \'reboot after panic\' /var/adm/messages', :acceptable_exit_codes => [0,1,2]) @logger.log_level = :warn elsif host[:platform] =~ /osx/ syslog_name = "system.log" elsif host[:platform] =~ /fedora/ on(host, "journalctl --no-pager > /var/log/messages") elsif host[:platform] =~ /aix/ on(host, "alog -o -t console > /var/log/messages") end syslog_path = File.join(syslog_dir, syslog_name) if host.file_exist?(syslog_path) archive_file_from(host, syslog_path, {}, archive_root, archive_name) end ## turn the logger back on in case someone else wants to log things @logger.log_level = previous_level end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/000077500000000000000000000000001527241624000222175ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/agent/000077500000000000000000000000001527241624000233155ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/agent/agent_disable_lockfile.rb000066400000000000000000000076651527241624000303110ustar00rootroot00000000000000test_name "C4553 - agent --disable/--enable functionality should manage the agent lockfile properly" tag 'audit:integration', # lockfile uses the standard `vardir` location to store/query lockfile. # The validation of the `vardir` at the OS level # should be accomplished in another test. 'audit:high', 'audit:refactor', # This test should not require a master. Remove the use of `with_puppet_running_on`. 'shard:group1' # For splitting out groups of tests for slow test runners # # This test is intended to ensure that puppet agent --enable/--disable # work properly, both in terms of complying with our public "API" around # lockfile semantics ( https://docs.openvoxproject.org/openvox/latest/configuration.html#agent_catalog_run_lockfile ), and # in terms of actually restricting or allowing new agent runs to begin. # require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils initialize_temp_dirs() @all_tests_passed = false ############################################################################### # BEGIN TEST LOGIC ############################################################################### teardown do if @all_tests_passed then remove_temp_dirs() end agents.each do |agent| on(agent, puppet('agent', "--enable")) end end tuples = [ ["reason not specified", false], ["I'm busy; go away.'", true] ] with_puppet_running_on(master, {}) do tuples.each do |expected_message, explicitly_specify_message| step "disable the agent; specify message? '#{explicitly_specify_message}', message: '#{expected_message}'" do agents.each do |agent| if (explicitly_specify_message) on(agent, puppet('agent', "--disable \"#{expected_message}\"")) else on(agent, puppet('agent', "--disable")) end agent_disabled_lockfile = "#{agent.puppet['vardir']}/state/agent_disabled.lock" unless file_exists?(agent, agent_disabled_lockfile) then fail_test("Failed to create disabled lock file '#{agent_disabled_lockfile}' on agent '#{agent}'") end lock_file_content = file_contents(agent, agent_disabled_lockfile) # This is a hack; we should parse the JSON into a hash, but I don't # think I have a library available from the acceptance test framework # that I can use to do that. So I'm falling back to regex. lock_file_content_regex = /"disabled_message"\s*:\s*"#{expected_message}"/ unless lock_file_content =~ lock_file_content_regex fail_test("Disabled lock file contents invalid; expected to match '#{lock_file_content_regex}', got '#{lock_file_content}' on agent '#{agent}'") end end end step "attempt to run the agent (message: '#{expected_message}')" do agents.each do |agent| on(agent, puppet('agent', "--test"), :acceptable_exit_codes => [1]) do |result| disabled_regex = /administratively disabled.*'#{expected_message}'/ unless result.stdout =~ disabled_regex fail_test("Unexpected output from attempt to run agent disabled; expecting to match '#{disabled_regex}', got '#{result.stdout}' on agent '#{agent}'") unless agent['locale'] == 'ja' end end end end step "enable the agent (message: '#{expected_message}')" do agents.each do |agent| agent_disabled_lockfile = "#{agent.puppet['vardir']}/state/agent_disabled.lock" on(agent, puppet('agent', "--enable")) if file_exists?(agent, agent_disabled_lockfile) then fail_test("Failed to remove disabled lock file '#{agent_disabled_lockfile}' on agent '#{agent}'") end end end step "verify that we can run the agent (message: '#{expected_message}')" do agents.each do |agent| on(agent, puppet('agent', "--test")) end end end # tuples block end # with_puppet_running_on block @all_tests_passed = true OpenVoxProject-openvox-ebcec1e/acceptance/tests/agent/agent_fails_with_unknown_resource.rb000066400000000000000000000053071527241624000326440ustar00rootroot00000000000000test_name "agent run should fail if it finds an unknown resource type" do tag 'audit:high', 'audit:integration', 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils step "agent should fail when it can't find a resource" do vendor_modules_path = master.tmpdir('vendor_modules') tmp_environment = mk_tmp_environment_with_teardown(master, 'tmp') site_pp_content = <<-SITEPP define foocreateresource($one) { $msg = 'hello' notify { $name: message => $msg } } class example($x) { if $x == undef or $x == [] or $x == '' { notice 'foo' return() } notice 'bar' } node default { class { example: x => [] } create_resources('foocreateresource', {'blah'=>{'one'=>'two'}}) mycustomtype{'foobar':} } SITEPP manifests_path = "#{test_tmpdir}/#{tmp_environment}/manifests" on(master, "mkdir -p '#{manifests_path}'") create_remote_file(master, "#{manifests_path}/site.pp", site_pp_content) custom_type_content = <<-CUSTOMTYPE Puppet::Type.newtype(:mycustomtype) do @doc = "Create a new mycustomtype thing." newparam(:name, :namevar => true) do desc "Name of mycustomtype instance" end def refresh end end CUSTOMTYPE type_path = "#{vendor_modules_path}/foo/lib/puppet/type" on(master, "mkdir -p '#{type_path}'") create_remote_file(master, "#{type_path}/mycustomtype.rb", custom_type_content) on(master, "chmod -R 750 '#{vendor_modules_path}' '#{test_tmpdir}/#{tmp_environment}'") on(master, "chown -R #{master.puppet['user']}:#{master.puppet['group']} '#{vendor_modules_path}' '#{test_tmpdir}/#{tmp_environment}'") master_opts = { 'main' => { 'environment' => tmp_environment, 'vendormoduledir' => vendor_modules_path } } with_puppet_running_on(master, master_opts) do agents.each do |agent| teardown do agent.rm_rf(vendor_modules_path) end # override vendormoduledir in case agent and server are on the same host agent_dir = get_test_file_path(agent, 'vendormodulepath') on(agent, puppet('agent', '-t', '--environment', tmp_environment, '--vendormoduledir', agent_dir), acceptable_exit_codes: [1]) do |result| assert_match(/Error: Failed to apply catalog: Resource type 'Mycustomtype' was not found/, result.stderr) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/agent/agent_parses_json_catalog.rb000066400000000000000000000016761527241624000310520ustar00rootroot00000000000000test_name "C99978: Agent parses a JSON catalog" tag 'risk:high', 'audit:high', # tests defined catalog format 'audit:integration', # There is no OS specific risk here. 'server', 'catalog:json', 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' require 'json' step "Agent parses a JSON catalog" do agents.each do |agent| # Path to a ruby binary ruby = Puppet::Acceptance::CommandUtils.ruby_command(agent) # Refresh the catalog on(agent, puppet("agent --test")) # The catalog file should be parseable JSON json_catalog = File.join(agent.puppet['client_datadir'], 'catalog', "#{agent.puppet['certname']}.json") on(agent, "cat #{json_catalog} | #{ruby} -rjson -e 'JSON.parse(STDIN.read)'") # Can the agent parse it as JSON? on(agent, puppet("catalog find --terminus json > /dev/null")) end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/agent/fallback_to_cached_catalog.rb000066400000000000000000000016551527241624000310730ustar00rootroot00000000000000test_name "fallback to the cached catalog" tag 'audit:high', 'audit:integration', # This test is not OS sensitive. 'audit:refactor', # A catalog fixture can be used for this test. Remove the usage of `with_puppet_running_on`. 'shard:group4' # For splitting out groups of tests for slow test runners step "run agents once to cache the catalog" do with_puppet_running_on master, {} do on(agents, puppet("agent -t")) end end step "run agents again, verify they use cached catalog" do agents.each do |agent| # can't use --test, because that will set usecacheonfailure=false # We use a server that the agent can't possibly talk to in order # to guarantee that no communication can take place. on(agent, puppet("agent --onetime --no-daemonize --server puppet.example.com --verbose")) do |result| assert_match(/Using cached catalog/, result.stdout) unless agent['locale'] == 'ja' end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/agent/last_run_summary_report.rb000066400000000000000000000114201527241624000306370ustar00rootroot00000000000000test_name "The 'last_run_summary.yaml' report has the right location and permissions" do tag 'audit:high', 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils agents.each do |agent| skip_test('This test does not work on Windows in japanese') if agent['platform'] =~ /windows/ && agent['locale'] == 'ja' custom_publicdir = agent.tmpdir('custom_public_dir') statedir = on(agent, puppet('config print statedir')).stdout.chomp fail_test("The 'statedir' config is not set!") if statedir.empty? publicdir = on(agent, puppet('config print publicdir')).stdout.chomp fail_test("The 'publicdir' config is not set!") if publicdir.empty? teardown do agent.rm_rf(custom_publicdir) agent.rm_rf("#{publicdir}/*") unless publicdir.empty? on(agent, puppet("config set publicdir #{publicdir}")) end step "Check if '#{publicdir}' was created during puppet installation" do on(agent, "ls #{publicdir}", :acceptable_exit_codes => [0]) end step "Check if '#{publicdir}' has '0755' permissions" do if agent['platform'] =~ /windows/ on(agent, "icacls #{publicdir}") do |result| # Linux 'Owner' permissions class equivalent assert_match(/BUILTIN\\Administrators:.*\(F\)/, result.stdout) # Known issue on Windows: 'C:\ProgramData\PuppetLabs\puppet' permissions are inherited # by its subfolders and it does not have any permissions for 'Everyone' (see 'PuppetAppDir' # in 'puppet-agent/resources/windows/wix/appdatafiles.wxs') # Below line should be added when solution is found: # assert_match(/Everyone:.*\(RX\)/, result.stdout) end else on(agent, "ls -al #{publicdir}") do |result| assert_match(/rwxr-xr-x.+\.$/, result.stdout) end end end step "Create the 'last_run_summary.yaml' report file by applying catalog" do on(agent, puppet('agent -t')) do |result| assert_match('Applied catalog', result.stdout) end end step "Check if the 'last_run_summary.yaml' report file created has '0640' permissions" do if agent['platform'] =~ /windows/ on(agent, "icacls #{File.join(publicdir, 'last_run_summary.yaml')}") do |result| # Linux 'Owner' premissions class equivalent assert_match('Administrator:(R,W', result.stdout) # Linux 'Group' permissions class equivalent assert_match('None:(R)', result.stdout) # Linux 'Public' permissions class equivalent assert_match('Everyone:(Rc,S,RA)', result.stdout) # According to icacls docs: # Rc = Read control # S = Synchronize # RA = Read attributes # More at https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/icacls end else on(agent, "ls -al #{publicdir}") do |result| assert_match(/rw-r-----.+last_run_summary\.yaml$/, result.stdout) end end end step "Check that '#{statedir}' exists and has no 'last_run_summary.yaml' file" do on(agent, "ls #{statedir}",:acceptable_exit_codes => [0]) do |result| refute_match(/last_run_summary.yaml/, result.stdout) end end step "Check that 'publicdir' can be reconfigured" do on(agent, puppet("config set publicdir #{custom_publicdir}")) on(agent, puppet('config print publicdir')) do |result| assert_match(custom_publicdir, result.stdout) end end step "Create a new 'last_run_summary.yaml' report file by applying catalog" do on(agent, puppet('agent -t')) do |result| assert_match('Applied catalog', result.stdout) end end step "Check if the 'last_run_summary.yaml' report file was created in the new location and still has '0640' permissions" do if agent['platform'] =~ /windows/ on(agent, "icacls #{File.join(custom_publicdir, 'last_run_summary.yaml')}") do |result| # Linux 'Owner' premissions class equivalent assert_match('Administrator:(R,W', result.stdout) # Linux 'Group' permissions class equivalent assert_match('None:(R)', result.stdout) # Linux 'Public' permissions class equivalent assert_match('Everyone:(Rc,S,RA)', result.stdout) # According to icacls docs: # Rc = Read control # S = Synchronize # RA = Read attributes # More at https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/icacls end else on(agent, "ls -al #{custom_publicdir}") do |result| assert_match(/rw-r-----.+last_run_summary\.yaml$/, result.stdout) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/aix/000077500000000000000000000000001527241624000230005ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/aix/aix_package_provider.rb000066400000000000000000000071241527241624000274770ustar00rootroot00000000000000test_name "aix package provider should work correctly" do tag 'audit:high', 'audit:acceptance', # OS specific by definition. 'shard:group2' # For splitting out groups of tests for slow test runners confine :to, :platform => /aix/ dir = "/tmp/aix-packages-#{$$}" def assert_package_version(package, expected_version) # The output of lslpp is a colon-delimited list like: # sudo:sudo.rte:1.8.6.4: : :C: :Configurable super-user privileges runtime: : : : : : :0:0:/: # We want the version, so grab the third field on(hosts, "lslpp -qLc #{package} | cut -f3 -d:") do |result| actual_version = result.stdout.chomp assert_equal(expected_version, actual_version, "Installed package version #{actual_version} does not match expected version #{expected_version}") end end def get_package_manifest(package, version, sourcedir) <<-MANIFEST package { '#{package}': ensure => '#{version}', provider => aix, source => '#{sourcedir}', } MANIFEST end package = 'sudo.rte' version1 = '1.7.10.4' version2 = '1.8.6.4' teardown do on hosts, "rm -rf #{dir}" on hosts, "installp -u #{package}" end step "download packages to use for test" do on hosts, "mkdir -p #{dir}" on hosts, "curl https://artifactory.delivery.puppetlabs.net/artifactory/generic_enterprise__local/misc/sudo.#{version1}.aix51.lam.bff > #{dir}/sudo.#{version1}.aix51.lam.bff" on hosts, "curl https://artifactory.delivery.puppetlabs.net/artifactory/generic_enterprise__local/misc/sudo.#{version2}.aix51.lam.bff > #{dir}/sudo.#{version2}.aix51.lam.bff" end step "install the older version of package" do apply_manifest_on(hosts, get_package_manifest(package, version1, dir), :catch_failures => true) end step "verify package is installed and at the correct version" do assert_package_version package, version1 end step "install a newer version of the package" do apply_manifest_on(hosts, get_package_manifest(package, version2, dir), :catch_failures => true) end step "verify package is installed and at the newer version" do assert_package_version package, version2 end step "test that downgrading fails by trying to install an older version of the package" do apply_manifest_on(hosts, get_package_manifest(package, version1, dir), :acceptable_exit_codes => [4,6]) do |res| assert_match(/aix package provider is unable to downgrade packages/, res.stderr, "Didn't get an error about downgrading packages") end end step "uninstall the package" do apply_manifest_on(hosts, get_package_manifest(package, 'absent', dir), :catch_failures => true) end step "verify the package is gone" do on hosts, "lslpp -qLc #{package}", :acceptable_exit_codes => [1] end step "install the older version of package" do apply_manifest_on(hosts, get_package_manifest(package, version1, dir), :catch_failures => true) end step "verify package is installed and at the correct version" do assert_package_version package, version1 end step "install latest version of the package" do apply_manifest_on(hosts, get_package_manifest(package, 'latest', dir), :catch_failures => true) end step "verify package is installed and at the correct version" do assert_package_version package, version2 end step "PUP-7818 remove a package without defining the source metaparameter" do manifest = get_package_manifest(package, 'latest', dir) manifest = manifest + "package { 'nonexistant_example_package.rte': ensure => absent, }" apply_manifest_on(hosts, manifest, :catch_failures => true) end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/aix/nim_package_provider.rb000066400000000000000000000077321527241624000275060ustar00rootroot00000000000000test_name "NIM package provider should work correctly" tag 'audit:high', 'audit:acceptance', # OS specific by definition 'shard:group3' # For splitting out groups of tests for slow test runners # nim test is slow, confine to only aix 7.2 and recent puppet versions confine :to, :platform => "aix" do |aix| version = on(aix, 'puppet --version').stdout version && Gem::Version.new(version) > Gem::Version.new('6.4.0') && on(aix, 'facter os.release.full').stdout == '7.2' end teardown do test_apply('cdrecord', 'absent', '') test_apply('puppet.test.rte', 'absent', '') end def assert_package_version(package, expected_version) # The output of lslpp is a colon-delimited list like: # sudo:sudo.rte:1.8.6.4: : :C: :Configurable super-user privileges runtime: : : : : : :0:0:/: # We want the version, so grab the third field on(hosts, "lslpp -qLc #{package} | cut -f3 -d:") do |result| actual_version = result.stdout.chomp assert_equal(expected_version, actual_version, "Installed package version #{actual_version} does not match expected version #{expected_version}") end end def get_manifest(package, ensure_value) < '#{ensure_value}', source => 'lpp_custom', provider => nim, } MANIFEST end def test_apply(package_name, ensure_value, expected_version) manifest = get_manifest(package_name, ensure_value) on hosts, puppet_apply(["--detailed-exitcodes", "--verbose"]), {:stdin => manifest, :acceptable_exit_codes => [2]} step "validate installed package version" do assert_package_version package_name, expected_version end step "run again to ensure idempotency" do on hosts, puppet_apply(["--detailed-exitcodes", "--verbose"]), {:stdin => manifest, :acceptable_exit_codes => [0]} end step "validate installed package version" do assert_package_version package_name, expected_version end end # These two packages live in an LPP source on the NIM master. Details # on our nim masters are available at # https://confluence.puppetlabs.com/display/OPS/IBM+Power+LPARs package_types = { "RPM" => { :package_name => "cdrecord", :old_version => '1.9-6', :new_version => '1.9-9' }, "BFF" => { :package_name => "puppet.test.rte", :old_version => '1.0.0.0', :new_version => '2.0.0.0' } } step "Setup: ensure test packages are not installed" do pkgs = ['cdrecord', 'puppet.test.rte'] pkgs.each do |pkg| on hosts, puppet_apply(["--detailed-exitcodes", "--verbose"]), {:stdin => get_manifest(pkg, 'absent'), :acceptable_exit_codes => [0,2]} end end package_types.each do |package_type, details| step "install a #{package_type} package via 'ensure=>present'" do package_name = details[:package_name] version = details[:new_version] test_apply(package_name, 'present', version) end step "uninstall a #{package_type} package via 'ensure=>absent'" do package_name = details[:package_name] version = '' test_apply(package_name, 'absent', version) end step "install a #{package_type} package via 'ensure=>'" do package_name = details[:package_name] version = details[:old_version] test_apply(package_name, version, version) end step "upgrade a #{package_type} package via 'ensure=>'" do package_name = details[:package_name] version = details[:new_version] test_apply(package_name, version, version) end step "attempt to downgrade a #{package_type} package via 'ensure=>'" do package_name = details[:package_name] version = details[:old_version] manifest = get_manifest(package_name, version) on(hosts, puppet_apply("--verbose", "--detailed-exitcodes"), { :stdin => manifest, :acceptable_exit_codes => [4,6] }) do |result| assert_match(/NIM package provider is unable to downgrade packages/, result.stderr, "Didn't get an error about downgrading packages") end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/allow_arbitrary_node_name_fact_for_agent.rb000066400000000000000000000101611527241624000327660ustar00rootroot00000000000000test_name "node_name_fact should be used to determine the node name for puppet agent" tag 'audit:high', 'audit:integration', # Tests that the server properly overrides certname with node_name fact. # Testing of passenger master is no longer needed. 'server', 'shard:group4' # For splitting out groups of tests for slow test runners success_message = "node_name_fact setting was correctly used to determine the node name" testdir = master.tmpdir("nodenamefact") node_names = [] on agents, facter('kernel') do |result| node_names << result.stdout.chomp end node_names.uniq! step "Prepare for custom tk-auth rules" do on master, 'cp /etc/puppetlabs/puppetserver/conf.d/auth.conf /etc/puppetlabs/puppetserver/conf.d/auth.bak' modify_tk_config(master, options['puppetserver-config'], {'jruby-puppet' => {'use-legacy-auth-conf' => false}}) end teardown do modify_tk_config(master, options['puppetserver-config'], {'jruby-puppet' => {'use-legacy-auth-conf' => true}}) on master, 'cp /etc/puppetlabs/puppetserver/conf.d/auth.bak /etc/puppetlabs/puppetserver/conf.d/auth.conf' service(master, :reload, master['puppetservice']) end step "Setup tk-auth rules" do tka_header = <<-HEADER authorization: { version: 1 rules: [ { match-request: { path: "/puppet/v3/file" type: path } allow: "*" sort-order: 500 name: "puppetlabs file" }, HEADER tka_node_rules = node_names.map do |node_name| <<-NODE_RULES { match-request: { path: "/puppet/v3/catalog/#{node_name}" type: path method: [get, post] } allow: "*" sort-order: 500 name: "puppetlabs catalog #{node_name}" }, { match-request: { path: "/puppet/v3/node/#{node_name}" type: path method: get } allow: "*" sort-order: 500 name: "puppetlabs node #{node_name}" }, { match-request: { path: "/puppet/v3/report/#{node_name}" type: path method: put } allow: "*" sort-order: 500 name: "puppetlabs report #{node_name}" }, NODE_RULES end tka_footer = <<-FOOTER { match-request: { path: "/" type: path } deny: "*" sort-order: 999 name: "puppetlabs deny all" } ] } FOOTER tk_auth = [tka_header, tka_node_rules, tka_footer].flatten.join("\n") apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) file { '/etc/puppetlabs/puppetserver/conf.d/auth.conf': ensure => file, mode => '0644', content => '#{tk_auth}', } MANIFEST end step "Setup site.pp for node name based classification" do site_manifest = <<-SITE_MANIFEST node default { notify { "false": } } node #{node_names.map { |name| %Q["#{name}"] }.join(", ")} { notify { "#{success_message}": } } SITE_MANIFEST apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) $directories = [ '#{testdir}', '#{testdir}/environments', '#{testdir}/environments/production', '#{testdir}/environments/production/manifests', ] file { $directories: ensure => directory, mode => '0755', } file { '#{testdir}/environments/production/manifests/manifest.pp': ensure => file, mode => '0644', content => '#{site_manifest}', } MANIFEST end step "Ensure nodes are classified based on the node name fact" do master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", }, 'master' => { 'node_terminus' => 'plain', }, } with_puppet_running_on(master, master_opts, testdir) do on(agents, puppet('agent', "--no-daemonize --verbose --onetime --node_name_fact kernel")) do |result| assert_match(/defined 'message'.*#{success_message}/, result.stdout) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/allow_arbitrary_node_name_for_agent.rb000066400000000000000000000073751527241624000320060ustar00rootroot00000000000000test_name "node_name_value should be used as the node name for puppet agent" tag 'audit:high', 'audit:integration', # Tests that the server properly overrides certname with node_name fact. # Testing of passenger master is no longer needed. 'server', 'shard:group1' # For splitting out groups of tests for slow test runners success_message = "node_name_value setting was correctly used as the node name" testdir = master.tmpdir('nodenamevalue') step "Prepare for custom tk-auth rules" do on master, 'cp /etc/puppetlabs/puppetserver/conf.d/auth.conf /etc/puppetlabs/puppetserver/conf.d/auth.bak' modify_tk_config(master, options['puppetserver-config'], {'jruby-puppet' => {'use-legacy-auth-conf' => false}}) end teardown do on master, 'cp /etc/puppetlabs/puppetserver/conf.d/auth.bak /etc/puppetlabs/puppetserver/conf.d/auth.conf' modify_tk_config(master, options['puppetserver-config'], {'jruby-puppet' => {'use-legacy-auth-conf' => true}}) service(master, :reload, master['puppetservice']) end step "Setup tk-auth rules" do tk_auth = <<-TK_AUTH authorization: { version: 1 rules: [ { match-request: { path: "/puppet/v3/file" type: path } allow: "*" sort-order: 500 name: "puppetlabs file" }, { match-request: { path: "/puppet/v3/catalog/specified_node_name" type: path method: [get, post] } allow: "*" sort-order: 500 name: "puppetlabs catalog" }, { match-request: { path: "/puppet/v3/node/specified_node_name" type: path method: get } allow: "*" sort-order: 500 name: "puppetlabs node" }, { match-request: { path: "/puppet/v3/report/specified_node_name" type: path method: put } allow: "*" sort-order: 500 name: "puppetlabs report" }, { match-request: { path: "/" type: path } deny: "*" sort-order: 999 name: "puppetlabs deny all" } ] } TK_AUTH apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) file { '/etc/puppetlabs/puppetserver/conf.d/auth.conf': ensure => file, mode => '0644', content => '#{tk_auth}', } MANIFEST end step "Setup site.pp for node name based classification" do site_manifest = <<-SITE_MANIFEST node default { notify { "false": } } node specified_node_name { notify { "#{success_message}": } } SITE_MANIFEST apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) $directories = [ '#{testdir}', '#{testdir}/environments', '#{testdir}/environments/production', '#{testdir}/environments/production/manifests', ] file { $directories: ensure => directory, mode => '0755', } file { '#{testdir}/environments/production/manifests/manifest.pp': ensure => file, mode => '0644', content => '#{site_manifest}', } MANIFEST end step "Ensure nodes are classified based on the node name fact" do master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", }, 'master' => { 'node_terminus' => 'plain', }, } with_puppet_running_on(master, master_opts, testdir) do on(agents, puppet('agent', "-t --node_name_value specified_node_name"), :acceptable_exit_codes => [0,2]) do |result| assert_match(/defined 'message'.*#{success_message}/, result.stdout) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/apply/000077500000000000000000000000001527241624000233445ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/apply/classes/000077500000000000000000000000001527241624000250015ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/apply/classes/parameterized_classes.rb000077500000000000000000000033271527241624000317070ustar00rootroot00000000000000test_name "parametrized classes" tag 'audit:high', 'audit:unit', # This should be covered at the unit layer. 'shard:group2' # For splitting out groups of tests for slow test runners ######################################################################## step "should allow param classes" manifest = %q{ class x($y, $z) { notice("${y}-${z}") } class {x: y => '1', z => '2'} } apply_manifest_on(agents, manifest) do |result| fail_test "inclusion after parameterization failed" unless result.stdout.include? "1-2" end ######################################################################## # REVISIT: This was ported from the old set of tests, but I think that # the desired behaviour has recently changed. --daniel 2010-12-23 step "should allow param class post inclusion" manifest = %q{ class x($y, $z) { notice("${y}-${z}") } class {x: y => '1', z => '2'} include x } apply_manifest_on(agents, manifest) do |result| fail_test "inclusion after parameterization failed" unless result.stdout.include? "1-2" end ######################################################################## step "should allow param classes defaults" manifest = %q{ class x($y, $z='2') { notice("${y}-${z}") } class {x: y => '1'} } apply_manifest_on(agents, manifest) do |result| fail_test "the default didn't apply as expected" unless result.stdout.include? "1-2" end ######################################################################## step "should allow param class defaults to be overridden" manifest = %q{ class x($y, $z='2') { notice("${y}-${z}") } class {x: y => '1', z => '3'} } apply_manifest_on(agents, manifest) do |result| fail_test "the override didn't happen as we expected" unless result.stdout.include? "1-3" end OpenVoxProject-openvox-ebcec1e/acceptance/tests/apply/classes/should_allow_param_override.rb000077500000000000000000000010431527241624000331020ustar00rootroot00000000000000test_name "should allow param override" tag 'audit:high', 'audit:unit', # This should be covered at the unit layer. 'shard:group3' # For splitting out groups of tests for slow test runners manifest = %q{ class parent { notify { 'msg': message => parent, } } class child inherits parent { Notify['msg'] {message => 'child'} } include parent include child } apply_manifest_on(agents, manifest) do |result| fail_test "parameter override didn't work" unless result.stdout.include? "defined 'message' as 'child'" end OpenVoxProject-openvox-ebcec1e/acceptance/tests/apply/classes/should_allow_param_undef_override.rb000077500000000000000000000021401527241624000342620ustar00rootroot00000000000000test_name "should allow overriding a parameter to undef in inheritence" tag 'audit:high', 'audit:unit', # This should be covered at the unit layer. 'shard:group4' # For splitting out groups of tests for slow test runners agents.each do |agent| dir = agent.tmpdir('class_undef_override') out = File.join(dir, 'class_undef_override_out') source = File.join(dir, 'class_undef_override_test') manifest = %Q{ class parent { file { 'test': path => '#{out}', source => '#{source}', } } class child inherits parent { File['test'] { source => undef, content => 'hello new world!', } } include parent include child } step "prepare the target file on all systems" on(agent, "echo 'hello world!' > #{out}") step "apply the manifest" apply_manifest_on(agent, manifest) step "verify the file content" on(agent, "cat #{out}") do |result| fail_test "the file was not touched" if result.stdout.include? "hello world!" fail_test "the file was not updated" unless result.stdout.include? "hello new world" end on(agent, "rm -rf #{dir}") end OpenVoxProject-openvox-ebcec1e/acceptance/tests/apply/classes/should_include_resources_from_class.rb000077500000000000000000000006651527241624000346430ustar00rootroot00000000000000test_name "resources declared in a class can be applied with include" tag 'audit:high', 'audit:unit', # This should be covered at the unit layer. 'shard:group1' # For splitting out groups of tests for slow test runners manifest = %q{ class x { notify{'a':} } include x } apply_manifest_on(agents, manifest) do |result| fail_test "the resource did not apply" unless result.stdout.include?("defined 'message' as 'a'") end should_not_auto_include_resources_from_class.rb000077500000000000000000000007251527241624000364710ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/apply/classestest_name "resources declared in classes are not applied without include" tag 'audit:high', 'audit:unit', # This should be covered at the unit layer. 'shard:group2' # For splitting out groups of tests for slow test runners manifest = %q{ class x { notify { 'test': message => 'never invoked' } } } apply_manifest_on(agents, manifest) do |result| fail_test "found the notify despite not including it" if result.stdout.include? "never invoked" end OpenVoxProject-openvox-ebcec1e/acceptance/tests/catalog_with_binary_data.rb000066400000000000000000000060741527241624000275550ustar00rootroot00000000000000test_name "C100300: Catalog containing binary data is applied correctly" do require 'puppet/acceptance/common_utils' require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/agent_fqdn_utils' extend Puppet::Acceptance::AgentFqdnUtils tag 'risk:high', 'server', 'shard:group3' # For splitting out groups of tests for slow test runners test_num = 'c100300' tmp_environment = mk_tmp_environment_with_teardown(master, File.basename(__FILE__, '.*')) agent_tmp_dirs = {} agents.each do |agent| agent_tmp_dirs[agent_to_fqdn(agent)] = agent.tmpdir(tmp_environment) end teardown do step 'remove all test files on agents' do agents.each {|agent| on(agent, "rm -r '#{agent_tmp_dirs[agent_to_fqdn(agent)]}'", :accept_all_exit_codes => true)} end # Remove all traces of the last used environment agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end # note - master teardown is registered by #mk_tmp_environment_with_teardown end step "Create module with binary data file on master" do on(master, "mkdir -p '#{environmentpath}/#{tmp_environment}/modules/#{test_num}'/{manifests,files}") master_module_manifest = "#{environmentpath}/#{tmp_environment}/modules/#{test_num}/manifests/init.pp" master_module_binary_file = "#{environmentpath}/#{tmp_environment}/modules/#{test_num}/files/binary_data" create_remote_file(master, master_module_binary_file, "\xC0\xFF") on(master, "chmod 644 '#{master_module_binary_file}'") manifest = <<-MANIFEST class #{test_num}( ) { \$test_path = \$facts['networking']['fqdn'] ? #{agent_tmp_dirs} file { '#{test_num}': path => "\$test_path/#{test_num}", content => binary_file('#{test_num}/binary_data'), ensure => present, } } MANIFEST create_remote_file(master, master_module_manifest, manifest) on(master, "chmod 644 '#{master_module_manifest}'") end step "Create site.pp to classify nodes to include module" do site_pp_file = "#{environmentpath}/#{tmp_environment}/manifests/site.pp" site_pp = <<-SITE_PP node default { include #{test_num} } SITE_PP create_remote_file(master, site_pp_file, site_pp) on(master, "chmod 644 '#{site_pp_file}'") end step "start the master" do with_puppet_running_on(master, {}) do step "run puppet and ensure that binary data was correctly applied" do agents.each do |agent| on(agent, puppet('agent', '--test', "--environment '#{tmp_environment}'"), :acceptable_exit_codes => 2) on(agent, "#{Puppet::Acceptance::CommandUtils::ruby_command(agent)} -e 'puts File.binread(\"#{agent_tmp_dirs[agent_to_fqdn(agent)]}/#{test_num}\").bytes.map {|b| b.to_s(16)}'") do |res| assert_match(/c0\nff/, res.stdout, 'Binary file did not contain originally specified data') end end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/direct_puppet/000077500000000000000000000000001527241624000250665ustar00rootroot00000000000000cached_catalog_remediate_local_drift.rb000066400000000000000000000113651527241624000346240ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/direct_puppetrequire 'puppet/acceptance/static_catalog_utils' extend Puppet::Acceptance::StaticCatalogUtils test_name "PUP-5122: Puppet remediates local drift using code_id and content_uri" do tag 'audit:high', 'audit:acceptance', 'audit:refactor', # use mk_tmp_environment_with_teardown helper for environment construction 'server', 'shard:group4' # For splitting out groups of tests for slow test runners skip_test 'requires puppetserver installation' if @options[:type] != 'aio' basedir = master.tmpdir(File.basename(__FILE__, '.*')) module_dir = "#{basedir}/environments/production/modules" master_reportdir = create_tmpdir_for_user(master, 'reportdir') master_opts = { 'main' => { 'environmentpath' => "#{basedir}/environments" }, # The server no longer stores reports by default (reports = none); # request storage explicitly like the other report-checking tests do. 'master' => { 'reportdir' => master_reportdir, 'reports' => 'store' } } step "Add versioned-code parameters to puppetserver.conf and ensure the server is running" do setup_puppetserver_code_id_scripts(master, basedir) end teardown do cleanup_puppetserver_code_id_scripts(master, basedir) on master, "rm -rf #{basedir}" on master, "rm -rf #{master_reportdir}" agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step "Create a module and a file with content representing the first code_id version" do apply_manifest_on(master, < true) File { ensure => directory, mode => "0750", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{basedir}':; '#{basedir}/environments':; '#{basedir}/environments/production':; '#{basedir}/environments/production/manifests':; '#{module_dir}':; '#{module_dir}/foo':; '#{module_dir}/foo/files':; } MANIFEST end with_puppet_running_on master, master_opts, basedir do agents.each do |agent| agent_test_file_path = agent.tmpfile('foo_file') step "Add test file resource to site.pp on master with agent-specific file path" do apply_manifest_on(master, < true) File { owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { "#{basedir}/environments/production/manifests/site.pp" : ensure => file, mode => "0640", content => "node default { file { '#{agent_test_file_path}' : ensure => file, source => 'puppet:///modules/foo/foo.txt' } }", } file { "#{module_dir}/foo/files/foo.txt" : ensure => file, content => "code_version_1", mode => "0640", } MANIFEST end step "agent: #{agent}: Initial run: create the file with code version 1 and cache the catalog" on(agent, puppet("agent", "-t"), :acceptable_exit_codes => [0,2]) # When there is no drift, there should be no request made to the server # for file metadata or file content. A puppet run depending on # a non-server will fail if such a request is made. Verify the agent # sends a report. step "Remove existing reports from server reports directory" on(master, "rm -rf #{master_reportdir}/#{agent.node_name}/*") r = on(master, "ls #{master_reportdir}/#{agent.node_name} 2>/dev/null | wc -l").stdout.chomp assert_equal('0', r, "reports directory should be empty!") step "Verify puppet run without drift does not make file request from server" r = on(agent, puppet("agent", "--use_cached_catalog", "--server", "no_such_host", "--report_server", master.hostname, "--onetime", "--no-daemonize", "--detailed-exitcodes", "--verbose" )).stderr assert_equal(r, "", "Fail: Did agent try to contact server?") step "Verify report was delivered to server" r = on(master, "ls #{master_reportdir}/#{agent.node_name} | wc -l").stdout.chomp assert_equal('1', r, "Reports directory should have one file") step "agent: #{agent}: Remove the test file to simulate drift" on(agent, "rm -rf #{agent_test_file_path}") step "Alter the source file on the master to simulate a code update" apply_manifest_on(master, < true) file { "#{module_dir}/foo/files/foo.txt" : ensure => file, mode => "0640", content => "code_version_2", } MANIFEST step "Run agent again using --use_cached_catalog and ensure content from the first code_id is used" on(agent, puppet("agent", "-t", "--use_cached_catalog"), :acceptable_exit_codes => [0,2]) on(agent, "cat #{agent_test_file_path}") do |result| assert_equal('code_version_1', result.stdout) end end end end catalog_uuid_correlates_catalogs_with_reports.rb000066400000000000000000000052441527241624000367120ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/direct_puppettest_name "PUP-5872: catalog_uuid correlates catalogs with reports" do tag 'audit:high', 'audit:acceptance', 'audit:refactor', # remove dependence on server by adding a # catalog and report fixture to validate against. 'shard:group1' # For splitting out groups of tests for slow test runners master_reportdir = create_tmpdir_for_user(master, 'reportdir') def remove_reports_on_master(master_reportdir, agent_node_name) on(master, "rm -rf #{master_reportdir}/#{agent_node_name}/*") end def get_catalog_uuid_from_cached_catalog(host, agent_vardir, agent_node_name) cache_catalog_uuid = nil on(host, "cat #{agent_vardir}/client_data/catalog/#{agent_node_name}.json") do |result| cache_catalog_uuid = result.stdout.match(/"catalog_uuid":"([a-z0-9\-]*)",/)[1] end cache_catalog_uuid end def get_catalog_uuid_from_report(master_reportdir, agent_node_name) report_catalog_uuid = nil on(master, "cat #{master_reportdir}/#{agent_node_name}/*") do |result| report_catalog_uuid = result.stdout.match(/catalog_uuid: '?([a-z0-9\-]*)'?/)[1] end report_catalog_uuid end with_puppet_running_on(master, :master => { :reportdir => master_reportdir, :reports => 'store' }) do agents.each do |agent| agent_vardir = agent.tmpdir(File.basename(__FILE__, '.*')) step "agent: #{agent}: Initial run to retrieve a catalog and generate the first report" do on(agent, puppet("agent", "-t", "--vardir #{agent_vardir}"), :acceptable_exit_codes => [0,2]) end cache_catalog_uuid = get_catalog_uuid_from_cached_catalog(agent, agent_vardir, agent.node_name) step "agent: #{agent}: Ensure the catalog and report share the same catalog_uuid" do report_catalog_uuid = get_catalog_uuid_from_report(master_reportdir, agent.node_name) assert_equal(cache_catalog_uuid, report_catalog_uuid, "catalog_uuid found in cached catalog, #{cache_catalog_uuid} did not match report #{report_catalog_uuid}") end step "cleanup reports on master" do remove_reports_on_master(master_reportdir, agent.node_name) end step "Run with --use_cached_catalog and ensure catalog_uuid in the new report matches the cached catalog" do on(agent, puppet("agent", "--onetime", "--no-daemonize", "--use_cached_catalog", "--vardir #{agent_vardir}"), :acceptance_exit_codes => [0,2]) report_catalog_uuid = get_catalog_uuid_from_report(master_reportdir, agent.node_name) assert_equal(cache_catalog_uuid, report_catalog_uuid, "catalog_uuid found in cached catalog, #{cache_catalog_uuid} did not match report #{report_catalog_uuid}") end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/direct_puppet/static_catalog_env_control.rb000066400000000000000000000221271527241624000330100ustar00rootroot00000000000000test_name "Environment control of static catalogs" tag 'audit:high', 'audit:acceptance', 'audit:refactor', # use mk_tmp_environment_with_teardown helper for environment construction 'server', 'shard:group2' # For splitting out groups of tests for slow test runners skip_test 'requires puppetserver to test static catalogs' if @options[:type] != 'aio' require 'json' @testroot = master.tmpdir(File.basename(__FILE__, '/*')) @coderoot = "#{@testroot}/code" @confdir = master['puppetserver-confdir'] @master_opts = { 'main' => { 'environmentpath' => "#{@coderoot}/environments", }, } @production_files = {} @canary_files = {} @agent_manifests = {} @catalog_files = {} agents.each do |agent| hn = agent.node_name resdir = agent.tmpdir('results') @production_files[hn] = "#{resdir}/prod_hello_from_puppet_uri" @canary_files[hn] = "#{resdir}/can_hello_from_puppet_uri" @catalog_files[hn] = "#{on(agent, puppet('config', 'print', 'client_datadir')).stdout.chomp}/catalog/#{hn}.json" @agent_manifests[hn] = < file, mode => "0644", content => "class hello { notice('hello from production-hello') file { '#{resdir}' : ensure => directory, mode => '0755', } file { '#{resdir}/prod_hello_from_puppet_uri' : ensure => file, mode => '0644', source => 'puppet:///modules/hello/hello_msg', } }", } file { '#{@coderoot}/environments/canary/modules/can_hello/manifests/init.pp': ensure => file, mode => "0644", content => 'class can_hello { notice("hello from production-hello") file { "#{resdir}": ensure => directory, mode => "0755", } file { "#{resdir}/can_hello_from_puppet_uri" : ensure => file, mode => "0644", source => "puppet:///modules/can_hello/hello_msg", } }', } MANIFESTAGENT end # The code_content script needs to return the correct content whose checksum # matches the metadata contained in the static catalog. PRODUCTION_CONTENT = "Hello message from production/hello module, content from source attribute.".freeze CANARY_CONTENT = "Hello message from canary/can_hello module, content from source attribute.".freeze @manifest = < directory, mode => "0755", } file { '#{@testroot}':; '#{@coderoot}':; '#{@coderoot}/environments':; '#{@coderoot}/environments/production':; '#{@coderoot}/environments/production/manifests':; '#{@coderoot}/environments/production/modules':; '#{@coderoot}/environments/production/modules/hello':; '#{@coderoot}/environments/production/modules/hello/manifests':; '#{@coderoot}/environments/production/modules/hello/files':; '#{@coderoot}/environments/canary':; '#{@coderoot}/environments/canary/manifests':; '#{@coderoot}/environments/canary/modules':; '#{@coderoot}/environments/canary/modules/can_hello':; '#{@coderoot}/environments/canary/modules/can_hello/manifests':; '#{@coderoot}/environments/canary/modules/can_hello/files':; } file { '#{@coderoot}/code_id.sh' : ensure => file, mode => "0755", content => '#! /bin/bash echo "code_version_1" ', } file { '#{@coderoot}/code_content.sh' : ensure => file, mode => "0755", content => '#! /bin/bash # script arguments: # $1 environment # $2 code_id # $3 path relative to mount # use echo -n to omit newline if [ $1 == "production" ] ; then echo -n "#{PRODUCTION_CONTENT}" else echo -n "#{CANARY_CONTENT}" fi ', } file { '#{@coderoot}/environments/production/environment.conf': ensure => file, mode => "0644", content => 'environment_timeout = 0 ', } file { '#{@coderoot}/environments/canary/environment.conf': ensure => file, mode => "0644", content => 'environment_timeout = 0 static_catalogs = false ', } file { '#{@coderoot}/environments/production/manifests/site.pp': ensure => file, mode => "0644", content => "node default { include hello } ", } file { '#{@coderoot}/environments/canary/manifests/site.pp': ensure => file, mode => "0644", content => "node default { include can_hello } ", } file { '#{@coderoot}/environments/production/modules/hello/files/hello_msg': ensure => file, mode => "0644", content => "#{PRODUCTION_CONTENT}", } file { '#{@coderoot}/environments/canary/modules/can_hello/files/hello_msg': ensure => file, mode => "0644", content => "#{CANARY_CONTENT}", } MANIFEST teardown do on(master, "mv #{@confdir}/puppetserver.conf.bak #{@confdir}/puppetserver.conf") on(master, "rm -rf #{@testroot}") agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step 'apply main manifest, static_catalogs unspecified in global scope, unspecified in production environment, disabled in canary environment' on( master, "cp #{@confdir}/puppetserver.conf #{@confdir}/puppetserver.conf.bak" ) apply_manifest_on(master, @manifest, :catch_failures => true) step "Add versioned-code parameters to puppetserver.conf and ensure the server is running" puppetserver_config = "#{master['puppetserver-confdir']}/puppetserver.conf" on master, "cp #{puppetserver_config} #{@coderoot}/puppetserver.conf.bak" versioned_code_settings = { "jruby-puppet" => { "master-code-dir" => @coderoot }, "versioned-code" => { "code-id-command" => "#{@coderoot}/code_id.sh", "code-content-command" => "#{@coderoot}/code_content.sh" } } modify_tk_config(master, puppetserver_config, versioned_code_settings) step 'start puppet server' with_puppet_running_on master, @master_opts, @coderoot do agents.each do |agent| hn = agent.node_name apply_manifest_on(master, @agent_manifests[hn], :catch_failures => true) step 'agent gets a production catalog, should be static catalog by default' on( agent, puppet( 'agent', '-t', '--environment', 'production' ), :acceptable_exit_codes => [0, 2] ) step 'verify production environment' r = on(agent, "cat #{@catalog_files[hn]}") catalog_content = JSON.parse(r.stdout) assert_equal( catalog_content['environment'], 'production', 'catalog for unexpectected environment' ) step 'verify static catalog by finding metadata section in catalog' assert( catalog_content['metadata'] && catalog_content['metadata'][@production_files[hn]], 'metadata section of catalog not found' ) step 'agent gets a canary catalog, static catalog should be disabled' on( agent, puppet( 'agent', '-t', '--environment', 'canary' ), :acceptable_exit_codes => [0, 2] ) step 'verify canary environment' r = on(agent, "cat #{@catalog_files[hn]}") catalog_content = JSON.parse(r.stdout) assert_equal( catalog_content['environment'], 'canary', 'catalog for unexpectected environment' ) step 'verify not static catalog by absence of metadata section in catalog' assert_nil( catalog_content['metadata'], 'unexpected metadata section found in catalog' ) end end step 'enable static catalog for canary environment' @static_canary_manifest = < file, mode => "0644", content => 'environment_timeout = 0 static_catalogs = true ', } MANIFEST2 apply_manifest_on(master, @static_canary_manifest, :catch_failures => true) step 'disable global static catalog setting' @master_opts = { 'master' => { 'static_catalogs' => false }, 'main' => { 'environmentpath' => "#{@coderoot}/environments", }, } step 'bounce server for static catalog disable setting to take effect.' with_puppet_running_on master, @master_opts, @coderoot do agents.each do |agent| hn = agent.node_name apply_manifest_on(master, @agent_manifests[hn], :catch_failures => true) step 'agent gets a production catalog, should not be a static catalog' on( agent, puppet( 'agent', '-t', '--environment', 'production' ), :acceptable_exit_codes => [0, 2] ) step 'verify production environment' r = on(agent, "cat #{@catalog_files[hn]}") catalog_content = JSON.parse(r.stdout) assert_equal( catalog_content['environment'], 'production', 'catalog for unexpectected environment' ) step 'verify production environment, not static catalog' assert_nil( catalog_content['metadata'], 'unexpected metadata section found in catalog' ) step 'agent gets a canary catalog, static catalog should be enabled' on( agent, puppet( 'agent', '-t', '--environment', 'canary' ), :acceptable_exit_codes => [0, 2] ) step 'verify canary catalog' r = on(agent, "cat #{@catalog_files[hn]}") catalog_content = JSON.parse(r.stdout) assert_equal( catalog_content['environment'], 'canary', 'catalog for unexpectected environment' ) step 'verify canary static catalog' assert( catalog_content['metadata'] && catalog_content['metadata'][@canary_files[hn]], 'metadata section of catalog not found' ) end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/direct_puppet/supports_utf8.rb000066400000000000000000000055561527241624000302730ustar00rootroot00000000000000test_name "C97172: static catalogs support utf8" do require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/agent_fqdn_utils' extend Puppet::Acceptance::AgentFqdnUtils tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Review for agent side UTF validation. 'shard:group3' # For splitting out groups of tests for slow test runners app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) tmp_file = {} agents.each do |agent| tmp_file[agent_to_fqdn(agent)] = agent.tmpfile(tmp_environment) end teardown do # Remove all traces of the last used environment agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end step 'clean out produced resources' do agents.each do |agent| if tmp_file.has_key?(agent_to_fqdn(agent)) && !tmp_file[agent_to_fqdn(agent)].empty? on(agent, "rm -f '#{tmp_file[agent_to_fqdn(agent)]}'") end end end end file_contents = 'Mønti Pythøn ik den Hølie Gräilen, yër? € ‰ ㄘ 万 竹 Ü Ö' step 'create site.pp with utf8 chars' do manifest = < file, content => ' \$test_path = \$facts["networking"]["fqdn"] ? #{tmp_file} file { \$test_path: content => @(UTF8) #{file_contents} | UTF8 } ', } MANIFEST apply_manifest_on(master, manifest, :catch_failures => true) end step 'run agent(s)' do with_puppet_running_on(master, {}) do agents.each do |agent| config_version = '' config_version_matcher = /configuration version '(\d+)'/ on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :acceptable_exit_codes => 2).stdout do |result| config_version = result.match(config_version_matcher)[1] end on(agent, "cat '#{tmp_file[agent_to_fqdn(agent)]}'").stdout do |result| assert_equal(file_contents, result, 'file contents did not match accepted') end on(agent, "rm -f '#{tmp_file[agent_to_fqdn(agent)]}'") on(agent, puppet("agent -t --environment '#{tmp_environment}' --use_cached_catalog"), :acceptable_exit_codes => 2).stdout do |result| assert_match(config_version_matcher, result, 'agent did not use cached catalog') second_config_version = result.match(config_version_matcher)[1] asset_equal(config_version, second_config_version, 'config version should have been the same') end on(agent, "cat '#{tmp_file[agent_to_fqdn(agent)]}'").stdout do |result| assert_equal(file_contents, result, 'file contents did not match accepted') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/000077500000000000000000000000001527241624000245635ustar00rootroot00000000000000broken_unassigned_environment_handled_gracefully.rb000066400000000000000000000036271527241624000370610ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/environmenttest_name 'PUP-3755 Test an un-assigned broken environment' tag 'audit:high', 'audit:integration', 'audit:refactor', # Use mk_tmp_environment_with_teardown helper 'server', 'shard:group4' # For splitting out groups of tests for slow test runners teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step 'setup environments' testdir = create_tmpdir_for_user(master, 'confdir') environment = 'debug' manifest = <<-MANIFEST File { ensure => directory, owner => #{master.puppet['user']}, group => #{master.puppet['group']}, mode => "0750", } file { "#{testdir}":; "#{testdir}/environments":; "#{testdir}/environments/production":; "#{testdir}/environments/production/manifests":; "#{testdir}/environments/production/modules":; "#{testdir}/environments/#{environment}":; "#{testdir}/environments/#{environment}/manifests":; "#{testdir}/environments/#{environment}/modules":; } # broken envioronment file { "#{testdir}/environments/production/manifests/site.pp": ensure => file, content => 'import "/tmp/bogus/*.pp"' } file { "#{testdir}/environments/#{environment}/manifests/site.pp": ensure => file, content => 'node default{\nnotify{"you win":}\n}' } MANIFEST apply_manifest_on(master, manifest, :catch_failures => true) step 'run agents, ensure no one complains about the other environment' master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments" } } with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| on(agent, puppet('agent', "--test --environment #{environment}"), :acceptable_exit_codes => (0..255)) do |result| assert_match(/you win/, result.stdout, 'agent did not pickup newly classified environment.') end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/can_enumerate_environments.rb000066400000000000000000000041761527241624000325350ustar00rootroot00000000000000test_name "Can enumerate environments via an HTTP endpoint" tag 'audit:high', 'audit:integration', 'server', 'shard:group1' # For splitting out groups of tests for slow test runners confine :except, :platform => /osx/ # see PUP-4820 def server_port(agent) setting_on(agent, "agent", "serverport") end def setting_on(host, section, name) on(host, puppet("config", "print", name, "--section", section)).stdout.chomp end def full_path(host, path) if host['platform'] =~ /win/ on(host, "cygpath '#{path}'").stdout.chomp else path end end def curl_master_from(agent, path, headers = '', &block) url = "https://#{master}:#{server_port(agent)}#{path}" cert_path = full_path(agent, setting_on(agent, "agent", "hostcert")) key_path = full_path(agent, setting_on(agent, "agent", "hostprivkey")) curl_base = "curl --tlsv1 -sg --cert \"#{cert_path}\" --key \"#{key_path}\" -k -H '#{headers}'" on agent, "#{curl_base} '#{url}'", &block end master_user = puppet_config(master, 'user', section: 'master') environments_dir = create_tmpdir_for_user master, "environments" apply_manifest_on(master, <<-MANIFEST) File { ensure => directory, owner => #{master_user}, group => #{master.puppet['group']}, mode => "0770", } file { "#{environments_dir}":; "#{environments_dir}/env1":; "#{environments_dir}/env2":; } MANIFEST master_opts = { :master => { :environmentpath => environments_dir } } if master.is_pe? master_opts[:master][:basemodulepath] = master['sitemoduledir'] end with_puppet_running_on(master, master_opts) do step "Ensure that an unauthenticated client cannot access the environments list" do on(master, "curl --tlsv1 -ksv https://#{master}:#{server_port(master)}/puppet/v3/environments", :acceptable_exit_codes => [0,7]) do |result| assert_match(/< HTTP\/1\.\d 403/, result.stderr) end end step "Ensure that an authenticated client can retrieve the list of environments" do curl_master_from(master, '/puppet/v3/environments') do |result| data = JSON.parse(result.stdout) assert_equal(["env1", "env2", "production"], data["environments"].keys.sort) end end end custom_type_provider_from_same_environment.rb000066400000000000000000000115111527241624000357710ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/environmenttest_name 'C59122: ensure provider from same env as custom type' do require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:integration', # This behavior is specific to the master to 'do the right thing' 'server', 'shard:group2' # For splitting out groups of tests for slow test runners app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) file_correct = "#{tmp_environment}-correct.txt" file_wrong = "#{tmp_environment}-wrong.txt" fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" fq_prod_environmentpath = "#{environmentpath}/production" teardown do step 'clean out production env' do on(master, "rm -rf #{fq_prod_environmentpath}/modules/*", :accept_all_exit_codes => true) on(master, "rm #{fq_prod_environmentpath}/manifests/site.pp", :accept_all_exit_codes => true) end step 'clean out file resources' do on(hosts, "rm #{file_correct} #{file_wrong}", :accept_all_exit_codes => true) end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step "create a custom type and provider in each of production and #{tmp_environment}" do type_name = 'test_custom_type' provider_name = 'universal' type_content = < directory } file { '#{fq_tmp_environmentpath}/modules/simple_type':; '#{fq_tmp_environmentpath}/modules/simple_type/lib':; '#{fq_tmp_environmentpath}/modules/simple_type/lib/puppet':; '#{fq_tmp_environmentpath}/modules/simple_type/lib/puppet/type/':; '#{fq_tmp_environmentpath}/modules/simple_type/lib/puppet/provider/':; '#{fq_tmp_environmentpath}/modules/simple_type/lib/puppet/provider/#{type_name}':; '#{fq_prod_environmentpath}/modules':; '#{fq_prod_environmentpath}/modules/simple_type':; '#{fq_prod_environmentpath}/modules/simple_type/lib':; '#{fq_prod_environmentpath}/modules/simple_type/lib/puppet':; '#{fq_prod_environmentpath}/modules/simple_type/lib/puppet/type/':; '#{fq_prod_environmentpath}/modules/simple_type/lib/puppet/provider/':; '#{fq_prod_environmentpath}/modules/simple_type/lib/puppet/provider/#{type_name}':; } file { '#{fq_tmp_environmentpath}/modules/simple_type/lib/puppet/type/#{type_name}.rb': ensure => file, content => '#{type_content}', } file { '#{fq_prod_environmentpath}/modules/simple_type/lib/puppet/type/#{type_name}.rb': ensure => file, content => '#{type_content}', } file { '#{fq_tmp_environmentpath}/modules/simple_type/lib/puppet/provider/#{type_name}/#{provider_name}.rb': ensure => file, content => '#{provider_content('correct', type_name, provider_name)}', } file { '#{fq_prod_environmentpath}/modules/simple_type/lib/puppet/provider/#{type_name}/#{provider_name}.rb': ensure => file, content => '#{provider_content('wrong', type_name, provider_name)}', } file { '#{fq_tmp_environmentpath}/manifests/site.pp': ensure => file, content => 'node default { #{type_name}{"#{file_correct}": ensure=>present} }', } file { '#{fq_prod_environmentpath}/manifests': } file { '#{fq_prod_environmentpath}/manifests/site.pp': ensure => file, content => 'node default { #{type_name}{"#{file_wrong}": ensure=>present} }', } MANIFEST apply_manifest_on(master, manifest, :catch_failures => true) end step "run agent in #{tmp_environment}, ensure it finds the correct provider" do with_puppet_running_on(master,{}) do agents.each do |agent| on(agent, puppet("agent -t --environment #{tmp_environment}"), :accept_all_exit_codes => true) do |result| assert_equal(2, result.exit_code, 'agent did not exit with the correct code of 2') assert_match(/#{file_correct}/, result.stdout, 'agent did not ensure the correct file') assert(agent.file_exist?(file_correct), 'puppet did not create the file') end end end end end directory_environment_production_created_master.rb000066400000000000000000000022331527241624000367710ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/environmenttest_name 'ensure production environment created by master if missing' tag 'audit:high', 'audit:integration', 'server', 'shard:group3' # For splitting out groups of tests for slow test runners testdir = create_tmpdir_for_user master, 'prod-env-created' step 'make environmentpath' master_user = puppet_config(master, 'user', section: 'master') apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) File { ensure => directory, owner => #{master_user}, group => #{master.puppet['group']}, mode => '0640', } file { "#{testdir}":; "#{testdir}/environments":; } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", } } step 'run master; ensure production environment created' with_puppet_running_on(master, master_opts, testdir) do on(master, "test -d '#{testdir}/environments/production'") step 'ensure catalog returned from production env with no changes' agents.each do |agent| on(agent, puppet("agent -t --environment production --detailed-exitcodes")) do |result| # detailed-exitcodes produces a 0 when no changes are made. assert_equal(0, result.exit_code) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/enc_nonexistent_directory_environment.rb000066400000000000000000000046431527241624000350320ustar00rootroot00000000000000test_name "Master should produce error if enc specifies a nonexistent environment" do require 'puppet/acceptance/classifier_utils.rb' extend Puppet::Acceptance::ClassifierUtils tag 'audit:high', 'audit:unit', 'server', 'shard:group4' # For splitting out groups of tests for slow test runners teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end testdir = create_tmpdir_for_user(master, 'nonexistent_env') apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) File { ensure => directory, owner => #{master.puppet['user']}, group => #{master.puppet['group']}, mode => '0755', } file { "#{testdir}":; "#{testdir}/environments":; "#{testdir}/environments/production":; "#{testdir}/environments/production/manifests":; "#{testdir}/environments/production/manifests/site.pp": ensure => file, mode => '0644', content => 'notify { "In the production environment": }'; } MANIFEST if master.is_pe? group = { 'name' => 'Environment Does Not Exist', 'description' => 'Classify our test agent nodes in an environment that does not exist.', 'environment' => 'doesnotexist', 'environment_trumps' => true, } create_group_for_nodes(agents, group) else apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) file { "#{testdir}/enc.rb": ensure => file, mode => '0775', content => '#!#{master['privatebindir']}/ruby puts "environment: doesnotexist" '; } MANIFEST end master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", } } master_opts['master'] = { 'node_terminus' => 'exec', 'external_nodes' => "#{testdir}/enc.rb", } if !master.is_pe? with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| on(agent, puppet("agent -t --verbose"), :acceptable_exit_codes => [1]) do |result| unless agent['locale'] == 'ja' assert_match(/Could not find a directory environment named 'doesnotexist'/, result.stderr, "Errors when nonexistent environment is specified") end refute_match(/In the production environment/, result.stdout, "Executed manifest from production environment") end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/environment_scenario-bad.rb000066400000000000000000000047241527241624000320720ustar00rootroot00000000000000test_name 'Test behavior of directory environments when environmentpath is set to a non-existent directory' do require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/classifier_utils' extend Puppet::Acceptance::ClassifierUtils tag 'audit:high', 'audit:unit', # The error responses for the agent should be covered by Ruby unit tests. # The server 404/400 response should be covered by server integration tests. 'server', 'shard:group1' # For splitting out groups of tests for slow test runners teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end classify_nodes_as_agent_specified_if_classifer_present step 'setup environments' testdir = create_tmpdir_for_user(master, 'confdir') puppet_conf_backup_dir = create_tmpdir_for_user(master, "puppet-conf-backup-dir") apply_manifest_on(master, environment_manifest(testdir), :catch_failures => true) step 'Test' do env_path = '/doesnotexist' master_opts = { 'main' => { 'environmentpath' => "#{env_path}", } } env = 'testing' results = use_an_environment(env, 'bad environmentpath', master_opts, testdir, puppet_conf_backup_dir, :directory_environments => true) expectations = { :puppet_config => { :exit_code => 0, :matches => [%r{basemodulepath = /etc/puppetlabs/code/modules:/opt/puppetlabs/puppet/modules}, %r{modulepath =}, %r{manifest =}, %r{config_version =}], }, :puppet_apply => { :exit_code => 1, :matches => [%r{Could not find a directory environment named '#{env}' anywhere in the path.*#{env_path}}], }, :puppet_agent => { :exit_code => 0, }, } agents.each do |host| unless host['locale'] == 'ja' expectations[:puppet_agent][:matches] = [%r{Environment '#{env}' not found on server, skipping initial pluginsync.}, %r{Local environment: '#{env}' doesn't match server specified environment 'production', restarting agent run with environment 'production'}] end end assert_review(review_results(results, expectations)) end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/feature_branch_configured_environment.rb000066400000000000000000000016421527241624000347140ustar00rootroot00000000000000test_name "Agent should use set environment after running with specified environment" do require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'server', 'shard:group2' # For splitting out groups of tests for slow test runners # Remove all traces of the last used environment teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end tmp_environment = mk_tmp_environment_with_teardown(master, 'special') agents.each do |agent| on(agent, puppet("agent -t --environment #{tmp_environment}")) do |result| assert_match(/Info: Using environment 'special_\w+'/, result.stdout) end on(agent, puppet('agent -t')) do |result| assert_match(/Info: Using environment 'production'/, result.stdout) end end end should_find_existing_production_environment.rb000066400000000000000000000126741527241624000361450ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/environmenttest_name "should find existing production environment" tag 'audit:medium', 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils agents.each do |agent| path_separator = agent.platform_defaults[:pathseparator] initial_environment = on(agent, puppet("config print environment")).stdout.chomp initial_environment_paths = on(agent, puppet("config print environmentpath")).stdout.chomp.split(path_separator) default_environment_path = '' custom_environment_path = agent.tmpdir('custom_environment') teardown do step 'uninstall the module' do uninstall_i18n_demo_module(master) uninstall_i18n_demo_module(agent) end step 'Remove custom environment paths' do environment_paths = on(agent, puppet("config print environmentpath")).stdout.chomp environment_paths.split(path_separator).each do |path| agent.rm_rf(path) unless initial_environment_paths.include?(path) end agent.rm_rf(custom_environment_path) end step 'Reset environment settings' do on(agent, puppet("config set environmentpath #{initial_environment_paths.join(path_separator)}")) on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end if initial_environment == 'production' on(agent, puppet("config delete environment")) else on(agent, puppet("config set environment #{initial_environment}")) end on(agent, puppet("agent -t")) end end step 'Ensure a clean environment with default settings' do step 'Remove the lastrunfile which contains the last used agent environment' do on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end step 'Change to the default environment setting' do on(agent, puppet("config delete environment")) on(agent, puppet("config print environment")) do |result| assert_match('production', result.stdout, "Default environment is not 'production' as expected") end end step 'Change to the default environmentpath setting and remove production folder' do on(agent, puppet("config delete environmentpath")) default_environment_path = on(agent, puppet("config print environmentpath")).stdout.chomp agent.rm_rf("#{default_environment_path}/production") end step 'Apply changes and expect puppet to create the production folder back' do on(agent, puppet("agent -t")) on(agent, "ls #{default_environment_path}") do |result| assert_match('production', result.stdout, "Default environment folder was not generated in last puppet run") end end end step 'Install a module' do install_i18n_demo_module(master) end step 'Expect output from the custom fact of the module' do on(agent, puppet("agent -t"), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/Error:.*i18ndemo/, result.stderr) end end step 'Add a custom environment path before the current one' do current_environment_path = on(agent, puppet("config print environmentpath")).stdout.chomp on(agent, puppet("config set environmentpath '#{custom_environment_path}#{path_separator}#{current_environment_path}'")) end step 'Expect the module to still be found' do on(agent, puppet("agent -t"), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/Error:.*i18ndemo/, result.stderr) end end step 'Expect no production environment folder changes' do on(agent, "ls #{custom_environment_path}") do |result| refute_match(/production/, result.stdout) end on(agent, "ls #{default_environment_path}") do |result| assert_match('production', result.stdout) end end step 'Remove production folder' do agent.rm_rf("#{default_environment_path}/production") end step 'Expect production environment folder to be recreated in the custom path' do on(agent, puppet("agent -t"), :acceptable_exit_codes => [0, 2]) do |result| step 'Expect the module to be gone on the server node' do refute_match(/Error:.*i18ndemo/, result.stderr) end if agent == master step 'Expect the production environment, along with the module, to be synced back on the agent node' do assert_match(/Error:.*i18ndemo/, result.stderr) end if agent != master end on(agent, "ls #{custom_environment_path}") do |result| assert_match('production', result.stdout, "Default environment folder was not generated in last puppet run") end on(agent, "ls #{default_environment_path}") do |result| refute_match(/production/, result.stdout) end end step 'Set back to just default environmentpath setting' do on(agent, puppet("config delete environmentpath")) end step 'Expect production environment folder to be found in both paths but use the default one' do on(agent, puppet("agent -t"), :acceptable_exit_codes => [0, 2]) do |result| step 'Expect the module to be gone' do refute_match(/Error:.*i18ndemo/, result.stderr) end if agent == master end on(agent, "ls #{default_environment_path}") do |result| assert_match('production', result.stdout, "Default environment folder was not generated in last puppet run") end on(agent, "ls #{custom_environment_path}") do |result| assert_match('production', result.stdout) end end end use_agent_environment_when_enc_doesnt_specify.rb000066400000000000000000000042551527241624000364010ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/environmenttest_name "Agent should use agent environment if there is an enc that does not specify the environment" do require 'puppet/acceptance/classifier_utils' extend Puppet::Acceptance::ClassifierUtils tag 'audit:high', 'audit:integration', 'server', 'shard:group4' # For splitting out groups of tests for slow test runners # Remove all traces of the last used environment teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end classify_nodes_as_agent_specified_if_classifer_present testdir = create_tmpdir_for_user(master, 'use_agent_env') create_remote_file(master, "#{testdir}/enc.rb", < true) File { ensure => directory, mode => "0770", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/manifests':; '#{testdir}/environments/more_different/':; '#{testdir}/environments/more_different/manifests':; } file { '#{testdir}/environments/production/manifests/site.pp': ensure => file, mode => "0640", content => 'notify { "production environment": }', } file { '#{testdir}/environments/more_different/manifests/more_different.pp': ensure => file, mode => "0640", content => 'notify { "more_different_string": }', } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", 'node_terminus' => 'exec', 'external_nodes' => "#{testdir}/enc.rb", }, } with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| run_agent_on(agent, "--no-daemonize --onetime --verbose --environment more_different") do |result| assert_match(/more_different_string/, result.stdout, "Did not find more_different_string from \"more_different\" environment") end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/use_agent_environment_when_no_enc.rb000066400000000000000000000036531527241624000340570ustar00rootroot00000000000000test_name "Agent should use agent environment if there is no enc-specified environment" do tag 'audit:high', 'audit:integration', 'audit:refactor', # This can be combined with use_agent_environment_when_enc_doesnt_specify test 'server', 'shard:group1' # For splitting out groups of tests for slow test runners # Remove all traces of the last used environment teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end testdir = create_tmpdir_for_user(master, 'use_agent_env') apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) File { ensure => directory, mode => "0770", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/manifests':; '#{testdir}/environments/more_different/':; '#{testdir}/environments/more_different/manifests':; } file { '#{testdir}/environments/production/manifests/site.pp': ensure => file, mode => "0640", content => 'notify { "production environment": }', } file { '#{testdir}/environments/more_different/manifests/more_different.pp': ensure => file, mode => "0640", content => 'notify { "more_different_string": }', } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", }, 'master' => { 'node_terminus' => 'plain' }, } with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| run_agent_on(agent, "--no-daemonize --onetime --verbose --environment more_different") do |result| assert_match(/more_different_string/, result.stdout, "Did not find more_different_string from \"more_different\" environment") end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/use_enc_environment.rb000066400000000000000000000051751527241624000311650ustar00rootroot00000000000000test_name 'Agent should use environment given by ENC and only compile a catalog once' do require 'puppet/acceptance/classifier_utils.rb' extend Puppet::Acceptance::ClassifierUtils tag 'audit:high', 'audit:integration', 'server', 'shard:group2' # For splitting out groups of tests for slow test runners # Remove all traces of the last used environment teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end testdir = create_tmpdir_for_user(master, 'use_enc_env') if master.is_pe? group = { 'name' => 'Special Environment', 'description' => 'Classify our test agent nodes in the special environment.', 'environment' => 'special', 'environment_trumps' => true, } create_group_for_nodes(agents, group) else create_remote_file(master, "#{testdir}/enc.rb", < true) File { ensure => directory, mode => "0770", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/manifests':; '#{testdir}/environments/special/':; '#{testdir}/environments/special/manifests':; } file { '#{testdir}/environments/production/manifests/site.pp': ensure => file, mode => "0640", content => 'notify { "production environment": }', } file { '#{testdir}/environments/special/manifests/different.pp': ensure => file, mode => "0640", content => 'notify { "expected_string": }', } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", }, } master_opts['master'] = { 'node_terminus' => 'exec', 'external_nodes' => "#{testdir}/enc.rb", } if !master.is_pe? with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| run_agent_on(agent, "--no-daemonize --onetime --verbose") do |result| assert_match(/expected_string/, result.stdout, "Did not find expected_string from \"special\" environment") caching_catalog_message_count = result.stdout.split(/Info: Caching catalog for/).length - 1 assert_equal(caching_catalog_message_count, 1, 'Should only compile and cache the catalog once during the run') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/use_enc_environment_for_files.rb000066400000000000000000000050641527241624000332120ustar00rootroot00000000000000test_name "Agent should use environment given by ENC for fetching remote files" do tag 'audit:high', 'audit:integration', 'audit:refactor', # This test should be rolled into use_enc_environment 'server', 'shard:group3' # For splitting out groups of tests for slow test runners # Remove all traces of the last used environment teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end testdir = create_tmpdir_for_user(master, 'respect_enc_test') create_remote_file(master, "#{testdir}/enc.rb", < true) File { ensure => directory, mode => "0770", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/special/':; '#{testdir}/environments/special/manifests':; '#{testdir}/environments/special/modules':; '#{testdir}/environments/special/modules/amod':; '#{testdir}/environments/special/modules/amod/files':; } file { '#{testdir}/environments/special/modules/amod/files/testy': ensure => file, mode => "0640", content => 'special_environment', } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", 'environment_timeout' => 0, }, 'master' => { 'node_terminus' => 'exec', 'external_nodes' => "#{testdir}/enc.rb", }, } with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| atmp = agent.tmpdir('respect_enc_test') teardown do on(agent, "rm -rf '#{atmp}'") end logger.debug "agent: #{agent} \tagent.tmpdir => #{atmp}" create_remote_file(master, "#{testdir}/environments/special/manifests/different.pp", < "puppet:///modules/amod/testy", } END on(master, "chmod 644 '#{testdir}/environments/special/manifests/different.pp'") run_agent_on(agent, "--no-daemonize --onetime --verbose --trace") on(agent, "cat '#{atmp}/special_testy'") do |result| assert_match(/special_environment/, result.stdout, "The file from environment 'special' was not found") end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/use_enc_environment_for_pluginsync.rb000066400000000000000000000042341527241624000343010ustar00rootroot00000000000000test_name "Agent should use environment given by ENC for pluginsync" do tag 'audit:high', 'audit:integration', 'audit:refactor', # This test should be rolled into use_enc_environment 'server', 'shard:group4' # For splitting out groups of tests for slow test runners # Remove all traces of the last used environment teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end testdir = create_tmpdir_for_user(master, 'respect_enc_test') create_remote_file(master, "#{testdir}/enc.rb", < true) File { ensure => directory, mode => "0770", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/special/':; '#{testdir}/environments/special/modules':; '#{testdir}/environments/special/modules/amod':; '#{testdir}/environments/special/modules/amod/lib':; '#{testdir}/environments/special/modules/amod/lib/puppet':; } file { '#{testdir}/environments/special/modules/amod/lib/puppet/foo.rb': ensure => file, mode => "0640", content => "#special_version", } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", }, 'master' => { 'node_terminus' => 'exec', 'external_nodes' => "#{testdir}/enc.rb" }, } with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| agent_vardir = agent.puppet['vardir'] teardown do on(agent, "rm -rf '#{agent_vardir}/lib'") end run_agent_on(agent, "-t --no-daemonize --onetime") on(agent, "cat '#{agent_vardir}/lib/puppet/foo.rb'") do |result| assert_match(/#special_version/, result.stdout, "The plugin from environment 'special' was not synced") end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/use_environment_from_environmentpath.rb000066400000000000000000000153151527241624000346610ustar00rootroot00000000000000test_name "Use environments from the environmentpath" do require 'puppet/acceptance/classifier_utils' extend Puppet::Acceptance::ClassifierUtils tag 'audit:high', 'audit:integration', 'server', 'shard:group1' # For splitting out groups of tests for slow test runners classify_nodes_as_agent_specified_if_classifer_present testdir = create_tmpdir_for_user(master, 'use_environmentpath') def generate_environment(path_to_env, environment) <<-EOS "#{path_to_env}/#{environment}":; "#{path_to_env}/#{environment}/manifests":; "#{path_to_env}/#{environment}/modules":; EOS end def generate_module_content(module_name, options = {}) base_path = options[:base_path] environment = options[:environment] env_path = options[:env_path] path_to_module = [base_path, env_path, environment, "modules"].compact.join("/") module_info = "module-#{module_name}" module_info << "-from-#{environment}" if environment <<-EOS "#{path_to_module}/#{module_name}":; "#{path_to_module}/#{module_name}/manifests":; "#{path_to_module}/#{module_name}/files":; "#{path_to_module}/#{module_name}/templates":; "#{path_to_module}/#{module_name}/lib":; "#{path_to_module}/#{module_name}/lib/facter":; "#{path_to_module}/#{module_name}/manifests/init.pp": ensure => file, mode => "0640", content => 'class #{module_name} { notify { "template-#{module_name}": message => template("#{module_name}/our_template.erb") } file { "$agent_file_location/file-#{module_info}": source => "puppet:///modules/#{module_name}/data" } }' ; "#{path_to_module}/#{module_name}/lib/facter/environment_fact_#{module_name}.rb": ensure => file, mode => "0640", content => "Facter.add(:environment_fact_#{module_name}) { setcode { 'environment fact from #{module_info}' } }" ; "#{path_to_module}/#{module_name}/files/data": ensure => file, mode => "0640", content => "data file from #{module_info}" ; "#{path_to_module}/#{module_name}/templates/our_template.erb": ensure => file, mode => "0640", content => "<%= @environment_fact_#{module_name} %>" ; EOS end def generate_site_manifest(path_to_manifest, *modules_to_include) <<-EOS "#{path_to_manifest}/site.pp": ensure => file, mode => "0640", content => "#{modules_to_include.map {|m| "include #{m}"}.join("\n")}" ; EOS end apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) File { ensure => directory, owner => #{master.puppet['user']}, group => #{master.puppet['group']}, mode => "0770", } file { "#{testdir}":; "#{testdir}/base":; "#{testdir}/additional":; "#{testdir}/modules":; #{generate_environment("#{testdir}/base", "shadowed")} #{generate_environment("#{testdir}/base", "onlybase")} #{generate_environment("#{testdir}/additional", "shadowed")} #{generate_module_content("atmp", :base_path => testdir, :env_path => 'base', :environment => 'shadowed')} #{generate_site_manifest("#{testdir}/base/shadowed/manifests", "atmp", "globalmod")} #{generate_module_content("atmp", :base_path => testdir, :env_path => 'base', :environment => 'onlybase')} #{generate_site_manifest("#{testdir}/base/onlybase/manifests", "atmp", "globalmod")} #{generate_module_content("atmp", :base_path => testdir, :env_path => 'additional', :environment => 'shadowed')} #{generate_site_manifest("#{testdir}/additional/shadowed/manifests", "atmp", "globalmod")} # And one global module (--modulepath setting) #{generate_module_content("globalmod", :base_path => testdir)} "#{testdir}/additional/production":; "#{testdir}/additional/production/manifests":; #{generate_site_manifest("#{testdir}/additional/production/manifests", "globalmod")} } MANIFEST def run_with_environment(agent, environment, options = {}) expected_exit_code = options[:expected_exit_code] || 2 step "running an agent in environment '#{environment}'" atmp = agent.tmpdir("use_environmentpath_#{environment}") teardown do on(agent, "rm -rf '#{atmp}'") end agent_config = [ "-t" ] agent_config << '--environment' << environment if environment # This to test how the agent behaves when using the directory environment # loaders (which will not load an environment if it does not exist) agent_config << "--environmentpath='$confdir/environments'" if agent != master agent_config << { 'ENV' => { "FACTER_agent_file_location" => atmp }, } on(agent, puppet("agent", *agent_config), :acceptable_exit_codes => [expected_exit_code]) do |result| yield atmp, result end end master_opts = { 'master' => { 'environmentpath' => "#{testdir}/additional:#{testdir}/base", 'basemodulepath' => "#{testdir}/modules", } } if master.is_pe? master_opts['master']['basemodulepath'] << ":#{master['sitemoduledir']}" end with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| run_with_environment(agent, "shadowed") do |tmpdir, catalog_result| ["module-atmp-from-shadowed", "module-globalmod"].each do |expected| assert_match(/environment fact from #{expected}/, catalog_result.stdout) end ["module-atmp-from-shadowed", "module-globalmod"].each do |expected| on(agent, "cat '#{tmpdir}/file-#{expected}'") do |file_result| assert_match(/data file from #{expected}/, file_result.stdout) end end end run_with_environment(agent, "onlybase") do |tmpdir, catalog_result| ["module-atmp-from-onlybase", "module-globalmod"].each do |expected| assert_match(/environment fact from #{expected}/, catalog_result.stdout) end ["module-atmp-from-onlybase", "module-globalmod"].each do |expected| on(agent, "cat '#{tmpdir}/file-#{expected}'") do |file_result| assert_match(/data file from #{expected}/, file_result.stdout) end end end run_with_environment(agent, "production", :expected_exit_code => 2) do |tmpdir, catalog_result| refute_match(/module-atmp/, catalog_result.stdout, "module-atmp was included despite the default environment being loaded") assert_match(/environment fact from module-globalmod/, catalog_result.stdout) on(agent, "cat '#{tmpdir}/file-module-globalmod'") do |file_result| assert_match(/data file from module-globalmod/, file_result.stdout) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/use_last_server_specified_environment.rb000066400000000000000000000056251527241624000347640ustar00rootroot00000000000000test_name "Agent should use the last server-specified environment if server is authoritative" do require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'server', 'shard:group2' # For splitting out groups of tests for slow test runners # Remove all traces of the last used environment teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end testdir = create_tmpdir_for_user(master, 'use_enc_env') create_remote_file(master, "#{testdir}/enc.rb", < true) File { ensure => directory, mode => "0770", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/manifests':; '#{testdir}/environments/special/':; '#{testdir}/environments/special/manifests':; } file { '#{testdir}/environments/production/manifests/site.pp': ensure => file, mode => "0640", content => 'notify { "production environment": }', } file { '#{testdir}/environments/special/manifests/different.pp': ensure => file, mode => "0640", content => 'notify { "special environment": }', } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", }, } master_opts['master'] = { 'node_terminus' => 'exec', 'external_nodes' => "#{testdir}/enc.rb", } if !master.is_pe? with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| step 'ensure the lastrunfile is absent for the first run' do on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end step 'first run: agent makes a node request to get the environment' do run_agent_on(agent, '--no-daemonize --onetime --debug') do |result| assert_match(/Local environment: 'production' doesn't match server specified node environment 'special', switching agent to 'special'/, result.stdout) assert_match(/Debug: HTTP GET .*\/puppet\/v3\/node/, result.stdout) assert_match(/Notice: special environment/, result.stdout) end end step 'second run: agent uses the environment from lastrunfile' do run_agent_on(agent, '--no-daemonize --onetime --debug') do |result| assert_match(/Debug: Successfully loaded last environment from the lastrunfile/, result.stdout) assert_match(/Notice: special environment/, result.stdout) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/environment/variables_refreshed_each_compilation.rb000066400000000000000000000104501527241624000344650ustar00rootroot00000000000000test_name 'C98115 compilation should get new values in variables on each compilation' do require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils confine :except, :platform => /^(aix|osx|solaris)/ tag 'audit:high', 'audit:integration', 'server', 'shard:group3' # For splitting out groups of tests for slow test runners teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" create_remote_file(master, "#{fq_tmp_environmentpath}/environment.conf", <<-CONF) environment_timeout = unlimited CONF # the module function loading logic is different from inside a single manifest # we exercise both here on(master, "mkdir -p '#{fq_tmp_environmentpath}'/modules/custom_time/{manifests,functions,facts.d}") create_remote_file(master, "#{fq_tmp_environmentpath}/modules/custom_time/manifests/init.pp", <<-FILE) class custom_time { $t = custom_time::my_system_time() notify { 'custom time': message => "module_${t}_module", } } FILE create_remote_file(master, "#{fq_tmp_environmentpath}/modules/custom_time/functions/my_system_time.pp", <<-FILE) function custom_time::my_system_time() { $facts['custom_time'] } FILE create_sitepp(master, tmp_environment, <<-SITE) function bar() { $facts['custom_time'] } class foo::bar { notify { "local_${bar()}_local": } } include foo::bar include custom_time SITE create_remote_file(master, "#{fq_tmp_environmentpath}/modules/custom_time/facts.d/custom_time.sh", <<-FILE) #!/bin/bash if [[ `uname` == 'Darwin' ]]; then echo -n "custom_time=$(date +%s)" else echo -n "custom_time=$(date +%s%N)" fi FILE on(master, "chmod -R 0777 '#{fq_tmp_environmentpath}/'") windows_fact_location = "#{fq_tmp_environmentpath}/modules/custom_time/facts.d/custom_time.ps1" create_remote_file(master, windows_fact_location, <<-FILE) echo "custom_time=$(get-date -format HHmmssffffff)" FILE on(master, "chmod -R 0666 '#{windows_fact_location}'") step "run agent in #{tmp_environment}, ensure it increments the customtime with each run" do with_puppet_running_on(master, {}) do local_custom_time_pattern = 'local_(\d+)_local' module_custom_time_pattern = 'module_(\d+)_module' agents.each do |agent| # ensure our custom facts have been synced on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :accept_all_exit_codes => true) local_custom_time1 = module_custom_time1 = nil local_custom_time2 = module_custom_time2 = nil on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :accept_all_exit_codes => [2]) do |result| assert_match(/Notice: #{local_custom_time_pattern}/, result.stdout, 'first custom time was not as expected') assert_match(/Notice: #{module_custom_time_pattern}/, result.stdout, 'first module uptime was not as expected') local_custom_time1 = result.stdout.match(/Notice: #{local_custom_time_pattern}/)[1].to_i module_custom_time1 = result.stdout.match(/Notice: #{module_custom_time_pattern}/)[1].to_i end sleep 1 on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :accept_all_exit_codes => [2]) do |result| assert_match(/Notice: #{local_custom_time_pattern}/, result.stdout, 'second custom time was not as expected') assert_match(/Notice: #{module_custom_time_pattern}/, result.stdout, 'second module uptime was not as expected') local_custom_time2 = result.stdout.match(/Notice: #{local_custom_time_pattern}/)[1].to_i module_custom_time2 = result.stdout.match(/Notice: #{module_custom_time_pattern}/)[1].to_i end assert(local_custom_time2 > local_custom_time1, 'local custom time did not change as expected if at all') assert(module_custom_time2 > module_custom_time1, 'module custom time did not change as expected if at all') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/face/000077500000000000000000000000001527241624000231155ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/face/4654_facts_face.rb000066400000000000000000000036561527241624000262140ustar00rootroot00000000000000test_name "Puppet facts face should resolve custom and external facts" tag 'audit:high', 'audit:integration', # The facter acceptance tests should be acceptance. # However, the puppet face merely needs to interact with libfacter. # So, this should be an integration test. 'shard:group4' # For splitting out groups of tests for slow test runners # # This test is intended to ensure that custom and external facts present # on the agent are resolved and displayed by the puppet facts face. # custom_fact = < < directory, } file { "#{agent.puppet['plugindest']}/facter/custom.rb": ensure => file, content => "#{custom_fact}", } file { "#{agent.puppet['pluginfactdest']}/external#{ext}": ensure => file, mode => "0755", content => "#{external_fact}", } MANIFEST step "Agent #{agent}: custom_fact and external_fact should be present in the output of `puppet facts`" on agent, puppet('facts') do |result| assert_match(/"custom_fact": "foo"/, result.stdout, "custom_fact did not match expected output") assert_match(/"external_fact": "bar"/, result.stdout, "external_fact did not match expected output") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/face/loadable_from_modules.rb000066400000000000000000000100271527241624000277600ustar00rootroot00000000000000test_name "Exercise loading a face from a module" # Because the module tool does not work on windows, we can't run this test there confine :except, :platform => 'windows' tag 'audit:high', 'audit:acceptance', # This has been OS sensitive. 'audit:refactor', # Remove the confine against windows and refactor to # accommodate the Windows platform. 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils initialize_temp_dirs metadata_json_file = <<-FILE { "name": "puppetlabs-helloworld", "version": "0.0.1", "author": "Puppet Labs", "summary": "Nginx Module", "license": "Apache Version 2.0", "source": "https://github.com/puppetlabs/puppetlabs-nginx", "project_page": "https://github.com/puppetlabs/puppetlabs-nginx", "issues_url": "https://github.com/puppetlabs/puppetlabs-nginx", "dependencies": [ {"name":"puppetlabs-stdlub","version_requirement":">= 1.0.0"} ] } FILE agents.each do |agent| if on(agent, facter("fips_enabled")).stdout =~ /true/ puts "Module build, loading and installing not supported on fips enabled platforms" next end environmentpath = get_test_file_path(agent, 'environments') dev_modulepath = "#{environmentpath}/dev/modules" module_base_dir = "#{dev_modulepath}/helloworld" teardown do on agent, "rm -rf #{module_base_dir}" end # make sure that we use the modulepath from the dev environment puppetconf = get_test_file_path(agent, 'puppet.conf') on agent, puppet("config", "set", "environmentpath", environmentpath, "--section", "main", "--config", puppetconf) on agent, puppet("config", "set", "environment", "dev", "--section", "user", "--config", puppetconf) mkdirs agent, module_base_dir create_remote_file(agent, "#{module_base_dir}/metadata.json", metadata_json_file) mkdirs agent, "#{module_base_dir}/lib/puppet/application" mkdirs agent, "#{module_base_dir}/lib/puppet/face" # copy application, face, and utility module create_remote_file(agent, "#{module_base_dir}/lib/puppet/application/helloworld.rb", <<'EOM') require 'puppet/face' require 'puppet/application/face_base' class Puppet::Application::Helloworld < Puppet::Application::FaceBase end EOM create_remote_file(agent, "#{module_base_dir}/lib/puppet/face/helloworld.rb", <<'EOM') Puppet::Face.define(:helloworld, '0.1.0') do summary "Hello world face" description "This is the hello world face" action 'actionprint' do summary "Prints hello world from an action" when_invoked do |options| puts "Hello world from an action" end end action 'moduleprint' do summary "Prints hello world from a required module" when_invoked do |options| require 'puppet/helloworld.rb' Puppet::Helloworld.print end end end EOM create_remote_file(agent, "#{module_base_dir}/lib/puppet/helloworld.rb", <<'EOM') module Puppet::Helloworld def print puts "Hello world from a required module" end module_function :print end EOM on(agent, puppet('help', '--config', puppetconf)) do |result| assert_match(/helloworld\s*Hello world face/, result.stdout, "Face missing from list of available subcommands") end on(agent, puppet('help', 'helloworld', '--config', puppetconf)) do |result| assert_match(/This is the hello world face/, result.stdout, "Descripion help missing") assert_match(/moduleprint\s*Prints hello world from a required module/, result.stdout, "help for moduleprint action missing") assert_match(/actionprint\s*Prints hello world from an action/, result.stdout, "help for actionprint action missing") end on(agent, puppet('helloworld', 'actionprint', '--config', puppetconf)) do |result| assert_match(/^Hello world from an action$/, result.stdout, "face did not print hello world") end on(agent, puppet('helloworld', 'moduleprint', '--config', puppetconf)) do |result| assert_match(/^Hello world from a required module$/, result.stdout, "face did not load module to print hello world") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/face/parser_validate.rb000066400000000000000000000054311527241624000266120ustar00rootroot00000000000000test_name 'parser validate' do tag 'audit:high', 'audit:unit', # Parser validation should be core to ruby # and platform agnostic. 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils app_type = File.basename(__FILE__, '.*') teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end agents.each do |agent| skip_test('this test fails on windows French due to Cygwin/UTF Issues - PUP-8319,IMAGES-492') if agent['platform'] =~ /windows/ && agent['locale'] == 'fr' step 'manifest with parser function call' do if agent.platform !~ /windows/ tmp_environment = mk_tmp_environment_with_teardown(agent, app_type) create_sitepp(agent, tmp_environment, <<-SITE) function validate_this() { notice('hello, puppet') } validate_this() SITE on(agent, puppet("parser validate --environment #{tmp_environment}"), :pty => true) # default manifest end # manifest with Type aliases create_test_file(agent, "#{app_type}.pp", <<-PP) function validate_this() { notice('hello, puppet') } validate_this() type MyInteger = Integer notice 42 =~ MyInteger PP tmp_manifest = get_test_file_path(agent, "#{app_type}.pp") on(agent, puppet("parser validate #{tmp_manifest}")) end step 'manifest with bad syntax' do create_test_file(agent, "#{app_type}_broken.pp", "notify 'hello there'") tmp_manifest = get_test_file_path(agent, "#{app_type}_broken.pp") on(agent, puppet("parser validate #{tmp_manifest}"), :accept_all_exit_codes => true) do |result| assert_equal(result.exit_code, 1, 'parser validate did not exit with 1 upon parse failure') expected = /Error: Could not parse for environment production: This Name has no effect\. A value was produced and then forgotten \(one or more preceding expressions may have the wrong form\) \(file: .*_broken\.pp, line: 1, column: 1\)/ assert_match(expected, result.output, "parser validate did not output correctly: '#{result.output}'. expected: '#{expected.to_s}'") unless agent['locale'] == 'ja' end end step '(large) manifest with exported resources' do fixture_path = File.join(File.dirname(__FILE__), '..', '..', 'fixtures/manifest_large_exported_classes_node.pp') create_test_file(agent, "#{app_type}_exported.pp", File.read(fixture_path)) tmp_manifest = get_test_file_path(agent, "#{app_type}_exported.pp") on(agent, puppet("parser validate #{tmp_manifest}")) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/000077500000000000000000000000001527241624000227765ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/enable_option_disable_i18n.rb000066400000000000000000000061431527241624000304670ustar00rootroot00000000000000test_name 'Verify that disable_i18n can be set to true and have translations disabled' do confine :except, :platform => /^solaris/ # translation not supported tag 'audit:medium', 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils language = 'ja_JP' step "configure server locale to #{language}" do configure_master_system_locale(language) end tmp_environment = mk_tmp_environment_with_teardown(master, File.basename(__FILE__, '.*')) step 'install a i18ndemo module' do install_i18n_demo_module(master, tmp_environment) end disable_i18n_default_master = master.puppet['disable_i18n'] teardown do step 'resetting the server locale' do on(master, puppet("config set disable_i18n #{ disable_i18n_default_master }")) reset_master_system_locale end step 'uninstall the module' do agents.each do |agent| uninstall_i18n_demo_module(agent) end uninstall_i18n_demo_module(master) end end agents.each do |agent| agent_language = enable_locale_language(agent, language) skip_test("test machine is missing #{agent_language} locale. Skipping") if agent_language.nil? shell_env_language = { 'LANGUAGE' => agent_language, 'LANG' => agent_language } disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) on(master, puppet("config set disable_i18n false")) reset_master_system_locale end step 'expect #{language} translation for a custom type' do site_pp_content = <<-PP node default { i18ndemo_type { '12345': } } PP create_sitepp(master, tmp_environment, site_pp_content) on(agent, puppet("agent -t --environment #{tmp_environment}", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |result| assert_match(/Error: .* \w+-i18ndemo type: 値ã�¯æœ‰12345効ã�ªå€¤ã�§ã�¯ã�‚りã�¾ã�›ã‚“/, result.stderr, 'missing error from invalid value for custom type param') end end step 'disable i18n' do on(agent, puppet("config set disable_i18n true")) on(master, puppet("config set disable_i18n true")) reset_master_system_locale end step 'expect no #{language} translation for a custom type' do site_pp_content = <<-PP node default { i18ndemo_type { '12345': } } PP create_sitepp(master, tmp_environment, site_pp_content) on(agent, puppet("agent -t --environment #{tmp_environment}", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |result| assert_match(/Error: .* Value 12345 is not a valid value for i18ndemo_type\:\:name/, result.stderr) end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modules/000077500000000000000000000000001527241624000244465ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modules/puppet_agent.rb000066400000000000000000000127641527241624000275000ustar00rootroot00000000000000test_name 'C100565: puppet agent with module should translate messages' do confine :except, :platform => /^solaris/ # translation not supported tag 'audit:medium', 'audit:acceptance', 'shard:group4' # For splitting out groups of tests for slow test runners skip_test('i18n test module uses deprecated function; update module to resume testing.') # function validate_absolute_path used https://github.com/eputnam/eputnam-i18ndemo/blob/621d06d/manifests/init.pp#L15 require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils language = 'ja_JP' disable_i18n_default_master = master.puppet['disable_i18n'] step 'enable i18n on master' do on(master, puppet("config set disable_i18n false")) end step "configure server locale to #{language}" do configure_master_system_locale(language) end tmp_environment = mk_tmp_environment_with_teardown(master, File.basename(__FILE__, '.*')) step 'install a i18ndemo module' do install_i18n_demo_module(master, tmp_environment) end teardown do step 'resetting the server locale' do on(master, puppet("config set disable_i18n #{ disable_i18n_default_master }")) reset_master_system_locale end step 'uninstall the module' do agents.each do |agent| uninstall_i18n_demo_module(agent) end uninstall_i18n_demo_module(master) end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end agents.each do |agent| skip_test('on windows this test only works on a machine with a japanese code page set') if agent['platform'] =~ /windows/ && agent['locale'] != 'ja' agent_language = enable_locale_language(agent, language) skip_test("test machine is missing #{agent_language} locale. Skipping") if agent_language.nil? shell_env_language = { 'LANGUAGE' => agent_language, 'LANG' => agent_language } type_path = agent.tmpdir('provider') disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) agent.rm_rf(type_path) end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) end step "Run puppet agent of a module with language #{agent_language} and verify the translations" do step 'verify custom fact translations' do site_pp_content_1 = <<-PP node default { class { 'i18ndemo': filename => '#{type_path}' } } PP create_sitepp(master, tmp_environment, site_pp_content_1) on(agent, puppet("agent -t --no-disable_i18n --environment #{tmp_environment}", 'ENV' => shell_env_language), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/.*\w+-i18ndemo fact: ã�“れã�¯\w+-i18ndemoã�‹ã‚‰ã�®ã‚«ã‚¹ã‚¿ãƒ ãƒ•ァクトã�‹ã‚‰ã�®ãƒ¬ã‚¤ã‚ºã�§ã�™/, result.stderr, 'missing translation for raise from ruby fact') end end unless agent['platform'] =~ /ubuntu-16.04/ # Condition to be removed after FACT-2799 gets resolved step 'verify custom type translations' do site_pp_content_2 = <<-PP node default { i18ndemo_type { 'hello': } } PP create_sitepp(master, tmp_environment, site_pp_content_2) on(agent, puppet("agent -t --environment #{tmp_environment}", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |result| assert_match(/Warning:.*\w+-i18ndemo type: 良ã�„値/, result.stderr, 'missing warning from custom type') end site_pp_content_3 = <<-PP node default { i18ndemo_type { '12345': } } PP create_sitepp(master, tmp_environment, site_pp_content_3) on(agent, puppet("agent -t --environment #{tmp_environment}", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |result| assert_match(/Error: .* \w+-i18ndemo type: 値ã�¯æœ‰12345効ã�ªå€¤ã�§ã�¯ã�‚りã�¾ã�›ã‚“/, result.stderr, 'missing error from invalid value for custom type param') end end step 'verify custom provider translation' do site_pp_content_4 = <<-PP node default { i18ndemo_type { 'hello': ensure => present, dir => '#{type_path}', } } PP create_sitepp(master, tmp_environment, site_pp_content_4) on(agent, puppet("agent -t --environment #{tmp_environment}", 'ENV' => shell_env_language)) do |result| assert_match(/Warning:.*\w+-i18ndemo provider: i18ndemo_typeã�¯å­˜åœ¨ã�—ã�¾ã�™ã�‹/, result.stderr, 'missing translated provider message') end end step 'verify function string translation' do site_pp_content_5 = <<-PP node default { notify { 'happy': message => happyfuntime('happy') } } PP create_sitepp(master, tmp_environment, site_pp_content_5) on(agent, puppet("agent -t --environment #{tmp_environment}", 'ENV' => shell_env_language), :acceptable_exit_codes => 2) do |result| assert_match(/Notice: --\*\w+-i18ndemo function: ã��れã�¯æ¥½ã�—ã�„時間ã�§ã�™\*--/, result.stdout, 'missing translated notice message') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modules/puppet_agent_cached_catalog.rb000066400000000000000000000132311527241624000324470ustar00rootroot00000000000000test_name 'C100566: puppet agent with module should translate messages when using a cached catalog' do confine :except, :platform => /^solaris/ # translation not supported tag 'audit:medium', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners skip_test('i18n test module uses deprecated function; update module to resume testing.') # function validate_absolute_path used https://github.com/eputnam/eputnam-i18ndemo/blob/621d06d/manifests/init.pp#L15 require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils language = 'ja_JP' disable_i18n_default_master = master.puppet['disable_i18n'] step 'enable i18n on master' do on(master, puppet("config set disable_i18n false")) end step "configure server locale to #{language}" do configure_master_system_locale(language) end tmp_environment = mk_tmp_environment_with_teardown(master, File.basename(__FILE__, '.*')) step 'install a i18ndemo module' do install_i18n_demo_module(master, tmp_environment) end teardown do step 'resetting the server locale' do on(master, puppet("config set disable_i18n #{ disable_i18n_default_master }")) reset_master_system_locale end step 'uninstall the module' do agents.each do |agent| uninstall_i18n_demo_module(agent) end uninstall_i18n_demo_module(master) end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end agents.each do |agent| skip_test('on windows this test only works on a machine with a japanese code page set') if agent['platform'] =~ /windows/ && agent['locale'] != 'ja' agent_language = enable_locale_language(agent, language) skip_test("test machine is missing #{agent_language} locale. Skipping") if agent_language.nil? shell_env_language = { 'LANGUAGE' => agent_language, 'LANG' => agent_language } type_path = agent.tmpdir('provider') disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) agent.rm_rf(type_path) end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) end unresolved_server = 'puppet.unresolved.host.example.com' step "Run puppet apply of a module with language #{agent_language} and verify the translations using the cached catalog" do step 'verify custom fact translations' do site_pp_content_1 = <<-PP node default { class { 'i18ndemo': filename => '#{type_path}' } } PP create_sitepp(master, tmp_environment, site_pp_content_1) on(agent, puppet("agent -t --environment #{tmp_environment}", 'ENV' => shell_env_language), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/.*\w+-i18ndemo fact: ã�“れã�¯\w+-i18ndemoã�‹ã‚‰ã�®ã‚«ã‚¹ã‚¿ãƒ ãƒ•ァクトã�‹ã‚‰ã�®ãƒ¬ã‚¤ã‚ºã�§ã�™/, result.stderr, 'missing translation for raise from ruby fact') end on(agent, puppet("agent -t --environment #{tmp_environment} --use_cached_catalog", 'ENV' => shell_env_language), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/.*\w+-i18ndemo fact: ã�“れã�¯\w+-i18ndemoã�‹ã‚‰ã�®ã‚«ã‚¹ã‚¿ãƒ ãƒ•ァクトã�‹ã‚‰ã�®ãƒ¬ã‚¤ã‚ºã�§ã�™/, result.stderr, 'missing translation for raise from ruby fact when using cached catalog') end end step 'verify custom provider translation' do site_pp_content_2 = <<-PP node default { i18ndemo_type { 'hello': ensure => present, dir => '#{type_path}', } } PP create_sitepp(master, tmp_environment, site_pp_content_2) on(agent, puppet("agent -t --environment #{tmp_environment}", 'ENV' => shell_env_language), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/Warning:.*\w+-i18ndemo provider: i18ndemo_typeã�¯å­˜åœ¨ã�—ã�¾ã�™ã�‹/, result.stderr, 'missing translated provider message') end on(agent, puppet("agent -t --server #{unresolved_server} --environment #{tmp_environment} --use_cached_catalog", 'ENV' => shell_env_language), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/Warning:.*\w+-i18ndemo provider: i18ndemo_typeã�¯å­˜åœ¨ã�—ã�¾ã�™ã�‹/, result.stderr, 'missing translated provider message when using cached catalog') end end step 'verify function string translation' do site_pp_content_3 = <<-PP node default { notify { 'happy': message => happyfuntime('happy') } } PP create_sitepp(master, tmp_environment, site_pp_content_3) on(agent, puppet("agent -t --environment #{tmp_environment}", 'ENV' => shell_env_language), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/Notice: --\*\w+-i18ndemo function: ã��れã�¯æ¥½ã�—ã�„時間ã�§ã�™\*--/, result.stdout, 'missing translated notice message') end on(agent, puppet("agent -t --server #{unresolved_server} --environment #{tmp_environment} --use_cached_catalog", 'ENV' => shell_env_language), :acceptable_exit_codes => [0, 2]) do |result| assert_match(/Notice: --\*\w+-i18ndemo function: ã��れã�¯æ¥½ã�—ã�„時間ã�§ã�™\*--/, result.stdout, 'missing translated notice message when using cached catalog') end end end end end puppet_agent_with_multiple_environments.rb000066400000000000000000000103741527241624000351710ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modulestest_name 'C100575: puppet agent with different modules in different environments should translate based on their module' do confine :except, :platform => /^solaris/ # translation not supported tag 'audit:medium', 'audit:acceptance', 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils language = 'ja_JP' app_type_1 = File.basename(__FILE__, '.*') + "_env_1" app_type_2 = File.basename(__FILE__, '.*') + "_env_2" tmp_environment_1 = mk_tmp_environment_with_teardown(master, app_type_1) tmp_environment_2 = mk_tmp_environment_with_teardown(master, app_type_2) full_path_env_1 = File.join(test_tmpdir, tmp_environment_1) full_path_env_2 = File.join(test_tmpdir, tmp_environment_2) tmp_po_file = master.tmpfile('tmp_po_file') disable_i18n_default_master = master.puppet['disable_i18n'] step 'enable i18n on master' do on(master, puppet("config set disable_i18n false")) end step 'install a i18ndemo module' do install_i18n_demo_module(master, tmp_environment_1) install_i18n_demo_module(master, tmp_environment_2) end step "configure server locale to #{language}" do configure_master_system_locale(language) end teardown do on(master, "rm -f '#{tmp_po_file}'") step 'uninstall the module' do agents.each do |agent| uninstall_i18n_demo_module(agent) end uninstall_i18n_demo_module(master) end step 'resetting the server locale' do on(master, puppet("config set disable_i18n #{ disable_i18n_default_master }")) reset_master_system_locale end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end agents.each do |agent| skip_test('on windows this test only works on a machine with a japanese code page set') if agent['platform'] =~ /windows/ && agent['locale'] != 'ja' agent_language = enable_locale_language(agent, language) skip_test("test machine is missing #{agent_language} locale. Skipping") if agent_language.nil? shell_env_language = { 'LANGUAGE' => agent_language, 'LANG' => agent_language } disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) end env_1_po_file = File.join(full_path_env_1, 'modules', I18NDEMO_NAME, 'locales', 'ja', "#{I18NDEMO_MODULE_NAME}.po") on(master, "sed -e 's/\\(msgstr \"\\)\\([^\"]\\)/\\1'\"ENV_1\"':\\2/' #{env_1_po_file} > #{tmp_po_file} && mv #{tmp_po_file} #{env_1_po_file}") env_2_po_file = File.join(full_path_env_2, 'modules', I18NDEMO_NAME, 'locales', 'ja', "#{I18NDEMO_MODULE_NAME}.po") on(master, "sed -e 's/\\(msgstr \"\\)\\([^\"]\\)/\\1'\"ENV_2\"':\\2/' #{env_2_po_file} > #{tmp_po_file} && mv #{tmp_po_file} #{env_2_po_file}") on(master, "chmod a+r '#{env_1_po_file}' '#{env_2_po_file}'") step 'verify function string translation' do site_pp_content = <<-PP node default { notify { 'happy': message => happyfuntime('happy') } } PP create_sitepp(master, tmp_environment_1, site_pp_content) on(agent, puppet("agent -t --environment #{tmp_environment_1}", 'ENV' => shell_env_language), :acceptable_exit_codes => 2) do |result| assert_match(/Notice: --\*(ENV_1:)?ENV_1:\w+-i18ndemo function: ã��れã�¯æ¥½ã�—ã�„時間ã�§ã�™\*--/, result.stdout, 'missing translated notice message for environment 1') end create_sitepp(master, tmp_environment_2, site_pp_content) on(agent, puppet("agent -t --environment #{tmp_environment_2}", 'ENV' => shell_env_language), :acceptable_exit_codes => 2) do |result| assert_match(/Notice: --\*(ENV_2:)?ENV_2:\w+-i18ndemo function: ã��れã�¯æ¥½ã�—ã�„時間ã�§ã�™\*--/, result.stdout, 'missing translated notice message for environment 2') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modules/puppet_apply.rb000066400000000000000000000100411527241624000275110ustar00rootroot00000000000000test_name 'C100567: puppet apply of module should translate messages' do confine :except, :platform => /^solaris/ # translation not supported tag 'audit:medium', 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners skip_test('i18n test module uses deprecated function; update module to resume testing.') # function validate_absolute_path used https://github.com/eputnam/eputnam-i18ndemo/blob/621d06d/manifests/init.pp#L15 require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils language = 'ja_JP' agents.each do |agent| skip_test('on windows this test only works on a machine with a japanese code page set') if agent['platform'] =~ /windows/ && agent['locale'] != 'ja' # REMIND - It was noted that skipping tests on certain platforms sometimes causes # beaker to mark the test as a failed even if the test succeeds on other targets. # Hence we just print a message and skip w/o telling beaker about it. if on(agent, facter("fips_enabled")).stdout =~ /true/ puts "Module build, loading and installing is not supported on fips enabled platforms" next end agent_language = enable_locale_language(agent, language) skip_test("test machine is missing #{agent_language} locale. Skipping") if agent_language.nil? shell_env_language = { 'LANGUAGE' => agent_language, 'LANG' => agent_language } type_path = agent.tmpdir('provider') step 'install a i18ndemo module' do install_i18n_demo_module(agent) end disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) uninstall_i18n_demo_module(agent) on(agent, "rm -rf '#{type_path}'") end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) end step "Run puppet apply of a module with language #{agent_language} and verify the translations" do step 'verify custom fact translations' do on(agent, puppet("apply -e \"class { 'i18ndemo': filename => '#{type_path}' }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/.*\w+-i18ndemo fact: ã�“れã�¯\w+-i18ndemoã�‹ã‚‰ã�®ã‚«ã‚¹ã‚¿ãƒ ãƒ•ァクトã�‹ã‚‰ã�®ãƒ¬ã‚¤ã‚ºã�§ã�™/, apply_result.stderr, 'missing translation for raise from ruby fact') end end unless agent['platform'] =~ /ubuntu-16.04/ # Condition to be removed after FACT-2799 gets resolved step 'verify custom translations' do on(agent, puppet("apply -e \"i18ndemo_type { 'hello': }\"", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |apply_result| assert_match(/Warning:.*\w+-i18ndemo type: 良ã�„値/, apply_result.stderr, 'missing warning from custom type') end on(agent, puppet("apply -e \"i18ndemo_type { '12345': }\"", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |apply_result| assert_match(/Error: .* \w+-i18ndemo type: 値ã�¯æœ‰12345効ã�ªå€¤ã�§ã�¯ã�‚りã�¾ã�›ã‚“/, apply_result.stderr, 'missing error from invalid value for custom type param') end end step 'verify custom provider translation' do on(agent, puppet("apply -e \"i18ndemo_type { 'hello': ensure => present, dir => '#{type_path}', }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/Warning:.*\w+-i18ndemo provider: i18ndemo_typeã�¯å­˜åœ¨ã�—ã�¾ã�™ã�‹/, apply_result.stderr, 'missing translated provider message') end end step 'verify function string translation' do on(agent, puppet("apply -e \"notify { 'happy': message => happyfuntime('happy') }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/Notice: --\*\w+-i18ndemo function: ã��れã�¯æ¥½ã�—ã�„時間ã�§ã�™\*--/, apply_result.stdout, 'missing translated notice message') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modules/puppet_apply_module_lang.rb000066400000000000000000000114021527241624000320610ustar00rootroot00000000000000test_name 'C100574: puppet apply using a module should translate messages in a language not supported by puppet' do confine :except, :platform => /^windows/ # Can't print Finish on an English or Japanese code page tag 'audit:medium', 'audit:acceptance', 'shard:group4' # For splitting out groups of tests for slow test runners skip_test('i18n test module uses deprecated function; update module to resume testing.') # function validate_absolute_path used https://github.com/eputnam/eputnam-i18ndemo/blob/621d06d/manifests/init.pp#L15 require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils language='fi_FI' agents.each do |agent| # REMIND - It was noted that skipping tests on certain platforms sometimes causes # beaker to mark the test as a failed even if the test succeeds on other targets. # Hence we just print a message and skip w/o telling beaker about it. if on(agent, facter("fips_enabled")).stdout =~ /true/ puts "Module build, loading and installing is not supported on fips enabled platforms" next end agent_language = enable_locale_language(agent, language) skip_test("test machine is missing #{agent_language} locale. Skipping") if agent_language.nil? shell_env_language = { 'LANGUAGE' => agent_language, 'LANG' => agent_language } type_path = agent.tmpdir('provider') disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) uninstall_i18n_demo_module(agent) on(agent, "rm -rf '#{type_path}'") end step 'install a i18ndemo module' do install_i18n_demo_module(agent) end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) end step "Run puppet apply of a module with language #{agent_language} and verify default english returned" do step 'verify custom fact message translated and applied catalog message not translatated' do on(agent, puppet("apply -e \"class { 'i18ndemo': filename => '#{type_path}' }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/i18ndemo_fact: tämä on korotus mukautetusta tosiasiasta \w+-i18ndemo/, apply_result.stderr, 'missing translated message for raise from ruby fact') assert_match(/Notice: Applied catalog in [0-9.]+ seconds/, apply_result.stdout, 'missing untranslated message for catalog applied') end end unless agent['platform'] =~ /ubuntu-16.04/ # Condition to be removed after FACT-2799 gets resolved step 'verify warning translated from init.pp' do on(agent, puppet("apply -e \"class { 'i18ndemo': filename => '#{type_path}' }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/Warning: .*I18ndemo-tiedoston luominen/, apply_result.stderr, 'missing translated warning from init.pp') end on(agent, puppet("apply -e \"class { 'i18ndemo': param1 => false }\"", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |apply_result| assert_match(/Error: .* tiedostoa ei voitu luoda./, apply_result.stderr, 'missing translated message for fail from init.pp') end end step 'verify custom type messages translated' do on(agent, puppet("apply -e \"i18ndemo_type { 'hello': }\"", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |apply_result| assert_match(/Warning: .* Hyvä arvo i18ndemo_type::name/, apply_result.stderr, 'missing translated warning from custom type') end on(agent, puppet("apply -e \"i18ndemo_type { '12345': }\"", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |apply_result| assert_match(/Error: .* Arvo 12345 ei ole kelvollinen arvo i18ndemo_type::name/, apply_result.stderr, 'missing translated error from invalid value for custom type param') end end step 'verify custom provider translation' do on(agent, puppet("apply -e \"i18ndemo_type { 'hello': ensure => present, dir => '#{type_path}', }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/Warning: .* Onko i18ndemo_type olemassa\?/, apply_result.stderr, 'missing translated provider message') end end step 'verify function string translation' do on(agent, puppet("apply -e \"notify { 'happy': message => happyfuntime('happy') }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/Notice: --\*SE ON HAUSKAA AIKAA\*--/, apply_result.stdout, 'missing translated notice message') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modules/puppet_apply_unsupported_lang.rb000066400000000000000000000102211527241624000331620ustar00rootroot00000000000000test_name 'C100568: puppet apply of module for an unsupported language should fall back to english' do tag 'audit:medium', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners skip_test('i18n test module uses deprecated function; update module to resume testing.') # function validate_absolute_path used https://github.com/eputnam/eputnam-i18ndemo/blob/621d06d/manifests/init.pp#L15 require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils unsupported_language='hu_HU' shell_env_language = { 'LANGUAGE' => unsupported_language, 'LANG' => unsupported_language } agents.each do |agent| # REMIND - It was noted that skipping tests on certain platforms sometimes causes # beaker to mark the test as a failed even if the test succeeds on other targets. # Hence we just print a message and skip w/o telling beaker about it. if on(agent, facter("fips_enabled")).stdout =~ /true/ puts "Module build, loading and installing is not supported on fips enabled platforms" next end type_path = agent.tmpdir('provider') disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) uninstall_i18n_demo_module(agent) on(agent, "rm -rf '#{type_path}'") end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) end step 'install a i18ndemo module' do install_i18n_demo_module(agent) end step "Run puppet apply of a module with language #{unsupported_language} and verify default english returned" do step 'verify custom fact messages not translatated' do on(agent, puppet("apply -e \"class { 'i18ndemo': filename => '#{type_path}' }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/.*i18ndemo_fact: this is a raise from a custom fact from \w+-i18ndemo/, apply_result.stderr, 'missing untranslated message for raise from ruby fact') end end step 'verify warning not translated from init.pp' do on(agent, puppet("apply -e \"class { 'i18ndemo': filename => '#{type_path}' }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/Warning:.*Creating an i18ndemo file/, apply_result.stderr, 'missing untranslated warning from init.pp') end on(agent, puppet("apply -e \"class { 'i18ndemo': param1 => false }\"", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |apply_result| assert_match(/Error:.*Failed to create/, apply_result.stderr, 'missing untranslated message for fail from init.pp') end end step 'verify custom type messages not translated' do on(agent, puppet("apply -e \"i18ndemo_type { 'hello': }\"", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |apply_result| assert_match(/Warning:.*Good value for i18ndemo_type::name/, apply_result.stderr, 'missing untranslated warning from custom type') end on(agent, puppet("apply -e \"i18ndemo_type { '12345': }\"", 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |apply_result| assert_match(/Error:.*Value 12345 is not a valid value for i18ndemo_type::name/, apply_result.stderr, 'missing untranslated error from invalid value for custom type param') end end step 'verify custom provider translation' do on(agent, puppet("apply -e \"i18ndemo_type { 'hello': ensure => present, dir => '#{type_path}', }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/Warning:.* Does i18ndemo_type exist\?/, apply_result.stderr, 'missing untranslated provider message') end end step 'verify function string translation' do on(agent, puppet("apply -e \"notify { 'happy': message => happyfuntime('happy') }\"", 'ENV' => shell_env_language)) do |apply_result| assert_match(/Notice: --\*IT'S HAPPY FUN TIME\*--/, apply_result.stdout, 'missing untranslated notice message') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modules/puppet_describe.rb000066400000000000000000000044231527241624000301530ustar00rootroot00000000000000test_name 'C100576: puppet describe with module type translates message' do confine :except, :platform => /^solaris/ # translation not supported tag 'audit:medium', 'audit:acceptance', 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils language = 'ja_JP' agents.each do |agent| skip_test('on windows this test only works on a machine with a japanese code page set') if agent['platform'] =~ /windows/ && agent['locale'] != 'ja' # REMIND - It was noted that skipping tests on certain platforms sometimes causes # beaker to mark the test as a failed even if the test succeeds on other targets. # Hence we just print a message and skip w/o telling beaker about it. if on(agent, facter("fips_enabled")).stdout =~ /true/ puts "Module build, loading and installing is not supported on fips enabled platforms" next end agent_language = enable_locale_language(agent, language) skip_test("test machine is missing #{agent_language} locale. Skipping") if agent_language.nil? shell_env_language = { 'LANGUAGE' => agent_language, 'LANG' => agent_language } disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) uninstall_i18n_demo_module(agent) end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) end step 'install a i18ndemo module' do install_i18n_demo_module(agent) end step "Run puppet describe from a module with language #{agent_language} and verify the translations" do on(agent, puppet('describe i18ndemo_type', 'ENV' => shell_env_language)) do |result| assert_match(/\w+-i18ndemo type: dirパラメータã�¯ã€�検査ã�™ã‚‹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ‘スをã�¨ã‚Šã�¾ã�™/, result.stdout, 'missing translation of dir parameter from i18ndemo_type') assert_match(/\w+-i18ndemo type: nameパラメータã�«ã�¯ã€�大文字ã�¨å°�文字ã�®å¤‰æ•°A-Za-zã�Œä½¿ç”¨ã�•れã�¾ã�™/, result.stdout, 'missing translation of name parameter from i18ndemo_type') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modules/puppet_face.rb000066400000000000000000000054761527241624000273020ustar00rootroot00000000000000test_name 'C100573: puppet application/face with module translates messages' do confine :except, :platform => /^solaris/ # translation not supported tag 'audit:medium', 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils language = 'ja_JP' agents.each do |agent| skip_test('on windows this test only works on a machine with a japanese code page set') if agent['platform'] =~ /windows/ && agent['locale'] != 'ja' # REMIND - It was noted that skipping tests on certain platforms sometimes causes # beaker to mark the test as a failed even if the test succeeds on other targets. # Hence we just print a message and skip w/o telling beaker about it. if on(agent, facter("fips_enabled")).stdout =~ /true/ puts "Module build, loading and installing is not supported on fips enabled platforms" next end agent_language = enable_locale_language(agent, language) skip_test("test machine is missing #{agent_language} locale. Skipping") if agent_language.nil? shell_env_language = { 'LANGUAGE' => agent_language, 'LANG' => agent_language } disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) uninstall_i18n_demo_module(agent) end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) end step 'install a i18ndemo module' do install_i18n_demo_module(agent) end step "Run puppet i18ndemo (face/application from a module with language #{agent_language} and verify the translations" do step 'puppet --help contains i18ndemo summary translation' do on(agent, puppet('--help', 'ENV' => shell_env_language)) do |result| assert_match(/\s*i18ndemo\s+\w+-i18ndemo face: I18ndemoモジュールã�®äººå½¢ã�®é¡”ã�®ä¾‹/, result.stdout, 'missing translation of i18ndemo help summary') end end step 'puppet i18ndemo --help contains test_face summary' do on(agent, puppet('i18ndemo --help', 'ENV' => shell_env_language)) do |result| assert_match(/\s*test_face\s+\w+-i18ndemo face: test_faceアクションã�®ãƒ˜ãƒ«ãƒ—ã�®è¦�ç´„/, result.stdout, 'missing translation of i18ndemo face help summary') end end step 'puppet i18ndemo test_face contains translated warning' do on(agent, puppet('i18ndemo', 'ENV' => shell_env_language)) do |result| assert_match(/Warning: \w+-i18ndemo face: i18ndemo test_faceã�Œå‘¼ã�³å‡ºã�•れã�¾ã�—ã�Ÿ/, result.stderr, 'missing translation of Warning message from i18ndemo face') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/modules/puppet_resource.rb000066400000000000000000000043241527241624000302220ustar00rootroot00000000000000test_name 'C100572: puppet resource with module translates messages' do confine :except, :platform => /^solaris/ # translation not supported tag 'audit:medium', 'audit:acceptance', 'shard:group4' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/i18n_utils' extend Puppet::Acceptance::I18nUtils require 'puppet/acceptance/i18ndemo_utils' extend Puppet::Acceptance::I18nDemoUtils language = 'ja_JP' agents.each do |agent| skip_test('on windows this test only works on a machine with a japanese code page set') if agent['platform'] =~ /windows/ && agent['locale'] != 'ja' # REMIND - It was noted that skipping tests on certain platforms sometimes causes # beaker to mark the test as a failed even if the test succeeds on other targets. # Hence we just print a message and skip w/o telling beaker about it. if on(agent, facter("fips_enabled")).stdout =~ /true/ puts "Module build, loading and installing is not supported on fips enabled platforms" next end agent_language = enable_locale_language(agent, language) skip_test("test machine is missing #{agent_language} locale. Skipping") if agent_language.nil? shell_env_language = { 'LANGUAGE' => agent_language, 'LANG' => agent_language } disable_i18n_default_agent = agent.puppet['disable_i18n'] teardown do on(agent, puppet("config set disable_i18n #{ disable_i18n_default_agent }")) uninstall_i18n_demo_module(agent) end step 'enable i18n' do on(agent, puppet("config set disable_i18n false")) end step 'install a i18ndemo module' do install_i18n_demo_module(agent) end step "Run puppet resource for a module with language #{agent_language} and verify the translations" do step 'puppet resource i18ndemo_type information contains translation' do on(agent, puppet('resource i18ndemo_type', 'ENV' => shell_env_language), :acceptable_exit_codes => 1) do |result| assert_match(/Warning: Puppet::Type::I18ndemo_type::ProviderRuby: \w+-i18ndemo type: i18ndemo_typeã�‹ã‚‰ã�®è­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸/, result.stderr, 'missing translation of resource i18ndemo_type information') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/i18n/translation_fallback.rb000066400000000000000000000016501527241624000275020ustar00rootroot00000000000000test_name 'C100560: puppet agent run output falls back to english when language not available' do # No confines because even on non-translation supported OS' we should still fall back to english tag 'audit:medium', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners agents.each do |agent| step 'Run Puppet apply with language Hungarian and check the output' do unsupported_language='hu_HU' on(agent, puppet("agent -t", 'ENV' => {'LANG' => unsupported_language, 'LANGUAGE' => ''})) do |apply_result| assert_match(/Applying configuration version '[^']*'/, apply_result.stdout, 'agent run should default to english translation') assert_match(/Applied catalog in [0-9.]* seconds/, apply_result.stdout, 'agent run should default to english translation') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/language/000077500000000000000000000000001527241624000240025ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/language/binary_data_type.rb000066400000000000000000000114721527241624000276520ustar00rootroot00000000000000test_name 'C98346: Binary data type' do require 'puppet/acceptance/puppet_type_test_tools.rb' extend Puppet::Acceptance::PuppetTypeTestTools tag 'audit:high', 'audit:integration', # Tests that binary data is retains integrity # between server and agent transport/application. # The weak link here is final ruby translation and # should not be OS sensitive. 'server', 'shard:group2' # For splitting out groups of tests for slow test runners teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) tmp_filename_win = tmp_filename_else = '' agents.each do |agent| # ugh... this won't work with more than two agents of two types if agent.platform =~ /32$/ tmp_filename_win = "C:\\cygwin\\tmp\\#{tmp_environment}.txt" else tmp_filename_win = "C:\\cygwin64\\tmp\\#{tmp_environment}.txt" end tmp_filename_else = "/tmp/#{tmp_environment}.txt" on(agent, "echo 'old content' > '/tmp/#{tmp_environment}.txt'") end # create a fake module files... file for binary_file() on(master, puppet_apply("-e 'file{[\"#{environmentpath}/#{tmp_environment}/modules\",\"#{environmentpath}/#{tmp_environment}/modules/empty\",\"#{environmentpath}/#{tmp_environment}/modules/empty/files\"]: ensure => \"directory\"} file{\"#{environmentpath}/#{tmp_environment}/modules/empty/files/blah.txt\": content => \"binary, yo\"}'")) base64_relaxed = Base64.encode64("invasionfromspace#{random_string}").strip base64_strict = Base64.strict_encode64("invasion from space #{random_string}\n") base64_urlsafe = Base64.urlsafe_encode64("invasion from-space/#{random_string}\n") test_resources = [ { :type => 'notify', :parameters => { :namevar => "1:$hell" }, :pre_code => "$hell = Binary('hello','%b')", :assertions => { :assert_match => 'Notice: 1:hell' } }, { :type => 'notify', :parameters => { :namevar => "2:$relaxed" }, :pre_code => "$relaxed = Binary('#{base64_relaxed}')", :assertions => { :assert_match => "Notice: 2:#{base64_relaxed}" } }, { :type => 'notify', :parameters => { :namevar => "3:$cHVwcGV0" }, :pre_code => "$cHVwcGV0 = Binary('cHVwcGV0')", :assertions => { :assert_match => 'Notice: 3:cHVwcGV0' } }, { :type => 'notify', :parameters => { :namevar => "4:$strict" }, :pre_code => "$strict = Binary('#{base64_strict}')", :assertions => { :assert_match => "Notice: 4:#{base64_strict}" } }, { :type => 'notify', :parameters => { :namevar => "5:$urlsafe" }, :pre_code => "$urlsafe = Binary('#{base64_urlsafe}')", :assertions => { :assert_match => "Notice: 5:#{base64_urlsafe}" } }, { :type => 'notify', :parameters => { :namevar => "6:$byte_array" }, :pre_code => "$byte_array = Binary([67,68])", :assertions => { :assert_match => "Notice: 6:Q0Q=" } }, { :type => 'notify', :parameters => { :namevar => "7:${empty_array}empty" }, :pre_code => "$empty_array = Binary([])", :assertions => { :assert_match => "Notice: 7:empty" } }, { :type => 'notify', :parameters => { :namevar => "8:${relaxed[1]}" }, :assertions => { :assert_match => "Notice: 8:bg==" } }, { :type => 'notify', :parameters => { :namevar => "9:${relaxed[1,3]}" }, :assertions => { :assert_match => "Notice: 9:bnZh" } }, { :type => 'notify', :parameters => { :namevar => "A:${utf8}" }, :pre_code => '$utf8=String(Binary([0xF0, 0x9F, 0x91, 0x92]),"%s")', :assertions => { :assert_match => 'Notice: A:\\xF0\\x9F\\x91\\x92' } }, { :type => 'notify', :parameters => { :namevar => "B:${type($bin_file)}" }, :pre_code => '$bin_file=binary_file("empty/blah.txt")', :assertions => { :assert_match => 'Notice: B:Binary' } }, { :type => 'file', :parameters => { :namevar => "$pup_tmp_filename", :content => "$relaxed" }, :pre_code => "$pup_tmp_filename = if $facts['os']['family'] == 'windows' { '#{tmp_filename_win}' } else { '#{tmp_filename_else}' }", :assertions => { :assert_match => /#{base64_relaxed}/ } }, ] sitepp_content = generate_manifest(test_resources) assertion_code = generate_assertions(test_resources) create_sitepp(master, tmp_environment, sitepp_content) step "run agent in #{tmp_environment}, run all assertions" do with_puppet_running_on(master, {}) do agents.each do |agent| on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :acceptable_exit_codes => [2]) do |result| run_assertions(assertion_code, result) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/language/exported_resources.rb000066400000000000000000000164331527241624000302620ustar00rootroot00000000000000test_name "C94788: exported resources using a yaml terminus for storeconfigs" do require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:integration', 'audit:refactor', # This could be a component of a larger workflow scenario. 'server', 'shard:group3' # For splitting out groups of tests for slow test runners skip_test 'requires puppetserver to service restart' if @options[:type] != 'aio' app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) exported_username = 'er0ck' teardown do step 'stop puppet server' do service(master, :stop, master['puppetservice']) end step 'remove cached agent json catalogs from the master' do on(master, "rm -f #{File.join(master.puppet['yamldir'],'catalog','*')}", :accept_all_exit_codes => true) end on(master, "mv #{File.join('','tmp','puppet.conf')} #{master.puppet['confdir']}", :accept_all_exit_codes => true) step 'clean out collected resources' do on(hosts, puppet_resource("user #{exported_username} ensure=absent"), :accept_all_exit_codes => true) end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end storeconfigs_backend_name = 'json_storeconfigs' step 'create a yaml storeconfigs terminus in the modulepath' do moduledir = File.join(environmentpath,tmp_environment,'modules') terminus_class_name = 'JsonStoreconfigs' manifest = < directory, } file { '#{moduledir}':; '#{moduledir}/yaml_terminus':; '#{moduledir}/yaml_terminus/lib':; '#{moduledir}/yaml_terminus/lib/puppet':; '#{moduledir}/yaml_terminus/lib/puppet/indirector':; '#{moduledir}/yaml_terminus/lib/puppet/indirector/catalog':; '#{moduledir}/yaml_terminus/lib/puppet/indirector/facts':; '#{moduledir}/yaml_terminus/lib/puppet/indirector/node':; '#{moduledir}/yaml_terminus/lib/puppet/indirector/resource':; } file { '#{moduledir}/yaml_terminus/lib/puppet/indirector/catalog/#{storeconfigs_backend_name}.rb': ensure => file, content => ' require "puppet/indirector/catalog/yaml" class Puppet::Resource::Catalog::#{terminus_class_name} < Puppet::Resource::Catalog::Yaml def save(request) raise ArgumentError.new("You can only save objects that respond to :name") unless request.instance.respond_to?(:name) file = path(request.key) basedir = File.dirname(file) # This is quite likely a bad idea, since we are not managing ownership or modes. Dir.mkdir(basedir) unless Puppet::FileSystem.exist?(basedir) begin # We cannot dump anonymous modules in yaml, so dump to json File.open(file, "w") { |f| f.write request.instance.to_json } rescue TypeError => detail Puppet.err "Could not save \#{self.name} \#{request.key}: \#{detail}" end end def find(request) nil end end ', } file { '#{moduledir}/yaml_terminus/lib/puppet/indirector/facts/#{storeconfigs_backend_name}.rb': ensure => file, content => ' require "puppet/indirector/facts/yaml" class Puppet::Node::Facts::#{terminus_class_name} < Puppet::Node::Facts::Yaml def find(request) nil end end ', } file { '#{moduledir}/yaml_terminus/lib/puppet/indirector/node/#{storeconfigs_backend_name}.rb': ensure => file, content => ' require "puppet/indirector/node/yaml" class Puppet::Node::#{terminus_class_name} < Puppet::Node::Yaml def find(request) nil end end ', } file { '#{moduledir}/yaml_terminus/lib/puppet/indirector/resource/#{storeconfigs_backend_name}.rb': ensure => file, content => ' require "puppet/indirector/yaml" require "puppet/resource/catalog" class Puppet::Resource::#{terminus_class_name} < Puppet::Indirector::Yaml desc "Read resource instances from cached catalogs" def search(request) catalog_dir = File.join(Puppet.run_mode.server? ? Puppet[:yamldir] : Puppet[:clientyamldir], "catalog", "*") results = Dir.glob(catalog_dir).collect { |file| catalog = Puppet::Resource::Catalog.convert_from(:json, File.read(file)) if catalog.name == request.options[:host] next end catalog.resources.select { |resource| resource.type == request.key && resource.exported }.map! { |res| data_hash = res.to_data_hash parameters = data_hash["parameters"].map do |name, value| Puppet::Parser::Resource::Param.new(:name => name, :value => value) end attrs = {:parameters => parameters, :scope => request.options[:scope]} result = Puppet::Parser::Resource.new(res.type, res.title, attrs) result.collector_id = "\#{catalog.name}|\#{res.type}|\#{res.title}" result } }.flatten.compact results end end ', } # all the filtering is taken care of in the terminii # so any tests on filtering belong with puppetdb or pe file { '#{environmentpath}/#{tmp_environment}/manifests/site.pp': ensure => file, content => ' node "#{master.hostname}" { @@user{"#{exported_username}": ensure => present,} } node "default" { # collect resources on all nodes (puppet prevents collection on same node) User<<| |>> } ', } MANIFEST apply_manifest_on(master, manifest, :catch_failures => true) end # must specify environment in puppet.conf for it to pickup the terminus code in an environment module # but we have to bounce the server to pickup the storeconfigs... config anyway # we can't use with_puppet_running_on here because it uses puppet resource to bounce the server # puppet resource tries to use yaml_storeconfig's path() which doesn't exist # and fails back to yaml which indicates an attempted directory traversal and fails. # we could implemnt path() properly, but i'm just going to start the server the old fashioned way # and... config set is broken and doesn't add a main section step 'turn on storeconfigs, start puppetserver the old fashioned way' do on(master, "cp #{File.join(master.puppet['confdir'],'puppet.conf')} #{File.join('','tmp')}") on(master, "echo [main] >> #{File.join(master.puppet['confdir'],'puppet.conf')}") on(master, "echo environment=#{tmp_environment} >> #{File.join(master.puppet['confdir'],'puppet.conf')}") on(master, puppet('config set storeconfigs true --section main')) on(master, puppet("config set storeconfigs_backend #{storeconfigs_backend_name} --section main")) service(master, :restart, master['puppetservice']) step 'run the master agent to export the resources' do on(master, puppet("agent -t --environment #{tmp_environment}")) end agents.each do |agent| next if agent == master step 'run the agents to collect exported resources' do on(agent, puppet("agent -t --environment #{tmp_environment}"), :acceptable_exit_codes => 2) on(agent, puppet_resource("user #{exported_username}"), :accept_all_exit_codes => true) do |result| assert_match(/present/, result.stdout, 'collected resource not found') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/language/functions_in_puppet_language.rb000066400000000000000000000135301527241624000322670ustar00rootroot00000000000000test_name 'Puppet executes functions written in the Puppet language' tag 'audit:high', 'audit:integration', 'audit:refactor', # use mk_tmp_environment_with_teardown helper for environment construction 'server', 'shard:group4' # For splitting out groups of tests for slow test runners teardown do on master, 'rm -rf /etc/puppetlabs/code/modules/jenny' on master, 'rm -rf /etc/puppetlabs/code/environments/tommy' on master, 'rm -rf /etc/puppetlabs/code/environments/production/modules/one' on master, 'rm -rf /etc/puppetlabs/code/environments/production/modules/three' agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step 'Create some functions' do manifest = <<-EOF File { ensure => 'present', owner => 'root', group => 'root', mode => '0644', } file {['/etc/puppetlabs/', '/etc/puppetlabs/code/', '/etc/puppetlabs/code/modules/', '/etc/puppetlabs/code/modules/jenny', '/etc/puppetlabs/code/modules/jenny/functions', '/etc/puppetlabs/code/modules/jenny/functions/nested', '/etc/puppetlabs/code/environments', '/etc/puppetlabs/code/environments/production', '/etc/puppetlabs/code/environments/production/modules', '/etc/puppetlabs/code/environments/production/modules/one', '/etc/puppetlabs/code/environments/production/modules/one/functions', '/etc/puppetlabs/code/environments/production/modules/one/manifests', '/etc/puppetlabs/code/environments/production/modules/three', '/etc/puppetlabs/code/environments/production/modules/three/functions', '/etc/puppetlabs/code/environments/production/modules/three/manifests', '/etc/puppetlabs/code/environments/tommy', '/etc/puppetlabs/code/environments/tommy/modules', '/etc/puppetlabs/code/environments/tommy/modules/two', '/etc/puppetlabs/code/environments/tommy/modules/two/functions', ]: ensure => directory, mode => '0755', } # "Global" functions, no env file { '/etc/puppetlabs/code/modules/jenny/functions/mini.pp': content => 'function jenny::mini($a, $b) {if $a <= $b {$a} else {$b}}', require => File['/etc/puppetlabs/code/modules/jenny/functions'], } file { '/etc/puppetlabs/code/modules/jenny/functions/nested/maxi.pp': content => 'function jenny::nested::maxi($a, $b) {if $a >= $b {$a} else {$b}}', require => File['/etc/puppetlabs/code/modules/jenny/functions/nested'], } # Module "one", "production" env file { '/etc/puppetlabs/code/environments/production/modules/one/functions/foo.pp': content => 'function one::foo() {"This is the one::foo() function in the production environment"}', require => File['/etc/puppetlabs/code/environments/production/modules/one/functions'], } file { '/etc/puppetlabs/code/environments/production/modules/one/manifests/init.pp': content => 'class one { }', require => File['/etc/puppetlabs/code/environments/production/modules/one/manifests'], } # Module "three", "production" env file { '/etc/puppetlabs/code/environments/production/modules/three/functions/baz.pp': content => 'function three::baz() {"This is the three::baz() function in the production environment"}', require => File['/etc/puppetlabs/code/environments/production/modules/three/functions'], } file { '/etc/puppetlabs/code/environments/production/modules/three/manifests/init.pp': content => 'class three { }', require => File['/etc/puppetlabs/code/environments/production/modules/three/functions'], } # Module "two", "tommy" env file { '/etc/puppetlabs/code/environments/tommy/modules/two/functions/bar.pp': content => 'function two::bar() {"This is the two::bar() function in the tommy environment"}', require => File['/etc/puppetlabs/code/environments/tommy/modules/two/functions'], } EOF apply_manifest_on(master, manifest, {:catch_failures => true, :acceptable_exit_codes => [0,1]}) end manifest = <<-MANIFEST notice 'jenny::mini(1, 2) =', jenny::mini(1,2) notice 'jenny::nested::maxi(1, 2) =', jenny::nested::maxi(1,2) notice 'one::foo() =', one::foo() require 'one'; notice 'three::baz() =', three::baz() MANIFEST rc = apply_manifest_on(master, manifest, {:accept_all_exit_codes => true,}) step 'Call a global function' do fail_test 'Failed to call a "global" function' \ unless rc.stdout.include?('jenny::mini(1, 2) = 1') end step 'Call a global nested function' do fail_test 'Failed to call a "global" nested function' \ unless rc.stdout.include?('jenny::nested::maxi(1, 2) = 2') end step 'Call an env-specific function' do fail_test 'Failed to call a function defined in the current environment' \ unless rc.stdout.include?('This is the one::foo() function in the production environment') end step 'Call a function defined in an un-included module' do fail_test 'Failed to call a function defined in an un-required module' \ unless rc.stdout.include?('This is the three::baz() function in the production environment') end manifest = <<-MANIFEST.strip notice "two::bar() =", two::bar() MANIFEST # This should fail step 'Call a function not defined in the current environment' do rc = on master, puppet("apply -e '#{manifest}' --environment production"), {:accept_all_exit_codes => true,} fail_test 'Should not be able to call a function not defined in the current environment' \ unless rc.stderr.include?("Error: Evaluation Error: Unknown function: 'two::bar'") end step 'Call an env-specific function in a non-default environment' do rc = on master, puppet("apply -e '#{manifest}' --environment tommy") fail_test 'Failed to call env-specific function from that environment' \ unless rc.stdout.include?('This is the two::bar() function in the tommy environment') end OpenVoxProject-openvox-ebcec1e/acceptance/tests/language/objects_in_catalog.rb000066400000000000000000000024461527241624000301460ustar00rootroot00000000000000test_name 'C99627: can use Object types in the catalog and apply/agent' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:integration', 'audit:refactor', # The use of apply on a reference system should # be adequate to test puppet. Running this in # context of server/agent should not be necessary. 'shard:group1' # For splitting out groups of tests for slow test runners manifest = <<-PP type Mod::Foo = Object[{ attributes => { 'name' => String, 'size' => Integer[0, default] } }] define mod::foo_notifier(Mod::Foo $foo) { notify { $foo.name: } } class mod { mod::foo_notifier { xyz: foo => Mod::Foo('A foo', 42) } } include mod PP agents.each do |agent| # This is currently only expected to work with apply as the custom data type # definition will not be present on the agent to deserialize properly step "apply manifest on agent #{agent.hostname} and assert notify output" do apply_manifest_on(agent, manifest) do |result| assert(result.exit_code == 0, "agent didn't exit properly: (#{result.exit_code})") assert_match(/A foo/, result.stdout, 'agent didn\'t notify correctly') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/language/pcore_generate_env_isolation.rb000066400000000000000000000062451527241624000322510ustar00rootroot00000000000000test_name 'C98345: ensure puppet generate assures env. isolation' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:integration', 'server', 'shard:group2' # For splitting out groups of tests for slow test runners teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) tmp_environment2 = mk_tmp_environment_with_teardown(master, app_type) fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" fq_tmp_environmentpath2 = "#{environmentpath}/#{tmp_environment2}" type_name = 'conflicting' relative_type_dir = 'modules/conflict/lib/puppet/type' relative_type_path = "#{relative_type_dir}/#{type_name}.rb" step 'create custom type in two environments' do on(master, "mkdir -p #{fq_tmp_environmentpath}/#{relative_type_dir}") on(master, "mkdir -p #{fq_tmp_environmentpath2}/#{relative_type_dir}") custom_type1 = <<-END Puppet::Type.newtype(:#{type_name}) do newparam :name, :namevar => true END custom_type2 = "#{custom_type1}" custom_type2 << " newparam :other\n" custom_type1 << " end\n" custom_type2 << " end\n" create_remote_file(master, "#{fq_tmp_environmentpath}/#{relative_type_path}", custom_type1) create_remote_file(master, "#{fq_tmp_environmentpath2}/#{relative_type_path}", custom_type2) site_pp1 = <<-PP notify{$environment:} #{type_name}{"somename":} PP site_pp2 = <<-PP notify{$environment:} #{type_name}{"somename": other => "uhoh"} PP create_sitepp(master, tmp_environment, site_pp1) create_sitepp(master, tmp_environment2, site_pp2) end on master, "chmod -R 755 #{test_tmpdir}/#{tmp_environment}" on master, "chmod -R 755 #{test_tmpdir}/#{tmp_environment2}" with_puppet_running_on(master,{}) do agents.each do |agent| on(agent, puppet("agent -t --environment #{tmp_environment}"), :acceptable_exit_codes => 2) step 'run agent in environment with type with an extra parameter. try to use this parameter' do on(agent, puppet("agent -t --environment #{tmp_environment2}"), :accept_all_exit_codes => true) do |result| unless agent['locale'] == 'ja' assert_match("Error: no parameter named 'other'", result.output, 'did not produce environment isolation issue as expected') end end end end step 'generate pcore files' do on(master, puppet("generate types --environment #{tmp_environment}")) on(master, puppet("generate types --environment #{tmp_environment2}")) end agents.each do |agent| step 'rerun agents after generate, ensure proper runs' do on(agent, puppet("agent -t --environment #{tmp_environment}"), :acceptable_exit_codes => 2) on(agent, puppet("agent -t --environment #{tmp_environment2}"), :acceptable_exit_codes => 2) end end end end pcore_resource_types_should_have_precedence_over_ruby.rb000066400000000000000000000071671527241624000373600ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/languagetest_name 'C98097 - generated pcore resource types should be loaded instead of ruby for custom types' do tag 'audit:high', 'audit:integration', 'audit:refactor', # use `mk_tmp_environment_with_teardown` helper to build environment 'server', 'shard:group3' # For splitting out groups of tests for slow test runners environment = 'production' step 'setup - install module with custom ruby resource type' do #{{{ testdir = master.tmpdir('c98097') codedir = "#{testdir}/codedir" site_manifest_content =< true) do desc "Name of mycustomtype instance" $stderr.puts "this indicates that we are running ruby code and should not be seen when running generated pcore resource" end def refresh end end EOM apply_manifest_on(master, < true) File { ensure => directory, mode => "0755", } file {[ '#{codedir}', '#{codedir}/environments', '#{codedir}/environments/#{environment}', '#{codedir}/environments/#{environment}/manifests', '#{codedir}/environments/#{environment}/modules', '#{codedir}/environments/#{environment}/modules/mymodule', '#{codedir}/environments/#{environment}/modules/mymodule/manifests', '#{codedir}/environments/#{environment}/modules/mymodule/lib', '#{codedir}/environments/#{environment}/modules/mymodule/lib/puppet', '#{codedir}/environments/#{environment}/modules/mymodule/lib/puppet/type' ]: } file { '#{codedir}/environments/#{environment}/manifests/site.pp': ensure => file, content => '#{site_manifest_content}', } file { '#{codedir}/environments/#{environment}/modules/mymodule/lib/puppet/type/mycustomtype.rb': ensure => file, content => '#{custom_type_content}', } MANIFEST conf_opts = { 'main' => { 'environmentpath' => "#{codedir}/environments" } } backup_file = backup_the_file(master, puppet_config(master, 'confdir', section: 'master'), testdir, 'puppet.conf') lay_down_new_puppet_conf master, conf_opts, testdir teardown do restore_puppet_conf_from_backup( master, backup_file ) # See PUP-6995 on(master, "rm -f #{puppet_config(master, 'yamldir', section: 'master')}/node/*.yaml") agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end #}}} catalog_results = {} catalog_results[master.hostname] = { 'ruby_cat' => '', 'pcore_cat' => '' } step 'compile catalog using ruby resource' do on master, puppet('catalog', 'find', master.hostname) do |result| assert_match(/running ruby code/, result.stderr) catalog_results[master.hostname]['ruby_cat'] = JSON.parse(result.stdout.sub(/^[^{]+/,'')) end end step 'generate pcore type from ruby type' do on master, puppet('generate', 'types', '--environment', environment) end step 'compile catalog and make sure that ruby code is NOT executed' do on master, puppet('catalog', 'find', master.hostname) do |result| refute_match(/running ruby code/, result.stderr) catalog_results[master.hostname]['pcore_cat'] = JSON.parse(result.stdout.sub(/^[^{]+/,'')) end end step 'ensure that the resources created in the catalog using ruby and pcore are the same' do assert_equal(catalog_results[master.hostname]['ruby_cat']['resources'], catalog_results[master.hostname]['pcore_cat']['resources']) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/language/resource_refs_with_nested_arrays.rb000066400000000000000000000014361527241624000331570ustar00rootroot00000000000000test_name "#7681: Allow using array variables in resource references" tag 'audit:high', 'audit:unit', 'shard:group4' # For splitting out groups of tests for slow test runners agents.each do |agent| test_manifest = < "#{agent.echo('the first command')}", path => "#{agent.path}", logoutput => true, } exec { "second": command => "#{agent.echo('the second command')}", path => "#{agent.path}", logoutput => true, } exec { "third": command => "#{agent.echo('the final command')}", path => "#{agent.path}", logoutput => true, require => Exec[$exec_names], } MANIFEST apply_manifest_on(agent, test_manifest) do |result| assert_match(/Exec\[third\].*the final command/, result.stdout) end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/language/sensitive_data_type.rb000066400000000000000000000165671527241624000304110ustar00rootroot00000000000000test_name 'C98120, C98077: Sensitive Data is redacted on CLI, logs, reports' do require 'puppet/acceptance/puppet_type_test_tools.rb' extend Puppet::Acceptance::PuppetTypeTestTools tag 'audit:high', 'audit:acceptance', # Tests that sensitive data is retains integrity # between server and agent transport/application. # Leaving at acceptance layer due to validate # written logs. 'server', 'shard:group1' # For splitting out groups of tests for slow test runners teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) tmp_filename_win = tmp_filename_else = '' agents.each do |agent| # ugh... this won't work with more than two agents of two types if agent.platform =~ /32$/ tmp_filename_win = "C:\\cygwin\\tmp\\#{tmp_environment}.txt" else tmp_filename_win = "C:\\cygwin64\\tmp\\#{tmp_environment}.txt" end tmp_filename_else = "/tmp/#{tmp_environment}.txt" on agent, "echo 'old content' > /tmp/#{tmp_environment}.txt" end # first attempts at a reasonable table driven test. needs API work # FIXME: # expand this to other resource types, make parameters arbitrary, make assertions arbitrary # FIXME: add context messaging to each instance notify_redacted = 'Sensitive \[value redacted\]' file_redacted = 'changed \[redacted\] to \[redacted\]' test_resources = [ {:type => 'notify', :parameters => {:namevar => "1:${Sensitive.new('sekrit1')}"}, :assertions => [{:refute_match => 'sekrit1'}, {:assert_match => "1:#{notify_redacted}"}]}, {:type => 'notify', :parameters => {:namevar => "2:${Sensitive.new($meh2)}"}, :pre_code => '$meh2="sekrit2"', :assertions => [{:refute_match => 'sekrit2'}, {:assert_match => "2:#{notify_redacted}"}]}, {:type => 'notify', :parameters => {:namevar => "3:meh", :message => '"3:${Sensitive.new(\'sekrit3\')}"'}, :assertions => [{:refute_match => 'sekrit3'}, {:assert_match => "3:#{notify_redacted}"}]}, {:type => 'notify', :parameters => {:namevar => "4:meh", :message => "Sensitive.new($meh4)"}, :pre_code => '$meh4="sekrit4"', :assertions => [{:refute_match => 'sekrit4'}, {:assert_match => file_redacted}]}, {:type => 'notify', :parameters => {:namevar => "5:meh", :message => "$meh5"}, :pre_code => '$meh5=Sensitive.new("sekrit5")', :assertions => [{:refute_match => 'sekrit5'}, {:assert_match => file_redacted}]}, {:type => 'notify', :parameters => {:namevar => "6:meh", :message => '"6:${meh6}"'}, :pre_code => '$meh6=Sensitive.new("sekrit6")', :assertions => [{:refute_match => 'sekrit6'}, {:assert_match => "6:#{notify_redacted}"}]}, {:type => 'notify', :parameters => {:namevar => "7:${Sensitive('sekrit7')}"}, :assertions => [{:refute_match => 'sekrit7'}, {:assert_match => "7:#{notify_redacted}"}]}, # unwrap(), these should be en-clair {:type => 'notify', :parameters => {:namevar => "8:${unwrap(Sensitive.new('sekrit8'))}"}, :assertions => {:assert_match => "8:sekrit8"}}, {:type => 'notify', :parameters => {:namevar => "9:meh", :message => '"9:${unwrap(Sensitive.new(\'sekrit9\'))}"'}, :assertions => {:assert_match => "9:sekrit9"}}, {:type => 'notify', :parameters => {:namevar => "A:meh", :message => '"A:${unwrap($mehA)}"'}, :pre_code => '$mehA=Sensitive.new("sekritA")', :assertions => {:assert_match => "A:sekritA"}}, {:type => 'notify', :parameters => {:namevar => "B:meh", :message => '"B:${$mehB.unwrap}"'}, :pre_code => '$mehB=Sensitive.new("sekritB")', :assertions => {:assert_match => "B:sekritB"}}, {:type => 'notify', :parameters => {:namevar => "C:meh", :message => '"C:${$mehC.unwrap |$unwrapped| { "blk_${unwrapped}_blk" } } nonblk_${mehC}_nonblk"'}, :pre_code => '$mehC=Sensitive.new("sekritC")', :assertions => {:assert_match => ["C:blk_sekritC_blk", "nonblk_#{notify_redacted}_nonblk"]}}, # for --show_diff {:type => 'file', :parameters => {:namevar => "$pup_tmp_filename", :content => "Sensitive.new('sekritD')"}, :pre_code => "$pup_tmp_filename = if $facts['os']['family'] == 'windows' { '#{tmp_filename_win}' } else { '#{tmp_filename_else}' }", :assertions => [{:refute_match => 'sekritD'}, {:assert_match => /#{tmp_environment}\.txt..content. #{file_redacted}/}]}, ] sitepp_content = generate_manifest(test_resources) assertion_code = generate_assertions(test_resources) # Make a copy of the full set of 'test_resources' but filtered down to include # only the assertions of type ':refute_match'. So for example, where the # 'test_resources' array might have an entry like this... # # {:type => 'notify', ... # :assertions => [{:refute_match => 'sekrit1'}, # {:assert_match => "1:#{notify_redacted}"}]} # # ... the ':assert_match' entry would be filtered out in the new # 'refutation_resources' array, producing: # # {:type => 'notify', ... # :assertions => [{:refute_match => 'sekrit1'}]} # # This is done so that when validating the log output, we can refute the # existence of any of the sensitive info in the log without having to # assert that redacted info is in the log. The redacted info appears in # the console output from the Puppet agent run - by virtue of including a # '--debug' flag on the agent command line - whereas the redacted info is not # expected to be piped into the log. refutation_resources = test_resources.collect do |assertion_group| refutation_group = assertion_group.clone refutation_group[:assertions] = assertion_group[:assertions].select do |assertion| assertion.has_key?(:refute_match) end refutation_group end refutation_code = generate_assertions(refutation_resources) create_sitepp(master, tmp_environment, sitepp_content) step "run agent in #{tmp_environment}, run all assertions" do with_puppet_running_on(master,{}) do agents.each do |agent| # redirect logging to a temp location to avoid platform specific syslogs on(agent, puppet("agent -t --debug --trace --show_diff --environment #{tmp_environment}"), :accept_all_exit_codes => true) do |result| assert_equal(result.exit_code, 2,'puppet agent run failed') run_assertions(assertion_code, result) unless agent['locale'] == 'ja' step "assert no redacted data in log" do run_assertions(refutation_code, result) end end # don't do this before the agent log scanning, above. it will skew the results step "assert no redacted data in vardir" do # no recursive grep in solaris :facepalm: on(agent, "find #{agent.puppet['vardir']} -type f | xargs grep sekrit", :accept_all_exit_codes => true) do |result| refute_match(/sekrit(1|2|3|6|7)/, result.stdout, 'found redacted data we should not have') #TODO: if/when this is fixed, we should just be able to eval(assertion_code_ in this result block also! expect_failure 'file resource contents will end up in the cached catalog en-clair' do refute_match(/sekritD/, result.stdout, 'found redacted file data we should not have') end end end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/language/server_set_facts.rb000066400000000000000000000037521527241624000276770ustar00rootroot00000000000000test_name 'C64667: ensure server_facts is set and error if any value is overwritten by an agent' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:acceptance', # Validating server/client interaction 'server', 'shard:group2' # For splitting out groups of tests for slow test runners teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) step 'ensure $server_facts exist' do create_sitepp(master, tmp_environment, <<~SITE) $server_facts_hash_exists_and_is_not_empty = ($server_facts =~ Hash) and ($server_facts.length != 0) notify { "server_facts hash exists and is not empty: ${server_facts_hash_exists_and_is_not_empty}": } SITE master_opts = {} with_puppet_running_on(master, master_opts) do agents.each do |agent| on(agent, puppet("agent -t --environment #{tmp_environment}"), :acceptable_exit_codes => 2) do |result| assert_match(/Notify\[server_facts hash exists and is not empty: true\]/, result.stdout, "#{agent}: $server_facts should have some stuff" ) end end end end step 'ensure puppet issues a warning if an agent overwrites a server fact' do agents.each do |agent| on(agent, puppet("agent -t", 'ENV' => { 'FACTER_server_facts' => 'overwrite' }), :acceptable_exit_codes => 1) do |result| # Do not perform this check on non-English hosts unless agent['locale'] == 'ja' assert_match(/Error.*Attempt to assign to a reserved variable name: 'server_facts'/, result.stderr, "#{agent}: $server_facts should error if overwritten" ) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/loader/000077500000000000000000000000001527241624000234655ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/loader/autoload_from_resource_type_decl.rb000066400000000000000000000146601527241624000326130ustar00rootroot00000000000000test_name 'C100303: Resource type statement triggered auto-loading works both with and without generated types' do tag 'risk:high', 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/agent_fqdn_utils' extend Puppet::Acceptance::AgentFqdnUtils # create the file and make sure its empty and accessible by everyone def empty_execution_log_file(host, path) create_remote_file(host, path, '') on(host, "chmod 777 '#{path}'") end app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" relative_type_dir = 'modules/one/lib/puppet/type' relative_type_path = "#{relative_type_dir}/type_tst.rb" execution_log = {} execution_log[agent_to_fqdn(master)] = master.tmpfile('master_autoload_resource') agents.each do |agent| execution_log[agent_to_fqdn(agent)] = agent.tmpfile('agent_autoload_resource') end teardown do on(master, "rm -f '#{execution_log[agent_to_fqdn(master)]}'") agents.each do |agent| on(agent, "rm -f '#{execution_log[agent_to_fqdn(agent)]}'") on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step 'create custom type' do on(master, "mkdir -p '#{fq_tmp_environmentpath}/#{relative_type_dir}'") # create a custom type that will write out to a different file on each agent # this way we can verify whether the newtype code was executed on each system custom_type = <<-END Puppet::Type.newtype(:type_tst) do newparam(:name, :namevar => true) do fqdn = Facter.value('networking.fqdn') if fqdn == '#{agent_to_fqdn(master)}' File.open("#{execution_log[agent_to_fqdn(master)]}", 'a+') { |f| f.puts("found_type_tst: " + Time.now.to_s) } end END agents.each do |agent| custom_type << <<-END if fqdn == '#{agent_to_fqdn(agent)}' File.open("#{execution_log[agent_to_fqdn(agent)]}", 'a+') { |f| f.puts("found_type_tst: " + Time.now.to_s) } end END end custom_type << <<-END Puppet.notice("found_type_tst") end end END create_remote_file(master, "#{fq_tmp_environmentpath}/#{relative_type_path}", custom_type) site_pp = <<-PP Resource['type_tst'] { 'found_type': } PP create_sitepp(master, tmp_environment, site_pp) end on(master, "chmod -R 755 '#{test_tmpdir}/#{tmp_environment}'") # when the agent does its run, the newtype is executed on both the agent and master nodes # so we should see a message in the execution log file on the agent and the master agents.each do |agent| with_puppet_running_on(master, {}) do empty_execution_log_file(master, execution_log[agent_to_fqdn(master)]) empty_execution_log_file(agent, execution_log[agent_to_fqdn(agent)]) on(agent, puppet("agent -t --environment '#{tmp_environment}'")) do |puppet_result| assert_match(/\/File\[.*\/type_tst.rb\]\/ensure: defined content as/, puppet_result.stdout, 'Expected to see defined content message for type: type_tst') assert_match(/Notice: found_type_tst/, puppet_result.stdout, 'Expected to see the notice from the new type: type_tst') end on(master, "cat '#{execution_log[agent_to_fqdn(master)]}'") do |cat_result| assert_match(/found_type_tst:/, cat_result.stdout, "Expected to see execution log entry on master #{agent_to_fqdn(master)}") end on(agent, "cat '#{execution_log[agent_to_fqdn(agent)]}'") do |cat_result| assert_match(/found_type_tst:/, cat_result.stdout, "Expected to see execution log entry on agent #{agent_to_fqdn(agent)}") end end end # when generating the pcore the newtype should only be run on the master node step 'generate pcore files' do # start with an empty execution log empty_execution_log_file(master, execution_log[agent_to_fqdn(master)]) agents.each do |agent| empty_execution_log_file(agent, execution_log[agent_to_fqdn(agent)]) end on(master, puppet("generate types --environment '#{tmp_environment}'")) do |puppet_result| assert_match(/Notice: Generating '\/.*\/type_tst\.pp' using 'pcore' format/, puppet_result.stdout, 'Expected to see Generating message for type: type_tst') assert_match(/Notice: found_type_tst/, puppet_result.stdout, 'Expected to see log entry on master ') end # we should see a log entry on the master node on(master, "cat '#{execution_log[agent_to_fqdn(master)]}'") do |cat_result| assert_match(/found_type_tst:/, cat_result.stdout, "Expected to see execution log entry on master #{agent_to_fqdn(master)}") end # we should not see any log entries on any of the agent nodes agents.each do |agent| next if agent == master on(agent, "cat '#{execution_log[agent_to_fqdn(agent)]}'") do |cat_result| assert_empty(cat_result.stdout.chomp, "Expected execution log file to be empty on agent node #{agent_to_fqdn(agent)}") end end end empty_execution_log_file(master, execution_log[agent_to_fqdn(master)]) agents.each do |agent| next if agent == master empty_execution_log_file(agent, execution_log[agent_to_fqdn(agent)]) # this test is relying on the beaker helper with_puppet_running_on() to restart the server # Compilation should now work using the generated types, # so we should only see a log entry on the agent node and nothing on the master node with_puppet_running_on(master, {}) do on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :acceptable_exit_codes => 0) do |puppet_result| assert_match(/Notice: found_type_tst/, puppet_result.stdout, 'Expected to see output from new type: type_tst') end end on(agent, "cat '#{execution_log[agent_to_fqdn(agent)]}'") do |cat_result| assert_match(/found_type_tst:/, cat_result.stdout, "Expected to see an execution log entry on agent #{agent_to_fqdn(agent)}") end end on(master, "cat '#{execution_log[agent_to_fqdn(master)]}'") do |cat_result| assert_empty(cat_result.stdout.chomp, "Expected master execution log to be empty #{agent_to_fqdn(master)}") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/loader/func4x_loadable_from_modules.rb000066400000000000000000000064621527241624000316270ustar00rootroot00000000000000test_name "Exercise a module with 4x function and 4x system function" # Purpose: # Test that a packed puppet can call a 4x system function, and that a 4x function in # a module can be called. # # Method: # * Manually construct a very simple module with a manifest that creates a file. # * The file has content that depends on logic that calls both a system function (reduce), and # a function supplied in the module (helloworld::mul10). # * The module is manually constructed to allow the test to also run on Windows where the module tool # is not supported. # * The module is included by calling 'include' from 'puppet apply'. # * Puppet apply is executed to generate the file with the content. # * The generated contents is asserted. # TODO: The test can be improved by adding yet another module that calls the function in helloworld. # TODO: The test can be improved to also test loading of a non namespaced function require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils tag 'audit:high', 'audit:unit', # This should be covered adequately by unit tests 'shard:group4' # For splitting out groups of tests for slow test runners initialize_temp_dirs agents.each do |agent| # The modulepath to use in environment 'dev' envs_path = get_test_file_path(agent, 'environments') dev_modulepath = get_test_file_path(agent, 'environments/dev/modules') target_path = get_test_file_path(agent, 'output') mkdirs agent, target_path # make sure that we use the modulepath from the dev environment puppetconf = get_test_file_path(agent, 'puppet.conf') on agent, puppet("config", "set", "environmentpath", envs_path, "--section", "main", "--config", puppetconf) on agent, puppet("config", "set", "environment", "dev", "--section", "user", "--config", puppetconf) # Where the functions in the written modules should go helloworld_functions = 'helloworld/lib/puppet/functions/helloworld' # Clean out the module that will be written to ensure no interference from a previous run on agent, "rm -rf #{File.join(dev_modulepath, 'helloworld')}" mkdirs agent, File.join(dev_modulepath, helloworld_functions) # Write a module # Write the function helloworld::mul10, that multiplies its argument by 10 create_remote_file(agent, File.join(dev_modulepath, helloworld_functions, "mul10.rb"), <<'SOURCE') Puppet::Functions.create_function(:'helloworld::mul10') do def mul10(x) x * 10 end end SOURCE # Write a manifest that calls a 4x function (reduce), and calls a function defined in the module # (helloworld::mul10). # mkdirs agent, File.join(dev_modulepath, "helloworld", "manifests") create_remote_file(agent, File.join(dev_modulepath, "helloworld", "manifests", "init.pp"), < 'file', mode => '0666', content => [1,2,3].reduce("Generated") |$memo, $n| { "${memo}, ${n} => ${helloworld::mul10($n)}" } } } SOURCE # Run apply to generate the file with the output on(agent, puppet('apply', '-e', "'include helloworld'", '--config', puppetconf)) # Assert that the file was written with the generated content on(agent, "cat #{File.join(target_path, 'result.txt')}") do |result| assert_match(/^Generated, 1 => 10, 2 => 20, 3 => 30$/, result.stdout, "Generated the wrong content") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/loader/resource_triggers_autoload.rb000066400000000000000000000041621527241624000314420ustar00rootroot00000000000000test_name 'C100296: can auto-load defined types using a Resource statement' do tag 'risk:high', 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end relative_define_type_dir = 'modules/one/manifests' relative_define_type_1_path = "#{relative_define_type_dir}/tst1.pp" relative_define_type_2_path = "#{relative_define_type_dir}/tst2.pp" step 'create custom type in two environments' do on(master, "mkdir -p #{fq_tmp_environmentpath}/#{relative_define_type_dir}") define_type_1 = <<-END define one::tst1($var) { notify { "tst1: ${var}": } } END define_type_2 = <<-END define one::tst2($var) { notify { "tst2: ${var}": } } END create_remote_file(master, "#{fq_tmp_environmentpath}/#{relative_define_type_1_path}", define_type_1) create_remote_file(master, "#{fq_tmp_environmentpath}/#{relative_define_type_2_path}", define_type_2) site_pp = <<-PP each(['tst1', 'tst2']) |$nr| { Resource["one::${nr}"] { "some_title_${nr}": var => "Define found one::${nr}" } } PP create_sitepp(master, tmp_environment, site_pp) end on(master, "chmod -R 755 #{test_tmpdir}/#{tmp_environment}") with_puppet_running_on(master, {}) do agents.each do |agent| on(agent, puppet("agent -t --environment #{tmp_environment}"), :acceptable_exit_codes => 2) do |puppet_result| assert_match(/Notice: tst1: Define found one::tst1/, puppet_result.stdout, 'Expected to see output from define notify') assert_match(/Notice: tst2: Define found one::tst2/, puppet_result.stdout, 'Expected to see output from define notify') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/000077500000000000000000000000001527241624000235305ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/config3_interpolation.rb000066400000000000000000000053251527241624000303610ustar00rootroot00000000000000test_name 'C99578: lookup should allow interpolation in hiera3 configs' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:integration', 'audit:refactor', # This test specifically tests interpolation on the master. # Recommend adding an additonal test that validates # lookup in a masterless setup. 'server', 'shard:group2' # For splitting out groups of tests for slow test runners app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" master_confdir = puppet_config(master, 'confdir', section: 'master') hiera_conf_backup = master.tmpfile('C99578-hiera-yaml') step "backup global hiera.yaml" do on(master, "cp -a #{master_confdir}/hiera.yaml #{hiera_conf_backup}", :acceptable_exit_codes => [0,1]) end teardown do on(master, "mv #{hiera_conf_backup} #{master_confdir}/hiera.yaml", :acceptable_exit_codes => [0,1]) agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step "create hiera configs in #{tmp_environment} and global" do step "create global hiera.yaml and module data" do create_remote_file(master, "#{master_confdir}/hiera.yaml", <<-HIERA) --- :backends: - "yaml" :hierarchy: - "%{calling_class_path}" - "%{calling_class}" - "%{calling_module}" - "common" HIERA on(master, "mkdir -p #{fq_tmp_environmentpath}/hieradata/") on(master, "mkdir -p #{fq_tmp_environmentpath}/modules/some_mod/manifests") create_remote_file(master, "#{fq_tmp_environmentpath}/modules/some_mod/manifests/init.pp", <<-PP) class some_mod { notify { "${lookup('environment_key')}": } } PP create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/some_mod.yaml", <<-YAML) --- environment_key: "env value" YAML create_sitepp(master, tmp_environment, <<-SITE) include some_mod SITE on(master, "chmod -R 775 #{fq_tmp_environmentpath}") on(master, "chmod -R 775 #{master_confdir}") end end with_puppet_running_on(master,{}) do agents.each do |agent| step "agent lookup" do on(agent, puppet('agent', "-t --environment #{tmp_environment} --debug"), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 2, "agent lookup didn't exit properly: (#{result.exit_code})") assert_match(/env value/, result.stdout, "agent lookup didn't find correct key") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/config5_interpolation.rb000066400000000000000000000112421527241624000303560ustar00rootroot00000000000000test_name 'C99578: hiera5 lookup config with interpolated scoped nested variables' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:integration', 'audit:refactor', # This test specifically tests interpolation on the master. # Recommend adding an additonal test that validates # lookup in a masterless setup. 'server', 'shard:group3' # For splitting out groups of tests for slow test runners app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type + '1') fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step "create environment hiera5.yaml and environment data" do create_remote_file(master, "#{fq_tmp_environmentpath}/hiera.yaml", <<-HIERA) --- version: 5 defaults: datadir: 'hieradata' data_hash: yaml_data hierarchy: - name: "Global settings" path: "global.yaml" - name: "Role specific settings" paths: - "roles/%{::roles.0}.yaml" - name: "Other Role specific settings" paths: - "roles/%{roles2.0}.yaml" - name: "scoped variable" paths: - "roles/%{::myclass::myvar.0}.yaml" - name: "nested hash variable" paths: - "roles/%{::hash_array.key1.0}.yaml" HIERA on(master, "mkdir -p #{fq_tmp_environmentpath}/hieradata/roles") create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/global.yaml", <<-YAML) roles: - test1 roles2: - test2 data: - "from global" YAML create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/roles/test1.yaml", <<-YAML) data: - 'from test1' YAML create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/roles/test2.yaml", <<-YAML) data: - 'from test2' YAML create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/roles/test3.yaml", <<-YAML) data: - 'from test3' YAML create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/roles/test4.yaml", <<-YAML) data: - 'from test4' YAML create_sitepp(master, tmp_environment, <<-SITE) class myclass { $myvar = ['test3'] } include myclass $hash_array = {key1 => ['test4']} $roles = lookup('roles') $data = lookup('data', Array[String], 'unique') notify{"data: ${data}":} $hiera_array_data = hiera_array('data') notify{"hiera_array_data: ${hiera_array_data}":} $roles2 = lookup('roles2') $data2 = lookup('data', Array[String], 'unique') notify{"data2: ${data2}":} $hiera_array_data2 = hiera_array('data') notify{"hiera_array_data2: ${hiera_array_data2}":} SITE on(master, "chmod -R 775 #{fq_tmp_environmentpath}") end with_puppet_running_on(master,{}) do agents.each do |agent| step "agent lookups: #{agent.hostname}, hiera5" do on(agent, puppet('agent', "-t --environment #{tmp_environment}"), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 2, "agent lookup didn't exit properly: (#{result.exit_code})") assert_match(/data: \[from global, from test1/, result.stdout, "agent lookup didn't interpolate with hiera value") assert_match(/hiera_array_data: \[from global, from test1/, result.stdout, "agent hiera_array didn't interpolate with hiera value") assert_match(/data2: \[from global, from test1, from test2/, result.stdout, "agent lookup didn't interpolate non-global scope with hiera value") assert_match(/hiera_array_data2: \[from global, from test1, from test2/, result.stdout, "agent hiera_array didn't interpolate non-global scope with hiera value") assert_match(/data2: \[from global, from test1, from test2, from test3/, result.stdout, "agent lookup didn't interpolate class scope with hiera value") assert_match(/hiera_array_data2: \[from global, from test1, from test2, from test3/, result.stdout, "agent hiera_array didn't interpolate class scope with hiera value") assert_match(/data2: \[from global, from test1, from test2, from test3, from test4\]/, result.stdout, "agent lookup didn't interpolate nested hashes with hiera value") assert_match(/hiera_array_data2: \[from global, from test1, from test2, from test3, from test4\]/, result.stdout, "agent hiera_array didn't interpolate nested hashes with hiera value") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/hiera3_custom_backend.rb000066400000000000000000000104351527241624000302740ustar00rootroot00000000000000test_name 'C99630: hiera v3 custom backend' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/temp_file_utils.rb' extend Puppet::Acceptance::TempFileUtils tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not needed for this test. Refactor # to use puppet apply with a local module tree. 'shard:group4' # For splitting out groups of tests for slow test runners skip_test 'puppetserver gem install needs jruby-openssl for https sources, which does not load in FIPS mode' if master.fips_mode? app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" puppetserver_config = "#{master['puppetserver-confdir']}/puppetserver.conf" existing_loadpath = read_tk_config_string(on(master, "cat #{puppetserver_config}").stdout.strip)['jruby-puppet']['ruby-load-path'].first confdir = puppet_config(master, 'confdir', section: 'master') hiera_conf_backup = master.tmpfile('C99629-hiera-yaml') step "backup global hiera.yaml" do on(master, "cp -a #{confdir}/hiera.yaml #{hiera_conf_backup}", :acceptable_exit_codes => [0,1]) end teardown do step 'delete custom backend, restore default hiera config' do on(master, "rm #{existing_loadpath}/hiera/backend/custom_backend.rb", :acceptable_exit_codes => [0,1]) on(master, "mv #{hiera_conf_backup} #{confdir}/hiera.yaml", :acceptable_exit_codes => [0,1]) on(master, "/opt/puppetlabs/server/bin/puppetserver gem uninstall --executables --force hiera") on(master, "/opt/puppetlabs/puppet/bin/gem uninstall --executables --force hiera") end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step "install hiera v3 gem" do # for puppet agent <-> server, hiera must be installed using puppetserver's gem command on(master, "/opt/puppetlabs/server/bin/puppetserver gem install --no-document hiera") # for puppet lookup, hiera must be installed using puppet's gem command on(master, "/opt/puppetlabs/puppet/bin/gem install --no-document hiera") end step "create hiera v5 config and v3 custom backend" do on(master, "cp #{confdir}/hiera.yaml /tmp") create_remote_file(master, "#{confdir}/hiera.yaml", <<-HIERA) --- version: 5 hierarchy: - name: Test hiera3_backend: custom HIERA on(master, "chmod -R #{PUPPET_CODEDIR_PERMISSIONS} #{confdir}") on(master, "mkdir -p #{existing_loadpath}/hiera/backend/") custom_backend_rb = <<-RB class Hiera module Backend class Custom_backend def lookup(key, scope, order_override, resolution_type, context) return 'custom value' unless (key == 'lookup_options') end end end end RB create_remote_file(master, "#{existing_loadpath}/hiera/backend/custom_backend.rb", custom_backend_rb) on(master, "chmod #{PUPPET_CODEDIR_PERMISSIONS} #{existing_loadpath}/hiera/backend/custom_backend.rb") end step "create site.pp which calls lookup on our keys" do create_sitepp(master, tmp_environment, <<-SITE) notify { "${lookup('anykey')}": } SITE on(master, "chmod -R #{PUPPET_CODEDIR_PERMISSIONS} #{fq_tmp_environmentpath}") end step 'assert lookups using lookup subcommand on the master' do on(master, puppet('lookup', "--environment #{tmp_environment}", '--explain', 'anykey'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "lookup subcommand didn't exit properly: (#{result.exit_code})") assert_match(/custom value/, result.stdout, "lookup subcommand didn't find correct key") end end with_puppet_running_on(master,{}) do agents.each do |agent| step "agent manifest lookup on #{agent.hostname}" do on(agent, puppet('agent', "-t --environment #{tmp_environment}"), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 2, "agent lookup didn't exit properly: (#{result.exit_code})") assert_match(/custom value/, result.stdout, "agent lookup didn't find correct key") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/hiera_eyaml_backend.rb000066400000000000000000000217661527241624000300170ustar00rootroot00000000000000test_name 'hiera-eyaml backend resolves encrypted values via eyaml_lookup_key' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/temp_file_utils.rb' extend Puppet::Acceptance::TempFileUtils tag 'audit:high', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners skip_test 'hiera-eyaml needs jruby-openssl, which does not load in puppetserver in FIPS mode' if master.fips_mode? app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" confdir = puppet_config(master, 'confdir', section: 'master') eyaml_keysdir = "#{confdir}/eyaml-keys" private_key = "#{eyaml_keysdir}/private_key.pkcs7.pem" public_key = "#{eyaml_keysdir}/public_key.pkcs7.pem" teardown do step 'remove eyaml keys' do on(master, "rm -rf #{eyaml_keysdir}", :acceptable_exit_codes => [0, 1]) end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end # hiera-eyaml ships preinstalled in both the openvox-agent and openvox-server # so no gem install is needed. The eyaml CLI lives at # /opt/puppetlabs/puppet/bin/eyaml from the agent gem. step 'generate PKCS7 keypair with the eyaml CLI' do on(master, "mkdir -p #{eyaml_keysdir}") on(master, "/opt/puppetlabs/puppet/bin/eyaml createkeys " \ "--pkcs7-private-key=#{private_key} " \ "--pkcs7-public-key=#{public_key}") # puppetserver runs as the puppet user and must be able to read the private key. # Root (the beaker connection user) bypasses mode bits, so puppet lookup on the primary still works. on(master, "chown -R puppet:puppet #{eyaml_keysdir}") on(master, "chmod 0500 #{eyaml_keysdir}") on(master, "chmod 0400 #{private_key}") on(master, "chmod 0444 #{public_key}") end encrypted_secret = nil encrypted_password = nil step 'encrypt distinct values using the eyaml CLI' do encrypt_cmd = lambda do |plaintext| result = on(master, "/opt/puppetlabs/puppet/bin/eyaml encrypt " \ "--pkcs7-public-key=#{public_key} " \ "--output=string --string='#{plaintext}'") ciphertext = result.stdout.strip # Restrict to base64 characters so embedded newlines or whitespace fail loudly here # rather than silently producing invalid YAML when interpolated below. assert_match(/\AENC\[PKCS7,[A-Za-z0-9+\/=]+\]\z/, ciphertext, "eyaml encrypt did not produce a single-line PKCS7 block: #{ciphertext.inspect}") ciphertext end encrypted_secret = encrypt_cmd.call('super_secret_value') encrypted_password = encrypt_cmd.call('nested_password_value') assert(encrypted_secret != encrypted_password, 'PKCS7 ciphertexts for distinct plaintexts collided; encryption is not randomized as expected') end step 'configure environment hiera.yaml to use eyaml_lookup_key and write data files' do on(master, "mkdir -p #{tmp_environmentpath}/data") on(master, "mkdir -p #{tmp_environmentpath}/modules/eyaml_test/manifests") create_remote_file(master, "#{tmp_environmentpath}/hiera.yaml", <<-HIERA) --- version: 5 hierarchy: - name: 'Encrypted secrets (eyaml backend)' lookup_key: eyaml_lookup_key paths: - 'secrets.eyaml' options: pkcs7_private_key: #{private_key} pkcs7_public_key: #{public_key} - name: 'Plain YAML' data_hash: yaml_data paths: - 'common.yaml' HIERA # secrets.eyaml exercises three documented hiera-eyaml shapes in one file: # a top-level encrypted scalar, an encrypted value nested inside a hash, # a plain (unencrypted) value living alongside encrypted ones, and a class # parameter key (eyaml_test::api_key) for automatic class-parameter lookup. create_remote_file(master, "#{tmp_environmentpath}/data/secrets.eyaml", <<-EYAML) --- eyaml_secret: #{encrypted_secret} eyaml_nested: password: #{encrypted_password} username: 'plain_user_in_eyaml_file' eyaml_plain_in_eyaml: 'mixed_plaintext_value' eyaml_test::api_key: #{encrypted_secret} EYAML create_remote_file(master, "#{tmp_environmentpath}/data/common.yaml", <<-YAML) --- plain_value: 'plaintext_from_yaml' YAML create_remote_file(master, "#{tmp_environmentpath}/modules/eyaml_test/manifests/init.pp", <<-MANIFEST) class eyaml_test(String $api_key) { notify { "param=${api_key}": } } MANIFEST create_sitepp(master, tmp_environment, <<-SITE) notify { "eyaml=${lookup('eyaml_secret')}": } notify { "plain=${lookup('plain_value')}": } notify { "nested_pw=${lookup('eyaml_nested')['password']}": } notify { "nested_user=${lookup('eyaml_nested')['username']}": } notify { "mixed=${lookup('eyaml_plain_in_eyaml')}": } include eyaml_test SITE on(master, "chmod -R #{PUPPET_CODEDIR_PERMISSIONS} #{tmp_environmentpath}") end step 'puppet lookup decrypts a top-level eyaml value' do on(master, puppet('lookup', "--environment #{tmp_environment}", 'eyaml_secret'), :accept_all_exit_codes => true) do |result| assert_equal(0, result.exit_code, "puppet lookup eyaml_secret failed (#{result.exit_code}): #{result.stderr}") assert_match(/super_secret_value/, result.stdout, 'puppet lookup did not decrypt the top-level eyaml value') refute_match(/ENC\[PKCS7/, result.stdout, 'puppet lookup returned ciphertext for the top-level eyaml value') end end step 'puppet lookup decrypts an eyaml value nested inside a hash and preserves plaintext siblings' do on(master, puppet('lookup', "--environment #{tmp_environment}", 'eyaml_nested'), :accept_all_exit_codes => true) do |result| assert_equal(0, result.exit_code, "puppet lookup eyaml_nested failed (#{result.exit_code}): #{result.stderr}") assert_match(/nested_password_value/, result.stdout, 'puppet lookup did not decrypt the nested eyaml value') assert_match(/plain_user_in_eyaml_file/, result.stdout, 'puppet lookup lost the plaintext sibling inside an eyaml hash') refute_match(/ENC\[PKCS7/, result.stdout, 'puppet lookup returned ciphertext instead of the decrypted nested value') end end step 'puppet lookup returns plaintext values stored in an eyaml file unchanged' do on(master, puppet('lookup', "--environment #{tmp_environment}", 'eyaml_plain_in_eyaml'), :accept_all_exit_codes => true) do |result| assert_equal(0, result.exit_code, "puppet lookup eyaml_plain_in_eyaml failed (#{result.exit_code}): #{result.stderr}") assert_match(/mixed_plaintext_value/, result.stdout, 'puppet lookup did not return a plaintext value from an eyaml-backed file') end end step 'puppet lookup still resolves plain YAML data alongside the eyaml hierarchy' do on(master, puppet('lookup', "--environment #{tmp_environment}", 'plain_value'), :accept_all_exit_codes => true) do |result| assert_equal(0, result.exit_code, "puppet lookup plain_value failed (#{result.exit_code}): #{result.stderr}") assert_match(/plaintext_from_yaml/, result.stdout, 'puppet lookup did not return the plain yaml value') end end with_puppet_running_on(master, {}) do agents.each do |agent| step "agent run on #{agent} receives decrypted values and exercises class-parameter automatic lookup" do on(agent, puppet('agent', "-t --environment #{tmp_environment}"), :accept_all_exit_codes => true) do |result| assert_equal(2, result.exit_code, "agent run did not apply changes (#{result.exit_code}): #{result.stderr}") assert_match(/eyaml=super_secret_value/, result.stdout, 'agent did not receive the decrypted top-level eyaml value') assert_match(/nested_pw=nested_password_value/, result.stdout, 'agent did not receive the decrypted nested eyaml value') assert_match(/nested_user=plain_user_in_eyaml_file/, result.stdout, 'agent did not receive a plaintext sibling inside an eyaml hash') assert_match(/mixed=mixed_plaintext_value/, result.stdout, 'agent did not receive a plaintext value stored in an eyaml file') assert_match(/plain=plaintext_from_yaml/, result.stdout, 'agent did not receive the plain yaml value') assert_match(/param=super_secret_value/, result.stdout, 'class parameter automatic lookup did not decrypt eyaml_test::api_key') refute_match(/ENC\[PKCS7/, result.stdout, 'agent received raw ciphertext instead of the decrypted value') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/lookup.rb000066400000000000000000000333401527241624000253710ustar00rootroot00000000000000test_name "Lookup data using the agnostic lookup function" do # pre-docs: # https://puppet-on-the-edge.blogspot.com/2015/01/puppet-40-data-in-modules-and.html tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not needed for this test. Refactor # to use puppet apply with a local module tree. # Use mk_tmp_environment_with_teardown to create environment. 'server', 'shard:group2' # For splitting out groups of tests for slow test runners testdir = master.tmpdir('lookup') module_name = "data_module" module_name2 = "other_module" hash_name = "hash_name" array_key = "array_key" env_data_implied_key = "env_data_implied" env_data_implied_value = "env_implied_a" env_data_key = "env_data" env_data_value = "env_a" env_hash_key = "env_hash_key" env_hash_value = "env_class_a" env_array_value0 = "env_array_a" env_array_value1 = "env_array_b" module_data_implied_key = "module_data_implied" module_data_implied_value = "module_implied_b" module_data_key = "module_data" module_data_value = "module_b" module_data_value_other = "other_module_b" module_hash_key = "module_hash_key" module_hash_value = "module_class_b" module_array_value0 = "module_array_a" module_array_value1 = "module_array_b" env_data_override_implied_key = "env_data_override_implied" env_data_override_implied_value = "env_override_implied_c" env_data_override_key = "env_data_override" env_data_override_value = "env_override_c" hiera_data_implied_key = "apache_server_port_implied" hiera_data_implied_value = "8080" hiera_data_key = "apache_server_port" hiera_data_value = "9090" hiera_hash_key = "hiera_hash_key" hiera_hash_value = "hiera_class_c" hiera_array_value0 = "hiera_array_a" hiera_array_value1 = "hiera_array_b" automatic_data_key = "automatic_data_key" automatic_data_value = "automatic_data_value" automatic_default_value = "automatic_default_value" def mod_manifest_entry(module_name = nil, testdir, module_data_implied_key, module_data_implied_value, module_data_key, module_data_value, hash_name, module_hash_key, module_hash_value, array_key, module_array_value0, module_array_value1) if module_name module_files_manifest = < file, content => " Puppet::Functions.create_function(:'#{module_name}::data') do def data() { '#{module_name}::#{module_data_implied_key}' => '#{module_data_implied_value}', '#{module_name}::#{module_data_key}' => '#{module_data_value}', '#{module_name}::#{hash_name}' => {'#{module_hash_key}' => '#{module_hash_value}'}, '#{module_name}::#{array_key}' => ['#{module_array_value0}', '#{module_array_value1}'] } end end ", mode => "0640", } PP module_files_manifest end end def mod_manifest_metadata_json(module_name = nil, testdir) if module_name < file, content => ' { "name": "tester-#{module_name}", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [ ] } ', mode => "0644", } # Hiera 5 module layer: bind the module data function # (replaces the removed metadata.json "data_provider" key) file { '#{testdir}/environments/production/modules/#{module_name}/hiera.yaml': ensure => file, content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: #{module_name}::data ', mode => "0644", } file { '#{testdir}/environments/production/modules/#{module_name}/lib/puppet/bindings': ensure => absent, force => true, } PPmetadata end end teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end module_manifest1 = mod_manifest_entry(module_name, testdir, module_data_implied_key, module_data_implied_value, module_data_key, module_data_value, hash_name, module_hash_key, module_hash_value, array_key, module_array_value0, module_array_value1) module_manifest2 = mod_manifest_entry(module_name2, testdir, module_data_implied_key, module_data_implied_value, module_data_key, module_data_value_other, hash_name, module_hash_key, module_hash_value, array_key, module_array_value0, module_array_value1) metadata_manifest1 = mod_manifest_metadata_json(module_name, testdir) metadata_manifest2 = mod_manifest_metadata_json(module_name2, testdir) apply_manifest_on(master, <<-PP, :catch_failures => true) File { ensure => directory, mode => "0750", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}':; '#{testdir}/hieradata':; '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/manifests':; '#{testdir}/environments/production/modules':; '#{testdir}/environments/production/lib':; '#{testdir}/environments/production/lib/puppet':; '#{testdir}/environments/production/lib/puppet/functions':; '#{testdir}/environments/production/lib/puppet/functions/environment':; '#{testdir}/environments/production/modules/#{module_name}':; '#{testdir}/environments/production/modules/#{module_name}/manifests':; '#{testdir}/environments/production/modules/#{module_name}/lib':; '#{testdir}/environments/production/modules/#{module_name}/lib/puppet':; '#{testdir}/environments/production/modules/#{module_name}/lib/puppet/bindings':; '#{testdir}/environments/production/modules/#{module_name}/lib/puppet/bindings/#{module_name}':; '#{testdir}/environments/production/modules/#{module_name}/lib/puppet/functions':; '#{testdir}/environments/production/modules/#{module_name}/lib/puppet/functions/#{module_name}':; '#{testdir}/environments/production/modules/#{module_name2}':; '#{testdir}/environments/production/modules/#{module_name2}/manifests':; '#{testdir}/environments/production/modules/#{module_name2}/lib':; '#{testdir}/environments/production/modules/#{module_name2}/lib/puppet':; '#{testdir}/environments/production/modules/#{module_name2}/lib/puppet/bindings':; '#{testdir}/environments/production/modules/#{module_name2}/lib/puppet/bindings/#{module_name2}':; '#{testdir}/environments/production/modules/#{module_name2}/lib/puppet/functions':; '#{testdir}/environments/production/modules/#{module_name2}/lib/puppet/functions/#{module_name2}':; } file { '#{testdir}/hiera.yaml': ensure => file, content => '--- :backends: - "yaml" :logger: "console" :hierarchy: - "global" :yaml: :datadir: "#{testdir}/hieradata" ', mode => "0640", } file { '#{testdir}/hieradata/global.yaml': ensure => file, content => "--- #{hiera_data_key}: #{hiera_data_value} #{module_name}::#{hiera_data_implied_key}: #{hiera_data_implied_value} #{module_name}::#{hash_name}: #{hiera_hash_key}: #{hiera_hash_value} #{module_name}::#{array_key}: - #{hiera_array_value0} - #{hiera_array_value1} #{module_name}::#{automatic_data_key}: #{automatic_data_value} ", mode => "0640", } file { '#{testdir}/environments/production/environment.conf': ensure => file, content => ' environment_timeout = 0 ', mode => "0640", } # Hiera 5 environment layer: bind the environment data function # (replaces the removed environment_data_provider setting; the function # lives in /lib/puppet/functions/environment/data.rb) file { '#{testdir}/environments/production/hiera.yaml': ensure => file, content => '--- version: 5 hierarchy: - name: "Environment data function" v4_data_hash: environment::data ', mode => "0640", } # the function to provide data for this environment file { '#{testdir}/environments/production/lib/puppet/functions/environment/data.rb': ensure => file, content => " Puppet::Functions.create_function(:'environment::data') do def data() { '#{module_name}::#{env_data_implied_key}' => '#{env_data_implied_value}', '#{module_name}::#{env_data_override_implied_key}' => '#{env_data_override_implied_value}', '#{env_data_key}' => '#{env_data_value}', '#{module_name}::#{hash_name}' => {'#{env_hash_key}' => '#{env_hash_value}'}, '#{env_data_override_key}' => '#{env_data_override_value}', '#{module_name}::#{array_key}' => ['#{env_array_value0}', '#{env_array_value1}'] } end end ", mode => "0640", } # place module file segments here #{module_manifest1} # same key, different module and values #{module_manifest2} file { '#{testdir}/environments/production/modules/#{module_name}/manifests/init.pp': ensure => file, content => ' class #{module_name}($#{env_data_implied_key}, $#{module_data_implied_key}, $#{env_data_override_implied_key}, $#{hiera_data_implied_key}, $#{automatic_data_key}=$#{automatic_default_value}) { # lookup data from the environment function databinding notify { "#{env_data_implied_key} $#{env_data_implied_key}": } $lookup_env = lookup("#{env_data_key}") notify { "#{env_data_key} $lookup_env": } # lookup data from the module databinding notify { "#{module_data_implied_key} $#{module_data_implied_key}": } $lookup_module = lookup("#{module_name}::#{module_data_key}") notify { "#{module_data_key} $lookup_module": } # lookup data from another modules databinding $lookup_module2 = lookup("#{module_name2}::#{module_data_key}") notify { "#{module_data_key} $lookup_module2": } # ensure env can override module notify { "#{env_data_override_implied_key} $#{env_data_override_implied_key}": } $lookup_override = lookup("#{env_data_override_key}") notify { "#{env_data_override_key} $lookup_override": } # should fall-back to hiera global.yaml data notify { "#{hiera_data_implied_key} $#{hiera_data_implied_key}": } $lookup_port = lookup("#{hiera_data_key}") notify { "#{hiera_data_key} $lookup_port": } # should be able to merge hashes across sources # this mimicks/covers behavior for including classes $lookup_hash = lookup("#{module_name}::#{hash_name}",Hash[String,String],\\'hash\\') notify { "#{hash_name} $lookup_hash": } # should be able to make an array across sources # this mimicks/covers behavior for including classes $lookup_array = lookup("#{module_name}::#{array_key}",Array[String],\\'unique\\') notify { "yep": message => "#{array_key} $lookup_array" } # automatic data lookup of parametrized class notify { "#{automatic_data_key} $#{automatic_data_key}": } }', mode => "0640", } file { '#{testdir}/environments/production/manifests/site.pp': ensure => file, content => " node default { include #{module_name} }", mode => "0640", } PP apply_manifest_on(master, <<-PP, :catch_failures => true) #{metadata_manifest1} #{metadata_manifest2} PP master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", 'hiera_config' => "#{testdir}/hiera.yaml", }, } with_puppet_running_on master, master_opts, testdir do step "Lookup string data, binding specified in metadata.json" do agents.each do |agent| on(agent, puppet('agent', "-t"), :acceptable_exit_codes => [0, 2]) do |result| assert_match("#{env_data_implied_key} #{env_data_implied_value}", result.stdout) assert_match("#{env_data_key} #{env_data_value}", result.stdout) assert_match("#{module_data_implied_key} #{module_data_implied_value}", result.stdout) assert_match("#{module_data_key} #{module_data_value}", result.stdout) assert_match("#{module_data_key} #{module_data_value_other}", result.stdout) assert_match("#{env_data_override_implied_key} #{env_data_override_implied_value}", result.stdout) assert_match("#{env_data_override_key} #{env_data_override_value}", result.stdout) assert_match("#{hiera_data_implied_key} #{hiera_data_implied_value}", result.stdout) assert_match("#{hiera_data_key} #{hiera_data_value}", result.stdout) assert_match("#{hash_name} {#{module_hash_key} => #{module_hash_value}, #{env_hash_key} => #{env_hash_value}, #{hiera_hash_key} => #{hiera_hash_value}}", result.stdout) assert_match("#{array_key} [#{hiera_array_value0}, #{hiera_array_value1}, #{env_array_value0}, #{env_array_value1}, #{module_array_value0}, #{module_array_value1}]", result.stdout) assert_match("#{automatic_data_key} #{automatic_data_value}", result.stdout) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/lookup_rich_values.rb000066400000000000000000000123251527241624000277550ustar00rootroot00000000000000test_name 'C99044: lookup should allow rich data as values' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not needed for this test. Refactor # to use puppet apply with a local environment. 'server', 'shard:group3' # For splitting out groups of tests for slow test runners # The following two lines are required for the puppetserver service to # start correctly. These should be removed when PUP-7102 is resolved. confdir = puppet_config(master, 'confdir', section: 'master') on(master, "chown puppet:puppet #{confdir}/hiera.yaml") app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" sensitive_value_rb = 'foot, no mouth' sensitive_value_pp = 'toe, no step' sensitive_value_pp2 = 'toe, no module' teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step "create ruby lookup function in #{tmp_environment}" do on(master, "mkdir -p #{fq_tmp_environmentpath}/lib/puppet/functions/environment") create_remote_file(master, "#{fq_tmp_environmentpath}/hiera.yaml", <<-HIERA) --- version: 5 hierarchy: - name: Test data_hash: rich_data_test - name: Test2 data_hash: some_mod::rich_data_test2 - name: Test3 data_hash: rich_data_test3 HIERA create_remote_file(master, "#{fq_tmp_environmentpath}/lib/puppet/functions/rich_data_test.rb", <<-FUNC) Puppet::Functions.create_function(:rich_data_test) do def rich_data_test(options, context) rich_type_instance = Puppet::Pops::Types::PSensitiveType::Sensitive.new("#{sensitive_value_rb}") { 'environment_key' => rich_type_instance, } end end FUNC end step "create puppet language lookup function in #{tmp_environment} module" do on(master, "mkdir -p #{fq_tmp_environmentpath}/modules/some_mod/functions") create_remote_file(master, "#{fq_tmp_environmentpath}/modules/some_mod/functions/rich_data_test2.pp", <<-FUNC) function some_mod::rich_data_test2($options, $context) { { "environment_key2" => Sensitive('#{sensitive_value_pp}'), } } FUNC on(master, "chmod -R a+rw #{fq_tmp_environmentpath}") end step "C99571: create puppet language lookup function in #{tmp_environment}" do on(master, "mkdir -p #{fq_tmp_environmentpath}/functions") create_remote_file(master, "#{fq_tmp_environmentpath}/functions/rich_data_test3.pp", <<-FUNC) function rich_data_test3($options, $context) { { "environment_key3" => Sensitive('#{sensitive_value_pp2}'), } } FUNC on(master, "chmod -R a+rw #{fq_tmp_environmentpath}") end step "create site.pp which calls lookup on our keys" do create_sitepp(master, tmp_environment, <<-SITE) notify { "${unwrap(lookup('environment_key'))}": } notify { "${unwrap(lookup('environment_key2'))}": } notify { "${unwrap(lookup('environment_key3'))}": } SITE end step 'assert lookups using lookup subcommand' do on(master, puppet('lookup', "--environment #{tmp_environment}", 'environment_key'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "lookup subcommand using ruby function didn't exit properly: (#{result.exit_code})") assert_match(sensitive_value_rb, result.stdout, "lookup subcommand using ruby function didn't find correct key") end on(master, puppet('lookup', "--environment #{tmp_environment}", 'environment_key2'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "lookup subcommand using puppet function in module didn't exit properly: (#{result.exit_code})") assert_match(sensitive_value_pp, result.stdout, "lookup subcommand using puppet function in module didn't find correct key") end on(master, puppet('lookup', "--environment #{tmp_environment}", 'environment_key3'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "lookup subcommand using puppet function didn't exit properly: (#{result.exit_code})") assert_match(sensitive_value_pp2, result.stdout, "lookup subcommand using puppet function didn't find correct key") end end with_puppet_running_on(master,{}) do agents.each do |agent| step "agent lookup in ruby function" do on(agent, puppet('agent', "-t --environment #{tmp_environment}"), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 2, "agent lookup using ruby function didn't exit properly: (#{result.exit_code})") assert_match(sensitive_value_rb, result.stdout, "agent lookup using ruby function didn't find correct key") assert_match(sensitive_value_pp, result.stdout, "agent lookup using puppet function in module didn't find correct key") assert_match(sensitive_value_pp2, result.stdout, "agent lookup using puppet function didn't find correct key") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/merge_strategies.rb000066400000000000000000000212111527241624000274030ustar00rootroot00000000000000test_name 'C99903: merge strategies' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not needed for this test. Refactor # to use puppet apply with a local module tree. 'shard:group4' # For splitting out groups of tests for slow test runners app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type + '1') fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" tmp_environment2 = mk_tmp_environment_with_teardown(master, app_type + '2') fq_tmp_environmentpath2 = "#{environmentpath}/#{tmp_environment2}" master_confdir = puppet_config(master, 'confdir', section: 'master') hiera_conf_backup = master.tmpfile(app_type) teardown do step "restore default global hiera.yaml" do on(master, "mv #{hiera_conf_backup} #{master_confdir}/hiera.yaml", :acceptable_exit_codes => [0,1]) end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step "create global hiera.yaml and environment data" do step "backup global hiera.yaml" do on(master, "cp -a #{master_confdir}/hiera.yaml #{hiera_conf_backup}") end create_remote_file(master, "#{master_confdir}/hiera.yaml", <<-HIERA) --- :backends: - yaml :yaml: :datadir: "/etc/puppetlabs/code/environments/%{::environment}/hieradata" :hierarchy: - "host" - "roles" - "profiles" - "%{facts.os.name}" - "%{facts.os.family}" - "%{facts.kernel}" - "common" :merge_behavior: deeper :deep_merge_options: :merge_hash_arrays: true HIERA on(master, "chown puppet:puppet #{master_confdir}/hiera.yaml") on(master, "mkdir -p #{fq_tmp_environmentpath}/hieradata/") create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/host.yaml", <<-YAML) --- profiles: webserver: apache: httpd: modules: - mpm_prefork - php - ssl arrayed_hash: the_hash: - array1: key1: val1 key2: val2 array: - foo YAML create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/profiles.yaml", <<-YAML) profiles: webserver: apache: httpd: modules: - auth_kerb - authnz_ldap - cgid - php - status array: - bar YAML create_sitepp(master, tmp_environment, <<-SITE) notify { "hiera_hash: ${hiera_hash ('profiles')['webserver']['apache']['httpd']['modules']}": } notify { "lookup1: ${lookup ('profiles')['webserver']['apache']['httpd']['modules']}": } notify { "lookup1b: ${lookup ({'name' => 'profiles', 'merge' => 'deep'})['webserver']['apache']['httpd']['modules']}": } notify { "hiera_merge_hash: ${hiera_hash ('arrayed_hash')}": } notify { "lookup_arrayed_hash: ${lookup ({'name' => 'arrayed_hash', 'merge' => {'strategy' => 'deep', 'merge_hash_arrays' => true}})}": } notify { "hiera-array: ${hiera ('array')}": } notify { "hiera_array: ${hiera_array ('array')}": } notify { "lookup-array: ${lookup ('array')}": } SITE on(master, "chmod -R 775 #{fq_tmp_environmentpath}") end step "create another environment, hiera5 config and environment data: #{tmp_environment2}" do create_remote_file(master, "#{fq_tmp_environmentpath2}/hiera.yaml", <<-HIERA) --- version: 5 hierarchy: - name: "%{environment}/host" data_hash: yaml_data path: "hieradata/host.yaml" - name: "%{environment}/profiles" data_hash: yaml_data path: "hieradata/profiles.yaml" HIERA on(master, "mkdir -p #{fq_tmp_environmentpath2}/hieradata/") create_remote_file(master, "#{fq_tmp_environmentpath2}/hieradata/host.yaml", <<-YAML) --- profiles: webserver: apache: httpd: modules: - mpm_prefork - php - ssl arrayed_hash: the_hash: - array1: key1: val1 key2: val2 array: - foo lookup_options: 'profiles': merge: strategy: deep YAML create_remote_file(master, "#{fq_tmp_environmentpath2}/hieradata/profiles.yaml", <<-YAML) profiles: webserver: apache: httpd: modules: - auth_kerb - authnz_ldap - cgid - php - status array: - bar lookup_options: 'profiles': merge: strategy: deep YAML create_sitepp(master, tmp_environment2, <<-SITE) notify { "hiera_hash: ${hiera_hash ('profiles')['webserver']['apache']['httpd']['modules']}": } notify { "lookup2: ${lookup ('profiles')['webserver']['apache']['httpd']['modules']}": } notify { "lookup2b: ${lookup ({'name' => 'profiles', 'merge' => 'first'})['webserver']['apache']['httpd']['modules']}": } notify { "hiera_merge_hash: ${hiera_hash ('arrayed_hash')}": } notify { "lookup_arrayed_hash: ${lookup ({'name' => 'arrayed_hash', 'merge' => {'strategy' => 'deep', 'merge_hash_arrays' => true}})}": } notify { "hiera-array: ${hiera ('array')}": } notify { "hiera_array: ${hiera_array ('array')}": } notify { "lookup-array: ${lookup ('array')}": } SITE on(master, "chmod -R 775 #{fq_tmp_environmentpath2}") end with_puppet_running_on(master,{}) do agents.each do |agent| step "agent lookups #{agent.hostname}, hiera3" do on(agent, puppet('agent', "-t --environment #{tmp_environment}"), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 2, "agent lookup didn't exit properly: (#{result.exit_code})") # hiera_hash will honor old global merge strategies, which were a bad idea assert_match(/hiera_hash: \[auth_kerb, authnz_ldap, cgid, php, status, mpm_prefork, ssl\]/, result.stdout, "1: agent hiera_hash didn't find correct key") # so, lookup doesn't honor them except on a by-key or by-lookup basis assert_match(/lookup1: \[mpm_prefork, php, ssl\]/, result.stdout, "1: agent lookup didn't find correct key") assert_match(/lookup1b: \[auth_kerb, authnz_ldap, cgid, php, status, mpm_prefork, ssl\]/, result.stdout, "1b: agent lookup didn't find correct key") assert_match(/hiera_merge_hash: {the_hash => \[{array1 => {key1 => val1, key2 => val2}}\]}/, result.stdout, "agent hiera_hash 1 merge_hash_arrays didn't work properly") assert_match(/lookup_arrayed_hash: {the_hash => \[{array1 => {key1 => val1, key2 => val2}}\]}/, result.stdout, "agent lookup 1 deep merge with merge_hash_arrays didn't work properly") assert_match(/hiera-array: \[foo\]/, result.stdout, "hiera() lookup of an array with deeper should be merged") assert_match(/hiera_array: \[foo, bar\]/, result.stdout, "hiera_array() lookup of an array should be merged") assert_match(/lookup-array: \[foo\]/, result.stdout, "lookup() lookup of an array should default to first") end end step "agent lookups #{agent.hostname}, hiera5" do on(agent, puppet('agent', "-t --environment #{tmp_environment2}"), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 2, "agent lookup didn't exit properly: (#{result.exit_code})") assert_match(/hiera_hash: \[auth_kerb, authnz_ldap, cgid, php, status, mpm_prefork, ssl\]/, result.stdout, "2: agent hiera_hash didn't find correct key") assert_match(/lookup2: \[auth_kerb, authnz_ldap, cgid, php, status, mpm_prefork, ssl\]/, result.stdout, "2: agent lookup didn't find correct key") assert_match(/lookup2b: \[mpm_prefork, php, ssl\]/, result.stdout, "2b: agent lookup didn't find correct key") assert_match(/hiera_merge_hash: {the_hash => \[{array1 => {key1 => val1, key2 => val2}}\]}/, result.stdout, "agent hiera_hash 2 merge_hash_arrays didn't work properly") assert_match(/lookup_arrayed_hash: {the_hash => \[{array1 => {key1 => val1, key2 => val2}}\]}/, result.stdout, "agent lookup 2 deep merge with merge_hash_arrays didn't work properly") assert_match(/hiera-array: \[foo\]/, result.stdout, "hiera() 2 lookup in hiera5 of an array should default to first") assert_match(/hiera_array: \[foo, bar\]/, result.stdout, "hiera_array() 2 lookup of an array should be merged") assert_match(/lookup-array: \[foo\]/, result.stdout, "lookup() 2 lookup in hiera5 of an array should default to first") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/v3_config_and_data.rb000066400000000000000000000123431527241624000275500ustar00rootroot00000000000000test_name 'C99629: hiera v5 can use v3 config and data' do require 'puppet/acceptance/environment_utils.rb' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not needed for this test. Refactor # to use puppet apply with a local module tree. 'shard:group1' # For splitting out groups of tests for slow test runners app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" hiera_conf_backup = master.tmpfile('C99629-hiera-yaml') step "create hiera v3 global config and data" do confdir = puppet_config(master, 'confdir', section: 'master') step "backup global hiera.yaml" do on(master, "cp -a #{confdir}/hiera.yaml #{hiera_conf_backup}", :acceptable_exit_codes => [0,1]) end teardown do step "restore global hiera.yaml" do on(master, "mv #{hiera_conf_backup} #{confdir}/hiera.yaml", :acceptable_exit_codes => [0,1]) end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step "create global hiera.yaml and module data" do create_remote_file(master, "#{confdir}/hiera.yaml", <<-HIERA) --- :backends: - "yaml" - "json" - "hocon" :hierarchy: - "somesuch" - "common" HIERA on(master, "mkdir -p #{fq_tmp_environmentpath}/hieradata/") create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/somesuch.yaml", <<-YAML) --- environment_key1: "env value1" environment_key3: "env value3" YAML create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/somesuch.json", <<-JSON) { "environment_key1" : "wrong value", "environment_key2" : "env value2" } JSON step "C99628: add hocon backend and data" do create_remote_file(master, "#{fq_tmp_environmentpath}/hieradata/somesuch.conf", <<-HOCON) environment_key4 = "hocon value", HOCON end create_sitepp(master, tmp_environment, <<-SITE) notify { "${lookup('environment_key1')}": } notify { "${lookup('environment_key2')}": } notify { "${lookup('environment_key3')}": } notify { "${lookup('environment_key4')}": } SITE on(master, "chmod -R 775 #{fq_tmp_environmentpath}") on(master, "chmod -R 775 #{confdir}") end end step 'assert lookups using lookup subcommand' do step 'assert lookup --explain using lookup subcommand' do on(master, puppet('lookup', "--environment #{tmp_environment}", 'environment_key1 --explain'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "1: lookup subcommand didn't exit properly: (#{result.exit_code})") assert_match(/env value1/, result.stdout, "1: lookup subcommand didn't find correct key") assert_match(/hiera configuration version 3/, result.stdout, "hiera config version not reported properly") assert_match(/#{fq_tmp_environmentpath}\/hieradata\/somesuch\.yaml/, result.stdout, "hiera hierarchy abs path not reported properly") assert_match(/path: "somesuch"/, result.stdout, "hiera hierarchy path not reported properly") end end on(master, puppet('lookup', "--environment #{tmp_environment}", 'environment_key2'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "2: lookup subcommand didn't exit properly: (#{result.exit_code})") assert_match(/env value2/, result.stdout, "2: lookup subcommand didn't find correct key") end on(master, puppet('lookup', "--environment #{tmp_environment}", 'environment_key3'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "3: lookup subcommand didn't exit properly: (#{result.exit_code})") assert_match(/env value3/, result.stdout, "3: lookup subcommand didn't find correct key") end on(master, puppet('lookup', "--environment #{tmp_environment}", 'environment_key4'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "4: lookup subcommand didn't exit properly: (#{result.exit_code})") assert_match(/hocon value/, result.stdout, "4: lookup subcommand didn't find correct key") end end with_puppet_running_on(master,{}) do agents.each do |agent| step "agent lookup" do on(agent, puppet('agent', "-t --environment #{tmp_environment}"), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 2, "agent lookup didn't exit properly: (#{result.exit_code})") assert_match(/env value1/, result.stdout, "1: agent lookup didn't find correct key") assert_match(/env value2/, result.stdout, "2: agent lookup didn't find correct key") assert_match(/env value3/, result.stdout, "3: agent lookup didn't find correct key") assert_match(/hocon value/, result.stdout, "4: agent lookup didn't find correct key") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/lookup/v4_hieradata_with_v5_configs.rb000066400000000000000000000117521527241624000315730ustar00rootroot00000000000000test_name 'C99572: v4 hieradata with v5 configs' do require 'puppet/acceptance/puppet_type_test_tools.rb' extend Puppet::Acceptance::PuppetTypeTestTools tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not needed for this test. Refactor # to use puppet apply with a local module tree. 'shard:group2' # For splitting out groups of tests for slow test runners app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) fq_tmp_environmentpath = "#{environmentpath}/#{tmp_environment}" confdir = puppet_config(master, 'confdir', section: 'master') hiera_conf_backup = master.tmpfile('C99572-hiera-yaml') step "backup global hiera.yaml" do on(master, "cp -a #{confdir}/hiera.yaml #{hiera_conf_backup}", :acceptable_exit_codes => [0,1]) end teardown do step "restore global hiera.yaml" do on(master, "mv #{hiera_conf_backup} #{confdir}/hiera.yaml", :acceptable_exit_codes => [0,1]) end agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end step "create global hiera.yaml and data" do create_remote_file(master, "#{confdir}/hiera.yaml", <<-HIERA) --- version: 5 hierarchy: - name: "%{environment}" data_hash: yaml_data path: "%{environment}.yaml" - name: common data_hash: yaml_data path: "common.yaml" HIERA on(master, "chmod 755 #{confdir}/hiera.yaml") create_remote_file(master, "#{confdir}/#{tmp_environment}.yaml", <<-YAML) --- environment_key: environment_key-global_env_file global_key: global_key-global_env_file YAML create_remote_file(master, "#{confdir}/common.yaml", <<-YAML) --- environment_key: environment_key-global_common_file global_key: global_key-global_common_file YAML end step "create environment hiera.yaml and data" do on(master, "mkdir -p #{fq_tmp_environmentpath}/data") create_remote_file(master, "#{fq_tmp_environmentpath}/hiera.yaml", <<-HIERA) --- version: 5 hierarchy: - name: "%{environment}" data_hash: yaml_data path: "%{environment}.yaml" - name: common data_hash: yaml_data path: "common.yaml" - name: hocon data_hash: hocon_data path: "common.conf" HIERA create_remote_file(master, "#{fq_tmp_environmentpath}/data/#{tmp_environment}.yaml", <<-YAML) --- environment_key: "environment_key-env_file" YAML create_remote_file(master, "#{fq_tmp_environmentpath}/data/common.yaml", <<-YAML) --- environment_key: "environment_key-common_file" global_key: "global_key-common_file" YAML step "C99628: add hocon backend and data" do create_remote_file(master, "#{fq_tmp_environmentpath}/data/common.conf", <<-HOCON) environment_key2 = "hocon value", HOCON end create_sitepp(master, tmp_environment, <<-SITE) notify { "${lookup('environment_key')}": } notify { "${lookup('global_key')}": } notify { "${lookup('environment_key2')}": } SITE on(master, "chmod -R 755 #{fq_tmp_environmentpath}") end step 'assert lookups using lookup subcommand' do on(master, puppet('lookup', "--environment #{tmp_environment}", 'environment_key'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "1: lookup subcommand didn't exit properly: (#{result.exit_code})") assert_match(/environment_key-env_file/, result.stdout, 'lookup environment_key subcommand didn\'t find correct key') end on(master, puppet('lookup', "--environment #{tmp_environment}", 'global_key'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "2: lookup subcommand didn't exit properly: (#{result.exit_code})") assert_match(/global_key-common_file/, result.stdout, 'lookup global_key subcommand didn\'t find correct key') end on(master, puppet('lookup', "--environment #{tmp_environment}", 'environment_key2'), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 0, "3: lookup subcommand didn't exit properly: (#{result.exit_code})") assert_match(/hocon value/, result.stdout, 'lookup environment_key2 subcommand didn\'t find correct key') end end with_puppet_running_on(master,{}) do agents.each do |agent| step 'agent lookup' do on(agent, puppet('agent', "-t --environment #{tmp_environment}"), :accept_all_exit_codes => true) do |result| assert(result.exit_code == 2, "agent lookup didn't exit properly: (#{result.exit_code})") assert_match(/global_key-common_file/m, result.stdout, 'agent lookup didn\'t find global key') assert_match(/environment_key-env_file/m, result.stdout, 'agent lookup didn\'t find environment_key') assert_match(/hocon value/m, result.stdout, 'agent lookup didn\'t find environment_key2') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/modulepath.rb000066400000000000000000000106651527241624000247160ustar00rootroot00000000000000test_name 'Supports vendored modules' do tag 'risk:high', 'shard:group3' # For splitting out groups of tests for slow test runners # beacon custom type emits a message so we can tell where the # type was loaded from, e.g. vendored, global, and whether the # type was loaded locally or pluginsynced from the master. def beacon_type(message) return < true) newproperty(:message) do def sync; true; end def retrieve; :absent; end def insync?(is); false; end defaultto { "#{message}" } end end END end def global_modules(host) if host.platform =~ /windows/ '/cygdrive/c/ProgramData/PuppetLabs/code/modules' else '/etc/puppetlabs/code/modules' end end def vendor_modules(host) if host.platform =~ /windows/ # escape spaces "/cygdrive/c/Program\\ Files/Puppet\\ Labs/Puppet/puppet/vendor_modules" else '/opt/puppetlabs/puppet/vendor_modules' end end teardown do hosts.each do |host| on(host, "rm -rf #{vendor_modules(host)}/beacon") on(host, "rm -rf #{global_modules(host)}/beacon") libdir = host.puppet['vardir'] on(host, "rm -rf #{libdir}") end on(master, "rm -rf /etc/puppetlabs/code/environments/production/modules/beacon") on(master, "rm -f /etc/puppetlabs/code/environments/production/manifests/site.pp") end step 'delete libdir' do hosts.each do |host| on(host, "rm -rf #{host.puppet['libdir']}") end end step 'create vendored module with a custom type' do hosts.each do |host| vendor_dir = vendor_modules(host) on(host, "mkdir -p #{vendor_dir}/beacon/lib/puppet/type") # unescape, because net-scp escapes vendor_dir.gsub!(/\\/, '') create_remote_file(host, "#{vendor_dir}/beacon/lib/puppet/type/beacon.rb", beacon_type("vendored module from #{host}")) end end step 'vendored modules work locally' do hosts.each do |host| on(host, puppet("apply -e \"beacon { 'ping': }\"")) do |result| assert_match(/defined 'message' as 'vendored module from #{host}'/, result.stdout) end end end step 'vendored modules can be excluded' do hosts.each do |host| on(host, puppet("describe --vendormoduledir '' beacon"), accept_all_exit_codes: true) do |result| assert_match(/Unknown type beacon/, result.stdout) end end end step 'global modules override vendored modules' do agents.each do |agent| # skip the agent on the master, as we don't want to install the # global module on the master until later next if agent == master global_dir = global_modules(agent) on(agent, "mkdir -p #{global_dir}/beacon/lib/puppet/type") # global_dir doesn't have spaces, so don't need to escape create_remote_file(agent, "#{global_dir}/beacon/lib/puppet/type/beacon.rb", beacon_type("global module from #{agent}")) on(agent, puppet("apply -e \"beacon { 'ping': }\"")) do |result| assert_match(/defined 'message' as 'global module from #{agent}'/, result.stdout) end end end step "prepare server" do create_remote_file(master, "/etc/puppetlabs/code/environments/production/manifests/site.pp", "beacon { 'ping': }") on(master, "chown -R puppet:puppet /etc/puppetlabs/code/environments/production/manifests/site.pp") on(master, "chown -R puppet:puppet #{vendor_modules(master)}") end with_puppet_running_on(master, {}) do step "agent doesn't pluginsync the vendored module, instead using its local vendored module" do agents.each do |agent| on(agent, puppet("agent -t"), :acceptable_exit_codes => [0,2]) do |result| assert_match(/defined 'message' as 'vendored module from #{agent}'/, result.stdout) end end end step "agent downloads and uses newly installed global module from the server" do global_dir = global_modules(master) on(master, "mkdir -p #{global_dir}/beacon/lib/puppet/type") create_remote_file(master, "#{global_dir}/beacon/lib/puppet/type/beacon.rb", beacon_type("server module from #{master}")) on(master, "chown -R puppet:puppet #{global_dir}") agents.each do |agent| on(agent, puppet("agent -t"), :acceptable_exit_codes => [0,2]) do |result| assert_match(/defined 'message' as 'server module from #{master}'/, result.stdout) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/ordering/000077500000000000000000000000001527241624000240305ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/ordering/master_agent_application.rb000066400000000000000000000026501527241624000314140ustar00rootroot00000000000000test_name "Puppet applies resources without dependencies in file order over the network" tag 'audit:high', 'audit:integration', 'server', 'shard:group4' # For splitting out groups of tests for slow test runners testdir = master.tmpdir('application_order') apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) File { ensure => directory, mode => "0750", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}':; '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/manifests':; '#{testdir}/environments/production/manifests/site.pp': ensure => file, mode => "0640", content => ' notify { "first": } notify { "second": } notify { "third": } notify { "fourth": } notify { "fifth": } notify { "sixth": } notify { "seventh": } notify { "eighth": } '; } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", } } with_puppet_running_on(master, master_opts) do agents.each do |agent| on(agent, puppet('agent', "--no-daemonize --onetime --verbose")) do |result| if result.stdout !~ /Notice: first.*Notice: second.*Notice: third.*Notice: fourth.*Notice: fifth.*Notice: sixth.*Notice: seventh.*Notice: eighth/m fail_test "Output did not include the notify resources in the correct order" end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/000077500000000000000000000000001527241624000256035ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/calling_all_functions.rb000066400000000000000000000365261527241624000324750ustar00rootroot00000000000000test_name 'Calling all functions.. test in progress!' tag 'audit:high', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners # create single manifest calling all functions step 'Apply manifest containing all function calls' def manifest_call_each_function_from_array(functions) manifest = '' # use index to work around puppet's immutable variables # use variables so we can concatenate strings functions.each_with_index do |function,index| if function[:rvalue] manifest << "$pre#{index} = \"sayeth #{function[:name].capitalize}: Scope(Class[main]): \" " manifest << "$output#{index} = #{function[:name]}(#{function[:args]}) " manifest << "#{function[:lambda]} notice \"${pre#{index}}${output#{index}}\"\n" else manifest << "$pre#{index} = \"sayeth #{function[:name].capitalize}: \" " manifest << "notice \"${pre#{index}}\"\n" manifest << "#{function[:name]}(#{function[:args]}) " manifest << "#{function[:lambda]}\n" end end manifest end agents.each do |agent| testdir = agent.tmpdir('calling_all_functions') # if agent["platform"] =~ /win/ # generator = {:args => '"c:/windows/system32/tasklist.exe"', :expected => /\nImage Name/} # else # generator = {:args => '"/bin/date"', :expected => /\w\w\w.*?\d\d:\d\d\:\d\d/} # end # create list of 3x functions and args # notes: hiera functions are well tested elsewhere, included for completeness # special cases: contain (call this from call_em_all) # do fail last because it errors out functions_3x = [ {:name => :alert, :args => '"consider yourself on alert"', :lambda => nil, :expected => 'consider yourself on alert', :rvalue => false}, {:name => :binary_file, :args => '"call_em_all/rickon.txt"', :lambda => nil, :expected => '', :rvalue => true}, #{:name => :break, :args => '', :lambda => nil, :expected => '', :rvalue => false}, # this is explicitly called from call_em_all module which is included below #{:name => :contain, :args => 'call_em_all', :lambda => nil, :expected => '', :rvalue => true}, # below doens't instance the resource. no output {:name => :create_resources, :args => 'notify, {"w"=>{message=>"winter is coming"}}', :lambda => nil, :expected => '', :rvalue => false}, {:name => :crit, :args => '"consider yourself critical"', :lambda => nil, :expected => 'consider yourself critical', :rvalue => false}, {:name => :debug, :args => '"consider yourself bugged"', :lambda => nil, :expected => '', :rvalue => false}, # no output expected unless run with debug {:name => :defined, :args => 'File["/tmp"]', :lambda => nil, :expected => 'false', :rvalue => true}, {:name => :dig, :args => '[100]', :lambda => nil, :expected => '[100]', :rvalue => true}, # Expect sha256 hash value for the digest {:name => :digest, :args => '"Sansa"', :lambda => nil, :expected => '4ebf3a5527313f06c7965749d7764c15cba6fe86da11691ca9bd0ce448563979', :rvalue => true}, {:name => :emerg, :args => '"consider yourself emergent"', :lambda => nil, :expected => 'consider yourself emergent', :rvalue => false}, {:name => :err, :args => '"consider yourself in err"', :lambda => nil, :expected => 'consider yourself in err', :rvalue => false}, {:name => :file, :args => '"call_em_all/rickon.txt"', :lambda => nil, :expected => 'who?', :rvalue => true}, {:name => :fqdn_rand, :args => '100000', :lambda => nil, :expected => /Fqdn_rand: Scope\(Class\[main\]\): \d{1,5}/, :rvalue => true}, # generate requires a fully qualified exe; which requires specifics for windows vs posix #{:name => :generate, :args => generator[:args], :lambda => nil, :expected => generator[:expected], :rvalue => true}, {:name => :hiera_array, :args => 'date,default_array', :lambda => nil, :expected => 'default_array', :rvalue => true}, {:name => :hiera_hash, :args => 'date,default_hash', :lambda => nil, :expected => 'default_hash', :rvalue => true}, {:name => :hiera_include, :args => 'date,call_em_all', :lambda => nil, :expected => '', :rvalue => false}, {:name => :hiera, :args => 'date,default_date', :lambda => nil, :expected => 'default_date', :rvalue => true}, {:name => :include, :args => 'call_em_all', :lambda => nil, :expected => '', :rvalue => false}, {:name => :info, :args => '"consider yourself informed"', :lambda => nil, :expected => '', :rvalue => false}, # no ouput unless in debug mode {:name => :inline_template, :args => '\'empty<%= @x %>space\'', :lambda => nil, :expected => 'emptyspace', :rvalue => true}, # test the living life out of this thing in lookup.rb, and it doesn't allow for a default value #{:name => :lookup, :args => 'date,lookup_date', :lambda => nil, :expected => '', :rvalue => true}, # well tested elsewhere {:name => :sha256, :args => '"Bran"', :lambda => nil, :expected => '824264f7f73d6026550b52a671c50ad0c4452af66c24f3784e30f515353f2ce0', :rvalue => true}, # Integer.new {:name => :Integer, :args => '"100"', :lambda => nil, :expected => '100', :rvalue => true}, {:name => :notice, :args => '"consider yourself under notice"', :lambda => nil, :expected => 'consider yourself under notice', :rvalue => false}, {:name => :realize, :args => 'User[arya]', :lambda => nil, :expected => '', :rvalue => false}, # TODO: create a virtual first {:name => :regsubst, :args => '"Cersei","Cer(\\\\w)ei","Daenery\\\\1"',:lambda => nil, :expected => 'Daenerys', :rvalue => true}, # explicitly called in call_em_all; implicitly called by the include above #{:name => :require, :args => '[4,5,6]', :lambda => nil, :expected => '', :rvalue => true}, # 4x output contains brackets around scanf output {:name => :scanf, :args => '"Eddard Stark","%6s"', :lambda => nil, :expected => '[Eddard]', :rvalue => true}, {:name => :sha1, :args => '"Sansa"', :lambda => nil, :expected => '4337ce5e4095e565d51e0ef4c80df1fecf238b29', :rvalue => true}, {:name => :shellquote, :args => '["-1", "--two"]', :lambda => nil, :expected => '-1 --two', :rvalue => true}, # 4x output contains brackets around split output and commas btwn values {:name => :split, :args => '"9,8,7",","', :lambda => nil, :expected => '[9, 8, 7]', :rvalue => true}, {:name => :sprintf, :args => '"%b","123"', :lambda => nil, :expected => '1111011', :rvalue => true}, {:name => :step, :args => '[100,99],1', :lambda => nil, :expected => 'Iterator[Integer]-Value', :rvalue => true}, # explicitly called in call_em_all #{:name => :tag, :args => '[4,5,6]', :lambda => nil, :expected => '', :rvalue => true}, {:name => :tagged, :args => '"yer_it"', :lambda => nil, :expected => 'false', :rvalue => true}, {:name => :template, :args => '"call_em_all/template.erb"', :lambda => nil, :expected => 'no defaultsno space', :rvalue => true}, {:name => :type, :args => '42', :lambda => nil, :expected => 'Integer[42, 42]', :rvalue => true}, {:name => :versioncmp, :args => '"1","2"', :lambda => nil, :expected => '-1', :rvalue => true}, {:name => :warning, :args => '"consider yourself warned"', :lambda => nil, :expected => 'consider yourself warned', :rvalue => false}, # do this one last or it will not allow the others to run. {:name => :fail, :args => '"Jon Snow"', :lambda => nil, :expected => /Error:.*Jon Snow/, :rvalue => false}, ] puppet_version = on(agent, puppet('--version')).stdout.chomp functions_4x = [ {:name => :assert_type, :args => '"String[1]", "Valar morghulis"', :lambda => nil, :expected => 'Valar morghulis', :rvalue => true}, {:name => :each, :args => '[1,2,3]', :lambda => '|$x| {$x}', :expected => '[1, 2, 3]', :rvalue => true}, {:name => :epp, :args => '"call_em_all/template.epp",{x=>droid}', :lambda => nil, :expected => 'This is the droid you are looking for!', :rvalue => true}, {:name => :filter, :args => '[4,5,6]', :lambda => '|$x| {true}', :expected => '[4, 5, 6]', :rvalue => true}, # find_file() called by binary_file #{:name => :find_file, :args => '[4,5,6]', :lambda => '|$x| {true}', :expected => '[4, 5, 6]', :rvalue => true}, {:name => :inline_epp, :args => '\'<%= $x %>\',{x=>10}', :lambda => nil, :expected => '10', :rvalue => true}, #{:name => :lest, :args => '100', :lambda => '"100"', :expected => '100', :rvalue => true}, {:name => :map, :args => '[7,8,9]', :lambda => '|$x| {$x * $x}', :expected => '[49, 64, 81]', :rvalue => true}, {:name => :match, :args => '"abc", /b/', :lambda => nil, :expected => '[b]', :rvalue => true}, #{:name => :next, :args => '100', :lambda => nil, :expected => '100', :rvalue => true}, {:name => :reduce, :args => '[4,5,6]', :lambda => '|$sum, $n| { $sum+$n }', :expected => '15', :rvalue => true}, #{:name => :return, :args => '100', :lambda => nil, :expected => '100', :rvalue => true}, {:name => :reverse_each, :args => '[100,99]', :lambda => nil, :expected => 'Iterator[Integer]-Value', :rvalue => true}, # :reuse,:recycle {:name => :slice, :args => '[1,2,3,4,5,6], 2', :lambda => nil, :expected => '[[1, 2], [3, 4], [5, 6]]', :rvalue => true}, {:name => :strftime, :args => 'Timestamp("4216-09-23T13:14:15.123 UTC"), "%C"', :lambda => nil, :expected => '42', :rvalue => true}, {:name => :then, :args => '100', :lambda => '|$x| {$x}', :expected => '100', :rvalue => true}, {:name => :with, :args => '1, "Catelyn"', :lambda => '|$x, $y| {"$x, $y"}', :expected => '1, Catelyn', :rvalue => true}, ] module_manifest = < directory, } file { '#{testdir}':; '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/modules':; '#{testdir}/environments/production/modules/tagged':; '#{testdir}/environments/production/modules/tagged/manifests':; '#{testdir}/environments/production/modules/contained':; '#{testdir}/environments/production/modules/contained/manifests':; '#{testdir}/environments/production/modules/required':; '#{testdir}/environments/production/modules/required/manifests':; '#{testdir}/environments/production/modules/call_em_all':; '#{testdir}/environments/production/modules/call_em_all/manifests':; '#{testdir}/environments/production/modules/call_em_all/templates':; '#{testdir}/environments/production/modules/call_em_all/files':; } file { '#{testdir}/environments/production/modules/tagged/manifests/init.pp': ensure => file, content => 'class tagged { notice tagged tag yer_it }', } file { '#{testdir}/environments/production/modules/required/manifests/init.pp': ensure => file, content => 'class required { notice required }', } file { '#{testdir}/environments/production/modules/contained/manifests/init.pp': ensure => file, content => 'class contained { notice contained }', } file { '#{testdir}/environments/production/modules/call_em_all/manifests/init.pp': ensure => file, content => 'class call_em_all { notice call_em_all contain contained require required tag yer_it }', } file { '#{testdir}/environments/production/modules/call_em_all/files/rickon.txt': ensure => file, content => 'who?', } file { '#{testdir}/environments/production/modules/call_em_all/templates/template.epp': ensure => file, content => 'This is the <%= $x %> you are looking for!', } file { '#{testdir}/environments/production/modules/call_em_all/templates/template.erb': ensure => file, content => 'no defaults<%= @x %>no space', } PP apply_manifest_on(agent, module_manifest, :catch_failures => true) scope = 'Scope(Class[main]):' # apply the 4x function manifest with future parser puppet_apply_options = {:modulepath => "#{testdir}/environments/production/modules/", :acceptable_exit_codes => 1} puppet_apply_options[:future_parser] = true if puppet_version =~ /\A3\./ apply_manifest_on(agent, manifest_call_each_function_from_array(functions_4x), puppet_apply_options) do |result| functions_4x.each do |function| expected = "#{function[:name].capitalize}: #{scope} #{function[:expected]}" unless agent['locale'] == 'ja' assert_match(expected, result.output, "#{function[:name]} output didn't match expected value") end end end file_path = agent.tmpfile('apply_manifest.pp') create_remote_file(agent, file_path, manifest_call_each_function_from_array(functions_3x)) trusted_3x = puppet_version =~ /\A3\./ ? '--trusted_node_data ' : '' on(agent, puppet("apply #{trusted_3x} --color=false --modulepath #{testdir}/environments/production/modules/ #{file_path}"), :acceptable_exit_codes => 1 ) do |result| functions_3x.each do |function| # append the function name to the matcher so it's more expressive if function[:expected].is_a?(String) if function[:name] == :fail expected = function[:expected] elsif function[:name] == :crit expected = "#{function[:name].capitalize}ical: #{scope} #{function[:expected]}" elsif function[:name] == :emerg expected = "#{function[:name].capitalize}ency: #{scope} #{function[:expected]}" elsif function[:name] == :err expected = "#{function[:name].capitalize}or: #{scope} #{function[:expected]}" elsif function[:expected] == '' expected = "#{function[:name].capitalize}: #{function[:expected]}" else expected = "#{function[:name].capitalize}: #{scope} #{function[:expected]}" end elsif function[:expected].is_a?(Regexp) expected = function[:expected] else raise 'unhandled function expectation type (we allow String or Regexp)' end unless agent['locale'] == 'ja' assert_match(expected, result.output, "#{function[:name]} output didn't match expected value") end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/hiera/000077500000000000000000000000001527241624000266735ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/hiera/lookup_data.rb000066400000000000000000000040531527241624000315240ustar00rootroot00000000000000test_name "Lookup data using the hiera parser function" tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not required for this test. Replace with agents.each 'shard:group2' # For splitting out groups of tests for slow test runners testdir = master.tmpdir('hiera') step 'Setup' apply_manifest_on(master, <<-PP, :catch_failures => true) File { ensure => directory, mode => "0750", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}':; '#{testdir}/hieradata':; '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/manifests':; '#{testdir}/environments/production/modules':; } file { '#{testdir}/hiera.yaml': ensure => file, content => '--- :backends: - "yaml" :logger: "console" :hierarchy: - "%{environment}" - "global" :yaml: :datadir: "#{testdir}/hieradata" ', mode => "0640", } file { '#{testdir}/hieradata/global.yaml': ensure => file, content => "--- port: 8080 ", mode => "0640", } file { '#{testdir}/environments/production/modules/apache':; '#{testdir}/environments/production/modules/apache/manifests':; } file { '#{testdir}/environments/production/modules/apache/manifests/init.pp': ensure => file, content => ' class apache { $port = hiera("port") notify { "port from hiera": message => "apache server port: ${port}" } }', mode => "0640", } file { '#{testdir}/environments/production/manifests/site.pp': ensure => file, content => " node default { include apache }", mode => "0640", } PP step "Try to lookup string data" master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", 'hiera_config' => "#{testdir}/hiera.yaml", }, } with_puppet_running_on master, master_opts, testdir do agents.each do |agent| on(agent, puppet('agent', "-t"), :acceptable_exit_codes => [2]) do |result| assert_match('apache server port: 8080', result.stdout) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/hiera_array/000077500000000000000000000000001527241624000300715ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/hiera_array/lookup_data.rb000066400000000000000000000046021527241624000327220ustar00rootroot00000000000000test_name "Lookup data using the hiera_array parser function" tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not required for this test. Replace with agents.each 'shard:group3' # For splitting out groups of tests for slow test runners testdir = master.tmpdir('hiera') step 'Setup' apply_manifest_on(master, <<-PP, :catch_failures => true) File { ensure => directory, mode => "0750", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}':; '#{testdir}/hieradata':; '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/manifests':; '#{testdir}/environments/production/modules':; } file { '#{testdir}/hiera.yaml': ensure => file, content => '--- :backends: - "yaml" :logger: "console" :hierarchy: - "%{environment}" - "global" :yaml: :datadir: "#{testdir}/hieradata" ', mode => "0640"; } file { '#{testdir}/hieradata/global.yaml': ensure => file, content => "--- port: '8080' ntpservers: ['global.ntp.puppetlabs.com'] ", mode => "0640"; } file { '#{testdir}/hieradata/production.yaml': ensure => file, content => "--- ntpservers: ['production.ntp.puppetlabs.com'] ", mode => "0640"; } file { '#{testdir}/environments/production/modules/ntp':; '#{testdir}/environments/production/modules/ntp/manifests':; } file { '#{testdir}/environments/production/modules/ntp/manifests/init.pp': ensure => file, content => ' class ntp { $ntpservers = hiera_array("ntpservers") define print { $server = $name notify { "ntpserver ${server}": } } ntp::print { $ntpservers: } }', mode => "0640"; } file { '#{testdir}/environments/production/manifests/site.pp': ensure => file, content => " node default { include ntp }", mode => "0640"; } PP step "Try to lookup array data" master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", 'hiera_config' => "#{testdir}/hiera.yaml", }, } with_puppet_running_on master, master_opts, testdir do agents.each do |agent| on(agent, puppet('agent', "-t"), :acceptable_exit_codes => [2]) do |result| assert_match('ntpserver global.ntp.puppetlabs.com', result.stdout) assert_match('ntpserver production.ntp.puppetlabs.com', result.stdout) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/hiera_hash/000077500000000000000000000000001527241624000276765ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/hiera_hash/lookup_data.rb000066400000000000000000000044451527241624000325340ustar00rootroot00000000000000test_name "Lookup data using the hiera_hash parser function" tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not required for this test. Replace with agents.each 'shard:group4' # For splitting out groups of tests for slow test runners testdir = master.tmpdir('hiera') step 'Setup' apply_manifest_on(master, <<-PP, :catch_failures => true) File { ensure => directory, mode => "0750", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{testdir}':; '#{testdir}/hieradata':; '#{testdir}/environments':; '#{testdir}/environments/production':; '#{testdir}/environments/production/manifests':; '#{testdir}/environments/production/modules':; } file { '#{testdir}/hiera.yaml': ensure => file, content => '--- :backends: - "yaml" :logger: "console" :hierarchy: - "%{environment}" - "global" :yaml: :datadir: "#{testdir}/hieradata" ', mode => "0640"; } file { '#{testdir}/hieradata/global.yaml': ensure => file, content => "--- database_user: name: postgres uid: 500 gid: 500 ", mode => "0640"; } file { '#{testdir}/hieradata/production.yaml': ensure => file, content => "--- database_user: shell: '/bin/bash' ", mode => "0640"; } file { '#{testdir}/environments/production/modules/ntp/':; '#{testdir}/environments/production/modules/ntp/manifests':; } file { '#{testdir}/environments/production/modules/ntp/manifests/init.pp': ensure => file, content => 'class ntp { $database_user = hiera_hash("database_user") notify { "the database user": message => "name: ${database_user["name"]} shell: ${database_user["shell"]}" } }', mode => "0640"; } file { '#{testdir}/environments/production/manifests/site.pp': ensure => file, content => " node default { include ntp }", mode => "0640"; } PP step "Try to lookup hash data" master_opts = { 'main' => { 'environmentpath' => "#{testdir}/environments", 'hiera_config' => "#{testdir}/hiera.yaml", }, } with_puppet_running_on master, master_opts, testdir do agents.each do |agent| on(agent, puppet('agent', "-t"), :acceptable_exit_codes => [2]) do |result| assert_match("name: postgres shell: /bin/bash", result.stdout) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/hiera_in_templates.rb000066400000000000000000000306221527241624000317670ustar00rootroot00000000000000test_name "Calling Hiera function from inside templates" tag 'audit:high', 'audit:integration', 'audit:refactor', # Master is not required for this test. Replace with agents.each 'shard:group1' # For splitting out groups of tests for slow test runners @module_name = "hieratest" @coderoot = master.tmpdir("#{@module_name}") @msg_default = 'message from default.yaml' @msg_production = 'message from production.yaml' @msg1os = 'message1 from {osfamily}.yaml' @msg2os = 'message2 from {osfamily}.yaml' @msg_fqdn = 'messsage from {fqdn}.yaml' @k1 = 'key1' @k2 = 'key2' @k3 = 'key3' @hval2p = 'hash_value2 from production.yaml' @hval3p = 'hash_value3 from production.yaml' @hval1os = 'hash_value1 from {osfamily}.yaml' @hval2os = 'hash_value2 from {osfamily}.yaml' @h_m_call = "hiera\\('message'\\)" @h_h_call = "hiera\\('hash_value'\\)" @h_i_call = "hiera\\('includes'\\)" @ha_m_call = "hiera_array\\('message'\\)" @ha_i_call = "hiera_array\\('includes'\\)" @hh_h_call = "hiera_hash\\('hash_value'\\)" @mod_default_msg = 'This file created by mod_default.' @mod_osfamily_msg = 'This file created by mod_osfamily.' @mod_production_msg = 'This file created by mod_production.' @mod_fqdn_msg = 'This file created by mod_fqdn.' @master_opts = { 'main' => { 'environmentpath' => "#{@coderoot}/environments", 'hiera_config' => "#{@coderoot}/hiera.yaml", }, } def create_environment(osfamilies, tmp_dirs) envroot = "#{@coderoot}/environments" production = "#{envroot}/production" modroot = "#{production}/modules" moduledir = "#{modroot}/#{@module_name}" hieradir = "#{@coderoot}/hieradata" osfamily_yamls = "" osfamilies.each do |osf| new_yaml = < " --- message: [ '#{@msg1os}', '#{@msg2os}', ] includes: '#{@module_name}::mod_osfamily' hash_value: #{@k1}: '#{@hval1os}' #{@k2}: '#{@hval2os}' " } NEW_YAML osfamily_yamls += new_yaml end environ = < file, owner => #{master.puppet['user']}, group => #{master.puppet['group']}, mode => "0644", } file { [ "#{@coderoot}", "#{envroot}", "#{production}", "#{production}/modules", "#{production}/manifests", "#{hieradir}", "#{moduledir}", "#{moduledir}/examples", "#{moduledir}/manifests", "#{moduledir}/templates", ] : ensure => directory, } file { '#{production}/manifests/site.pp': ensure => file, content => " node default { \\$msgs = hiera_array('message') notify {\\$msgs:} class {'#{@module_name}': result_dir => hiera('result_dir')[\\$facts['networking']['hostname']], } } ", } file {"#{@coderoot}/hiera.yaml": content => " --- :backends: - yaml :yaml: :datadir: #{@coderoot}/hieradata :hierarchy: - \\"%{clientcert}\\" - \\"%{environment}\\" - \\"%{os.family}\\" - \\"default\\" " } file {"#{hieradir}/default.yaml": content => " --- message: '#{@msg_default}' includes: '#{@module_name}::mod_default' result_dir: #{tmp_dirs} " } #{osfamily_yamls} file {"#{hieradir}/production.yaml": content => " --- message: '#{@msg_production}' includes: '#{@module_name}::mod_production' hash_value: #{@k2}: '#{@hval2p}' #{@k3}: '#{@hval3p}' " } file {"#{hieradir}/#{$fqdn}.yaml": content => " --- message: '#{@msg_fqdn}' includes: '#{@module_name}::mod_fqdn' " } file {"#{moduledir}/examples/init.pp": content => " include #{@module_name} " } file { "#{moduledir}/manifests/init.pp": content => " class #{@module_name} ( \\$result_dir, ) { file { \\$result_dir: ensure => directory, mode => '0755', } file {\\\"\\\${result_dir}/#{@module_name}_results_epp\\\": ensure => file, mode => '0644', content => epp('#{@module_name}/hieratest_results_epp.epp'), } file {\\\"\\\${result_dir}/#{@module_name}_results_erb\\\": ensure => file, mode => '0644', content => template('#{@module_name}/hieratest_results_erb.erb'), } } " } file { "#{moduledir}/manifests/mod_default.pp": content => " class #{@module_name}::mod_default { \\$result_dir = hiera('result_dir')[\\$facts['networking']['hostname']] notify{\\"module mod_default invoked.\\\\n\\":} file {\\\"\\\${result_dir}/mod_default\\\": ensure => 'file', mode => '0644', content => \\\"#{@mod_default_msg}\\\\n\\\", } } " } file { "#{moduledir}/manifests/mod_osfamily.pp": content => " class #{@module_name}::mod_osfamily { \\$result_dir = hiera('result_dir')[\\$facts['networking']['hostname']] notify{\\"module mod_osfamily invoked.\\\\n\\":} file {\\\"\\\${result_dir}/mod_osfamily\\\": ensure => 'file', mode => '0644', content => \\\"#{@mod_osfamily_msg}\\\\n\\\", } } " } file { "#{moduledir}/manifests/mod_production.pp": content => " class #{@module_name}::mod_production { \\$result_dir = hiera('result_dir')[\\$facts['networking']['hostname']] notify{\\"module mod_production invoked.\\\\n\\":} file {\\\"\\\${result_dir}/mod_production\\\": ensure => 'file', mode => '0644', content => '#{@mod_production_msg}', } } " } file { "#{moduledir}/manifests/mod_fqdn.pp": content => " class #{@module_name}::mod_fqdn { \\$result_dir = hiera('result_dir')[\\$facts['networking']['hostname']] notify{\\"module mod_fqdn invoked.\\\\n\\":} file {\\\"\\\${result_dir}/mod_fqdn\\\": ensure => 'file', mode => '0644', content => \\\"#{@mod_fqdn_msg}\\\\n\\\", } } " } file { "#{moduledir}/templates/hieratest_results_epp.epp": content => " hiera('message'): <%= hiera('message') %> hiera('hash_value'): <%= hiera('hash_value') %> hiera('includes'): <%= hiera('includes') %> hiera_array('message'): <%= hiera_array('message') %> hiera_array('includes'): <%= hiera_array('includes') %> hiera_hash('hash_value'): <%= hiera_hash('hash_value') %> hiera_include('includes'): <%= hiera_include('includes') %> " } file { "#{moduledir}/templates/hieratest_results_erb.erb": content => " hiera('message'): <%= scope().call_function('hiera', ['message']) %> hiera('hash_value'): <%= scope().call_function('hiera', ['hash_value']) %> hiera('includes'): <%= scope().call_function('hiera', ['includes']) %> hiera_array('message'): <%= scope().call_function('hiera_array', ['message']) %> hiera_array('includes'): <%= scope().call_function('hiera_array', ['includes']) %> hiera_hash('hash_value'): <%= scope().call_function('hiera_hash', ['hash_value']) %> " } ENV environ end def find_osfamilies family_hash = {} agents.each do |agent| res = on(agent, facter("os.family")) osf = res.stdout.chomp family_hash[osf] = 1 end family_hash.keys end def find_tmp_dirs tmp_dirs = "" host_to_result_dir = {} agents.each do |agent| h = on(agent, facter("networking.hostname")).stdout.chomp t = agent.tmpdir("#{@module_name}_results") tmp_dirs += " #{h}: '#{t}'\n" host_to_result_dir[h] = t end result = { 'tmp_dirs' => tmp_dirs, 'host_to_result_dir' => host_to_result_dir } result end step 'Setup' with_puppet_running_on master, @master_opts, @coderoot do res = find_tmp_dirs tmp_dirs = res['tmp_dirs'] host_to_result_dir = res['host_to_result_dir'] env_manifest = create_environment(find_osfamilies, tmp_dirs) apply_manifest_on(master, env_manifest, :catch_failures => true) agents.each do |agent| resultdir = host_to_result_dir[on(agent, facter("networking.hostname")).stdout.chomp] step "Applying catalog to agent: #{agent}. result files in #{resultdir}" on( agent, puppet('agent', "-t"), :acceptable_exit_codes => [2] ) step "####### Verifying hiera calls from erb template #######" r1 = on(agent, "cat #{resultdir}/hieratest_results_erb") result = r1.stdout step "Verifying hiera() call #1." assert_match( /#{@h_m_call}: #{@msg_production}/, result, "#{@h_m_call} failed. Expected: '#{@msg_production}'" ) step "Verifying hiera() call #2." assert_match( /#{@h_h_call}.*\"#{@k3}\" => \"#{@hval3p}\"/, result, "#{@h_h_call} failed. Expected: '\"#{@k3}\" => \"#{@hval3p}\"'" ) step "Verifying hiera() call #3." assert_match( /#{@h_h_call}.*\"#{@k2}\" => \"#{@hval2p}\"/, result, "#{@h_h_call} failed. Expected: '\"#{@k2}\" => \"#{@hval2p}\"'" ) step "Verifying hiera() call #4." assert_match( /#{@h_i_call}: #{@module_name}::mod_production/, result, "#{@h_i_call} failed. Expected:'#{@module_name}::mod_production'" ) step "Verifying hiera_array() call. #1" assert_match( /#{@ha_m_call}: \[\"#{@msg_production}\", \"#{@msg1os}\", \"#{@msg2os}\", \"#{@msg_default}\"\]/, result, "#{@ha_m_call} failed. Expected: '[\"#{@msg_production}\", \"#{@msg1os}\", \"#{@msg2os}\", \"#{@msg_default}\"]'" ) step "Verifying hiera_array() call. #2" assert_match( /#{@ha_i_call}: \[\"#{@module_name}::mod_production\", \"#{@module_name}::mod_osfamily\", \"#{@module_name}::mod_default\"\]/, result, "#{@ha_i_call} failed. Expected: '[\"#{@module_name}::mod_production\", \"#{@module_name}::mod_osfamily\", \"#{@module_name}::mod_default\"]'" ) step "Verifying hiera_hash() call. #1" assert_match( /#{@hh_h_call}:.*\"#{@k3}\" => \"#{@hval3p}\"/, result, "#{@hh_h_call} failed. Expected: '\"#{@k3}\" => \"#{@hval3p}\"'" ) step "Verifying hiera_hash() call. #2" assert_match( /#{@hh_h_call}:.*\"#{@k2}\" => \"#{@hval2p}\"/, result, "#{@hh_h_call} failed. Expected: '\"#{@k2}\" => \"#{@hval2p}\"'" ) step "Verifying hiera_hash() call. #3" assert_match( /#{@hh_h_call}:.*\"#{@k1}\" => \"#{@hval1os}\"/, result, "#{@hh_h_call} failed. Expected: '\"#{@k1}\" => \"#{@hval1os}\"'" ) r2 = on(agent, "cat #{resultdir}/mod_default") result = r2.stdout step "Verifying hiera_include() call. #1" assert_match( "#{@mod_default_msg}", result, "#{@hi_i_call} failed. Expected: '#{@mod_default_msg}'" ) r3 = on(agent, "cat #{resultdir}/mod_osfamily") result = r3.stdout step "Verifying hiera_include() call. #2" assert_match( "#{@mod_osfamily_msg}", result, "#{@hi_i_call} failed. Expected: '#{@mod_osfamily_msg}'" ) r4 = on(agent, "cat #{resultdir}/mod_production") result = r4.stdout step "Verifying hiera_include() call. #3" assert_match( "#{@mod_production_msg}", result, "#{@hi_i_call} failed. Expected: '#{@mod_production_msg}'" ) step "####### Verifying hiera calls from epp template #######" r5 = on(agent, "cat #{resultdir}/hieratest_results_epp") result = r5.stdout step "Verifying hiery() call #1." assert_match( /#{@h_m_call}: #{@msg_production}/, result, "#{@hi_m_call} failed. Expected '#{@msg_production}'" ) step "Verifying hiera() call #2." assert_match( /#{@h_h_call}.*#{@k3} => #{@hval3p}/, result, "#{@h_h_call} failed. Expected '#{@k3} => #{@hval3p}'" ) step "Verifying hiera() call #3." assert_match(/#{@h_h_call}.*#{@k2} => #{@hval2p}/, result, "#{@h_h_call} failed. Expected '#{@k2} => #{@hval2p}'" ) step "Verifying hiera() call #4." assert_match( /#{@h_i_call}: #{@module_name}::mod_production/, result, "#{@h_i_call} failed. Expected: '#{@module_name}::mod_production'" ) step "Verifying hiera_array() call. #1" assert_match( /#{@ha_m_call}: \[#{@msg_production}, #{@msg1os}, #{@msg2os}, #{@msg_default}\]/, result, "#{@ha_m_call} failed. Expected: '[#{@msg_production}, #{@msg1os}, #{@msg2os}, #{@msg_default}]'" ) step "Verifying hiera_array() call. #2" assert_match( /#{@ha_i_call}: \[#{@module_name}::mod_production, #{@module_name}::mod_osfamily, #{@module_name}::mod_default\]/, result, "#{@ha_i_call} failed. Expected: '[#{@module_name}::mod_production, #{@module_name}::mod_osfamily, #{@module_name}::mod_default'" ) step "Verifying hiera_hash() call. #1" assert_match( /#{@hh_h_call}:.*#{@k3} => #{@hval3p}/, result, "#{@hh_h_call} failed. Expected: '{@k3} => #{@hval3p}'" ) step "Verifying hiera_hash() call. #2" assert_match( /#{@hh_h_call}:.*#{@k2} => #{@hval2p}/, result, "#{@hh_h_call} failed. Expected '#{@k2} => #{@hval2p}'", ) step "Verifying hiera_hash() call. #3" assert_match( /#{@hh_h_call}:.*#{@k1} => #{@hval1os}/, result, "#{@hh_h_call}: failed. Expected: '#{@k1} => #{@hval1os}'" ) end end no_exception_in_reduce_with_bignum.rb000066400000000000000000000035321527241624000351570ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functionstest_name 'C97760: Integer in reduce() should not cause exception' do require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils tag 'audit:high', 'audit:unit', 'shard:group2' # For splitting out groups of tests for slow test runners # Remove all traces of the last used environment teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end app_type = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, app_type) step 'On master, create site.pp with integer' do create_sitepp(master, tmp_environment, <<-SITEPP) $data = [ { "certname"=>"xxxxxxxxx.some.domain", "parameters"=>{ "admin_auth_keys"=>{ "keyname1"=>{ "key"=>"ABCDEF", "options"=>["from=\\"10.0.0.0/8\\""] }, "keyname2"=>{ "key"=>"ABCDEF", }, "keyname3"=>{ "key"=>"ABCDEF", "options"=>["from=\\"10.0.0.0/8\\""], "type"=>"ssh-xxx" }, "keyname4"=>{ "key"=>"ABCDEF", "options"=>["from=\\"10.0.0.0/8\\""] } }, "admin_user"=>"ertxa", "admin_hosts"=>["1.2.3.4", "1.2.3.4", "1.2.3.4"], "admin_password"=>"ABCDEF", "sshd_ports"=>[22, 22, 24], "sudo_no_password_all"=>false, "sudo_no_password_commands"=>[], "sshd_config_template"=>"cfauth/sshd_config.epp", "sudo_env_keep"=>[] }, "exported"=>false}, ] $data_reduced = $data.reduce({}) |$m, $r|{ $cn = $r['certname'] notice({ $cn => $r['parameters'] }) } SITEPP end with_puppet_running_on(master, {}) do agents.each do |agent| on(agent, puppet("agent -t --environment #{tmp_environment}")) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/parser_functions/puppet_lookup_cmd.rb000066400000000000000000002204111527241624000316610ustar00rootroot00000000000000test_name "Puppet Lookup Command" tag 'audit:high', 'audit:acceptance', 'audit:refactor', # Master is not required for this test. Replace with agents.each # Wrap steps in blocks in accordance with Beaker style guide 'shard:group3' # For splitting out groups of tests for slow test runners # doc: # https://docs.openvoxproject.org/openvox/latest/hiera_automatic.html @module_name = "puppet_lookup_command_test" ### @testroot = "/etc/puppetlabs" @testroot = master.tmpdir("#{@module_name}") @coderoot = "#{@testroot}/code" @confdir = "#{@testroot}/puppet" @node1 = 'node1.example.org' @node2 = 'node2.example.org' @master_opts = { 'main' => { 'environmentpath' => "#{@coderoot}/environments", 'hiera_config' => "#{@coderoot}/hiera.yaml", }, } @manifest = < directory, mode => "0755", } file { '#{@confdir}':; '#{@coderoot}':; '#{@coderoot}/hieradata':; '#{@coderoot}/environments':; ##### default environment, production '#{@coderoot}/environments/production':; '#{@coderoot}/environments/production/data':; '#{@coderoot}/environments/production/functions':; '#{@coderoot}/environments/production/functions/environment':; '#{@coderoot}/environments/production/lib':; '#{@coderoot}/environments/production/lib/puppet':; '#{@coderoot}/environments/production/lib/puppet/functions':; '#{@coderoot}/environments/production/lib/puppet/functions/environment':; '#{@coderoot}/environments/production/manifests':; '#{@coderoot}/environments/production/modules':; # module mod1 hiera '#{@coderoot}/environments/production/modules/mod1':; '#{@coderoot}/environments/production/modules/mod1/manifests':; '#{@coderoot}/environments/production/modules/mod1/data':; '#{@coderoot}/environments/production/modules/mod1/functions':; '#{@coderoot}/environments/production/modules/mod1/lib':; '#{@coderoot}/environments/production/modules/mod1/lib/puppet':; '#{@coderoot}/environments/production/modules/mod1/lib/puppet/functions':; '#{@coderoot}/environments/production/modules/mod1/lib/puppet/functions/mod1':; # module mod2 ruby function '#{@coderoot}/environments/production/modules/mod2':; '#{@coderoot}/environments/production/modules/mod2/manifests':; '#{@coderoot}/environments/production/modules/mod2/data':; '#{@coderoot}/environments/production/modules/mod2/functions':; '#{@coderoot}/environments/production/modules/mod2/lib':; '#{@coderoot}/environments/production/modules/mod2/lib/puppet':; '#{@coderoot}/environments/production/modules/mod2/lib/puppet/functions':; '#{@coderoot}/environments/production/modules/mod2/lib/puppet/functions/mod2':; # module mod3 puppet function '#{@coderoot}/environments/production/modules/mod3':; '#{@coderoot}/environments/production/modules/mod3/manifests':; '#{@coderoot}/environments/production/modules/mod3/data':; '#{@coderoot}/environments/production/modules/mod3/functions':; '#{@coderoot}/environments/production/modules/mod3/not-lib':; '#{@coderoot}/environments/production/modules/mod3/not-lib/puppet':; '#{@coderoot}/environments/production/modules/mod3/not-lib/puppet/functions':; '#{@coderoot}/environments/production/modules/mod3/not-lib/puppet/functions/mod3':; # module mod4 none '#{@coderoot}/environments/production/modules/mod4':; '#{@coderoot}/environments/production/modules/mod4/manifests':; '#{@coderoot}/environments/production/modules/mod4/data':; '#{@coderoot}/environments/production/modules/mod4/functions':; '#{@coderoot}/environments/production/modules/mod4/lib':; '#{@coderoot}/environments/production/modules/mod4/lib/puppet':; '#{@coderoot}/environments/production/modules/mod4/lib/puppet/functions':; '#{@coderoot}/environments/production/modules/mod4/lib/puppet/functions/mod4':; ##### env1 hiera '#{@coderoot}/environments/env1':; '#{@coderoot}/environments/env1/data':; '#{@coderoot}/environments/env1/functions':; '#{@coderoot}/environments/env1/functions/environment':; '#{@coderoot}/environments/env1/lib':; '#{@coderoot}/environments/env1/lib/puppet':; '#{@coderoot}/environments/env1/lib/puppet/functions':; '#{@coderoot}/environments/env1/lib/puppet/functions/environment':; '#{@coderoot}/environments/env1/manifests':; '#{@coderoot}/environments/env1/modules':; # module mod1 hiera '#{@coderoot}/environments/env1/modules/mod1':; '#{@coderoot}/environments/env1/modules/mod1/manifests':; '#{@coderoot}/environments/env1/modules/mod1/data':; '#{@coderoot}/environments/env1/modules/mod1/functions':; '#{@coderoot}/environments/env1/modules/mod1/lib':; '#{@coderoot}/environments/env1/modules/mod1/lib/puppet':; '#{@coderoot}/environments/env1/modules/mod1/lib/puppet/functions':; '#{@coderoot}/environments/env1/modules/mod1/lib/puppet/functions/mod1':; # module mod2 ruby function '#{@coderoot}/environments/env1/modules/mod2':; '#{@coderoot}/environments/env1/modules/mod2/manifests':; '#{@coderoot}/environments/env1/modules/mod2/data':; '#{@coderoot}/environments/env1/modules/mod2/functions':; '#{@coderoot}/environments/env1/modules/mod2/lib':; '#{@coderoot}/environments/env1/modules/mod2/lib/puppet':; '#{@coderoot}/environments/env1/modules/mod2/lib/puppet/functions':; '#{@coderoot}/environments/env1/modules/mod2/lib/puppet/functions/mod2':; # module mod3 puppet function '#{@coderoot}/environments/env1/modules/mod3':; '#{@coderoot}/environments/env1/modules/mod3/manifests':; '#{@coderoot}/environments/env1/modules/mod3/data':; '#{@coderoot}/environments/env1/modules/mod3/functions':; '#{@coderoot}/environments/env1/modules/mod3/not-lib':; '#{@coderoot}/environments/env1/modules/mod3/not-lib/puppet':; '#{@coderoot}/environments/env1/modules/mod3/not-lib/puppet/functions':; '#{@coderoot}/environments/env1/modules/mod3/not-lib/puppet/functions/mod3':; # module mod4 none '#{@coderoot}/environments/env1/modules/mod4':; '#{@coderoot}/environments/env1/modules/mod4/manifests':; '#{@coderoot}/environments/env1/modules/mod4/data':; '#{@coderoot}/environments/env1/modules/mod4/functions':; '#{@coderoot}/environments/env1/modules/mod4/lib':; '#{@coderoot}/environments/env1/modules/mod4/lib/puppet':; '#{@coderoot}/environments/env1/modules/mod4/lib/puppet/functions':; '#{@coderoot}/environments/env1/modules/mod4/lib/puppet/functions/mod4':; ##### env2 ruby function '#{@coderoot}/environments/env2':; '#{@coderoot}/environments/env2/data':; '#{@coderoot}/environments/env2/functions':; '#{@coderoot}/environments/env2/functions/environment':; '#{@coderoot}/environments/env2/lib':; '#{@coderoot}/environments/env2/lib/puppet':; '#{@coderoot}/environments/env2/lib/puppet/functions':; '#{@coderoot}/environments/env2/lib/puppet/functions/environment':; '#{@coderoot}/environments/env2/manifests':; '#{@coderoot}/environments/env2/modules':; # module mod1 hiera '#{@coderoot}/environments/env2/modules/mod1':; '#{@coderoot}/environments/env2/modules/mod1/manifests':; '#{@coderoot}/environments/env2/modules/mod1/data':; '#{@coderoot}/environments/env2/modules/mod1/functions':; '#{@coderoot}/environments/env2/modules/mod1/lib':; '#{@coderoot}/environments/env2/modules/mod1/lib/puppet':; '#{@coderoot}/environments/env2/modules/mod1/lib/puppet/functions':; '#{@coderoot}/environments/env2/modules/mod1/lib/puppet/functions/mod1':; # module mod2 ruby function '#{@coderoot}/environments/env2/modules/mod2':; '#{@coderoot}/environments/env2/modules/mod2/manifests':; '#{@coderoot}/environments/env2/modules/mod2/data':; '#{@coderoot}/environments/env2/modules/mod2/functions':; '#{@coderoot}/environments/env2/modules/mod2/lib':; '#{@coderoot}/environments/env2/modules/mod2/lib/puppet':; '#{@coderoot}/environments/env2/modules/mod2/lib/puppet/functions':; '#{@coderoot}/environments/env2/modules/mod2/lib/puppet/functions/mod2':; # module mod3 puppet function '#{@coderoot}/environments/env2/modules/mod3':; '#{@coderoot}/environments/env2/modules/mod3/manifests':; '#{@coderoot}/environments/env2/modules/mod3/data':; '#{@coderoot}/environments/env2/modules/mod3/functions':; '#{@coderoot}/environments/env2/modules/mod3/not-lib':; '#{@coderoot}/environments/env2/modules/mod3/not-lib/puppet':; '#{@coderoot}/environments/env2/modules/mod3/not-lib/puppet/functions':; '#{@coderoot}/environments/env2/modules/mod3/not-lib/puppet/functions/mod3':; # module mod4 none '#{@coderoot}/environments/env2/modules/mod4':; '#{@coderoot}/environments/env2/modules/mod4/manifests':; '#{@coderoot}/environments/env2/modules/mod4/data':; '#{@coderoot}/environments/env2/modules/mod4/functions':; '#{@coderoot}/environments/env2/modules/mod4/lib':; '#{@coderoot}/environments/env2/modules/mod4/lib/puppet':; '#{@coderoot}/environments/env2/modules/mod4/lib/puppet/functions':; '#{@coderoot}/environments/env2/modules/mod4/lib/puppet/functions/mod4':; ##### env3 puppet function '#{@coderoot}/environments/env3':; '#{@coderoot}/environments/env3/data':; '#{@coderoot}/environments/env3/functions':; '#{@coderoot}/environments/env3/functions/environment':; '#{@coderoot}/environments/env3/not-lib':; '#{@coderoot}/environments/env3/not-lib/puppet':; '#{@coderoot}/environments/env3/not-lib/puppet/functions':; '#{@coderoot}/environments/env3/not-lib/puppet/functions/environment':; '#{@coderoot}/environments/env3/manifests':; '#{@coderoot}/environments/env3/modules':; # module mod1 hiera '#{@coderoot}/environments/env3/modules/mod1':; '#{@coderoot}/environments/env3/modules/mod1/manifests':; '#{@coderoot}/environments/env3/modules/mod1/data':; '#{@coderoot}/environments/env3/modules/mod1/functions':; '#{@coderoot}/environments/env3/modules/mod1/lib':; '#{@coderoot}/environments/env3/modules/mod1/lib/puppet':; '#{@coderoot}/environments/env3/modules/mod1/lib/puppet/functions':; '#{@coderoot}/environments/env3/modules/mod1/lib/puppet/functions/mod1':; # module mod2 ruby function '#{@coderoot}/environments/env3/modules/mod2':; '#{@coderoot}/environments/env3/modules/mod2/manifests':; '#{@coderoot}/environments/env3/modules/mod2/data':; '#{@coderoot}/environments/env3/modules/mod2/functions':; '#{@coderoot}/environments/env3/modules/mod2/lib':; '#{@coderoot}/environments/env3/modules/mod2/lib/puppet':; '#{@coderoot}/environments/env3/modules/mod2/lib/puppet/functions':; '#{@coderoot}/environments/env3/modules/mod2/lib/puppet/functions/mod2':; # module mod3 puppet function '#{@coderoot}/environments/env3/modules/mod3':; '#{@coderoot}/environments/env3/modules/mod3/manifests':; '#{@coderoot}/environments/env3/modules/mod3/data':; '#{@coderoot}/environments/env3/modules/mod3/functions':; '#{@coderoot}/environments/env3/modules/mod3/not-lib':; '#{@coderoot}/environments/env3/modules/mod3/not-lib/puppet':; '#{@coderoot}/environments/env3/modules/mod3/not-lib/puppet/functions':; '#{@coderoot}/environments/env3/modules/mod3/not-lib/puppet/functions/mod3':; # module mod4 none '#{@coderoot}/environments/env3/modules/mod4':; '#{@coderoot}/environments/env3/modules/mod4/manifests':; '#{@coderoot}/environments/env3/modules/mod4/data':; '#{@coderoot}/environments/env3/modules/mod4/functions':; '#{@coderoot}/environments/env3/modules/mod4/lib':; '#{@coderoot}/environments/env3/modules/mod4/lib/puppet':; '#{@coderoot}/environments/env3/modules/mod4/lib/puppet/functions':; '#{@coderoot}/environments/env3/modules/mod4/lib/puppet/functions/mod4':; ##### env4 none '#{@coderoot}/environments/env4':; '#{@coderoot}/environments/env4/data':; '#{@coderoot}/environments/env4/functions':; '#{@coderoot}/environments/env4/functions/environment':; '#{@coderoot}/environments/env4/lib':; '#{@coderoot}/environments/env4/lib/puppet':; '#{@coderoot}/environments/env4/lib/puppet/functions':; '#{@coderoot}/environments/env4/lib/puppet/functions/environment':; '#{@coderoot}/environments/env4/manifests':; '#{@coderoot}/environments/env4/modules':; # module mod1 hiera '#{@coderoot}/environments/env4/modules/mod1':; '#{@coderoot}/environments/env4/modules/mod1/manifests':; '#{@coderoot}/environments/env4/modules/mod1/data':; '#{@coderoot}/environments/env4/modules/mod1/functions':; '#{@coderoot}/environments/env4/modules/mod1/lib':; '#{@coderoot}/environments/env4/modules/mod1/lib/puppet':; '#{@coderoot}/environments/env4/modules/mod1/lib/puppet/functions':; '#{@coderoot}/environments/env4/modules/mod1/lib/puppet/functions/mod1':; # module mod2 ruby function '#{@coderoot}/environments/env4/modules/mod2':; '#{@coderoot}/environments/env4/modules/mod2/manifests':; '#{@coderoot}/environments/env4/modules/mod2/data':; '#{@coderoot}/environments/env4/modules/mod2/functions':; '#{@coderoot}/environments/env4/modules/mod2/lib':; '#{@coderoot}/environments/env4/modules/mod2/lib/puppet':; '#{@coderoot}/environments/env4/modules/mod2/lib/puppet/functions':; '#{@coderoot}/environments/env4/modules/mod2/lib/puppet/functions/mod2':; # module mod3 puppet function '#{@coderoot}/environments/env4/modules/mod3':; '#{@coderoot}/environments/env4/modules/mod3/manifests':; '#{@coderoot}/environments/env4/modules/mod3/data':; '#{@coderoot}/environments/env4/modules/mod3/functions':; '#{@coderoot}/environments/env4/modules/mod3/not-lib':; '#{@coderoot}/environments/env4/modules/mod3/not-lib/puppet':; '#{@coderoot}/environments/env4/modules/mod3/not-lib/puppet/functions':; '#{@coderoot}/environments/env4/modules/mod3/not-lib/puppet/functions/mod3':; # module mod4 none '#{@coderoot}/environments/env4/modules/mod4':; '#{@coderoot}/environments/env4/modules/mod4/manifests':; '#{@coderoot}/environments/env4/modules/mod4/data':; '#{@coderoot}/environments/env4/modules/mod4/functions':; '#{@coderoot}/environments/env4/modules/mod4/lib':; '#{@coderoot}/environments/env4/modules/mod4/lib/puppet':; '#{@coderoot}/environments/env4/modules/mod4/lib/puppet/functions':; '#{@coderoot}/environments/env4/modules/mod4/lib/puppet/functions/mod4':; } ## Global data provider config (hiera) file { '#{@coderoot}/hiera.yaml': ensure => file, mode => "0644", content => '--- :backends: - "yaml" :logger: "console" :hierarchy: - "global" :yaml: :datadir: "#{@coderoot}/hieradata" ', } ## facts file file { '#{@coderoot}/facts.yaml': ensure => file, mode => "0644", content => '--- my_data_key: "my_data_value" ', } file { '#{@coderoot}/hieradata/global.yaml': ensure => file, mode => "0644", content => '--- global_key: "global-hiera provided value for key" another_global_key: "global-hiera provided value for key" mod1::global_key: "global-hiera provided value for key" mod2::global_key: "global-hiera provided value for key" mod3::global_key: "global-hiera provided value for key" mod4::global_key: "global-hiera provided value for key" ', } ## Evironment data provider configuration file { '#{@coderoot}/environments/production/environment.conf': ensure => file, mode => "0644", content => 'environment_timeout = 0 ', } file { '#{@coderoot}/environments/env1/environment.conf': ensure => file, mode => "0644", content => 'environment_timeout = 0 ', } file { '#{@coderoot}/environments/env2/environment.conf': ensure => file, mode => "0644", content => 'environment_timeout = 0 ', } file { '#{@coderoot}/environments/env3/environment.conf': ensure => file, mode => "0644", content => 'environment_timeout = 0 ', } file { '#{@coderoot}/environments/env4/environment.conf': ensure => file, mode => "0644", content => 'environment_timeout = 0 ', } # Environment hiera data provider file { '#{@coderoot}/environments/production/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 4 ', } file { '#{@coderoot}/environments/production/data/common.yaml': ensure => file, mode => "0644", content => '--- global_key: "env-production hiera provided value" environment_key: "env-production hiera provided value" ', } file { '#{@coderoot}/environments/env1/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 4 ', } file { '#{@coderoot}/environments/env1/data/common.yaml': ensure => file, mode => "0644", content => '--- global_key: "env-env1 hiera provided value" environment_key: "env-env1 hiera provided value" ', } file { '#{@coderoot}/environments/env2/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Environment data function" v4_data_hash: environment::data ', } file { '#{@coderoot}/environments/env2/data/common.yaml': ensure => file, mode => "0644", content => '--- global_key: "env-env1 hiera provided value" environment_key: "env-env1 hiera provided value" ', } file { '#{@coderoot}/environments/env3/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Environment data function" v4_data_hash: environment::data ', } file { '#{@coderoot}/environments/env3/data/common.yaml': ensure => file, mode => "0644", content => '--- global_key: "env-env1 hiera provided value" environment_key: "env-env1 hiera provided value" ', } file { '#{@coderoot}/environments/env4/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: [] ', } file { '#{@coderoot}/environments/env4/data/common.yaml': ensure => file, mode => "0644", content => '--- global_key: "env-env1 hiera provided value" environment_key: "env-env1 hiera provided value" ', } # Environment ruby function data provider file { '#{@coderoot}/environments/production/lib/puppet/functions/environment/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'environment::data') do def data() { 'environment_key': 'env-production-ruby-function data() provided value', 'global_key': 'env-production-ruby-function data () provided value', } end end ", } file { '#{@coderoot}/environments/env1/lib/puppet/functions/environment/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'environment::data') do def data() { 'environment_key' => 'env-env1-ruby-function data() provided value', 'global_key' => 'env-env1-ruby-function data () provided value', } end end ", } file { '#{@coderoot}/environments/env2/lib/puppet/functions/environment/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'environment::data') do def data() { 'environment_key' => 'env-env2-ruby-function data() provided value', 'global_key' => 'env-env2-ruby-function data () provided value', } end end ", } file { '#{@coderoot}/environments/env3/not-lib/puppet/functions/environment/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'environment::data') do def data() { 'environment_key' => 'env-env3-ruby-function data() provided value', 'global_key' => 'env-env3-ruby-function data () provided value', } end end ", } file { '#{@coderoot}/environments/env4/lib/puppet/functions/environment/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'environment::data') do def data() { 'environment_key' => 'env-env4-ruby-function data() provided value', 'global_key' => 'env-env4-ruby-function data () provided value', } end end ", } # Environment puppet function data provider file { '#{@coderoot}/environments/production/functions/environment/data.pp': ensure => file, mode => "0755", content => 'function environment::data() { { "environment_key" => "env-production-puppet-function data() provided value", "global_key" => "env-production-puppet-function data() provided value", } } ', } file { '#{@coderoot}/environments/env1/functions/environment/data.pp': ensure => file, mode => "0755", content => 'function environment::data() { { "environment_key" => "env-env1-puppet-function data() provided value", "global_key" => "env-env1-puppet-function data() provided value", } } ', } file { '#{@coderoot}/environments/env2/functions/environment/data.pp': ensure => file, mode => "0755", content => 'function environment::data() { { "environment_key" => "env-env2-puppet-function data() provided value", "global_key" => "env-env2-puppet-function data() provided value", } } ', } file { '#{@coderoot}/environments/env3/functions/environment/data.pp': ensure => file, mode => "0755", content => 'function environment::data() { { "environment_key" => "env-env3-puppet-function data() provided value", "global_key" => "env-env3-puppet-function data() provided value", } } ', } file { '#{@coderoot}/environments/env4/functions/environment/data.pp': ensure => file, mode => "0755", content => 'function environment::data() { { "environment_key" => "env-env4-puppet-function data() provided value", "global_key" => "env-env4-puppet-function data() provided value", } } ', } ## Module data provider configuration # Module hiera data provider file { '#{@coderoot}/environments/production/modules/mod1/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 4 ', } file { '#{@coderoot}/environments/production/modules/mod1/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod1::module_key": "module-production-mod1-hiera provided value" "mod1::global_key": "module-production-mod1-hiera provided value" "environment_key": "module-production-mod1-hiera provided value" "global_key": "module-production-mod1-hiera provided value" ', } file { '#{@coderoot}/environments/production/modules/mod2/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod2::data ', } file { '#{@coderoot}/environments/production/modules/mod2/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod2::module_key": "module-production-mod2-hiera provided value" "mod2::global_key": "module-production-mod2-hiera provided value" "environment_key": "module-production-mod2-hiera provided value" "global_key": "module-production-mod2-hiera provided value" ', } file { '#{@coderoot}/environments/production/modules/mod3/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod3::data ', } file { '#{@coderoot}/environments/production/modules/mod3/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod3::module_key": "module-production-mod3-hiera provided value" "mod3::global_key": "module-production-mod3-hiera provided value" "environment_key": "module-production-mod3-hiera provided value" "global_key" => "module-production-mod3-hiera provided value" ', } file { '#{@coderoot}/environments/production/modules/mod4/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod4::module_key": "module-production-mod4-hiera provided value" "mod4::global_key": "module-production-mod4-hiera provided value" "environment_key": "module-production-mod4-hiera provided value" "global_key": "module-production-mod4-hiera provided value" ', } file { '#{@coderoot}/environments/env1/modules/mod1/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 4 ', } file { '#{@coderoot}/environments/env1/modules/mod1/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod1::module_key": "module-env1-mod1-hiera provided value" "global_key": "module-env1-mod1-hiera provided value" "environment_key": "module-env1-mod1-hiera provided value" ', } file { '#{@coderoot}/environments/env1/modules/mod2/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod2::data ', } file { '#{@coderoot}/environments/env1/modules/mod2/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod2::module_key": "module-env1-mod2-hiera provided value" "global_key": "module-env1-mod2-hiera provided value" "environment_key": "module-env1-mod2-hiera provided value" ', } file { '#{@coderoot}/environments/env1/modules/mod3/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod3::data ', } file { '#{@coderoot}/environments/env1/modules/mod3/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod3::module_key": "module-env1-mod3-hiera provided value" "global_key": "module-env1-mod3-hiera provided value" "environment_key": "module-env1-mod3-hiera provided value" ', } file { '#{@coderoot}/environments/env1/modules/mod4/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod4::module_key": "module-env1-mod4-hiera provided value" "global_key": "module-env1-mod4-hiera provided value" "environment_key": "module-env1-mod4-hiera provided value" ', } file { '#{@coderoot}/environments/env2/modules/mod1/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 4 ', } file { '#{@coderoot}/environments/env2/modules/mod1/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod1::module_key": "module-env2-mod1-hiera provided value" "global_key": "module-env2-mod1-hiera provided value" "environment_key": "module-env2-mod1-hiera provided value" ', } file { '#{@coderoot}/environments/env2/modules/mod2/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod2::data ', } file { '#{@coderoot}/environments/env2/modules/mod2/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod2::module_key": "module-env2-mod2-hiera provided value" "global_key": "module-env2-mod2-hiera provided value" "environment_key": "module-env2-mod2-hiera provided value" ', } file { '#{@coderoot}/environments/env2/modules/mod3/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod3::data ', } file { '#{@coderoot}/environments/env2/modules/mod3/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod3::module_key": "module-env2-mod3-hiera provided value" "global_key": "module-env2-mod3-hiera provided value" "environment_key": "module-env2-mod3-hiera provided value" ', } file { '#{@coderoot}/environments/env2/modules/mod4/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod4::module_key": "module-env2-mod4-hiera provided value" "global_key": "module-env2-mod4-hiera provided value" "environment_key": "module-env2-mod4-hiera provided value" ', } file { '#{@coderoot}/environments/env3/modules/mod1/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 4 ', } file { '#{@coderoot}/environments/env3/modules/mod1/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod1::module_key": "module-env3-mod1-hiera provided value" "global_key": "module-env3-mod1-hiera provided value" "environment_key": "module-env3-mod1-hiera provided value" ', } file { '#{@coderoot}/environments/env3/modules/mod2/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod2::data ', } file { '#{@coderoot}/environments/env3/modules/mod2/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod2::module_key": "module-env3-mod2-hiera provided value" "global_key": "module-env3-mod2-hiera provided value" "environment_key": "module-env3-mod2-hiera provided value" ', } file { '#{@coderoot}/environments/env3/modules/mod3/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod3::data ', } file { '#{@coderoot}/environments/env3/modules/mod3/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod3::module_key": "module-env3-mod3-hiera provided value" "global_key": "module-env3-mod3-hiera provided value" "environment_key": "module-env3-mod3-hiera provided value" ', } file { '#{@coderoot}/environments/env3/modules/mod4/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod4::module_key": "module-env3-mod4-hiera provided value" "global_key": "module-env3-mod4-hiera provided value" "environment_key": "module-env3-mod4-hiera provided value" ', } file { '#{@coderoot}/environments/env4/modules/mod1/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 4 ', } file { '#{@coderoot}/environments/env4/modules/mod1/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod1::module_key": "module-env4-mod1-hiera provided value" "global_key": "module-env4-mod1-hiera provided value" "environment_key": "module-env4-mod1-hiera provided value" ', } file { '#{@coderoot}/environments/env4/modules/mod2/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod2::data ', } file { '#{@coderoot}/environments/env4/modules/mod2/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod2::module_key": "module-env4-mod2-hiera provided value" "global_key": "module-env4-mod2-hiera provided value" "environment_key": "module-env4-mod2-hiera provided value" ', } file { '#{@coderoot}/environments/env4/modules/mod3/hiera.yaml': ensure => file, mode => "0644", content => '--- version: 5 hierarchy: - name: "Module data function" v4_data_hash: mod3::data ', } file { '#{@coderoot}/environments/env4/modules/mod3/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod3::module_key": "module-env4-mod3-hiera provided value" "global_key": "module-env4-mod3-hiera provided value" "environment_key": "module-env4-mod3-hiera provided value" ', } file { '#{@coderoot}/environments/env4/modules/mod4/data/common.yaml': ensure => file, mode => "0644", content => '--- "mod4::module_key": "module-env4-mod4-hiera provided value" "global_key": "module-env4-mod4-hiera provided value" "environment_key": "module-env4-mod4-hiera provided value" ', } # Module ruby function data provider file { '#{@coderoot}/environments/production/modules/mod1/lib/puppet/functions/mod1/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod1::data') do def data() { 'mod1::module_key' => 'module-production-mod1-ruby-function provided value', 'mod1::global_key' => 'module-production-mod1-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/production/modules/mod2/lib/puppet/functions/mod2/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod2::data') do def data() { 'mod2::module_key' => 'module-production-mod2-ruby-function provided value', 'mod2::global_key' => 'module-production-mod2-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/production/modules/mod3/not-lib/puppet/functions/mod3/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod3::data') do def data() { 'mod3::module_key' => 'module-production-mod3-ruby-function provided value', 'mod3::global_key' => 'module-production-mod3-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/production/modules/mod4/lib/puppet/functions/mod4/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod4::data') do def data() { 'mod4::module_key' => 'module-production-mod4-ruby-function provided value', 'mod4::global_key' => 'module-production-mod4-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env1/modules/mod1/lib/puppet/functions/mod1/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod1::data') do def data() { 'mod1::module_key' => 'module-env1-mod1-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env1/modules/mod2/lib/puppet/functions/mod2/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod2::data') do def data() { 'mod2::module_key' => 'module-env1-mod2-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env1/modules/mod3/not-lib/puppet/functions/mod3/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod3::data') do def data() { 'mod3::module_key' => 'module-env1-mod3-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env1/modules/mod4/lib/puppet/functions/mod4/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod4::data') do def data() { 'mod4::module_key' => 'module-env1-mod4-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env2/modules/mod1/lib/puppet/functions/mod1/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod1::data') do def data() { 'mod1::module_key' => 'module-env2-mod1-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env2/modules/mod2/lib/puppet/functions/mod2/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod2::data') do def data() { 'mod2::module_key' => 'module-env2-mod2-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env2/modules/mod3/not-lib/puppet/functions/mod3/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod3::data') do def data() { 'mod3::module_key' => 'module-env2-mod3-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env2/modules/mod4/lib/puppet/functions/mod4/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod4::data') do def data() { 'mod4::module_key' => 'module-env2-mod4-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env3/modules/mod1/lib/puppet/functions/mod1/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod1::data') do def data() { 'mod1::module_key' => 'module-env3-mod1-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env3/modules/mod2/lib/puppet/functions/mod2/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod2::data') do def data() { 'mod2::module_key' => 'module-env3-mod2-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env3/modules/mod3/not-lib/puppet/functions/mod3/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod3::data') do def data() { 'mod3::module_key' => 'module-env3-mod3-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env3/modules/mod4/lib/puppet/functions/mod4/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod4::data') do def data() { 'mod4::module_key' => 'module-env3-mod4-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env4/modules/mod1/lib/puppet/functions/mod1/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod1::data') do def data() { 'mod1::module_key' => 'module-env4-mod1-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env4/modules/mod2/lib/puppet/functions/mod2/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod2::data') do def data() { 'mod2::module_key' => 'module-env4-mod2-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env4/modules/mod3/not-lib/puppet/functions/mod3/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod3::data') do def data() { 'mod3::module_key' => 'module-env4-mod3-ruby-function provided value', } end end ", } file { '#{@coderoot}/environments/env4/modules/mod4/lib/puppet/functions/mod4/data.rb': ensure => file, mode => "0644", content => "Puppet::Functions.create_function(:'mod4::data') do def data() { 'mod4::module_key' => 'module-env4-mod4-ruby-function provided value', } end end ", } # Module puppet function data provider file { '#{@coderoot}/environments/production/modules/mod1/functions/data.pp': ensure => file, mode => "0644", content => "function mod1::data() { { 'mod1::module_key' => 'module-production-mod1-puppet-function provided value', 'mod1::global_key' => 'module-production-mod1-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/production/modules/mod2/functions/data.pp': ensure => file, mode => "0644", content => "function mod2::data() { { 'mod2::module_key' => 'module-production-mod2-puppet-function provided value', 'mod2::global_key' => 'module-production-mod2-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/production/modules/mod3/functions/data.pp': ensure => file, mode => "0644", content => "function mod3::data() { { 'mod3::module_key' => 'module-production-mod3-puppet-function provided value', 'mod3::global_key' => 'module-production-mod3-puppet-funtion provided value', } } ", } file { '#{@coderoot}/environments/production/modules/mod4/functions/data.pp': ensure => file, mode => "0644", content => "function mod4::data() { { 'mod4::module_key' => 'module-production-mod4-puppet-function provided value', 'mod4::global_key' => 'module-production-mod4-puppet-funtion provided value', } } ", } file { '#{@coderoot}/environments/env1/modules/mod1/functions/data.pp': ensure => file, mode => "0644", content => "function mod1::data() { { 'mod1::module_key' => 'module-env1-mod1-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env1/modules/mod2/functions/data.pp': ensure => file, mode => "0644", content => "function mod2::data() { { 'mod2::module_key' => 'module-env1-mod2-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env1/modules/mod3/functions/data.pp': ensure => file, mode => "0644", content => "function mod3::data() { { 'mod3::module_key' => 'module-env1-mod3-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env1/modules/mod4/functions/data.pp': ensure => file, mode => "0644", content => "function mod4::data() { { 'mod4::module_key' => 'module-env1-mod4-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env2/modules/mod1/functions/data.pp': ensure => file, mode => "0644", content => "function mod1::data() { { 'mod1::module_key' => 'module-env2-mod1-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env2/modules/mod2/functions/data.pp': ensure => file, mode => "0644", content => "function mod2::data() { { 'mod2::module_key' => 'module-env2-mod2-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env2/modules/mod3/functions/data.pp': ensure => file, mode => "0644", content => "function mod3::data() { { 'mod3::module_key' => 'module-env2-mod3-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env2/modules/mod4/functions/data.pp': ensure => file, mode => "0644", content => "function mod4::data() { { 'mod4::module_key' => 'module-env2-mod4-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env3/modules/mod1/functions/data.pp': ensure => file, mode => "0644", content => "function mod1::data() { { 'mod1::module_key' => 'module-env3-mod1-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env3/modules/mod2/functions/data.pp': ensure => file, mode => "0644", content => "function mod2::data() { { 'mod2::module_key' => 'module-env3-mod2-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env3/modules/mod3/functions/data.pp': ensure => file, mode => "0644", content => "function mod3::data() { { 'mod3::module_key' => 'module-env3-mod3-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env3/modules/mod4/functions/data.pp': ensure => file, mode => "0644", content => "function mod4::data() { { 'mod4::module_key' => 'module-env3-mod4-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env4/modules/mod1/functions/data.pp': ensure => file, mode => "0644", content => "function mod1::data() { { 'mod1::module_key' => 'module-env4-mod1-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env4/modules/mod2/functions/data.pp': ensure => file, mode => "0644", content => "function mod2::data() { { 'mod2::module_key' => 'module-env4-mod2-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env4/modules/mod3/functions/data.pp': ensure => file, mode => "0644", content => "function mod3::data() { { 'mod3::module_key' => 'module-env4-mod3-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/env4/modules/mod4/functions/data.pp': ensure => file, mode => "0644", content => "function mod4::data() { { 'mod4::module_key' => 'module-env4-mod4-puppet-function provided value', } } ", } file { '#{@coderoot}/environments/production/manifests/site.pp': ensure => file, mode => "0644", content => "node default { include mod1 include mod2 include mod3 include mod4 } ", } file { '#{@coderoot}/environments/env1/manifests/site.pp': ensure => file, mode => "0644", content => "node default { include mod1 include mod2 include mod3 include mod4 } ", } file { '#{@coderoot}/environments/env2/manifests/site.pp': ensure => file, mode => "0644", content => "node default { include mod1 include mod2 include mod3 include mod4 } ", } file { '#{@coderoot}/environments/env3/manifests/site.pp': ensure => file, mode => "0644", content => "node default { include mod1 include mod2 include mod3 include mod4 } ", } file { '#{@coderoot}/environments/env4/manifests/site.pp': ensure => file, mode => "0644", content => "node default { include mod1 include mod2 include mod2 include mod2 } ", } file { '#{@coderoot}/environments/production/modules/mod1/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod1 { notice("hello from production-mod1") } ', } file { '#{@coderoot}/environments/production/modules/mod2/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod2 { notice("hello from production-mod2") } ', } file { '#{@coderoot}/environments/production/modules/mod3/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod3 { notice("hello from production-mod3") } ', } file { '#{@coderoot}/environments/production/modules/mod4/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod4 { notice("hello from production-mod4") } ', } file { '#{@coderoot}/environments/env1/modules/mod1/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod1 { notice("hello from env1-mod1") } ', } file { '#{@coderoot}/environments/env1/modules/mod2/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod2 { notice("hello from env1-mod2") } ', } file { '#{@coderoot}/environments/env1/modules/mod3/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod3 { notice("hello from env1-mod3") } ', } file { '#{@coderoot}/environments/env1/modules/mod4/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod4 { notice("hello from env1-mod4") } ', } file { '#{@coderoot}/environments/env2/modules/mod1/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod1 { notice("hello from env2-mod1") } ', } file { '#{@coderoot}/environments/env2/modules/mod2/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod2 { notice("hello from env2-mod2") } ', } file { '#{@coderoot}/environments/env2/modules/mod3/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod3 { notice("hello from env2-mod3") } ', } file { '#{@coderoot}/environments/env2/modules/mod4/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod4 { notice("hello from env2-mod4") } ', } file { '#{@coderoot}/environments/env3/modules/mod1/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod1 { notice("hello from env3-mod1") } ', } file { '#{@coderoot}/environments/env3/modules/mod2/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod2 { notice("hello from env3-mod2") } ', } file { '#{@coderoot}/environments/env3/modules/mod3/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod3 { notice("hello from env3-mod3") } ', } file { '#{@coderoot}/environments/env3/modules/mod4/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod4 { notice("hello from env3-mod4") } ', } file { '#{@coderoot}/environments/env4/modules/mod1/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod1 { notice("hello from env4-mod1") } ', } file { '#{@coderoot}/environments/env4/modules/mod2/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod2 { notice("hello from env4-mod2") } ', } file { '#{@coderoot}/environments/env4/modules/mod3/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod3 { notice("hello from env4-mod3") } ', } file { '#{@coderoot}/environments/env4/modules/mod4/manifests/init.pp': ensure => file, mode => "0644", content => 'class mod4 { notice("hello from env4-mod4") } ', } file { '#{@coderoot}/environments/production/modules/mod1/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod1", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/production/modules/mod2/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod2", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/production/modules/mod3/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod3", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/production/modules/mod4/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod1", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env1/modules/mod1/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod1", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env1/modules/mod2/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod2", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env1/modules/mod3/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod3", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env1/modules/mod4/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod4", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env2/modules/mod1/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod1", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env2/modules/mod2/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod2", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env2/modules/mod3/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod3", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env2/modules/mod4/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod4", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env3/modules/mod1/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod1", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env3/modules/mod2/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod2", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env3/modules/mod3/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod3", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env3/modules/mod4/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod4", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env4/modules/mod1/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod1", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env4/modules/mod2/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod2", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env4/modules/mod3/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod3", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } file { '#{@coderoot}/environments/env4/modules/mod4/metadata.json': ensure => file, mode => "0644", content => '{ "name": "tester-mod4", "version": "0.1.0", "author": "tester", "summary": null, "license": "Apache-2.0", "source": "", "project_page": null, "issues_url": null, "dependencies": [] } ', } MANIFEST @env1puppetconfmanifest = < file, mode => "0664", content => "[server] vardir = /opt/puppetlabs/server/data/puppetserver logdir = /var/log/puppetlabs/puppetserver rundir = /var/run/puppetlabs/puppetserver pidfile = /var/run/puppetlabs/puppetserver/puppetserver.pid codedir = #{@coderoot} [main] environmentpath = #{@coderoot}/environments hiera_config = #{@coderoot}/hiera.yaml environment = env1 server = #{master.connection.hostname} ", } MANI1 @env2puppetconfmanifest = < file, mode => "0664", content => "[server] vardir = /opt/puppetlabs/server/data/puppetserver logdir = /var/log/puppetlabs/puppetserver rundir = /var/run/puppetlabs/puppetserver pidfile = /var/run/puppetlabs/puppetserver/puppetserver.pid codedir = #{@coderoot} [main] environmentpath = #{@coderoot}/environments hiera_config = #{@coderoot}/hiera.yaml environment = env2 server = #{master.connection.hostname} ", } MANI2 @env3puppetconfmanifest = < file, mode => "0664", content => "[server] vardir = /opt/puppetlabs/server/data/puppetserver logdir = /var/log/puppetlabs/puppetserver rundir = /var/run/puppetlabs/puppetserver pidfile = /var/run/puppetlabs/puppetserver/puppetserver.pid codedir = #{@coderoot} [main] environmentpath = #{@coderoot}/environments hiera_config = #{@coderoot}/hiera.yaml environment = env3 server = #{master.connection.hostname} ", } MANI3 @env4puppetconfmanifest = < file, mode => "0664", content => "[server] vardir = /opt/puppetlabs/server/data/puppetserver logdir = /var/log/puppetlabs/puppetserver rundir = /var/run/puppetlabs/puppetserver pidfile = /var/run/puppetlabs/puppetserver/puppetserver.pid codedir = #{@coderoot} [main] environmentpath = #{@coderoot}/environments hiera_config = #{@coderoot}/hiera.yaml environment = env4 server = #{master.connection.hostname} ", } MANI4 @encmanifest = < file, mode => "0755", content => "#!#{master['privatebindir']}/ruby nodename = ARGV.shift node2env = { '#{@node1}' => \\\"---\\\\n environment: env2\\\\n\\\", '#{@node2}' => \\\"---\\\\n environment: env3\\\\n\\\", } puts (\\\"\#{node2env[nodename]}\\\" ||'') ", } file { '#{@confdir}/puppet.conf' : ensure => file, mode => "0664", content => "[server] vardir = /opt/puppetlabs/server/data/puppetserver logdir = /var/log/puppetlabs/puppetserver rundir = /var/run/puppetlabs/puppetserver pidfile = /var/run/puppetlabs/puppetserver/puppetserver.pid codedir = #{@coderoot} [server] node_terminus = exec external_nodes = #{@coderoot}/enc.rb [main] environmentpath = #{@coderoot}/environments hiera_config = #{@coderoot}/hiera.yaml server = #{master.connection.hostname} ", } MANIENC teardown do on(master, "rm -f /etc/puppetlabs/puppet/ssl/certs/#{@node1}.pem") on(master, "rm -f /etc/puppetlabs/puppet/ssl/certs/#{@node2}.pem") on(master, "rm -f /etc/puppetlabs/puppet/ssl/ca/signed/#{@node1}.pem") on(master, "rm -f /etc/puppetlabs/puppet/ssl/ca/signed/#{@node2}.pem") on(master, "rm -f /etc/puppetlabs/puppet/ssl/private_keys/#{@node1}.pem") on(master, "rm -f /etc/puppetlabs/puppet/ssl/private_keys/#{@node2}.pem") on(master, "rm -f /etc/puppetlabs/puppet/ssl/public_keys/#{@node1}.pem") on(master, "rm -f /etc/puppetlabs/puppet/ssl/public_keys/#{@node2}.pem") end step 'apply main manifest' apply_manifest_on(master, @manifest, :catch_failures => true) step 'start puppet server' with_puppet_running_on master, @master_opts, @coderoot do step "global_key" rg = on(master, puppet('lookup', 'global_key')) result = rg.stdout assert_match( /global-hiera/, result, "global_key lookup failed, expected 'global-hiera'" ) step "production environment_key not provided" on(master, puppet('lookup', 'enviroment_key'), :acceptable_exit_codes => [1]) step "environment_key from environment env1" re1 = on(master, puppet('lookup', '--environment env1', 'environment_key')) result = re1.stdout assert_match( /env-env1 hiera/, result, "env1 environment_key lookup failed, expected 'env-env1 hiera'" ) step "environment_key from environment env2" re2 = on(master, puppet('lookup', '--environment env2', 'environment_key')) result = re2.stdout assert_match( /env-env2-ruby-function/, result, "env2 environment_key lookup failed, expected 'env-env2-puppet-function'" ) step "environment_key from environment env3" re3 = on(master, puppet('lookup', '--environment env3', 'environment_key')) result = re3.stdout assert_match( /env-env3-puppet-function/, result, "env3 environment_key lookup failed, expected 'env-env2-ruby-function data() provided value'" ) step "environment_key from environment env4" on(master, puppet('lookup', '--environment env4', 'environment_key'), :acceptable_exit_codes => [1]) step "production mod1 module_key" repm1 = on(master, puppet('lookup', 'mod1::module_key')) result = repm1.stdout assert_match( /module-production-mod1-hiera/, result, "production mod1 module_key lookup failed, expected 'module-production-mod1-hiera'" ) step "production mod2 module_key" repm2 = on(master, puppet('lookup', 'mod2::module_key')) result = repm2.stdout assert_match( /module-production-mod2-ruby-function/, result, "production mod2 module_key lookup failed, expected 'module-production-mod2-ruby-function'" ) step "production mod3 module_key" repm3 = on(master, puppet('lookup', 'mod3::module_key')) result = repm3.stdout assert_match( /module-production-mod3-puppet-function/, result, "production mod3 module_key lookup failed, expected 'module-production-mod3-puppet-function'" ) step "production mod4 module_key" on(master, puppet('lookup', 'mod4::module_key'), :acceptable_exit_codes => [1]) step "env1 mod1 module_key" re1m1 = on(master, puppet('lookup', '--environment env1', 'mod1::module_key')) result = re1m1.stdout assert_match( /module-env1-mod1-hiera/, result, "env1 mod1 module_key lookup failed, expected 'module-env1-mod1-hiera'" ) step "env1 mod2 module_key" re1m2 = on(master, puppet('lookup', '--environment env1', 'mod2::module_key')) result = re1m2.stdout assert_match( /module-env1-mod2-ruby-function/, result, "env1 mod2 module_key lookup failed, expected 'module-env1-mod2-ruby-function'" ) step "env1 mod3 module_key" re1m3 = on(master, puppet('lookup', '--environment env1', 'mod3::module_key')) result = re1m3.stdout assert_match( /module-env1-mod3-puppet-function/, result, "env1 mod3 module_key lookup failed, expected 'module-env1-mod3-puppet-function'" ) step "env1 mod4 module_key" on(master, puppet('lookup', '--environment env1', 'mod4::module_key'), :acceptable_exit_codes => [1]) step "env2 mod1 module_key" re2m1 = on(master, puppet('lookup', '--environment env2', 'mod1::module_key')) result = re2m1.stdout assert_match( /module-env2-mod1-hiera/, result, "env2 mod1 module_key lookup failed, expected 'module-env2-mod1-hiera'" ) step "env2 mod2 module_key" re2m2 = on(master, puppet('lookup', '--environment env2', 'mod2::module_key')) result = re2m2.stdout assert_match( /module-env2-mod2-ruby-function/, result, "env2 mod2 module_key lookup failed, expected 'module-env2-mod2-ruby-function'" ) step "env2 mod3 module_key" re2m3 = on(master, puppet('lookup', '--environment env2', 'mod3::module_key')) result = re2m3.stdout assert_match( /module-env2-mod3-puppet-function/, result, "env2 mod3 module_key lookup failed, expected 'module-env2-mod3-puppet-function'" ) step "env2 mod4 module_key" on(master, puppet('lookup', '--environment env2', 'mod4::module_key'), :acceptable_exit_codes => [1]) step "env3 mod1 module_key" re3m1 = on(master, puppet('lookup', '--environment env3', 'mod1::module_key')) result = re3m1.stdout assert_match( /module-env3-mod1-hiera/, result, "env3 mod1 module_key lookup failed, expected 'module-env3-mod1-hiera'" ) step "env3 mod2 module_key" re3m2 = on(master, puppet('lookup', '--environment env3', 'mod2::module_key')) result = re3m2.stdout assert_match( /module-env3-mod2-ruby-function/, result, "env3 mod2 module_key lookup failed, expected 'module-env3-mod2-ruby-function'" ) step "env3 mod3 module_key" re3m3 = on(master, puppet('lookup', '--environment env3', 'mod3::module_key')) result = re3m3.stdout assert_match( /module-env3-mod3-puppet-function/, result, "env3 mod3 module_key lookup failed, expected 'module-env3-mod3-puppet-function'" ) step "env3 mod4 module_key" # re3m4 = on(master, puppet('lookup', '--environment env3', 'mod4::module_key'), :acceptable_exit_codes => [1]) step "env4 mod1 module_key" re4m1 = on(master, puppet('lookup', '--environment env4', 'mod1::module_key')) result = re4m1.stdout assert_match( /module-env4-mod1-hiera/, result, "env4 mod2 environent_key lookup failed, expected 'module-env4-hiera'" ) step "env4 mod2 module_key" re4m2 = on(master, puppet('lookup', '--environment env4', 'mod2::module_key')) result = re4m2.stdout assert_match( /module-env4-mod2-ruby-function/, result, "env4 mod2 environent_key lookup failed, expected 'module-env4-mod2-ruby-function'" ) step "env4 mod3 module_key" re4m3 = on(master, puppet('lookup', '--environment env4', 'mod3::module_key')) result = re4m3.stdout assert_match( /module-env4-mod3-puppet-function/, result, "env4 mod3 module_key lookup failed, expected 'module-env4-mod3-puppet-function'" ) step "env4 mod4 module_key" on(master, puppet('lookup', '--environment env4', 'mod4::module_key'), :acceptable_exit_codes => [1]) step "global key explained" rxg = on(master, puppet('lookup', '--explain', 'global_key')) result = rxg.stdout assert_match( /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*Found key.*global-hiera/, result, "global_key explained failed, expected /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*Found key.*global-hiera/" ) step "environment env1 environment_key explained" rxe1 = on(master, puppet('lookup', '--explain', '--environment env1', 'environment_key')) result = rxe1.stdout assert_match( /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key/, result, "environment env1 enviroment_key lookup failed, expected /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key/" ) assert_match( /common.*\s*.*env-env1 hiera/, result, "environment env1 enviroment_key lookup failed, expected /common.*\s*.*env-env1 hiera/" ) step "environment env2 environment_key explained" rxe2 = on(master, puppet('lookup', '--explain', '--environment env2', 'environment_key')) result = rxe2.stdout assert_match( /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key/, result, "environment env2 enviroment_key lookup failed, expected /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key/" ) assert_match( /eprecated API function.*\s*.*env-env2-ruby-function/, result, "environment env2 enviroment_key lookup failed, expected /eprecated API function.*\s*.*env-env2-ruby-function/" ) step "environment env3 environment_key explained" rxe3 = on(master, puppet('lookup', '--explain', '--environment env3', 'environment_key')) result = rxe3.stdout assert_match( /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key/, result, "environment env3 enviroment_key lookup failed, expected /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key/" ) assert_match( /eprecated API function.*\s*.*env-env3-puppet-function/, result, "environment env3 enviroment_key lookup failed, expected /eprecated API function.*\s*.*env-env3-puppet-function/" ) step "environment env4 environment_key explained" rxe4 = on(master, puppet('lookup', '--explain', '--environment env4', 'environment_key')) result = rxe4.stdout assert_match( /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key.*environment_key/, result, "environment env4 environment_key lookup failed expected /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key.*environment_key.*\s.*did not find a value.*/" ) step "environment env1 mod4::module_key explained" rxe1m4 = on(master, puppet('lookup', '--explain', '--environment env1', 'mod4::module_key')) result = rxe1m4.stdout assert_match( /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key.*\s*Env.*\s*.*env1\/hiera.yaml\"\s*Hier.*common\"\s*Path.*\s*Orig.*\s*No such key.*\s*Module data provider.*not found\s*.*did not find a value.*/, result, "environment env1 mod4::module_key lookup explained failed." ) step "environment env2 mod3::module_key explained" rxe2m3 = on(master, puppet('lookup', '--explain', '--environment env2', 'mod3::module_key')) result = rxe2m3.stdout assert_match( /Global Data Provider.*Using configuration.*Hierarchy entry.*Path.*No such key/m, result, "global env2 mod3::module_key lookup --explain had correct output" ) assert_match( /Environment Data Provider.*Deprecated.*No such key/m, result, "environment env2 mod3::module_key lookup --explain had correct output" ) assert_match( /Module.*Data Provider.*Deprecated API function "mod3::data".*Found key.*module-env2-mod3-puppet-function provided value/m, result, "module env2 mod3::module_key lookup --explain had correct output" ) step "environment env3 mod2::module_key explained" rxe3m2 = on(master, puppet('lookup', '--explain', '--environment env3', 'mod2::module_key')) result = rxe3m2.stdout assert_match( /Global Data Provider.*Using configuration.*Hierarchy entry.*Path.*No such key/m, result, "global env2 mod3::module_key lookup --explain had correct output" ) assert_match( /Environment Data Provider.*Deprecated.*No such key/m, result, "environment env2 mod3::module_key lookup --explain had correct output" ) assert_match( /Module.*Data Provider.*Deprecated API function "mod2::data".*Found key.*module-env3-mod2-ruby-function provided value/m, result, "module env2 mod3::module_key lookup --explain had correct output" ) step "environment env4 mod1::module_key explained" rxe4m1 = on(master, puppet('lookup', '--explain', '--environment env4', 'mod1::module_key')) result = rxe4m1.stdout assert_match( /Global Data Provider.*\s*Using.*\s*Hier.*\s*Path.*\s*Orig.*\s*No such key.*\s*Environment Data Provider.*\s*Using.*\s*No such key.*\s*Module.*Data Provider.*\s*Using.*\s*Hier.*common\"\s*Path.*\s*Orig.*\s*Found key.*module-env4-mod1-hiera/, result, "environment env4 mod1::module_key lookup failed." ) step 'apply env1 puppet.conf manifest' apply_manifest_on(master, @env1puppetconfmanifest, :catch_failures => true) step "puppet.conf specified environment env1 environment_key" r = on(master, puppet('lookup', "--confdir #{@confdir}", 'environment_key')) result = r.stdout assert_match( /env-env1 hiera/, result, "puppet.conf specified environment env1, environment_key lookup failed, expected /env-env1 hiera/" ) step "puppet.conf specified environment env1 mod4::module_key" r = on(master, puppet('lookup', "--confdir #{@confdir}", 'mod4::module_key'), :acceptable_exit_codes => [1]) step 'apply env2 puppet.conf manifest' apply_manifest_on(master, @env2puppetconfmanifest, :catch_failures => true) step "puppet.conf specified environment env2 environment_key" r = on(master, puppet('lookup', "--confdir #{@confdir}", 'environment_key')) result = r.stdout assert_match( /env-env2-ruby-function/, result, "puppet.conf specified environment env2, environment_key lookup failed, expected /env-env2-ruby-function/" ) step "puppet.conf specified environment env2 mod3::module_key" r = on(master, puppet('lookup', "--confdir #{@confdir}", 'mod3::module_key')) result = r.stdout assert_match( /module-env2-mod3-puppet-function/, result, "puppet.conf specified environment env2 mod3::module_key lookup failed, expeccted /module-env2-mod3-puppet-function/" ) step 'apply env3 puppet.conf manifest' apply_manifest_on(master, @env3puppetconfmanifest, :catch_failures => true) step "puppet.conf specified environment env3 environment_key" r = on(master, puppet('lookup', "--confdir #{@confdir}", 'environment_key')) result = r.stdout assert_match( /env-env3-puppet-function/, result, "puppet.conf specified environment env1, environment_key lookup failed, expected /env-env3-puppet-function/" ) step "puppet.conf specified environment env3 mod2::module_key" r = on(master, puppet('lookup', "--confdir #{@confdir}", 'mod2::module_key')) result = r.stdout assert_match( /module-env3-mod2-ruby-function/, result, "puppet.conf specified environment env2 mod3::module_key lookup failed, expeccted /module-env3-mod2-ruby-function/" ) step 'apply env4 puppet.conf manifest' apply_manifest_on(master, @env4puppetconfmanifest, :catch_failures => true) step "puppet.conf specified environment env4 environment_key" r = on(master, puppet('lookup', "--confdir #{@confdir}", 'environment_key'), :acceptable_exit_codes => [1]) step "puppet.conf specified environment env4 mod1::module_key" r = on(master, puppet('lookup', "--confdir #{@confdir}", 'mod1::module_key')) result = r.stdout assert_match( /module-env4-mod1-hiera/, result, "puppet.conf specified environment env4 mod1::module_key lookup failed, expeccted /module-env4-mod1-hiera/" ) step 'apply enc manifest' apply_manifest_on(master, @encmanifest, :catch_failures => true) step "--compile uses environment specified in ENC" r = on(master, puppet('lookup', '--compile', "--node #{@node1}", "--confdir #{@confdir}", "--facts #{@coderoot}/facts.yaml", 'environment_key')) result = r.stderr assert_match( /CA is not available/, result, "lookup in ENC specified environment failed" ) step "handle certificate" on(master, "puppetserver ca generate --certname #{@node1}") on(master, "puppetserver ca generate --certname #{@node2}") on(master, "mkdir -p #{@testroot}/puppet/ssl/certs") on(master, "mkdir -p #{@testroot}/puppet/ssl/private_keys") on(master, "cp -a /etc/puppetlabs/puppet/ssl/certs/ca.pem #{@testroot}/puppet/ssl/certs") on(master, "cp -a /etc/puppetlabs/puppet/ssl/crl.pem #{@testroot}/puppet/ssl") on(master, "cp -a /etc/puppetlabs/puppet/ssl/private_keys/#{master.connection.hostname}.pem #{@testroot}/puppet/ssl/private_keys") on(master, "cp -a /etc/puppetlabs/puppet/ssl/certs/#{master.connection.hostname}.pem #{@testroot}/puppet/ssl/certs") step "--compile uses environment specified in ENC" r = on(master, puppet('lookup', '--compile', "--node #{@node1}", "--confdir #{@confdir}", "--facts #{@coderoot}/facts.yaml", 'environment_key')) result = r.stdout assert_match( /env-env2-ruby-function/, result, "lookup in ENC specified environment failed" ) step "without --compile does not use environment specified in ENC" r = on(master, puppet('lookup', "--node #{@node1}", "--confdir #{@confdir}", "--facts #{@coderoot}/facts.yaml", 'environment_key')) result = r.stdout assert_match( /env-production hiera provided value/, result, "lookup in production environment failed" ) step "lookup fails when there are no facts available" r = on(master, puppet('lookup', '--compile', "--node #{@node1}", "--confdir #{@confdir}", 'environment_key'), :acceptable_exit_codes => [1]) result = r.stderr assert_match( /No facts available/, result, "Expected to raise when there were no facts available." ) end OpenVoxProject-openvox-ebcec1e/acceptance/tests/pluginsync/000077500000000000000000000000001527241624000244125ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/pluginsync/3935_pluginsync_should_follow_symlinks.rb000066400000000000000000000026541527241624000345150ustar00rootroot00000000000000test_name "pluginsync should not error when modulepath is a symlink and no modules have plugin directories" tag 'audit:high', 'audit:integration', 'server', 'shard:group4' # For splitting out groups of tests for slow test runners step "Create a modulepath directory which is a symlink and includes a module without facts.d or lib directories" basedir = master.tmpdir("symlink_modulepath") target = "#{basedir}/target_dir" test_module_dir = "#{target}/module1" link_dest = "#{basedir}/link_dest" modulepath = "#{link_dest}" modulepath << "#{master['sitemoduledir']}" if master.is_pe? apply_manifest_on(master, < true) File { ensure => directory, mode => "0750", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{basedir}':; '#{target}':; '#{test_module_dir}':; } file { '#{link_dest}': ensure => link, target => '#{target}', } MANIFEST master_opts = { 'main' => { 'basemodulepath' => "#{modulepath}" } } with_puppet_running_on master, master_opts, basedir do agents.each do |agent| on(agent, puppet('agent', "-t")) do |result| refute_match(/Could not retrieve information from environment production source\(s\) puppet:\/\/\/pluginfacts/, result.stderr) refute_match(/Could not retrieve information from environment production source\(s\) puppet:\/\/\/plugins/, result.stderr) end end end 4420_pluginfacts_should_be_resolvable_on_agent.rb000066400000000000000000000102651527241624000357700ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/pluginsynctest_name "Pluginsync'ed external facts should be resolvable on the agent" do tag 'audit:high', 'audit:integration', 'shard:group1' # For splitting out groups of tests for slow test runners # # This test is intended to ensure that external facts downloaded onto an agent via # pluginsync are resolvable. In Linux, the external fact should have the same # permissions as its source on the master. # step "Create a codedir with a manifest and test module with external fact" codedir = master.tmpdir('4420-codedir') site_manifest_content = < true) File { ensure => directory, mode => "0755", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{codedir}':; '#{codedir}/environments':; '#{codedir}/environments/production':; '#{codedir}/environments/production/manifests':; '#{codedir}/environments/production/modules':; '#{codedir}/environments/production/modules/mymodule':; '#{codedir}/environments/production/modules/mymodule/manifests':; '#{codedir}/environments/production/modules/mymodule/facts.d':; } file { '#{codedir}/environments/production/manifests/site.pp': ensure => file, content => '#{site_manifest_content}', } file { '#{codedir}/environments/production/modules/mymodule/manifests/init.pp': ensure => file, content => 'class mymodule {}', } file { '#{codedir}/environments/production/modules/mymodule/facts.d/unix_external_fact.sh': ensure => file, mode => '755', content => '#{unix_fact}', } file { '#{codedir}/environments/production/modules/mymodule/facts.d/win_external_fact.bat': ensure => file, mode => '644', content => '#{win_fact}', } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{codedir}/environments" } } with_puppet_running_on(master, master_opts, codedir) do agents.each do |agent| factsd = agent.tmpdir('facts.d') pluginfactdest = agent.tmpdir('facts.d') teardown do on(master, "rm -rf '#{codedir}'") on(agent, "rm -rf '#{factsd}' '#{pluginfactdest}'") end step "Pluginsync the external fact to the agent and ensure it resolves correctly" do on(agent, puppet('agent', '-t', '--pluginfactdest', factsd), :acceptable_exit_codes => [2]) do |result| assert_match(/foo is bar/, result.stdout) end end step "Use plugin face to download to the agent" do on(agent, puppet('plugin', 'download', '--pluginfactdest', pluginfactdest)) do |result| assert_match(/Downloaded these plugins: .*external_fact/, result.stdout) unless agent['locale'] == 'ja' end end step "Ensure it resolves correctly" do on(agent, puppet('apply', '--pluginfactdest', pluginfactdest, '-e', "'notify { \"foo is ${foo}\": }'")) do |result| assert_match(/foo is bar/, result.stdout) end end # Linux specific tests next if agent['platform'] =~ /windows/ step "In Linux, ensure the pluginsync'ed external fact has the same permissions as its source" do on(agent, puppet('resource', "file '#{factsd}/unix_external_fact.sh'")) do |result| assert_match(/0755/, result.stdout) end end step "In Linux, ensure puppet apply uses the correct permissions" do test_source = File.join('/', 'tmp', 'test') on(agent, puppet('apply', "-e \"file { '#{test_source}': ensure => file, mode => '0456' }\"")) { 'source_permissions => use,' => /0456/, 'source_permissions => ignore,' => /0644/, '' => /0644/ }.each do |source_permissions, mode| on(agent, puppet('apply', "-e \"file { '/tmp/test_target': ensure => file, #{source_permissions} source => '#{test_source}' }\"")) on(agent, puppet('resource', "file /tmp/test_target")) do |result| assert_match(mode, result.stdout) end on(agent, "rm -f /tmp/test_target") end end end end end 4847_pluginfacts_should_be_resolvable_from_applications.rb000066400000000000000000000046161527241624000377270ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/pluginsynctest_name "Pluginsync'ed custom facts should be resolvable during application runs" do tag 'audit:high', 'audit:integration', 'shard:group2' # For splitting out groups of tests for slow test runners # # This test is intended to ensure that custom facts downloaded onto an agent via # pluginsync are resolvable by puppet applications besides agent/apply. # require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils tmp_environment = mk_tmp_environment_with_teardown(master, 'resolve') master_module_dir = "#{environmentpath}/#{tmp_environment}/modules/module_name" master_type_dir = "#{master_module_dir}/lib/puppet/type" master_module_type_file = "#{master_type_dir}/test4847.rb" master_provider_dir = "#{master_module_dir}/lib/puppet/provider/test4847" master_provider_file = "#{master_provider_dir}/only.rb" master_facter_dir = "#{master_module_dir}/lib/facter" master_facter_file = "#{master_facter_dir}/foo.rb" on(master, "mkdir -p '#{master_type_dir}' '#{master_provider_dir}' '#{master_facter_dir}'") teardown do on(master, "rm -rf '#{master_module_dir}'") # Remove all traces of the last used environment agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end test_type = <<-TYPE Puppet::Type.newtype(:test4847) do newparam(:name, :namevar => true) end TYPE create_remote_file(master, master_module_type_file, test_type) test_provider = <<-PROVIDER Puppet::Type.type(:test4847).provide(:only) do def self.instances warn "fact foo=\#{Facter.value('foo')}" [] end end PROVIDER create_remote_file(master, master_provider_file, test_provider) foo_fact_content = <<-FACT_FOO Facter.add('foo') do setcode do 'bar' end end FACT_FOO create_remote_file(master, master_facter_file, foo_fact_content) on(master, "chmod 755 '#{master_module_type_file}' '#{master_provider_file}' '#{master_facter_file}'") with_puppet_running_on(master, {}) do agents.each do |agent| on(agent, puppet("agent -t --environment #{tmp_environment}")) on(agent, puppet('resource test4847')) do |result| assert_match(/fact foo=bar/, result.stderr) end end end end 7316_apps_should_be_available_via_pluginsync.rb000066400000000000000000000074001527241624000354420ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/pluginsynctest_name 'the pluginsync functionality should sync app definitions, and they should be runnable afterwards' do tag 'audit:high', 'audit:integration', 'shard:group3' # For splitting out groups of tests for slow test runners # # This test is intended to ensure that pluginsync syncs app definitions to the agents. # Further, the apps should be runnable on the agent after the sync has occurred. # require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils tmp_environment = mk_tmp_environment_with_teardown(master, 'app') master_module_dir = "#{environmentpath}/#{tmp_environment}/modules" on(master, "mkdir -p '#{master_module_dir}'") teardown do on(master, "rm -rf '#{master_module_dir}'") # Remove all traces of the last used environment agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end app_name = "superbogus" app_desc = "a simple application for testing application delivery via plugin sync" app_output = "Hello from the #{app_name} application" master_module_file_content = <<-HERE require 'puppet/application' class Puppet::Application::#{app_name.capitalize} < Puppet::Application def help <<-HELP puppet-#{app_name}(8) -- #{app_desc} ======== HELP end def main() puts("#{app_output}") end end HERE # here we create a custom app, which basically doesn't do anything except # for print a hello-world message # master_module_app_path = "#{master_module_dir}/#{app_name}/lib/puppet/application" master_module_app_file = "#{master_module_app_path}/#{app_name}.rb" on(master, "mkdir -p '#{master_module_app_path}'") create_remote_file(master, master_module_app_file, master_module_file_content) on(master, "chmod 755 '#{master_module_app_file}'") step "start the master" do with_puppet_running_on(master, {}) do agents.each do |agent| agent_lib_dir = agent.tmpdir('agent_lib_sync') agent_module_app_file = "#{agent_lib_dir}/puppet/application/#{app_name}.rb" teardown do on(agent, "rm -rf '#{agent_lib_dir}'") end # the module files shouldn't exist on the agent yet because they haven't been synced step "verify that the module files don't exist on the agent path" do if file_exists?(agent, agent_module_app_file) fail_test("app file already exists on agent: '#{agent_module_app_file}'") end end step "run the agent" do on(agent, puppet("agent --libdir='#{agent_lib_dir}' --test --environment '#{tmp_environment}'")) do |result| refute_match( /The \`source_permissions\` parameter is deprecated/, result.stderr, "pluginsync should not get a deprecation warning for source_permissions") end end step "verify that the module files were synced down to the agent" do unless file_exists?(agent, agent_module_app_file) fail_test("The app file we expect was not not synced to agent: '#{agent_module_app_file}'") end end step "verify that the application shows up in help" do on(agent, PuppetCommand.new(:help, "--libdir='#{agent_lib_dir}'")) do |result| assert_match(/^\s+#{app_name}\s+#{app_desc}/, result.stdout) end end step "verify that we can run the application" do on(agent, PuppetCommand.new(:"#{app_name}", "--libdir='#{agent_lib_dir}'")) do |result| assert_match(/^#{app_output}/, result.stdout) end end end end end end 7316_faces_with_app_stubs_should_be_available_via_pluginsync.rb000066400000000000000000000140721527241624000406760ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/pluginsynctest_name "the pluginsync functionality should sync app definitions, and they should be runnable afterwards" tag 'audit:high', 'audit:integration', 'server', 'shard:group4' # For splitting out groups of tests for slow test runners # # This test is intended to ensure that pluginsync syncs face definitions to the agents. # Further, the face should be runnable on the agent after the sync has occurred. # # (NOTE: When this test is passing, it should resolve both #7316 re: verifying that apps/faces can # be run on the agent node after a plugin sync, and #6753 re: being able to run a face without # having a placeholder stub file in the "applications" directory.) # require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils initialize_temp_dirs() all_tests_passed = false ############################################################################### # BEGIN TEST LOGIC ############################################################################### # create some vars to point to the directories that we're going to point the master/agents at environments_dir = "environments" master_module_dir = "#{environments_dir}/production/modules" agent_lib_dir = "agent_lib" app_name = "superbogus" app_desc = "a simple %1$s for testing %1$s delivery via plugin sync" app_output = "Hello from the #{app_name} %s" master_module_face_content = <<-HERE Puppet::Face.define(:#{app_name}, '0.0.1') do copyright "Puppet Labs", 2011 license "Apache 2 license; see COPYING" summary "#{app_desc % "face"}" action(:foo) do summary "a test action defined in the test face in the main puppet lib dir" default when_invoked do |*args| puts "#{app_output % "face"}" end end end HERE master_module_app_content = <<-HERE require 'puppet/application/face_base' class Puppet::Application::#{app_name.capitalize} < Puppet::Application::FaceBase end HERE # this begin block is here for handling temp file cleanup via an "ensure" block # at the very end of the test. begin # here we create a custom app, which basically doesn't do anything except for # print a hello-world message agent_module_face_file = "#{agent_lib_dir}/puppet/face/#{app_name}.rb" master_module_face_file = "#{master_module_dir}/#{app_name}/lib/puppet/face/#{app_name}.rb" agent_module_app_file = "#{agent_lib_dir}/puppet/application/#{app_name}.rb" master_module_app_file = "#{master_module_dir}/#{app_name}/lib/puppet/application/#{app_name}.rb" # copy all the files to the master step "write our simple module out to the master" do create_test_file(master, master_module_app_file, master_module_app_content, :mkdirs => true) create_test_file(master, master_module_face_file, master_module_face_content, :mkdirs => true) end step "verify that the app file exists on the master" do unless test_file_exists?(master, master_module_app_file) then fail_test("Failed to create app file '#{get_test_file_path(master, master_module_app_file)}' on master") end unless test_file_exists?(master, master_module_face_file) then fail_test("Failed to create face file '#{get_test_file_path(master, master_module_face_file)}' on master") end end master_opts = { 'main' => { 'environmentpath' => "#{get_test_file_path(master, environments_dir)}", } } step "start the master" do with_puppet_running_on master, master_opts do # the module files shouldn't exist on the agent yet because they haven't been synced step "verify that the module files don't exist on the agent path" do agents.each do |agent| if test_file_exists?(agent, agent_module_app_file) then fail_test("app file already exists on agent: '#{get_test_file_path(agent, agent_module_app_file)}'") end if test_file_exists?(agent, agent_module_app_file) then fail_test("face file already exists on agent: '#{get_test_file_path(agent, agent_module_face_file)}'") end end end step "run the agent" do agents.each do |agent| on(agent, puppet('agent', "--libdir=\"#{get_test_file_path(agent, agent_lib_dir)}\" ", "--trace --test") ) end end end end step "verify that the module files were synced down to the agent" do agents.each do |agent| unless test_file_exists?(agent, agent_module_app_file) then fail_test("The app file we expected was not synced to the agent: '#{get_test_file_path(agent, agent_module_app_file)}'") end unless test_file_exists?(agent, agent_module_face_file) then fail_test("The face file we expected was not not synced to the agent: '#{get_test_file_path(agent, agent_module_face_file)}'") end end end step "verify that the application shows up in help" do agents.each do |agent| on(agent, PuppetCommand.new(:help, "--libdir=\"#{get_test_file_path(agent, agent_lib_dir)}\"")) do |result| assert_match(/^\s+#{app_name}\s+#{app_desc % "face"}/, result.stdout) end end end step "verify that we can run the application" do agents.each do |agent| on(agent, PuppetCommand.new(:"#{app_name}", "--libdir=\"#{get_test_file_path(agent, agent_lib_dir)}\"")) do |result| assert_match(/^#{app_output % "face"}/, result.stdout) end end end step "clear out the libdir on the agents in preparation for the next test" do agents.each do |agent| on(agent, "rm -rf #{get_test_file_path(agent, agent_lib_dir)}/*") end end all_tests_passed = true ensure ########################################################################################## # Clean up all of the temp files created by this test. It would be nice if this logic # could be handled outside of the test itself; I envision a stanza like this one appearing # in a very large number of the tests going forward unless it is handled by the framework. ########################################################################################## if all_tests_passed then remove_temp_dirs() end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/pluginsync/feature/000077500000000000000000000000001527241624000260455ustar00rootroot00000000000000pluginsync_should_sync_features.rb000066400000000000000000000172741527241624000350310ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/pluginsync/featuretest_name "the pluginsync functionality should sync feature and function definitions" do tag 'audit:high', 'audit:integration', 'shard:group1' # For splitting out groups of tests for slow test runners # # This test is intended to ensure that pluginsync syncs feature definitions to # the agents. It checks the feature twice; once to make sure that it gets # loaded successfully during the run in which it was synced, and once to ensure # that it still gets loaded successfully during the subsequent run (in which it # should not be synced because the files haven't changed.) # require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils teardown do agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end module_name = 'superbogus' tmp_environment = mk_tmp_environment_with_teardown(master, 'sync') master_module_dir = "#{environmentpath}/#{tmp_environment}/modules" master_module_type_path = "#{master_module_dir}/#{module_name}/lib/puppet/type/" master_module_feature_path = "#{master_module_dir}/#{module_name}/lib/puppet/feature" master_module_function_path = "#{master_module_dir}/#{module_name}/lib/puppet/functions" master_module_function_path_namespaced = "#{master_module_dir}/#{module_name}/lib/puppet/functions/superbogus" on(master, "mkdir -p '#{master_module_dir}'") on(master, "mkdir -p '#{master_module_type_path}' '#{master_module_feature_path}' '#{master_module_function_path}' #{master_module_function_path_namespaced}") master_module_type_file = "#{master_module_type_path}/#{module_name}.rb" master_module_type_content = <<-HERE module Puppet Type.newtype(:#{module_name}) do newparam(:name) do isnamevar end newproperty(:testfeature) do def sync Puppet.info("The value of the #{module_name} feature is: \#{Puppet.features.#{module_name}?}") end def retrieve :absent end def insync?(is) false end end end end HERE create_remote_file(master, master_module_type_file, master_module_type_content) master_module_feature_file = "#{master_module_feature_path}/#{module_name}.rb" master_module_feature_content = <<-HERE Puppet.features.add(:#{module_name}) do Puppet.info("#{module_name} feature being queried") true end HERE create_remote_file(master, master_module_feature_file, master_module_feature_content) on(master, "chmod 755 '#{master_module_type_file}' '#{master_module_feature_file}'") master_module_function_file = "#{master_module_function_path}/bogus_function.rb" master_module_function_content = <<-HERE Puppet::Functions.create_function(:bogus_function) do dispatch :bogus_function do end def bogus_function() three = call_function('round', 3.14) hostname = `facter hostname` "Three is \#{three}. bogus_function reporting hostname is \#{hostname}" end end HERE create_remote_file(master, master_module_function_file, master_module_function_content) on(master, "chmod 755 '#{master_module_function_file}' '#{master_module_function_file}'") master_module_namespaced_function_file = "#{master_module_function_path_namespaced}/bogus_function2.rb" master_module_namespaced_function_content = <<-HERE Puppet::Functions.create_function(:'superbogus::bogus_function2') do dispatch :bogus_function2 do end def bogus_function2() four = call_function('round', 4.14) hostname = `facter hostname` "Four is \#{four}. bogus_function reporting hostname is \#{hostname}" end end HERE create_remote_file(master, master_module_namespaced_function_file, master_module_namespaced_function_content) on(master, "chmod 755 '#{master_module_namespaced_function_file}'") site_pp = <<-HERE #{module_name} { "This is the title of the #{module_name} type instance in site.pp": testfeature => "Hi. I'm setting the testfeature property of #{module_name} here in site.pp", } notify { module_function: message => Deferred('bogus_function', []) } notify { module_function2: message => Deferred('superbogus::bogus_function2', []) } HERE create_sitepp(master, tmp_environment, site_pp) # These master opts should not be necessary whence content negotation for # Puppet 6.0.0 is completed, and this should just be removed. master_opts = { 'master' => { 'rich_data' => 'true' } } step 'start the master' do with_puppet_running_on(master, master_opts) do agents.each do |agent| agent_lib_dir = agent.tmpdir('libdir') agent_module_type_file = "#{agent_lib_dir}/puppet/type/#{module_name}.rb" agent_module_feature_file = "#{agent_lib_dir}/puppet/feature/#{module_name}.rb" agent_module_function_file = "#{agent_lib_dir}/puppet/functions/bogus_function.rb" agent_module_namespaced_function_file = "#{agent_lib_dir}/puppet/functions/superbogus/bogus_function2.rb" facter_hostname = fact_on(agent, 'hostname') step "verify that the module files don't exist on the agent path" do [agent_module_type_file, agent_module_feature_file, agent_module_function_file].each do |file_path| if file_exists?(agent, file_path) fail_test("file should not exist on the agent yet: '#{file_path}'") end end end step 'run the agent and verify that it loaded the feature' do on(agent, puppet("agent -t --libdir='#{agent_lib_dir}' --rich_data --environment '#{tmp_environment}'"), :acceptable_exit_codes => [2]) do |result| assert_match(/The value of the #{module_name} feature is: true/, result.stdout, "Expected agent stdout to include confirmation that the feature was 'true'") assert_match(/Three is 3. bogus_function reporting hostname is #{facter_hostname}/, result.stdout, "Expect the agent stdout to run bogus_function and report hostname") assert_match(/Four is 4. bogus_function reporting hostname is #{facter_hostname}/, result.stdout, "Expect the agent stdout to run bogus_function and report hostname") end end step 'verify that the module files were synced down to the agent' do [agent_module_type_file, agent_module_feature_file, agent_module_function_file, agent_module_namespaced_function_file].each do |file_path| unless file_exists?(agent, file_path) fail_test("Expected file to exist on the agent now: '#{file_path}'") end end end step 'run the agent again with a cached catalog' do on(agent, puppet("agent -t --libdir='#{agent_lib_dir}' --use_cached_catalog --rich_data --environment '#{tmp_environment}'"), :acceptable_exit_codes => [2]) do |result| assert_match(/The value of the #{module_name} feature is: true/, result.stdout, "Expected agent stdout to include confirmation that the feature was 'true'") assert_match(/Three is 3. bogus_function reporting hostname is #{facter_hostname}/, result.stdout, "Expect the agent stdout to run bogus_function and report hostname") assert_match(/Four is 4. bogus_function reporting hostname is #{facter_hostname}/, result.stdout, "Expect the agent stdout to run bogus_function and report hostname") end end end end end end files_earlier_in_modulepath_take_precendence.rb000066400000000000000000000033751527241624000357440ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/pluginsynctest_name "earlier modules take precendence over later modules in the modulepath" tag 'audit:high', 'audit:integration', 'server', 'shard:group2' # For splitting out groups of tests for slow test runners step "Create some modules in the modulepath" basedir = master.tmpdir("module_precedence") module_dir1 = "#{basedir}/environments/production/modules1" module_dir2 = "#{basedir}/modules2" modulepath = "#{module_dir1}:#{module_dir2}" modulepath << ":#{master['sitemoduledir']}" if master.is_pe? apply_manifest_on(master, < true) File { ensure => directory, mode => "0750", owner => #{master.puppet['user']}, group => #{master.puppet['group']}, } file { '#{basedir}':; '#{module_dir2}':; '#{module_dir2}/a':; '#{module_dir2}/a/lib':; '#{basedir}/environments':; '#{basedir}/environments/production':; '#{module_dir1}':; '#{module_dir1}/a':; '#{module_dir1}/a/lib':; } file { '#{basedir}/environments/production/environment.conf': ensure => file, content => "modulepath='#{modulepath}'", mode => "0640", } file { "mod1": ensure => file, path => "#{module_dir1}/a/lib/foo.rb", content => "'from the first module'", mode => "0640", } file { "mod2": ensure => file, path => "#{module_dir2}/a/lib/foo.rb", content => "'from the second module'", mode => "0640", } MANIFEST master_opts = { 'main' => { 'environmentpath' => "#{basedir}/environments", } } with_puppet_running_on master, master_opts, basedir do agents.each do |agent| on(agent, puppet('agent', "-t")) on(agent, "cat \"#{agent.puppet['vardir']}/lib/foo.rb\"") do |result| assert_match(/from the first module/, result.stdout, "The synced plugin was not found or the wrong version was synced") end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/000077500000000000000000000000001527241624000240515ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/000077500000000000000000000000001527241624000254445ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/apt_install_package_with_range.rb000066400000000000000000000037001527241624000341650ustar00rootroot00000000000000test_name "apt can install range if package is not installed" do confine :to, :platform => /debian|ubuntu/ tag 'audit:high', 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = "helloworld" available_package_versions = ['1.0-1', '1.19-1', '2.0-1'] repo_fixture_path = File.join(File.dirname(__FILE__), '..', '..', '..', 'fixtures', 'debian-repo') agents.each do |agent| scp_to(agent, repo_fixture_path, '/tmp') file_manifest = resource_manifest('file', '/etc/apt/sources.list.d/tmp.list', ensure: 'present', content: 'deb [trusted=yes] file:/tmp/debian-repo ./') apply_manifest_on(agent, file_manifest) on(agent, 'apt-get update') teardown do package_absent(agent, package, '--allow-downgrades') file_manifest = resource_manifest('file', '/etc/apt/sources.list.d/tmp.list', ensure: 'absent') apply_manifest_on(agent, file_manifest) on(agent, 'rm -rf /tmp/debian-repo') on(agent, 'apt-get update') end step "Ensure that package is installed first if not present" do package_manifest = resource_manifest('package', package, ensure: "<=#{available_package_versions[1]}") apply_manifest_on(agent, package_manifest) installed_package_version = on(agent.name, "apt-cache policy #{package} | sed -n -e 's/Installed: //p'").stdout assert_match(available_package_versions[1], installed_package_version) end step "Ensure that package is updated" do package_manifest = resource_manifest('package', package, ensure: ">#{available_package_versions[1]}") apply_manifest_on(agent, package_manifest) installed_package_version = on(agent.name, "apt-cache policy #{package} | sed -n -e 's/Installed: //p'").stdout assert_match(available_package_versions[2], installed_package_version) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/dnfmodule_enable_only.rb000066400000000000000000000040411527241624000323140ustar00rootroot00000000000000test_name "dnfmodule can change flavors" do confine :to, :platform => /el-8-x86_64/ # only el/centos 8 have the appstream repo tag 'audit:high', 'shard:group4' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils without_profile = '389-ds' with_profile = 'swig' agents.each do |agent| skip_test('appstream repo not present') unless on(agent, 'dnf repolist').stdout.include?('appstream') teardown do apply_manifest_on(agent, resource_manifest('package', without_profile, ensure: 'absent', provider: 'dnfmodule')) apply_manifest_on(agent, resource_manifest('package', with_profile, ensure: 'absent', provider: 'dnfmodule')) end end step "Enable module with no default profile: #{without_profile}" do apply_manifest_on(agent, resource_manifest('package', without_profile, ensure: 'present', provider: 'dnfmodule'), expect_changes: true) on(agent, "dnf module list --enabled | grep #{without_profile}") end step "Ensure idempotency for: #{without_profile}" do apply_manifest_on(agent, resource_manifest('package', without_profile, ensure: 'present', provider: 'dnfmodule'), catch_changes: true) end step "Enable module with a profile: #{with_profile}" do apply_manifest_on(agent, resource_manifest('package', with_profile, ensure: 'present', enable_only: true, provider: 'dnfmodule'), expect_changes: true) on(agent, "dnf module list --enabled | grep #{with_profile}") end step "Ensure idempotency for: #{with_profile}" do apply_manifest_on(agent, resource_manifest('package', with_profile, ensure: 'present', enable_only: true, provider: 'dnfmodule'), catch_changes: true) end step "Install a flavor for: #{with_profile}" do apply_manifest_on(agent, resource_manifest('package', with_profile, ensure: 'present', flavor: 'common', provider: 'dnfmodule'), expect_changes: true) on(agent, "dnf module list --installed | grep #{with_profile}") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/dnfmodule_ensure_versionable.rb000066400000000000000000000031571527241624000337260ustar00rootroot00000000000000test_name "dnfmodule is versionable" do confine :to, :platform => /el-8-x86_64/ # only el/centos 8 have the appstream repo tag 'audit:high', 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = "postgresql" agents.each do |agent| skip_test('appstream repo not present') unless on(agent, 'dnf repolist').stdout.include?('appstream') teardown do apply_manifest_on(agent, resource_manifest('package', package, ensure: 'absent', provider: 'dnfmodule')) end end step "Ensure we get the newer version by default" do apply_manifest_on(agent, resource_manifest('package', package, ensure: 'present', provider: 'dnfmodule')) on(agent, 'postgres --version') do |version| assert_match('postgres (PostgreSQL) 10', version.stdout, 'package version not correct') end end step "Ensure we get a specific version if we want it" do apply_manifest_on(agent, resource_manifest('package', package, ensure: '9.6', provider: 'dnfmodule')) on(agent, 'postgres --version') do |version| assert_match('postgres (PostgreSQL) 9.6', version.stdout, 'package version not correct') end end step "Ensure we can disable a package" do apply_manifest_on(agent, resource_manifest('package', package, ensure: :disabled, provider: 'dnfmodule')) on(agent, "dnf module list | grep #{package}") do |output| output.stdout.each_line do |line| assert_match("\[x\]", line, 'package not disabled') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/dnfmodule_manages_flavors.rb000066400000000000000000000025751527241624000332060ustar00rootroot00000000000000test_name "dnfmodule can change flavors" do confine :to, :platform => /el-8-x86_64/ # only el/centos 8 have the appstream repo tag 'audit:high', 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = "postgresql" agents.each do |agent| skip_test('appstream repo not present') unless on(agent, 'dnf repolist').stdout.include?('appstream') teardown do apply_manifest_on(agent, resource_manifest('package', package, ensure: 'absent', provider: 'dnfmodule')) end end step "Install the client #{package} flavor" do apply_manifest_on(agent, resource_manifest('package', package, ensure: 'present', flavor: 'client', provider: 'dnfmodule')) on(agent, "dnf module list --installed | grep #{package} | sed -E 's/\\[d\\] //g'") do |output| assert_match('client [i]', output.stdout, 'installed flavor not correct') end end step "Install the server #{package} flavor" do apply_manifest_on(agent, resource_manifest('package', package, ensure: 'present', flavor: 'server', provider: 'dnfmodule')) on(agent, "dnf module list --installed | grep #{package} | sed -E 's/\\[d\\] //g'") do |output| assert_match('server [i]', output.stdout, 'installed flavor not correct') end end end dpkg_ensure_latest_virtual_packages.rb000066400000000000000000000042131527241624000352000ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/packagetest_name "dpkg ensure latest with allow_virtual set to true, the virtual package should detect and install a real package" do confine :to, :platform => /debian/ tag 'audit:high', 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils pkg = "rubygems" agents.each do |agent| ruby_present = on(agent, 'dpkg -s ruby', accept_all_exit_codes: true).exit_code == 0 teardown do if ruby_present apply_manifest_on(agent, resource_manifest('package', 'ruby', ensure: 'present')) else apply_manifest_on(agent, resource_manifest('package', 'ruby', ensure: 'absent')) end end step "Uninstall system ruby if already present" do apply_manifest_on(agent, resource_manifest('package', 'ruby', ensure: 'absent')) if ruby_present end step "Ensure latest should install ruby instead of rubygems when allow_virtual is set to true" do package_manifest_with_allow_virtual = resource_manifest('package', pkg, ensure: 'latest', allow_virtual: true) apply_manifest_on(agent, package_manifest_with_allow_virtual, expect_changes: true) output = on(agent, "dpkg-query -W --showformat='${Status} ${Package} ${Version} [${Provides}]\n' ").output lines = output.split("\n") matched_line = lines.find { |package| package.match(/[\[ ](#{Regexp.escape(pkg)})[\],]/)} package_line_info = matched_line.split real_package_name = package_line_info[3] real_package_installed_version = package_line_info[4] installed_version = on(agent, "apt-cache policy #{real_package_name} | sed -n -e 's/Installed: //p'").stdout.strip assert_match(real_package_installed_version, installed_version) end step "Ensure latest should not install ruby package if it's already installed and exit code should be 0" do package_manifest_with_allow_virtual = resource_manifest('package', pkg, ensure: 'latest', allow_virtual: true) apply_manifest_on(agent, package_manifest_with_allow_virtual, :catch_changes => true) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/dpkg_hold_true_package_is_latest.rb000066400000000000000000000017421527241624000345110ustar00rootroot00000000000000test_name "dpkg ensure hold package is latest installed" do confine :to, :platform => /debian-9-amd64/ tag 'audit:high', 'shard:group4' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = "nginx" agents.each do |agent| teardown do package_absent(agent, package, '--allow-downgrades') end end step"Ensure that package is installed first if not present" do expected_package_version = on(agent.name, "apt-cache policy #{package} | sed -n -e 's/Candidate: //p'").stdout package_manifest = resource_manifest('package', package, mark: "hold") apply_manifest_on(agent, package_manifest) do |result| installed_package_version = on(agent.name, "apt-cache policy #{package} | sed -n -e 's/Installed: //p'").stdout assert_match(expected_package_version, installed_package_version) end end end dpkg_hold_true_should_preserve_version.rb000066400000000000000000000017201527241624000357420ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/packagetest_name "dpkg ensure hold package should preserve version if package is already installed" do confine :to, :platform => /debian-9-amd64/ tag 'audit:high', 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = "openssl" step "Ensure hold should lock to specific installed version" do existing_installed_version = on(agent.name, "dpkg -s #{package} | sed -n -e 's/Version: //p'").stdout existing_installed_version.delete!(' ') package_manifest_hold = resource_manifest('package', package, mark: "hold") apply_manifest_on(agent, package_manifest_hold) do installed_version = on(agent.name, "apt-cache policy #{package} | sed -n -e 's/Installed: //p'").stdout installed_version.delete!(' ') assert_match(existing_installed_version, installed_version) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/gem.rb000066400000000000000000000124161527241624000265450ustar00rootroot00000000000000test_name "gem provider should install and uninstall" do confine :to, :template => /centos-7-x86_64|redhat-7-x86_64/ tag 'audit:high', 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = 'colorize' agents.each do |agent| # On a Linux host with only the 'agent' role, the puppet command fails when another Ruby is installed earlier in the PATH: # # [root@agent ~]# env PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/opt/puppetlabs/bin" puppet apply -e ' notify { "Hello": }' # Activating bundler (2.0.2) failed: # Could not find 'bundler' (= 2.0.2) among 5 total gem(s) # To install the version of bundler this project requires, run `gem install bundler -v '2.0.2'` # # Magically, the puppet command succeeds on a Linux host with both the 'master' and 'agent' roles. # # Puppet's Ruby makes a fine target. Unfortunately, it's first in the PATH on Windows: PUP-6134. # Also, privatebindir isn't a directory on Windows, it's a PATH: # https://github.com/puppetlabs/beaker-puppet/blob/master/lib/beaker-puppet/install_utils/aio_defaults.rb # # These tests depend upon testing being confined to /centos-7-x86_64|redhat-7-x86_64/. if agent['roles'].include?('master') original_path = agent.get_env_var('PATH').split('=').last # https://github.com/puppetlabs/puppet-agent/blob/master/resources/files/puppet-agent.sh puppet_agent_sh_path = '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/opt/puppetlabs/bin' system_gem_command = '/usr/bin/gem' teardown do step "Teardown: Uninstall System Ruby, and reset PATH" do package_absent(agent, 'ruby') agent.clear_env_var('PATH') agent.add_env_var('PATH', original_path) end end step "Setup: Install System Ruby, and set PATH to place System Ruby ahead of Puppet Ruby" do package_present(agent, 'ruby') agent.add_env_var('PATH', puppet_agent_sh_path) end step "Install a gem package in System Ruby" do package_manifest = resource_manifest('package', package, { ensure: 'present', provider: 'gem' } ) apply_manifest_on(agent, package_manifest, :catch_failures => true) do list = on(agent, "#{system_gem_command} list").stdout assert_match(/#{package} \(/, list) end on(agent, "#{system_gem_command} uninstall #{package}") end step "Uninstall a gem package in System Ruby" do on(agent, "/usr/bin/gem install #{package}") package_manifest = resource_manifest('package', package, { ensure: 'absent', provider: 'gem' } ) apply_manifest_on(agent, package_manifest, :catch_failures => true) do list = on(agent, "#{system_gem_command} list").stdout refute_match(/#{package} \(/, list) end on(agent, "#{system_gem_command} uninstall #{package}") end step "Uninstall System Ruby, and reset PATH" do package_absent(agent, 'ruby') agent.add_env_var('PATH', original_path) end end puppet_gem_command = "#{agent['privatebindir']}/gem" step "Install a gem package with a target command" do package_manifest = resource_manifest('package', package, { ensure: 'present', provider: 'gem', command: puppet_gem_command } ) apply_manifest_on(agent, package_manifest, :catch_failures => true) do list = on(agent, "#{puppet_gem_command} list").stdout assert_match(/#{package} \(/, list) end on(agent, "#{puppet_gem_command} uninstall #{package}") end step "Install a gem package in a certain min max range" do package_manifest1 = resource_manifest('package', package, { ensure: '>0.5 <0.7', provider: 'gem' } ) package_manifest2 = resource_manifest('package', package, { ensure: '>0.7 <0.8.1', provider: 'gem' } ) # Install package (with version between 0.5 and 0.7) apply_manifest_on(agent, package_manifest1, :expect_changes => true) do list = on(agent, "#{puppet_gem_command} list").stdout assert_match(/#{package} \((0.6.0)\)/, list) end # Reapply same manifest and expect no changes apply_manifest_on(agent, package_manifest1, :catch_changes => true) # Install besides existing package (with version between 0.7 and 0.8.1) and expect changes apply_manifest_on(agent, package_manifest2, :expect_changes => true) do list = on(agent, "#{puppet_gem_command} list").stdout assert_match(/#{package} \((0.8.0, 0.6.0)\)/, list) end on(agent, "#{puppet_gem_command} uninstall #{package} --all") end step "Uninstall a gem package with a target command" do on(agent, "#{puppet_gem_command} install #{package}") package_manifest = resource_manifest('package', package, { ensure: 'absent', provider: 'gem', command: puppet_gem_command } ) apply_manifest_on(agent, package_manifest, :catch_failures => true) do list = on(agent, "#{puppet_gem_command} list").stdout refute_match(/#{package} \(/, list) end on(agent, "#{puppet_gem_command} uninstall #{package}") end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/pip.rb000066400000000000000000000072611527241624000265670ustar00rootroot00000000000000test_name "pip provider should install, use install_options with latest, and uninstall" do confine :to, :template => /centos/ tag 'audit:high', 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = 'colorize' pip_command = 'pip' teardown do on(agent, "#{pip_command} uninstall #{package} --disable-pip-version-check --yes", :accept_all_exit_codes => true) end agents.each do |agent| step "Setup: Install EPEL Repository, Python and Pip" do package_present(agent, 'epel-release') if agent.platform =~ /el-8/ package_present(agent, 'python2') package_present(agent, 'python2-pip') pip_command = 'pip2' else package_present(agent, 'python') package_present(agent, 'python-pip') end end step "Ensure presence of a pip package" do package_manifest = resource_manifest('package', package, { ensure: 'present', provider: 'pip' } ) apply_manifest_on(agent, package_manifest, :catch_failures => true) do list = on(agent, "#{pip_command} list --disable-pip-version-check").stdout assert_match(/#{package} \(/, list) end on(agent, "#{pip_command} uninstall #{package} --disable-pip-version-check --yes") end step "Install a pip package using version range" do package_manifest1 = resource_manifest('package', package, { ensure: '<=1.1.0', provider: 'pip' } ) package_manifest2 = resource_manifest('package', package, { ensure: '<1.0.4', provider: 'pip' } ) # Make a fresh package install (with version lower than or equal to 1.1.0) apply_manifest_on(agent, package_manifest1, :expect_changes => true) do list = on(agent, "#{pip_command} list --disable-pip-version-check").stdout match = list.match(/#{package} \((.+)\)/) installed_version = match[1] if match assert_match(installed_version, '1.1.0') end # Reapply same manifest and expect no changes apply_manifest_on(agent, package_manifest1, :catch_changes => true) # Reinstall over existing package (with version lower than 1.0.4) and expect changes (to be 1.0.3) apply_manifest_on(agent, package_manifest2, :expect_changes => true) do list = on(agent, "#{pip_command} list --disable-pip-version-check").stdout match = list.match(/#{package} \((.+)\)/) installed_version = match[1] if match assert_match(installed_version, '1.0.3') end on(agent, "#{pip_command} uninstall #{package} --disable-pip-version-check --yes") end step "Ensure latest with pip uses install_options" do on(agent, "#{pip_command} install #{package} --disable-pip-version-check") package_manifest = resource_manifest('package', package, { ensure: 'latest', provider: 'pip', install_options: { '--index' => 'https://pypi.python.org/simple' } } ) result = apply_manifest_on(agent, package_manifest, { :catch_failures => true, :debug => true } ) assert_match(/--index=https:\/\/pypi.python.org\/simple/, result.stdout) on(agent, "#{pip_command} uninstall #{package} --disable-pip-version-check --yes") end step "Uninstall a pip package" do on(agent, "#{pip_command} install #{package} --disable-pip-version-check") package_manifest = resource_manifest('package', package, { ensure: 'absent', provider: 'pip' } ) apply_manifest_on(agent, package_manifest, :catch_failures => true) do list = on(agent, "#{pip_command} list --disable-pip-version-check").stdout refute_match(/#{package} \(/, list) end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/puppetserver_gem.rb000066400000000000000000000030041527241624000313620ustar00rootroot00000000000000test_name "puppetserver_gem provider should install and uninstall" do tag 'audit:high', 'server', 'shard:group4' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils skip_test 'puppetserver_gem is only suitable on server nodes' unless master skip_test 'the puppetserver_gem provider is not functional in FIPS mode' if master.fips_mode? package = 'world_airports' teardown do # Ensure the gem is uninstalled if anything goes wrong # TODO maybe execute this only if something fails, as it takes time on(master, "puppetserver gem uninstall #{package}") end step "Installing a gem executes without error" do package_manifest = resource_manifest('package', package, { ensure: 'present', provider: 'puppetserver_gem' } ) apply_manifest_on(master, package_manifest, catch_failures: true) do list = on(master, "puppetserver gem list").stdout assert_match(/#{package} \(/, list) end # Run again for idempotency apply_manifest_on(master, package_manifest, catch_changes: true) end step "Uninstalling a gem executes without error" do package_manifest = resource_manifest('package', package, { ensure: 'absent', provider: 'puppetserver_gem' } ) apply_manifest_on(master, package_manifest, catch_failures: true) do list = on(master, "puppetserver gem list").stdout refute_match(/#{package} \(/, list) end end end rpm_ensure_install_multiversion_package.rb000066400000000000000000000076601527241624000361230ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/packagetest_name "rpm should install packages with multiple versions" do confine :to, :platform => /redhat|centos|el|fedora/ tag 'audit:high', 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = "kernel-devel-puppet" repo_fixture_path = File.join(File.dirname(__FILE__), '..', '..', '..', 'fixtures', 'el-repo') repo_content = <<-REPO [local] name=EL-releasever - test packages baseurl=file:///tmp/el-repo enabled=1 gpgcheck=0 protect=1 REPO agents.each do |agent| initially_installed_versions = [] scp_to(agent, repo_fixture_path, '/tmp') file_manifest = resource_manifest('file', '/etc/yum.repos.d/local.repo', ensure: 'present', content: repo_content) apply_manifest_on(agent, file_manifest) teardown do on(agent, 'rm -rf /tmp/el-repo') on(agent, 'rm -f /etc/yum.repos.d/local.repo') available_versions = on(agent, "yum --showduplicates list #{package} | sed -e '1,/Available Packages/ d' | awk '{print $2}'").stdout initially_installed_versions.each do |version| if available_versions.include? version package_manifest = resource_manifest('package', package, ensure: version, install_only: true) apply_manifest_on(agent, package_manifest, :catch_failures => true) end end end step "Uninstall package versions for clean setup" do initially_installed_versions = on(agent, "yum --showduplicates list #{package} | sed -e '1,/Installed Packages/ d' -e '/Available Packages/,$ d' | awk '{print $2}'").stdout.split("\n") package_manifest = resource_manifest('package', package, ensure: 'absent', install_only: true) apply_manifest_on(agent, package_manifest, :catch_failures => true) do remaining_installed_versions = on(agent, "yum --showduplicates list #{package} | sed -e '1,/Installed Packages/ d' -e '/Available Packages/,$ d' | awk '{print $2}'").stdout assert(remaining_installed_versions.empty?) end available_versions = on(agent, "yum --showduplicates list #{package} | sed -e '1,/Available Packages/ d' | awk '{print $2}'").stdout.split("\n") if available_versions.size < 2 skip_test "we need at least two package versions to perform the multiversion rpm test" end end step "Ensure oldest version of multiversion package is installed" do oldest_version = on(agent, "yum --showduplicates list #{package} | sed -e '1,/Available Packages/ d' | head -1 | awk '{print $2}'").stdout.strip package_manifest = resource_manifest('package', package, ensure: oldest_version, install_only: true) apply_manifest_on(agent, package_manifest, :catch_failures => true) do installed_version = on(agent, "rpm -q #{package}").stdout assert_match(oldest_version, installed_version) end end step "Ensure newest package multiversion package in installed" do newest_version = on(agent, "yum --showduplicates list #{package} | sed -e '1,/Available Packages/ d' | tail -1 | awk '{print $2}'").stdout.strip package_manifest = resource_manifest('package', package, ensure: newest_version, install_only: true) apply_manifest_on(agent, package_manifest, :catch_failures => true) do installed_version = on(agent, "rpm -q #{package}").stdout assert_match(newest_version, installed_version) end end step "Ensure rpm will uninstall multiversion package" do package_manifest = resource_manifest('package', package, ensure: 'absent', install_only: true) apply_manifest_on(agent, package_manifest, :catch_failures => true) do remaining_installed_versions = on(agent, "yum --showduplicates list #{package} | sed -e '1,/Installed Packages/ d' -e '/Available Packages/,$ d' | awk '{print $2}'").stdout assert(remaining_installed_versions.empty?) end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/provider/package/yum_semantic_versioning.rb000066400000000000000000000061641527241624000327400ustar00rootroot00000000000000test_name "yum provider should use semantic versioning for ensuring desired version" do confine :to, :platform => /el-7/ tag 'audit:high', 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = 'yum-utils' lower_package_version = '1.1.31-34.el7' middle_package_version = '1.1.31-42.el7' higher_package_version = '1.1.31-45.el7' agents.each do |agent| yum_command = 'yum' step "Setup: Skip test if box already has the package installed" do on(agent, "rpm -q #{package}", :acceptable_exit_codes => [1,0]) do |result| skip_test "package #{package} already installed on this box" unless result.output =~ /package #{package} is not installed/ end end step "Setup: Skip test if package versions are not available" do on(agent, "yum list #{package} --showduplicates", :acceptable_exit_codes => [1,0]) do |result| versions_available = [lower_package_version, middle_package_version, higher_package_version].all? { |needed_versions| result.output.include? needed_versions } skip_test "package #{package} versions not available on the box" unless versions_available end end step "Using semantic versioning to downgrade to a desired version <= X" do on(agent, "#{yum_command} install #{package} -y") package_manifest = resource_manifest('package', package, { ensure: "<=#{lower_package_version}", provider: 'yum' } ) apply_manifest_on(agent, package_manifest, :catch_failures => true) do installed_version = on(agent, "rpm -q #{package}").stdout assert_match(/#{lower_package_version}/, installed_version) end # idempotency test package_manifest = resource_manifest('package', package, { ensure: "<=#{lower_package_version}", provider: 'yum' } ) apply_manifest_on(agent, package_manifest, :catch_changes => true) on(agent, "#{yum_command} remove #{package} -y") end step "Using semantic versioning to ensure a version >X <=Y" do on(agent, "#{yum_command} install #{package} -y") package_manifest = resource_manifest('package', package, { ensure: ">#{lower_package_version} <=#{higher_package_version}", provider: 'yum' } ) apply_manifest_on(agent, package_manifest) do installed_version = on(agent, "rpm -q #{package}").stdout assert_match(/#{higher_package_version}/, installed_version) end on(agent, "#{yum_command} remove #{package} -y") end step "Using semantic versioning to install a version >X #{lower_package_version} <#{higher_package_version}", provider: 'yum' } ) # installing a version >X /sles/ tag 'audit:high', 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::PackageUtils extend Puppet::Acceptance::ManifestUtils package = "helloworld" available_package_versions = ['1.0-2', '1.19-2', '2.0-2'] repo_fixture_path = File.join(File.dirname(__FILE__), '..', '..', '..', 'fixtures', 'sles-repo') repo_content = <<-REPO [local] name=local - test packages baseurl=file:///tmp/sles-repo enabled=1 gpgcheck=0 REPO agents.each do |agent| scp_to(agent, repo_fixture_path, '/tmp') file_manifest = resource_manifest('file', '/etc/zypp/repos.d/local.repo', ensure: 'present', content: repo_content) apply_manifest_on(agent, file_manifest) teardown do package_absent(agent, package, '--force-yes') file_manifest = resource_manifest('file', '/etc/zypp/repos.d/local.repo', ensure: 'absent') apply_manifest_on(agent, file_manifest) on(agent, 'rm -rf /tmp/sles-repo') end step "Ensure that package is installed first if not present" do package_manifest = resource_manifest('package', package, ensure: "<=#{available_package_versions[1]}") apply_manifest_on(agent, package_manifest) installed_package_version = on(agent, "rpm -q #{package}").stdout assert_match(available_package_versions[1], installed_package_version) end step "Ensure that package is updated" do package_manifest = resource_manifest('package', package, ensure: ">#{available_package_versions[1]}") apply_manifest_on(agent, package_manifest) installed_package_version = on(agent, "rpm -q #{package}").stdout assert_match(available_package_versions[2], installed_package_version) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/r10k.rb000066400000000000000000000024131527241624000233210ustar00rootroot00000000000000# This test ONLY checks if r10k is executable without gem version conflicts, # due to running into problems here with gem version bumps in puppet-runtime. # It does not test r10k functionality itself. test_name 'Can install and execute r10k with no gem conflicts' tag 'shard:group4' # On pre-8.23.0, we already had fast_gettext installed to the # /opt/puppetlabs/puppet/lib/ruby/vendor_gems/gems directory, so # when r10k was installed, it would not install fast_gettext to # /opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems. Then, upon agent # upgrade, that version in vendor_gems was replaced with 4.1.0 and # since r10k has a dependency on gettext-setup which pins # fast_gettext to ~> 2.1, it would fail. Below simulates # this condition by removing any fast_gettext installed automatically # via 'gem install r10k'. # # To test this more robustly, we'll want to implement this test in an upgrade # test suite instead. on(master, '/opt/puppetlabs/puppet/bin/gem install r10k') on(master, 'rm -rf "/opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/gems/fast_gettext*"') on(master, 'rm -f /opt/puppetlabs/puppet/lib/ruby/gems/3.2.0/specifications/fast_gettext*.gemspec') on(master, '/opt/puppetlabs/puppet/bin/r10k') teardown { on(master, '/opt/puppetlabs/puppet/bin/gem uninstall -ax r10k') } OpenVoxProject-openvox-ebcec1e/acceptance/tests/reports/000077500000000000000000000000001527241624000237155ustar00rootroot00000000000000agent_sends_json_report_for_cached_catalog.rb000066400000000000000000000021161527241624000347300ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/reportstest_name "C100533: Agent sends json report for cached catalog" do tag 'risk:high', 'audit:high', 'audit:integration', 'server', 'shard:group1' # For splitting out groups of tests for slow test runners with_puppet_running_on(master, :main => {}) do expected_format = 'json' step "Perform agent run to ensure that catalog is cached" do agents.each do |agent| on(agent, puppet('agent', '-t'), :acceptable_exit_codes => [0,2]) end end step "Ensure agent sends #{expected_format} report for cached catalog" do agents.each do |agent| on(agent, puppet('agent', '-t', '--http_debug'), :acceptable_exit_codes => [0,2]) do |res| # Expected content-type should be in the headers of the # HTTP report payload being PUT to the server by the agent. unless res.stderr =~ /<- "PUT \/puppet\/v[3-9]\/report.*Content-Type: .*\/#{expected_format}/ fail_test("Report was not submitted in #{expected_format} format") end end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/reports/cached_catalog_status_in_report.rb000066400000000000000000000047311527241624000326340ustar00rootroot00000000000000test_name "PUP-5867: The report specifies whether a cached catalog was used, and if so, why" do tag 'audit:high', 'audit:integration', 'server', 'shard:group2' # For splitting out groups of tests for slow test runners master_reportdir = create_tmpdir_for_user(master, 'report_dir') teardown do on(master, "rm -rf #{master_reportdir}") end def remove_reports_on_master(master_reportdir, agent_node_name) on(master, "rm -rf #{master_reportdir}/#{agent_node_name}/*") end with_puppet_running_on(master, :master => { :reportdir => master_reportdir, :reports => 'store' }) do agents.each do |agent| step "cached_catalog_status should be 'not used' when a new catalog is retrieved" do step "Initial run: cache a newly retrieved catalog" do on(agent, puppet("agent", "-t"), :acceptable_exit_codes => [0,2]) end step "Run again and ensure report indicates that the cached catalog was not used" do on(agent, puppet("agent", "--onetime", "--no-daemonize"), :acceptable_exit_codes => [0, 2]) on(master, "cat #{master_reportdir}/#{agent.node_name}/*") do |result| assert_match(/cached_catalog_status: not_used/, result.stdout, "expected to find 'cached_catalog_status: not_used' in the report") end remove_reports_on_master(master_reportdir, agent.node_name) end end step "Run with --use_cached_catalog and ensure report indicates cached catalog was explicitly requested" do on(agent, puppet("agent", "--onetime", "--no-daemonize", "--use_cached_catalog"), :acceptable_exit_codes => [0, 2]) on(master, "cat #{master_reportdir}/#{agent.node_name}/*") do |result| assert_match(/cached_catalog_status: explicitly_requested/, result.stdout, "expected to find 'cached_catalog_status: explicitly_requested' in the report") end remove_reports_on_master(master_reportdir, agent.node_name) end step "On a run which fails to retrieve a new catalog, ensure report indicates cached catalog was used on failure" do on(agent, puppet("agent", "--onetime", "--no-daemonize", "--report_server #{master}", "--server nonexist"), :acceptable_exit_codes => [0, 2]) on(master, "cat #{master_reportdir}/#{agent.node_name}/*") do |result| assert_match(/cached_catalog_status: on_failure/, result.stdout, "expected to find 'cached_catalog_status: on_failure' in the report") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/reports/corrective_change_new_resource.rb000066400000000000000000000065551527241624000325070ustar00rootroot00000000000000test_name "C98092 - a new resource should not be reported as a corrective change" do require 'yaml' require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/agent_fqdn_utils' extend Puppet::Acceptance::AgentFqdnUtils tag 'audit:high', 'audit:integration', 'audit:refactor', # Uses a server currently but is testing agent report 'broken:images', 'shard:group3' # For splitting out groups of tests for slow test runners test_file_name = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, test_file_name) tmp_file = {} agents.each do |agent| tmp_file[agent_to_fqdn(agent)] = agent.tmpfile(tmp_environment) end teardown do step 'clean out produced resources' do agents.each do |agent| if tmp_file.has_key?(agent_to_fqdn(agent)) && tmp_file[agent_to_fqdn(agent)] != '' on(agent, "rm '#{tmp_file[agent_to_fqdn(agent)]}'", :accept_all_exit_codes => true) end on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end end step 'create file resource - site.pp to verify corrective change flag' do file_contents = 'this is a test' manifest = <<-MANIFEST file { '#{environmentpath}/#{tmp_environment}/manifests/site.pp': ensure => file, content => ' \$test_path = \$facts["networking"]["fqdn"] ? #{tmp_file} file { \$test_path: content => @(UTF8) #{file_contents} | UTF8 } ', } MANIFEST apply_manifest_on(master, manifest, :catch_failures => true) end step 'run agent(s)' do with_puppet_running_on(master, {}) do agents.each do |agent| #Run agent once to create new File resource step 'Run agent once to create new File resource' do on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :acceptable_exit_codes => 2) end #Verify the file resource is created step 'Verify the file resource is created' do on(agent, "cat '#{tmp_file[agent_to_fqdn(agent)]}'").stdout do |file_result| assert_equal(file_contents, file_result, 'file contents did not match accepted') end end end end end # Open last_run_report.yaml step 'Check report' do agents.each do |agent| on(agent, puppet('config print statedir')) do |command_result| report_path = command_result.stdout.chomp + '/last_run_report.yaml' on(agent, "cat '#{report_path}'").stdout do |report_contents| yaml_data = YAML::parse(report_contents) # Remove any Ruby class tags from the yaml yaml_data.root.each do |o| if o.respond_to?(:tag=) and o.tag != nil and o.tag.start_with?("!ruby") o.tag = nil end end report_yaml = yaml_data.to_ruby file_resource_details = report_yaml["resource_statuses"]["File[#{tmp_file[agent_to_fqdn(agent)]}]"] assert(file_resource_details.has_key?("corrective_change"), 'corrective_change key is missing') corrective_change_value = file_resource_details["corrective_change"] assert_equal(false, corrective_change_value, 'corrective_change flag should be false') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/reports/corrective_change_outside_puppet.rb000066400000000000000000000101111527241624000330370ustar00rootroot00000000000000test_name "C98093 - a resource changed outside of Puppet will be reported as a corrective change" do require 'yaml' require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/agent_fqdn_utils' extend Puppet::Acceptance::AgentFqdnUtils tag 'audit:high', 'audit:integration', 'audit:refactor', # Uses a server currently, but is testing agent report 'broken:images', 'shard:group4' # For splitting out groups of tests for slow test runners test_file_name = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, test_file_name) tmp_file = {} agents.each do |agent| tmp_file[agent_to_fqdn(agent)] = agent.tmpfile(tmp_environment) end teardown do step 'clean out produced resources' do agents.each do |agent| if tmp_file.has_key?(agent_to_fqdn(agent)) && tmp_file[agent_to_fqdn(agent)] != '' on(agent, "rm '#{tmp_file[agent_to_fqdn(agent)]}'", :accept_all_exit_codes => true) end on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end end step 'create file resource - site.pp to verify corrective change flag' do file_contents = 'this is a test' manifest = <<-MANIFEST file { '#{environmentpath}/#{tmp_environment}/manifests/site.pp': ensure => file, content => ' \$test_path = \$facts["networking"]["fqdn"] ? #{tmp_file} file { \$test_path: content => @(UTF8) #{file_contents} | UTF8 } ', } MANIFEST apply_manifest_on(master, manifest, :catch_failures => true) end step 'run agent(s)' do with_puppet_running_on(master, {}) do agents.each do |agent| #Run agent once to create new File resource step 'Run agent once to create new File resource' do on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :acceptable_exit_codes => 2) end #Verify the file resource is created step 'Verify the file resource is created' do on(agent, "cat '#{tmp_file[agent_to_fqdn(agent)]}'").stdout do |file_result| assert_equal(file_contents, file_result, 'file contents did not match accepted') end end #Delete the file step 'Delete the file' do on(agent, "rm '#{tmp_file[agent_to_fqdn(agent)]}'", :accept_all_exit_codes => true) end #Run agent to correct the file's absence step 'Run agent to correct the files absence' do on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :acceptable_exit_codes => 2) end #Verify the file resource is created step 'Verify the file resource is created' do on(agent, "cat '#{tmp_file[agent_to_fqdn(agent)]}'").stdout do |file_result| assert_equal(file_contents, file_result, 'file contents did not match accepted') end end end end end # Open last_run_report.yaml step 'Check report' do agents.each do |agent| on(agent, puppet('config print statedir')) do |command_result| report_path = command_result.stdout.chomp + '/last_run_report.yaml' on(agent, "cat '#{report_path}'").stdout do |report_contents| yaml_data = YAML::parse(report_contents) # Remove any Ruby class tags from the yaml yaml_data.root.each do |o| if o.respond_to?(:tag=) and o.tag != nil and o.tag.start_with?("!ruby") o.tag = nil end end report_yaml = yaml_data.to_ruby file_resource_details = report_yaml["resource_statuses"]["File[#{tmp_file[agent_to_fqdn(agent)]}]"] assert(file_resource_details.has_key?("corrective_change"), 'corrective_change key is missing') corrective_change_value = file_resource_details["corrective_change"] assert_equal(true, corrective_change_value, 'corrective_change flag should be true') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/reports/corrective_change_via_puppet.rb000066400000000000000000000105301527241624000321470ustar00rootroot00000000000000test_name "C98094 - a resource changed via Puppet manifest will not be reported as a corrective change" do require 'yaml' require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/agent_fqdn_utils' extend Puppet::Acceptance::AgentFqdnUtils tag 'audit:high', 'audit:integration', 'audit:refactor', # Uses a server currently, but is testing agent report 'broken:images', 'server', 'shard:group1' # For splitting out groups of tests for slow test runners test_file_name = File.basename(__FILE__, '.*') tmp_environment = mk_tmp_environment_with_teardown(master, test_file_name) tmp_file = {} original_test_data = 'this is my original important data' modified_test_data = 'this is my modified important data' agents.each do |agent| tmp_file[agent_to_fqdn(agent)] = agent.tmpfile(tmp_environment) end teardown do # Remove all traces of the last used environment agents.each do |agent| on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end step 'clean out produced resources' do agents.each do |agent| if tmp_file.has_key?(agent_to_fqdn(agent)) && tmp_file[agent_to_fqdn(agent)] != '' on(agent, "rm '#{tmp_file[agent_to_fqdn(agent)]}'", :accept_all_exit_codes => true) end end end end def create_manifest_for_file_resource(file_resource, file_contents, environment_name) manifest = <<-MANIFEST file { '#{environmentpath}/#{environment_name}/manifests/site.pp': ensure => file, content => ' \$test_path = \$facts["networking"]["fqdn"] ? #{file_resource} file { \$test_path: content => @(UTF8) #{file_contents} | UTF8 } ', } MANIFEST apply_manifest_on(master, manifest, :catch_failures => true) end step 'create file resource in site.pp' do create_manifest_for_file_resource(tmp_file, original_test_data, tmp_environment) end step 'run agent(s) to create the new resource' do with_puppet_running_on(master, {}) do agents.each do |agent| step 'Run agent once to create new File resource' do on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :acceptable_exit_codes => 2) end step 'Verify the file resource is created' do on(agent, "cat '#{tmp_file[agent_to_fqdn(agent)]}'").stdout do |file_contents| assert_equal(original_test_data, file_contents, 'file contents did not match expected contents') end end end step 'Change the manifest for the resource' do create_manifest_for_file_resource(tmp_file, modified_test_data, tmp_environment) end agents.each do |agent| step 'Run agent a 2nd time to change the File resource' do on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :acceptable_exit_codes => 2) end step 'Verify the file resource is created' do on(agent, "cat '#{tmp_file[agent_to_fqdn(agent)]}'").stdout do |file_contents| assert_equal(modified_test_data, file_contents, 'file contents did not match expected contents') end end end end end # Open last_run_report.yaml step 'Check report' do agents.each do |agent| on(agent, puppet('config print statedir')) do |command_result| report_path = command_result.stdout.chomp + '/last_run_report.yaml' on(agent, "cat '#{report_path}'").stdout do |report_contents| yaml_data = YAML::parse(report_contents) # Remove any Ruby class tags from the yaml yaml_data.root.each do |o| if o.respond_to?(:tag=) and o.tag != nil and o.tag.start_with?("!ruby") o.tag = nil end end report_yaml = yaml_data.to_ruby file_resource_details = report_yaml["resource_statuses"]["File[#{tmp_file[agent_to_fqdn(agent)]}]"] assert(file_resource_details.has_key?("corrective_change"), 'corrective_change key is missing') corrective_change_value = file_resource_details["corrective_change"] assert_equal(false, corrective_change_value, 'corrective_change flag for the changed resource should be false') end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/reports/submission.rb000066400000000000000000000043041527241624000264360ustar00rootroot00000000000000test_name "Report submission" tag 'audit:high', 'audit:integration', 'shard:group2' # For splitting out groups of tests for slow test runners if master.is_pe? require "time" def puppetdb hosts.detect { |h| h['roles'].include?('database') } end def sleep_until_queue_empty(timeout=60) metric = "org.apache.activemq:BrokerName=localhost,Type=Queue,Destination=com.puppetlabs.puppetdb.commands" queue_size = nil begin Timeout.timeout(timeout) do until queue_size == 0 result = on(puppetdb, %Q{curl http://localhost:8080/v3/metrics/mbean/#{CGI.escape(metric)}}) if md = /"?QueueSize"?\s*:\s*(\d+)/.match(result.stdout.chomp) queue_size = Integer(md[1]) end sleep 1 end end rescue Timeout::Error raise "Queue took longer than allowed #{timeout} seconds to empty" end end def query_last_report_time_on(agent) time_query_script = <<-EOS require "net/http" require "json" puppetdb_url = URI("http://localhost:8080/v3/reports") puppetdb_url.query = CGI.escape(%Q{query=["=","certname","#{agent}"]}) result = Net::HTTP.get(puppetdb_url) json = JSON.load(result) puts json.first["receive-time"] EOS on(puppetdb, "#{master[:privatebindir]}/ruby -e '#{time_query_script}'").output.chomp end last_times = {} agents.each do |agent| last_times[agent] = query_last_report_time_on(agent) end with_puppet_running_on(master, {}) do agents.each do |agent| on(agent, puppet('agent', "-t")) sleep_until_queue_empty current_time = Time.parse(query_last_report_time_on(agent)) last_time = Time.parse(last_times[agent]) assert(current_time > last_time, "Most recent report time #{current_time} is not newer than last report time #{last_time}") end end else testdir = create_tmpdir_for_user master, 'report_submission' teardown do on master, "rm -rf #{testdir}" end with_puppet_running_on(master, :main => { :reportdir => testdir, :reports => 'store' }) do agents.each do |agent| on(agent, puppet('agent', "-t")) on master, "grep -q #{agent.node_name} #{testdir}/*/*" end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/000077500000000000000000000000001527241624000240465ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/000077500000000000000000000000001527241624000247725ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/accept_array_commands.rb000066400000000000000000000012051527241624000316330ustar00rootroot00000000000000test_name "Be able to execute array commands" do tag 'audit:high', 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners agents.each do |agent| if agent.platform =~ /windows/ cmd = ['C:\Windows\System32\cmd.exe', '/c', 'echo', '*'] else cmd = ['/bin/echo', '*'] end exec_manifest = <<~MANIFEST exec { "test exec": command => #{cmd}, logoutput => true, } MANIFEST apply_manifest_on(agent, exec_manifest) do |output| assert_match('Notice: /Stage[main]/Main/Exec[test exec]/returns: *', output.stdout) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/accept_multi-line_commands.rb000066400000000000000000000015121527241624000325750ustar00rootroot00000000000000test_name "Be able to execute multi-line commands (#9996)" confine :except, :platform => 'windows' tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group4' # For splitting out groups of tests for slow test runners agents.each do |agent| temp_file_name = agent.tmpfile('9996-multi-line-commands') test_manifest = < "/bin/echo '#Test' > #{temp_file_name}; /bin/echo 'bob' >> #{temp_file_name};" } HERE expected_results = <64KB file to exceed pipe buffer. lorem_ipsum = < ['/bin', '/usr/bin', 'C:/cygwin32/bin', 'C:/cygwin64/bin', 'C:/cygwin/bin'], logoutput => true}") do |result| fail_test "didn't seem to run the command" unless result.stdout.include? 'executed successfully' unless agent['locale'] == 'ja' fail_test "didn't print output correctly" unless result.stdout.lines.select {|line| line =~ /\/returns:/}.count == 4097 end apply_manifest_on(agent, "exec {'echo': path => ['/bin', '/usr/bin', 'C:/cygwin32/bin', 'C:/cygwin64/bin', 'C:/cygwin/bin'], logoutput => true}") do |result| fail_test "didn't seem to run the command" unless result.stdout.include? 'executed successfully' unless agent['locale'] == 'ja' end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/should_not_run_command_creates.rb000066400000000000000000000026361527241624000335740ustar00rootroot00000000000000test_name "should not run command creates" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group2' # For splitting out groups of tests for slow test runners agents.each do |agent| touch = agent.tmpfile('touched') donottouch = agent.tmpfile('not-touched') manifest = %Q{ exec { "test#{Time.new.to_i}": command => '#{agent.touch(donottouch)}', creates => "#{touch}"} } step "prepare the agents for the test" on agent, "touch #{touch} && rm -f #{donottouch}" step "test using puppet apply" apply_manifest_on(agent, manifest) do |result| fail_test "looks like the thing executed, which it shouldn't" if result.stdout.include? 'executed successfully' end step "verify the file didn't get created" on agent, "test -f #{donottouch}", :acceptable_exit_codes => [1] step "prepare the agents for the second part of the test" on agent, "touch #{touch} ; rm -f #{donottouch}" step "test using puppet resource" on(agent, puppet_resource('exec', "test#{Time.new.to_i}", "command='#{agent.touch(donottouch)}'", "creates='#{touch}'")) do |result| fail_test "looks like the thing executed, which it shouldn't" if result.stdout.include? 'executed successfully' end step "verify the file didn't get created the second time" on agent, "test -f #{donottouch}", :acceptable_exit_codes => [1] end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/should_run_bad_command.rb000066400000000000000000000046131527241624000320110ustar00rootroot00000000000000test_name "tests that puppet can run badly written scripts that fork and inherit descriptors" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners def sleepy_daemon_script(agent) if agent['platform'] =~ /win/ # Windows uses a shorter sleep, because it's expected to wait until the end. return < true}") do |result| fail_test "didn't seem to run the command" unless result.stdout.include? 'executed successfully' unless agent['locale'] == 'ja' end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/should_run_command.rb000066400000000000000000000021721527241624000312010ustar00rootroot00000000000000test_name "tests that puppet correctly runs an exec." # original author: Dan Bode --daniel 2010-12-23 tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group4' # For splitting out groups of tests for slow test runners def before(agent) step "file to be touched should not exist." agent.tmpfile('test-exec') end def after(agent, touched) step "checking the output worked" on agent, "test -f #{touched}" step "clean up the system" on agent, "rm -f #{touched}" end agents.each do |agent| touched = before(agent) apply_manifest_on(agent, "exec {'test': command=>'#{agent.touch(touched)}'}") do |result| fail_test "didn't seem to run the command" unless result.stdout.include? 'executed successfully' unless agent['locale'] == 'ja' end after(agent, touched) touched = before(agent) on(agent, puppet_resource('-d', 'exec', 'test', "command='#{agent.touch(touched)}'}")) do |result| fail_test "didn't seem to run the command" unless result.stdout.include? 'executed successfully' unless agent['locale'] == 'ja' end after(agent, touched) end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/should_run_command_as_user.rb000066400000000000000000000035221527241624000327220ustar00rootroot00000000000000test_name "The exec resource should be able to run commands as a different user" do confine :except, :platform => 'windows' tag 'audit:high', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::BeakerUtils def random_username "pl#{rand(999999).to_i}" end def exec_resource_manifest(params = {}) default_params = { :logoutput => true, :path => '/usr/bin:/usr/sbin:/bin:/sbin', :command => 'echo Hello' } params = default_params.merge(params) params_str = params.map do |param, value| value_str = value.to_s value_str = "'#{value_str}'" if value.is_a?(String) " #{param} => #{value_str}" end.join(",\n") <<-MANIFEST exec { 'run_test_command': #{params_str} } MANIFEST end agents.each do |agent| username = random_username # Create our user. Ensure that we start with a clean slate. agent.user_absent(username) agent.user_present(username) teardown { agent.user_absent(username) } tmpdir = agent.tmpdir("forbidden") on(agent, "chmod 700 #{tmpdir}") step "Runs the command even when the user doesn't have permissions to access the pwd" do # Can't use apply_manifest_on here because that does not take the :cwd # as an option. tmpfile = agent.tmpfile("exec_user_perms_manifest") create_remote_file(agent, tmpfile, exec_resource_manifest(user: username)) on(agent, "cd #{tmpdir} && puppet apply #{tmpfile} --detailed-exitcodes", acceptable_exit_codes: [0, 2]) end step "Runs the command even when the user doesn't have permission to access the specified cwd" do apply_manifest_on(agent, exec_resource_manifest(user: username, cwd: tmpdir), catch_failures: true) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/should_run_command_in_cwd.rb000066400000000000000000000221201527241624000325170ustar00rootroot00000000000000test_name "The Exec resource should run commands in the specified cwd" do tag 'audit:high', 'audit:acceptance', 'shard:group2' # For splitting out groups of tests for slow test runners confine :except, :platform => /debian-12-amd64/ # PUP-12020 require 'puppet/acceptance/windows_utils' extend Puppet::Acceptance::WindowsUtils # Useful utility that converts a string literal # to a regex. We do a lot of assertions on file # paths here that we need to escape, so this is # a nice way of making the code more readable. def to_regex(str) Regexp.new(Regexp.escape(str)) end def exec_resource_manifest(command, params = {}) default_params = { :command => command } params = default_params.merge(params) params_str = params.map do |param, value| value_str = value.to_s # Single quote the strings in case our value is a Windows # path value_str = "'#{value_str}'" if value.is_a?(String) " #{param} => #{value_str}" end.join(",\n") <<-MANIFEST exec { 'run_test_command': #{params_str} } MANIFEST end def assert_file_on(host, filepath, failure_comment) if host.platform =~ /windows/ cmd = "cmd.exe /c \"type #{filepath.gsub('/', '\\')}\"" else cmd = "test -f #{filepath}" end on(host, cmd, :acceptable_exit_codes => [0, 1]) do |result| assert_equal(0, result.exit_code, failure_comment) end end agents.each do |agent| testdir = agent.tmpdir("mock_testdir") if agent.platform =~ /windows/ path = 'C:\Windows\System32' echo_to = 'cmd.exe /c echo testing >' cat = 'cmd.exe /c type' non_existant_dir = 'C:\does_not_exist' origin_working_dir = on(agent, 'cmd.exe /c echo %CD%').stdout.chomp else path = '/usr/bin:/usr/sbin:/bin:/sbin' echo_to = 'echo testing >' cat = 'cat' non_existant_dir = '/does_not_exist' origin_working_dir = on(agent, 'pwd').stdout.chomp end step "clean current working directory" do on(agent, "rm -f cwd_test*") end step "Defaults to the current directory if the CWD option is not provided" do apply_manifest_on(agent, exec_resource_manifest("#{echo_to} cwd_test1", {:path => path}), :catch_failures => true) assert_file_on(agent, File.join(origin_working_dir, 'cwd_test1'), 'Exec did not create file in origin pwd, exec resource not defaulting to pwd when no :cwd option is given') end step "Runs the command in the user specified CWD" do apply_manifest_on(agent, exec_resource_manifest("#{echo_to} cwd_test2", {:cwd => testdir, :path => path}), :catch_failures => true) assert_file_on(agent, File.join(testdir, 'cwd_test2'), 'Exec did not create file in test directory, exec resource not using :cwd given') end step "Errors if the user specified CWD does not exist" do apply_manifest_on(agent, exec_resource_manifest("#{echo_to} cwd_test3", {cwd: non_existant_dir, :path => path}), :expect_failures => true) do |result| assert_equal(4, result.exit_code, "Exec manifest still executed with non-existant :cwd") end end # "onlyif" testing will require some form of runnable test in the testdir for the # onlyif clause to actually execute. The runnable test we will use is attempting to # 'cat' an unqualified file that will only exist in the testdir create_remote_file(agent, File.join(testdir, 'testdir_onlyif.txt'), 'testing') step 'Runs a "check" command (:onlyif or :unless) in the user specified CWD' do apply_manifest_on(agent, exec_resource_manifest("#{echo_to} cwd_test4", {cwd: testdir, :path => path, :onlyif => "#{cat} testdir_onlyif.txt"}), :expect_changes => true) assert_file_on(agent, File.join(testdir, 'cwd_test4'), 'Exec did not create file in test directory, exec resource not using :cwd given') end step 'Does not run the exec if the "check" command (:onlyif or :unless) fails' do apply_manifest_on(agent, exec_resource_manifest("#{echo_to} cwd_test5", {cwd: testdir, :path => path, :onlyif => "foobar"}), :expect_failures => true) do |result| assert_equal(4, result.exit_code, "Exec manifest still executed with failed :onlyif clause") end end tmpdir_noaccess = agent.tmpdir("mock_dir") create_remote_file(agent, File.join(tmpdir_noaccess, 'noaccess.txt'), 'foobar') username = "pl#{rand(999999).to_i}" # The next two steps set up to test running with a CWD that the user does not have access to. # The setup for the test creates 1. a new user and 2. a new directory that the new user does # not have access to. step "Setup user for 'no access' test" do agent.user_present(username) if agent.platform =~ /solaris/ # for some reason applications of 'user_present' on solaris 10 don't manage the homedir correctly, so just # force a puppet apply to manage the user on agent, puppet_resource('user', username, "ensure=present managehome=true home=/export/home/#{username}") # we need to create the user directory ourselves in order for solaris users to successfully login on(agent, "mkdir /export/home/#{username} && chown -R #{username} /export/home/#{username}") elsif agent.platform =~ /osx/ # we need to create the user directory ourselves in order for macos users to successfully login on(agent, "mkdir /Users/#{username} && chown -R #{username}:80 /Users/#{username}") elsif agent.platform =~ /debian|ubuntu|sles/ # we need to create the user directory ourselves in order for deb users to successfully login on(agent, "mkdir /home/#{username} && chown -R #{username} /home/#{username}") end teardown { agent.user_absent(username) } end tmpdir_noaccess = agent.tmpdir("mock_noaccess") create_remote_file(agent, File.join(tmpdir_noaccess, 'noaccess.txt'), 'foobar') step "Setup restricted access directory for 'no access' test" do if agent.platform =~ /windows/ deny_administrator_access_to(agent, tmpdir_noaccess) deny_administrator_access_to(agent, File.join(tmpdir_noaccess, 'noaccess.txt')) else if agent.platform =~ /osx/ # This is a little nuts, but on MacOS the tmpdir returned from agent.tmpdir is located in # a directory that users other than root can't even access, i.e. other users won't have access # to either the noaccess dir itself (which we want) _or the tmpdir root it's located in_. This is # a problem since it will look to puppet like the noacceess dir doesn't exist at all, and so we # can't count on any reliaable failure since we want a return indicating no access, not a missing directory. # # To get around this for MacOS platforms we simply use the new user's homedir as the 'tmpdir' and # put the noaccess dir there. on(agent, "mkdir /Users/#{username}/noaccess_test && cp #{tmpdir_noaccess}/noaccess.txt /Users/#{username}/noaccess_test && chmod -R 600 /Users/#{username}/noaccess_test") tmpdir_noaccess = "/Users/#{username}/noaccess_test" end # remove permissions for all other users other than root, which should force puppet to fail when running as another user on(agent, "chmod -R 600 #{tmpdir_noaccess}") end end step "Errors if the user does not have access to the specified CWD" do manifest_path = agent.tmpfile('apply_manifest.pp') create_remote_file(agent, manifest_path, exec_resource_manifest("#{cat} noaccess.txt", {:cwd => tmpdir_noaccess, :path => path})) if agent.platform =~ /windows/ on(agent, "cmd.exe /c \"puppet apply #{manifest_path} --detailed-exitcodes\"", :acceptable_exit_codes => [4]) do |result| assert_equal(4, result.exit_code, "Exec manifest still executed inside restricted directory", ) end elsif agent.platform =~ /osx/ # on MacOS we need to copy the manifest to run to the user's home dir and give the user ownership. otherwise puppet won't run on it. on(agent, "cp #{manifest_path} /Users/#{username}/noaccess_manifest.pp && chown #{username}:80 /Users/#{username}/noaccess_manifest.pp") on(agent, "su - #{username} -c \"/opt/puppetlabs/bin/puppet apply /Users/#{username}/noaccess_manifest.pp --detailed-exitcodes\"", :acceptable_exit_codes => [4]) do |result| assert_equal(4, result.exit_code, "Exec manifest still executed inside restricted directory") end else on(agent, "chown #{username} #{manifest_path}") if agent.platform =~ /solaris|aix/ on(agent, "su - #{username} -c \"/opt/puppetlabs/bin/puppet apply #{manifest_path} --detailed-exitcodes\"", :acceptable_exit_codes => [4]) do |result| assert_equal(4, result.exit_code, "Exec manifest still executed inside restricted directory") end else on(agent, "su #{username} -c \"/opt/puppetlabs/bin/puppet apply #{manifest_path} --detailed-exitcodes\"", :acceptable_exit_codes => [4]) do |result| assert_equal(4, result.exit_code, "Exec manifest still executed inside restricted directory") end end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/should_set_environment_variables.rb000066400000000000000000000072641527241624000341550ustar00rootroot00000000000000test_name "The Exec resource should set user-specified environment variables" do tag 'audit:high', 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners # Would be nice to parse the actual values from puppet_output, # but that would require some complicated matching since # puppet_output contains other stuff. def assert_env_var_values(puppet_output, expected_values) expected_values.each do |env_var, value| assert_match(/#{env_var}=#{value}/, puppet_output, "Expected '#{env_var}=#{value}' to be printed as part of the output!") end end agents.each do |agent| # Calculate some top-level variables/functions we # will need for our tests. unless agent.platform =~ /windows/ path = '/usr/bin:/usr/sbin:/bin:/sbin' print_env_vars = lambda do |*env_vars| env_vars_str = env_vars.map do |env_var| "#{env_var}=$#{env_var}" end.join(" ") "echo #{env_vars_str}" end else # Powershell's directory is dependent on what version of Powershell is # installed on the system (e.g. v1.0, v2.0), so we need to programmatically # calculate the executable's directory to add to our PATH variable. powershell_path = on(agent, "cmd.exe /c where powershell.exe").stdout.chomp *powershell_dir, _ = powershell_path.split('\\') powershell_dir = powershell_dir.join('\\') path = "C:\Windows\System32;#{powershell_dir}" print_env_vars = lambda do |*env_vars| env_vars_str = env_vars.map do |env_var| "#{env_var}=$env:#{env_var}" end "powershell.exe \"Write-Host -NoNewLine #{env_vars_str}\"" end end # Easier to read than a def. The def. would require us # to specify the host as a param. in order to get the path # and print_cwd command, which is unnecessary clutter. exec_resource_manifest = lambda do |params = {}| default_params = { :logoutput => true, :path => path } params = default_params.merge(params) params_str = params.map do |param, value| value_str = value.to_s # Single quote the strings in case our value is a Windows # path value_str = "'#{value_str}'" if value.is_a?(String) " #{param} => #{value_str}" end.join(",\n") <<-MANIFEST exec { 'run_test_command': #{params_str} } MANIFEST end step 'Passes the user-specified environment variables into the command' do manifest = exec_resource_manifest.call( command: print_env_vars.call('ENV_VAR_ONE', 'ENV_VAR_TWO'), environment: ['ENV_VAR_ONE=VALUE_ONE', 'ENV_VAR_TWO=VALUE_TWO'] ) apply_manifest_on(agent, manifest) do |result| assert_env_var_values(result.stdout, ENV_VAR_ONE: 'VALUE_ONE', ENV_VAR_TWO: 'VALUE_TWO') end end step "Temporarily overrides previously set environment variables" do manifest = exec_resource_manifest.call( command: print_env_vars.call('ENV_VAR_ONE'), environment: ['ENV_VAR_ONE=VALUE_OVERRIDE'] ) apply_manifest_on(agent, manifest, environment: { 'ENV_VAR_ONE' => 'VALUE' }) do |result| assert_env_var_values(result.stdout, ENV_VAR_ONE: 'VALUE_OVERRIDE') end end step "Temporarily overrides previously set environment variables even if the passed-in value is empty" do manifest = exec_resource_manifest.call( command: print_env_vars.call('ENV_VAR_ONE'), environment: ['ENV_VAR_ONE='] ) apply_manifest_on(agent, manifest, environment: { 'ENV_VAR_ONE' => 'VALUE' }) do |result| assert_env_var_values(result.stdout, ENV_VAR_ONE: '') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/exec/should_set_path.rb000066400000000000000000000013071527241624000305050ustar00rootroot00000000000000test_name "the path statement should work to locate commands" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group4' # For splitting out groups of tests for slow test runners agents.each do |agent| file = agent.tmpfile('touched-should-set-path') step "clean up the system for the test" on agent, "rm -f #{file}" step "invoke the exec resource with a path set" on(agent, puppet_resource('exec', 'test', "command='#{agent.touch(file, false)}'", "path='#{agent.path}'")) step "verify that the files were created" on agent, "test -f #{file}" step "clean up the system after testing" on agent, "rm -f #{file}" end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/000077500000000000000000000000001527241624000247655ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/ascii_diff_output_content_attribute.rb000066400000000000000000000035151527241624000346330ustar00rootroot00000000000000test_name "ASCII Diff Output of Content Attribute" do tag 'audit:high', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners sha256 = Digest::SHA256.new agents.each do |agent| step 'When handling ASCII files' do target = agent.tmpfile('content_ASCII_file_test') initial_text = 'Initial Text' initial_text_sha_checksum = sha256.hexdigest(initial_text) updated_text = 'Updated Text' updated_text_sha_checksum = sha256.hexdigest(updated_text) on agent, puppet('config', 'set', 'diff', 'diff') step 'Ensure the test environment is clean' do on agent, "rm -f #{target}" end teardown do on agent, "rm -f #{target}" end step 'Create ASCII file using content' do manifest = "file { '#{target}': content => '#{initial_text}', ensure => present , checksum => 'sha256'}" on(agent, puppet('apply'), :stdin => manifest) do |result| assert_match(/ensure: defined content as '{sha256}#{initial_text_sha_checksum}'/, result.stdout, "#{agent}: checksum of ASCII file not matched") end end step 'Update existing ASCII file content' do manifest = "file { '#{target}': content => '#{updated_text}', ensure => present , checksum => 'sha256'}" on(agent, puppet('apply','--show_diff'), :stdin => manifest) do |result| assert_match(/content: content changed '{sha256}#{initial_text_sha_checksum}' to '{sha256}#{updated_text_sha_checksum}'/, result.stdout, "#{agent}: checksum of ASCII file not matched after update") assert_match(/^- ?#{initial_text}$/, result.stdout, "#{agent}: initial text not found in diff") assert_match(/^\+ ?#{updated_text}$/, result.stdout, "#{agent}: updated text not found in diff") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/bin_diff_output_content_attribute.rb000066400000000000000000000072131527241624000343120ustar00rootroot00000000000000test_name "Binary Diff Output of Content Attribute" do tag 'audit:high', 'audit:acceptance', 'shard:group2' # For splitting out groups of tests for slow test runners # cannot test binary diff on windows2012r2_ja-64-1 # Error: Could not write report for afire-lien.delivery.puppetlabs.net at C:/ProgramData/PuppetLabs/puppet/cache/reports/afire-lien.delivery.puppetlabs.net/201912041455.yaml: anchor value must contain alphanumerical characters only # Error: Could not send report: anchor value must contain alphanumerical characters only confine :except, {}, hosts.select { |host| host[:platform]=~ /windows/ && host[:locale] == 'ja' } sha256 = Digest::SHA256.new agents.each do |agent| step 'When handling binary files' do target = agent.tmpfile('content_binary_file_test') initial_bin_data = "\xc7\xd1\xfc\x84" initial_base64_data = Base64.encode64(initial_bin_data).chomp initial_sha_checksum = sha256.hexdigest(initial_bin_data) updated_bin_data = "\xc7\xd1\xfc\x85" updated_base64_data = Base64.encode64(updated_bin_data).chomp updated_sha_checksum = sha256.hexdigest(updated_bin_data) on(agent, puppet('config', 'set', 'diff', 'diff')) agent_default_external_encoding=nil on(agent, "#{ruby_command(agent)} -e \"puts Encoding.default_external\"") do |result| agent_default_external_encoding = result.stdout.chomp end if agent_default_external_encoding && agent_default_external_encoding != Encoding.default_external begin initial_bin_data=initial_bin_data.force_encoding(agent_default_external_encoding).encode(Encoding.default_external) updated_bin_data=updated_bin_data.force_encoding(agent_default_external_encoding).encode(Encoding.default_external) rescue Encoding::InvalidByteSequenceError #depending on agent_default_external_encoding, the conversion may fail, but this should not be a problem end end teardown do on agent, "rm -f #{target}" end step 'Ensure the test environment is clean' do on agent, "rm -f #{target}" end step 'Create binary file using content' do manifest = "file { '#{target}': content => Binary('#{initial_base64_data}'), ensure => present , checksum => 'sha256'}" on(agent, puppet('apply'), :stdin => manifest) do |result| assert_match(/ensure: defined content as '{sha256}#{initial_sha_checksum}'/, result.stdout, "#{agent}: checksum of binary file not matched") end end step 'Update existing binary file content' do manifest = "file { '#{target}': content => Binary('#{updated_base64_data}'), ensure => present , checksum => 'sha256'}" on(agent, puppet('apply','--show_diff'), :stdin => manifest) do |result| assert_match(/content: content changed '{sha256}#{initial_sha_checksum}' to '{sha256}#{updated_sha_checksum}'/, result.stdout, "#{agent}: checksum of binary file not matched after update") refute_match(/content: Received a Log attribute with invalid encoding:/, result.stdout, "#{agent}: Received a Log attribute with invalid encoding") if initial_bin_data.valid_encoding? && updated_bin_data.valid_encoding? assert_match(/^- ?#{initial_bin_data}$/, result.stdout, "#{agent}: initial utf-8 data not found in binary diff") assert_match(/^\+ ?#{updated_bin_data}$/, result.stdout, "#{agent}: updated utf-8 data not found in binary diff") else assert_match(/Binary files #{target} and .* differ/, result.stdout, "#{agent}: Binary file diff notice not matched") end end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/content_attribute.rb000066400000000000000000000043331527241624000310520ustar00rootroot00000000000000test_name "Content Attribute" tag 'audit:high', 'audit:refactor', # Use block stype test_name 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners agents.each do |agent| target = agent.tmpfile('content_file_test') step "Ensure the test environment is clean" on agent, "rm -f #{target}" step "Content Attribute: using raw content" checksums_fips = ['sha256', 'sha256lite'] checksums_no_fips = ['sha256', 'sha256lite', 'md5', 'md5lite'] if on(agent, facter("fips_enabled")).stdout =~ /true/ checksums = checksums_fips else checksums = checksums_no_fips end manifest = "file { '#{target}': content => 'This is the test file content', ensure => present }" manifest += checksums.collect {|checksum_type| "file { '#{target+checksum_type}': content => 'This is the test file content', ensure => present, checksum => #{checksum_type} }" }.join("\n") apply_manifest_on(agent, manifest) do |result| checksums.each do |checksum_type| refute_match(/content changed/, result.stdout, "#{agent}: shouldn't have overwrote #{target+checksum_type}") end end on(agent, "cat #{target}") do |result| assert_match(/This is the test file content/, result.stdout, "File content not matched on #{agent}") unless agent['locale'] == 'ja' end step "Content Attribute: illegal timesteps" ['mtime', 'ctime'].each do |checksum_type| manifest = "file { '#{target+checksum_type}': content => 'This is the test file content', ensure => present, checksum => #{checksum_type} }" apply_manifest_on(agent, manifest, :acceptable_exit_codes => [1]) do |result| assert_match(/Error: Validation of File\[#{target+checksum_type}\] failed: You cannot specify content when using checksum '#{checksum_type}'/, result.stderr, "#{agent}: expected failure") unless agent['locale'] == 'ja' end end step "Ensure the test environment is clean" on(agent, "rm -f #{target}") # The "checksum from filebucket" scenario was removed along with the # implicit filebucket retrieval for checksum-like content values # (openvox#170); content is now always managed literally. See # ticket_6541_invalid_filebucket_files.rb for coverage of the literal # behavior. end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/handle_fifo_files.rb000066400000000000000000000036571527241624000307450ustar00rootroot00000000000000test_name "should be able to handle fifo files" tag 'audit:high', 'audit:acceptance', 'shard:group4' # For splitting out groups of tests for slow test runners confine :except, :platform => /windows/ def ensure_content_to_file_manifest(file_path, ensure_value) return <<-MANIFEST file { "#{file_path}": ensure => #{ensure_value}, content => "Hello World" } MANIFEST end agents.each do |agent| tmp_path = agent.tmpdir("tmpdir") fifo_path = "#{tmp_path}/myfifo" teardown do agent.rm_rf(tmp_path) end step "create fifo" do on(agent, "mkfifo #{fifo_path}") end step "check that fifo got created" do on(agent, "ls -l #{fifo_path}") do |result| assert(result.stdout.start_with?('p')) end end step "puppet ensures given fifo is present" do apply_manifest_on(agent, ensure_content_to_file_manifest(fifo_path, 'present'), :acceptable_exit_codes => [2]) do |result| assert_match(/Warning: .+ Ensure set to :present but file type is fifo so no content will be synced/, result.stderr) end end step "check that given file is still a fifo" do on(agent, "ls -l #{fifo_path}") do |result| assert(result.stdout.start_with?('p')) end end step "puppet ensures given fifo is a regular file" do apply_manifest_on(agent, ensure_content_to_file_manifest(fifo_path, 'file'), :acceptable_exit_codes => [0]) do |result| assert_match(/Notice: .+\/myfifo\]\/ensure: defined content as '{/, result.stdout) refute_match(/Warning: .+ Ensure set to :present but file type is fifo so no content will be synced/, result.stderr) end end step "check that given fifo is now a regular file" do on(agent, "ls -l #{fifo_path}") do |result| assert(result.stdout.start_with?('-')) end end step "check that given file now has desired content" do on(agent, "cat #{fifo_path}") do |result| assert_equal('Hello World', result.stdout) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/handle_fifo_files_when_recursing.rb000066400000000000000000000037761527241624000340510ustar00rootroot00000000000000test_name "should be able to handle fifo files when recursing" tag 'audit:high', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners confine :except, :platform => /windows/ def ensure_owner_recursively_manifest(path, owner_value) return <<-MANIFEST file { "#{path}": ensure => present, recurse => true, owner => #{owner_value} } MANIFEST end agents.each do |agent| initial_owner = '' random_user = "pl#{rand(999).to_i}" tmp_path = agent.tmpdir("tmpdir") fifo_path = "#{tmp_path}/myfifo" teardown do agent.rm_rf(tmp_path) end step "create fifo file" do on(agent, "mkfifo #{fifo_path}") on(agent, puppet("resource user #{random_user} ensure=absent")) end step "check that fifo file got created" do on(agent, "ls -l #{fifo_path}") do |result| assert(result.stdout.start_with?('p')) initial_owner = result.stdout.split[2] end end step "create a new user" do on(agent, puppet("resource user #{random_user} ensure=present")) end step "puppet ensures '#{random_user}' as owner of path" do apply_manifest_on(agent, ensure_owner_recursively_manifest(tmp_path, random_user), :acceptable_exit_codes => [0]) do |result| assert_match(/#{tmp_path}\]\/owner: owner changed '#{initial_owner}' to '#{random_user}'/, result.stdout) refute_match(/Error: .+ Failed to generate additional resources using ‘eval_generate’: Cannot manage files of type fifo/, result.stderr) end end step "check that given file is still a fifo" do on(agent, "ls -l #{fifo_path}") do |result| assert(result.stdout.start_with?('p')) end end step "check ownership of fifo file" do on(agent, "ls -l #{fifo_path}") do |result| user = result.stdout.split[2] assert_equal(random_user, user) end end step "check ownership of tmp folder" do on(agent, "ls -ld #{tmp_path}") do |result| user = result.stdout.split[2] assert_equal(random_user, user) end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/should_create_directory.rb000066400000000000000000000023211527241624000322150ustar00rootroot00000000000000test_name "should create directory" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group2' # For splitting out groups of tests for slow test runners agents.each do |agent| target = agent.tmpfile("create-dir") teardown do step "clean up after the test run" do on(agent, "rm -rf #{target}") end end step "verify we can create a directory" do on(agent, puppet_resource("file", target, 'ensure=directory')) end step "verify the directory was created" do on(agent, "test -d #{target}") end dir_manifest = agent.tmpfile("dir-resource") create_remote_file(agent, dir_manifest, <<-PP) $dir='#{target}' $same_dir='#{target}/' file {$dir: ensure => directory, } file { $same_dir: ensure => directory, } PP step "verify we can't create same dir resource with a trailing slash" do options = {:acceptable_exit_codes => [1]} on(agent, puppet_apply("--noop #{dir_manifest}"), options) do |result| unless agent['locale'] == 'ja' assert_match('Cannot alias File', result.output, 'duplicate directory resources did not fail properly') end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/should_create_empty.rb000066400000000000000000000011761527241624000313560ustar00rootroot00000000000000test_name "should create empty file for 'present'" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners agents.each do |agent| target = agent.tmpfile("empty") step "clean up the system before we begin" on(agent, "rm -rf #{target}") step "verify we can create an empty file" on(agent, puppet_resource("file", target, 'ensure=present')) step "verify the target was created" on(agent, "test -f #{target} && test ! -s #{target}") step "clean up after the test run" on(agent, "rm -rf #{target}") end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/should_create_symlink.rb000066400000000000000000000050711527241624000317040ustar00rootroot00000000000000test_name "should create symlink" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group4' # For splitting out groups of tests for slow test runners def message 'hello world' end def reset_link_and_target(agent, link, target) step "clean up the system before we begin" on agent, "rm -rf #{target} #{link}" on agent, "echo '#{message}' > #{target}" end def verify_symlink(agent, link, target) step "verify the symlink was created" on(agent, "test -L #{link} && test -f #{link}") step "verify the symlink points to a file" on(agent, "test -f #{target}") step "verify the content is identical on both sides" on(agent, "cat #{link}") do |result| fail_test "link missing content" unless result.stdout.include?(message) end on(agent, "cat #{target}") do |result| fail_test "target missing content" unless result.stdout.include?(message) end end agents.each do |agent| if agent.platform.variant == 'windows' # symlinks are supported only on Vista+ (version 6.0 and higher) on(agent, facter('kernelmajversion')) do |result| skip_test "Test not supported on this platform" if result.stdout.chomp.to_f < 6.0 end end link_file = agent.tmpfile("symlink-link") target_file = agent.tmpfile("symlink-target") link_dir = agent.tmpdir("dir_symlink-link") target_dir = agent.tmpdir("dir-symlink-target") reset_link_and_target(agent, link_file, target_file) reset_link_and_target(agent, link_dir, target_dir) step "verify we can create a symlink with puppet resource" on(agent, puppet_resource("file", "#{link_file}", "ensure=#{target_file}")) verify_symlink(agent, link_file, target_file) reset_link_and_target(agent, link_file, target_file) step "verify that 'links => manage' preserves a symlink" apply_manifest_on(agent, "file { '#{link_file}': ensure => link, target => '#{target_file}', links => manage }") verify_symlink(agent, link_file, target_file) reset_link_and_target(agent, link_file, target_file) step "verify that 'links => manage' and 'recurse => true' preserves links in a directory" on(agent, puppet_resource("file", target_dir, "ensure=directory")) reset_link_and_target(agent, link_dir, "#{target_dir}/symlink-target") apply_manifest_on(agent, "file { '#{link_dir}': ensure => directory, target => '#{target_dir}', links => manage, recurse => true }") verify_symlink(agent, "#{link_dir}/symlink-target", "#{target_dir}/symlink-target") step "clean up after the test run" on agent, "rm -rf #{target_file} #{link_file} #{target_dir} #{link_dir}" end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/should_default_mode.rb000066400000000000000000000030001527241624000313110ustar00rootroot00000000000000test_name "file resource: set default modes" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners def regexp_mode(mode) Regexp.new("mode\s*=>\s*'0?#{mode}'") end agents.each do |agent| step "setup" parent = agent.tmpdir('default-mode-parent') on(agent, "rm -rf #{parent}") step "puppet should set execute bit on readable directories" on(agent, puppet_resource("file", parent, "ensure=directory", "mode=0644")) do |result| assert_match(regexp_mode(755), result.stdout) end step "include execute bit on newly created directories" dir = "#{parent}/dir" on(agent, "mkdir #{dir} && cd #{dir} && cd ..") step "exclude execute bit from newly created files" file = "#{parent}/file.txt" on(agent, "echo foobar > #{file}") on(agent, "#{file}", :acceptable_exit_codes => (1..255)) do |result| refute_match(/foobar/, result.stdout) end step "set execute bit on file if explicitly specified" file_750 = "#{parent}/file_750.txt" on(agent, puppet_resource("file", file_750, "ensure=file", "mode=0750")) do |result| assert_match(regexp_mode(750), result.stdout) end step "don't set execute bit if directory not readable" dir_600 = "#{parent}/dir_600" on(agent, puppet_resource("file", dir_600, "ensure=directory", "mode=0600")) do |result| assert_match(regexp_mode(700), result.stdout) # readable by owner, but not group end on(agent, "rm -rf #{parent}") end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/should_remove_dir.rb000066400000000000000000000020001527241624000310130ustar00rootroot00000000000000test_name "should remove directory, but force required" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group2' # For splitting out groups of tests for slow test runners agents.each do |agent| target = agent.tmpdir("delete-dir") step "clean up the system before we begin" on(agent, "rm -rf #{target} ; mkdir -p #{target}") step "verify we can't remove a directory without 'force'" on(agent, puppet_resource("file", target, 'ensure=absent')) do |result| fail_test "didn't tell us that force was required" unless result.stdout.include? "Not removing directory; use 'force' to override" unless agent['locale'] == 'ja' end step "verify the directory still exists" on(agent, "test -d #{target}") step "verify we can remove a directory with 'force'" on(agent, puppet_resource("file", target, 'ensure=absent', 'force=true')) step "verify that the directory is gone" on(agent, "test -d #{target}", :acceptable_exit_codes => [1]) end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/should_remove_file.rb000066400000000000000000000010721527241624000311640ustar00rootroot00000000000000test_name "should remove file" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners agents.each do |agent| target = agent.tmpfile('delete-file') step "clean up the system before we begin" on agent, "rm -rf #{target} && touch #{target}" step "verify we can remove a file" on(agent, puppet_resource("file", target, 'ensure=absent')) step "verify that the file is gone" on agent, "test -e #{target}", :acceptable_exit_codes => [1] end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/source_attribute.rb000066400000000000000000000277311527241624000307070ustar00rootroot00000000000000test_name "The source attribute" do require 'puppet/acceptance/module_utils' extend Puppet::Acceptance::ModuleUtils tag 'audit:high', 'audit:acceptance', 'server', 'shard:group4' # For splitting out groups of tests for slow test runners @target_file_on_windows = 'C:/windows/temp/source_attr_test' @target_file_on_nix = '/tmp/source_attr_test' @target_dir_on_windows = 'C:/windows/temp/source_attr_test_dir' @target_dir_on_nix = '/tmp/source_attr_test_dir' # In case any of the hosts happens to be fips enabled we limit to the lowest # common denominator. checksums_fips = [nil, 'sha256', 'sha256lite', 'ctime', 'mtime'] checksums_no_fips = [nil, 'sha256', 'sha256lite', 'md5', 'md5lite', 'ctime', 'mtime'] fips_host_present = hosts.any? { |host| on(host, facter("fips_enabled")).stdout =~ /true/ } if fips_host_present checksums = checksums_fips else checksums = checksums_no_fips end orig_installed_modules = get_installed_modules_for_hosts hosts teardown do rm_installed_modules_from_hosts orig_installed_modules, (get_installed_modules_for_hosts hosts) hosts.each do |host| file_to_rm = host['platform'] =~ /windows/ ? @target_file_on_windows : @target_file_on_nix dir_to_rm = host['platform'] =~ /windows/ ? @target_dir_on_windows : @target_dir_on_nix checksums.each do |checksum_type| on(host, "rm #{file_to_rm}#{checksum_type}", :acceptable_exit_codes => [0,1]) on(host, "rm -r #{dir_to_rm}#{checksum_type}", :acceptable_exit_codes => [0,1]) end end end step "Setup - create environment and test module" # set directories testdir = master.tmpdir('file_source_attr') env_dir = "#{testdir}/environments" prod_dir = "#{env_dir}/production" manifest_dir = "#{prod_dir}/manifests" manifest_file = "#{prod_dir}/manifests/site.pp" module_dir = "#{prod_dir}/modules" test_module_dir = "#{module_dir}/source_test_module" test_module_manifests_dir = "#{test_module_dir}/manifests" test_module_files_dir = "#{test_module_dir}/files" mod_manifest_file = "#{test_module_manifests_dir}/init.pp" mod_source_file = "#{test_module_files_dir}/source_file" mod_source_dir = "#{test_module_files_dir}/source_dir" mod_source_dir_file = "#{mod_source_dir}/source_dir_file" mod_source = ' the content is present' def mod_manifest_entry(checksum_type = nil) checksum = if checksum_type then "checksum => #{checksum_type}," else "" end manifest = <<-EOF $target_file#{checksum_type} = $::kernel ? { \\'windows\\' => \\'#{@target_file_on_windows}#{checksum_type}\\', default => \\'#{@target_file_on_nix}#{checksum_type}\\' } file { $target_file#{checksum_type}: source => \\'puppet:///modules/source_test_module/source_file\\', #{checksum} ensure => present } $target_dir#{checksum_type} = $::kernel ? { \\'windows\\' => \\'#{@target_dir_on_windows}#{checksum_type}\\', default => \\'#{@target_dir_on_nix}#{checksum_type}\\' } file { $target_dir#{checksum_type}: source => \\'puppet:///modules/source_test_module/source_dir\\', #{checksum} ensure => directory, recurse => true } EOF manifest end mod_manifest = <<-EOF class source_test_module { #{checksums.collect { |checksum_type| mod_manifest_entry(checksum_type) }.join("\n")} } EOF env_manifest = <<-EOF filebucket { \\'main\\': server => \\'#{master}\\', path => false, } File { backup => \\'main\\' } node default { include source_test_module } EOF # apply manifests to setup environment and modules apply_manifest_on(master, <<-MANIFEST, :catch_failures => true) File { ensure => directory, mode => '0755', } file { '#{testdir}':; '#{env_dir}':; '#{prod_dir}':; '#{manifest_dir}':; '#{module_dir}':; '#{test_module_dir}':; '#{test_module_manifests_dir}':; '#{test_module_files_dir}':; } file { '#{mod_manifest_file}': ensure => file, mode => '0644', content => '#{mod_manifest}', } file { '#{mod_source_file}': ensure => file, mode => '0644', content => '#{mod_source}', } file { '#{mod_source_dir}': ensure => directory, mode => '0755' } file { '#{mod_source_dir_file}': ensure => file, mode => '0644', content => '#{mod_source}', } file { '#{manifest_file}': ensure => file, mode => '0644', content => '#{env_manifest}', } MANIFEST step "When using a puppet:/// URI with a master/agent setup" master_opts = { 'main' => { 'environmentpath' => "#{env_dir}", }, } with_puppet_running_on(master, master_opts, testdir) do agents.each do |agent| # accept an exit code of 2 which is returned if there are changes step "create file the first run" on(agent, puppet('agent', "--test"), :acceptable_exit_codes => [0,2]) do file_to_check = agent['platform'] =~ /windows/ ? @target_file_on_windows : @target_file_on_nix dir_to_check = agent['platform'] =~ /windows/ ? @target_dir_on_windows : @target_dir_on_nix checksums.each do |checksum_type| on agent, "cat #{file_to_check}#{checksum_type}" do |result| assert_match(/the content is present/, result.stdout, "Result file not created #{checksum_type}") end on agent, "cat #{dir_to_check}#{checksum_type}/source_dir_file" do |result| assert_match(/the content is present/, result.stdout, "Result file not created #{checksum_type}") end end end step "second run should not update file" on(agent, puppet('agent', "--test"), :acceptable_exit_codes => [0,2]) do |result| refute_match(/content changed.*(md5|sha256)/, result.stdout, "Shouldn't have overwritten any files") # When using ctime/mtime, the agent compares the values from its # local file with the values on the master to determine if the # file is insync or not. If during the first run, the agent # creates the files, and the resulting ctime/mtime are still # behind the times on the master, then the 2nd agent run will # consider the file to not be insync, and will update it # again. This process will repeat until the agent updates the # file, and the resulting ctime/mtime are after the values on # the master, at which point it will have converged. if result.stdout =~ /content changed.*ctime/ Log.warn "Agent did not converge using ctime" end if result.stdout =~ /content changed.*mtime/ Log.warn "Agent did not converge using mtime" end end end =begin # Disable flaky test until PUP-4115 is addressed. step "touch files and verify they're updated with ctime/mtime" # wait until we're not at the mtime of files on the agents # this could be done cross-platform using Puppet, but a single puppet query is unlikely to be less than a second, # and iterating over all agents would be much slower sleep(1) on master, "touch #{mod_source_file} #{mod_source_dir_file}" agents.each do |agent| on(agent, puppet('agent', "--test"), :acceptable_exit_codes => [0,2]) do file_to_check = agent['platform'] =~ /windows/ ? @target_file_on_windows : @target_file_on_nix dir_to_check = agent['platform'] =~ /windows/ ? @target_dir_on_windows : @target_dir_on_nix ['ctime', 'mtime'].each do |time_type| assert_match(/File\[#{file_to_check}#{time_type}\]\/content: content changed/, stdout, "Should have updated files") assert_match(/File\[#{dir_to_check}#{time_type}\/source_dir_file\]\/content: content changed/, stdout, "Should have updated files") end end end =end end # TODO: Add tests for puppet:// URIs with multi-master/agent setups. step "When using puppet apply" agents.each do |agent| step "Setup testing local file sources" # create one larger manifest with all the files so we don't have to run # puppet apply per each checksum_type localsource_testdir = agent.tmpdir('local_source_file_test') source = "#{localsource_testdir}/source_mod/files/source" on agent, "mkdir -p #{File.dirname(source)}" # don't put a 'z' in this content source_content = 'Yay, this is the local file. I have to be bigger than 512 bytes so that my masters. yadda yadda yadda not a nice thing. lorem ipsem. alice bob went to fetch a pail of water. Lorem ipsum dolor sit amet, pede ipsum nam wisi lectus eget, sociis sed, commodo vitae velit eleifend. Vestibulum orci feugiat erat etiam pellentesque sed, imperdiet a integer nulla, mi tincidunt suscipit. Nec sed, mi tortor, in a consequat mattis proin scelerisque eleifend. In lectus magna quam. Magna quam vitae sociosqu. Adipiscing laoreet.' create_remote_file agent, source, source_content local_apply_manifest = "" target = {} checksums.each do |checksum_type| target[checksum_type] = "#{localsource_testdir}/target#{checksum_type}" checksum = if checksum_type then "checksum => #{checksum_type}," else "" end local_apply_manifest.concat("file { '#{target[checksum_type]}': source => '#{source}', ensure => present, #{checksum} }\n") end apply_manifest_on agent, local_apply_manifest checksums.each do |checksum_type| step "Using a local file path. #{checksum_type}" on(agent, "cat #{target[checksum_type]}") do |result| assert_match(/Yay, this is the local file./, result.stdout, "FIRST: File contents not matched on #{agent}") end end step "second run should not update any files" apply_manifest_on(agent, local_apply_manifest) do |result| refute_match(/content changed/, result.stdout, "Shouldn't have overwrote any files") end # changes in source file producing updates is tested elsewhere step "subsequent run should not update file using lite if only after byte 512 is changed" byte_after_md5lite = 513 source_content[byte_after_md5lite] = 'z' create_remote_file agent, source, source_content if fips_host_present apply_manifest_on(agent, "file { '#{localsource_testdir}/targetsha256lite': source => '#{source}', ensure => present, checksum => sha256lite }") do |result| refute_match(/(content changed|defined content)/, result.stdout, "Shouldn't have overwrote any files") end else apply_manifest_on(agent, "file { '#{localsource_testdir}/targetmd5lite': source => '#{source}', ensure => present, checksum => md5lite } file { '#{localsource_testdir}/targetsha256lite': source => '#{source}', ensure => present, checksum => sha256lite }") do |result| refute_match(/(content changed|defined content)/, result.stdout, "Shouldn't have overwrote any files") end end local_module_manifest = "" checksums.each do |checksum_type| on agent, "rm -rf #{target[checksum_type]}" checksum = if checksum_type then "checksum => #{checksum_type}," else "" end local_module_manifest.concat("file { '#{target[checksum_type]}': source => 'puppet:///modules/source_mod/source', ensure => present, #{checksum} }\n") end localsource_test_manifest = agent.tmpfile('local_source_test_manifest') create_remote_file agent, localsource_test_manifest, local_module_manifest on agent, puppet( %{apply --modulepath=#{localsource_testdir} #{localsource_test_manifest}} ) checksums.each do |checksum_type| step "Using a puppet:/// URI with checksum type: #{checksum_type}" on(agent, "cat #{target[checksum_type]}") do |result| assert_match(/Yay, this is the local file./, result.stdout, "FIRST: File contents not matched on #{agent}") end end step "second run should not update any files using apply with puppet:/// URI source" on(agent, puppet( %{apply --modulepath=#{localsource_testdir} #{localsource_test_manifest}} )) do |result| refute_match(/content changed/, result.stdout, "Shouldn't have overwrote any files") end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/symbolic_modes.rb000066400000000000000000000323521527241624000303270ustar00rootroot00000000000000test_name 'file resource: symbolic modes' do confine :except, :platform => /^windows/ confine :to, {}, hosts.select {|host| !host[:roles].include?('master')} tag 'audit:high', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils class FileSymlink attr_reader :mode, :path, :start_mode, :symbolic_mode def initialize(base_dir, file_type, symbolic_mode, mode, start_mode=nil) @base_dir = base_dir @file_type = file_type @symbolic_mode = symbolic_mode @mode = mode @start_mode = start_mode if @start_mode.nil? @path= "#{@base_dir}/#{@file_type}_#{@symbolic_mode}_#{@mode.to_s(8)}" else @path= "#{@base_dir}/#{@file_type}_#{@symbolic_mode}_#{@start_mode.to_s(8)}_#{@mode.to_s(8)}" end end # does the mode of the file/directory change from start_mode to puppet apply def mode_changes? ! @start_mode.nil? && @start_mode != @mode end def get_manifest "file { #{@path.inspect}: ensure => '#{@file_type}', mode => '#{@symbolic_mode}' }" end end class BaseTest include Beaker::DSL::Assertions def initialize(testcase, agent, base_dir) @testcase = testcase @agent = agent @base_dir = base_dir @file_list = [] @directory_list = [] end def assert_mode(agent, path, expected_mode) permissions = @testcase.stat(agent, path) assert_equal(expected_mode, permissions[2], "'#{path}' current mode #{permissions[2].to_s(8)} doesn't match expected mode #{expected_mode.to_s(8)}") end def manifest manifest_array = (@file_list + @directory_list).map {|x| x.get_manifest} @testcase.step(manifest_array) manifest_array.join("\n") end def puppet_reapply @testcase.apply_manifest_on(@agent, manifest) do |apply_result| refute_match(/mode changed/, apply_result.stdout, "reapplied the symbolic mode change") (@file_list + @directory_list).each do |file| refute_match(/#{Regexp.escape(file.path)}/, apply_result.stdout, "Expected to not see '#{file.path}' in 'puppet apply' output") end end end end class CreateTest < BaseTest def symlink_file(symbolic_mode, mode) @file_list << FileSymlink.new(@base_dir, 'file', symbolic_mode, mode) end def symlink_directory(symbolic_mode, mode) @directory_list << FileSymlink.new(@base_dir, 'directory', symbolic_mode, mode) end def puppet_apply apply_result = @testcase.apply_manifest_on(@agent, manifest).stdout (@file_list + @directory_list).each do |file| assert_match(/File\[#{Regexp.escape(file.path)}\]\/ensure: created/, apply_result, "Failed to create #{file.path}") assert_mode(@agent, file.path, file.mode) end end end class ModifyTest < BaseTest def symlink_file(symbolic_mode, start_mode, mode) @file_list << FileSymlink.new(@base_dir, 'file', symbolic_mode, mode, start_mode) end def symlink_directory(symbolic_mode, start_mode, mode) @directory_list << FileSymlink.new(@base_dir, 'directory', symbolic_mode, mode, start_mode) end def create_starting_state files = @file_list.collect {|x| "'#{x.path}'" } directories = @directory_list.collect {|x| "'#{x.path}'" } @testcase.on(@agent, "touch #{files.join(' ')}") @testcase.on(@agent, "mkdir -p #{directories.join(' ')}") @testcase.on(@agent, "chown symuser:symgroup #{files.join(' ')} #{directories.join(' ')}") cmd_list = [] (@file_list + @directory_list).each do |file| cmd_list << "chmod #{file.start_mode.to_s(8)} '#{file.path}'" end @testcase.on(@agent, cmd_list.join(' && ')) end def puppet_apply @testcase.step(manifest) apply_result = @testcase.apply_manifest_on(@agent, manifest).stdout @testcase.step(apply_result) (@file_list + @directory_list).each do |file| if file.mode_changes? assert_match(/File\[#{Regexp.escape(file.path)}.* mode changed '#{'%04o' % file.start_mode}'.* to '#{'%04o' % file.mode}'/, apply_result, "couldn't set mode to #{file.symbolic_mode}") else refute_match(/#{Regexp.escape(file.path)}.*mode changed/, apply_result, "reapplied the symbolic mode change for file #{file.path}") end assert_mode(@agent, file.path, file.mode) end end end # For your reference: # 4000 the set-user-ID-on-execution bit # 2000 the set-group-ID-on-execution bit # 1000 the sticky bit # 0400 Allow read by owner. # 0200 Allow write by owner. # 0100 For files, allow execution by owner. For directories, allow the # owner to search in the directory. # 0040 Allow read by group members. # 0020 Allow write by group members. # 0010 For files, allow execution by group members. For directories, allow # group members to search in the directory. # 0004 Allow read by others. # 0002 Allow write by others. # 0001 For files, allow execution by others. For directories allow others # to search in the directory. # # On Solaris 11 (from man chmod): # # 20#0 Set group ID on execution if # is 7, 5, 3, or 1. # Enable mandatory locking if # is 6, 4, 2, or 0. # ... # For directories, the set-gid bit can # only be set or cleared by using symbolic mode. # From https://www.gnu.org/software/coreutils/manual/html_node/Symbolic-Modes.html#Symbolic-Modes # Users # u the user who owns the file; # g other users who are in the file's group; # o all other users; # a all users; the same as 'ugo'. # # Operations # + to add the permissions to whatever permissions the users already have for the file; # - to remove the permissions from whatever permissions the users already have for the file; # = to make the permissions the only permissions that the users have for the file. # # Permissions # r the permission the users have to read the file; # w the permission the users have to write to the file; # x the permission the users have to execute the file, or search it if it is a directory. # s the meaning depends on which user (uga) the permission is associated with: # to set set-user-id-on-execution, use 'u' in the users part of the symbolic mode and 's' in the permissions part. # to set set-group-id-on-execution, use 'g' in the users part of the symbolic mode and 's' in the permissions part. # to set both user and group-id-on-execution, omit the users part of the symbolic mode (or use 'a') and use 's' in the permissions part. # t the restricted deletion flag (sticky bit), omit the users part of the symbolic mode (or use 'a') and use 't' in the permissions part. # X execute/search permission is affected only if the file is a directory or already had execute permission. # # Note we do not currently support the Solaris (l) permission: # l mandatory file and record locking refers to a file's ability to have its reading or writing # permissions locked while a program is accessing that file. # agents.each do |agent| is_solaris = agent['platform'].include?('solaris') on(agent, puppet('resource user symuser ensure=present')) on(agent, puppet('resource group symgroup ensure=present')) base_dir_create = agent.tmpdir('symbolic-modes-create_test') base_dir_modify = agent.tmpdir('symbolic-modes-modify_test') teardown do on(agent, puppet('resource user symuser ensure=absent')) on(agent, puppet('resource group symgroup ensure=absent')) on(agent, "rm -rf '#{base_dir_create}' '#{base_dir_modify}'") end create_test = CreateTest.new(self, agent, base_dir_create) create_test.symlink_file('u=r', 00444) create_test.symlink_file('u=w', 00244) create_test.symlink_file('u=x', 00144) create_test.symlink_file('u=rw', 00644) create_test.symlink_file('u=rwx', 00744) create_test.symlink_file('u=rwxt', 01744) create_test.symlink_file('u=rwxs', 04744) create_test.symlink_file('u=rwxts', 05744) create_test.symlink_file('ug=r', 00444) create_test.symlink_file('ug=rw', 00664) create_test.symlink_file('ug=rwx', 00774) create_test.symlink_file('ug=rwxt', 01774) create_test.symlink_file('ug=rwxs', 06774) create_test.symlink_file('ug=rwxts', 07774) create_test.symlink_file('ugo=r', 00444) create_test.symlink_file('ugo=rw', 00666) create_test.symlink_file('ugo=rwx', 00777) create_test.symlink_file('ugo=rwxt', 01777) #create_test.symlink_file('ugo=rwxs', 06777) ## BUG, puppet creates 07777 create_test.symlink_file('ugo=rwxts', 07777) create_test.symlink_file('u=rwx,go=rx', 00755) create_test.symlink_file('u=rwx,g=rx,o=r', 00754) create_test.symlink_file('u=rwx,g=rx,o=', 00750) create_test.symlink_file('a=rwx', 00777) create_test.symlink_file('u+r', 00644) create_test.symlink_file('u+w', 00644) create_test.symlink_file('u+x', 00744) create_test.symlink_directory('u=r', 00455) create_test.symlink_directory('u=w', 00255) create_test.symlink_directory('u=x', 00155) create_test.symlink_directory('u=rw', 00655) create_test.symlink_directory('u=rwx', 00755) create_test.symlink_directory('u=rwxt', 01755) create_test.symlink_directory('u=rwxs', 04755) create_test.symlink_directory('u=rwxts', 05755) create_test.symlink_directory('ug=r', 00445) create_test.symlink_directory('ug=rw', 00665) create_test.symlink_directory('ug=rwx', 00775) create_test.symlink_directory('ug=rwxt', 01775) create_test.symlink_directory('ug=rwxs', 06775) create_test.symlink_directory('ug=rwxts', 07775) create_test.symlink_directory('ugo=r', 00444) create_test.symlink_directory('ugo=rw', 00666) create_test.symlink_directory('ugo=rwx', 00777) create_test.symlink_directory('ugo=rwxt', 01777) #create_test.symlink_directory('ugo=rwxs', 06777) ## BUG, puppet creates 07777 create_test.symlink_directory('ugo=rwxts', 07777) create_test.symlink_directory('u=rwx,go=rx', 00755) create_test.symlink_directory('u=rwx,g=rx,o=r', 00754) create_test.symlink_directory('u=rwx,g=rx,o=', 00750) create_test.symlink_directory('a=rwx', 00777) create_test.symlink_directory('u+r', 00755) create_test.symlink_directory('u+w', 00755) create_test.symlink_directory('u+x', 00755) create_test.puppet_apply() create_test.puppet_reapply() modify_test = ModifyTest.new(self, agent, base_dir_modify) modify_test.symlink_file('u+r', 00200, 00600) modify_test.symlink_file('u+r', 00600, 00600) modify_test.symlink_file('u+w', 00500, 00700) modify_test.symlink_file('u+w', 00400, 00600) modify_test.symlink_file('u+x', 00700, 00700) modify_test.symlink_file('u+x', 00600, 00700) modify_test.symlink_file('u+X', 00100, 00100) modify_test.symlink_file('u+X', 00200, 00200) modify_test.symlink_file('u+X', 00410, 00510) modify_test.symlink_file('a+X', 00600, 00600) modify_test.symlink_file('a+X', 00700, 00711) modify_test.symlink_file('u+s', 00744, 04744) modify_test.symlink_file('g+s', 00744, 02744) modify_test.symlink_file('u+t', 00744, 01744) modify_test.symlink_file('u-r', 00200, 00200) modify_test.symlink_file('u-r', 00600, 00200) modify_test.symlink_file('u-w', 00500, 00500) modify_test.symlink_file('u-w', 00600, 00400) modify_test.symlink_file('u-x', 00700, 00600) modify_test.symlink_file('u-x', 00600, 00600) modify_test.symlink_file('u-s', 04744, 00744) modify_test.symlink_file('g-s', 02744, 00744) modify_test.symlink_file('u-t', 01744, 00744) modify_test.symlink_directory('u+r', 00200, 00600) modify_test.symlink_directory('u+r', 00600, 00600) modify_test.symlink_directory('u+w', 00500, 00700) modify_test.symlink_directory('u+w', 00400, 00600) modify_test.symlink_directory('u+x', 00700, 00700) modify_test.symlink_directory('u+x', 00600, 00700) modify_test.symlink_directory('u+X', 00100, 00100) modify_test.symlink_directory('u+X', 00200, 00300) modify_test.symlink_directory('u+X', 00410, 00510) modify_test.symlink_directory('a+X', 00600, 00711) modify_test.symlink_directory('a+X', 00700, 00711) modify_test.symlink_directory('u+s', 00744, 04744) modify_test.symlink_directory('g+s', 00744, 02744) modify_test.symlink_directory('u+t', 00744, 01744) modify_test.symlink_directory('u-r', 00200, 00200) modify_test.symlink_directory('u-r', 00600, 00200) modify_test.symlink_directory('u-w', 00500, 00500) modify_test.symlink_directory('u-w', 00600, 00400) modify_test.symlink_directory('u-x', 00700, 00600) modify_test.symlink_directory('u-x', 00600, 00600) modify_test.symlink_directory('u-s', 04744, 00744) # using chmod 2744 on a directory to set the start_mode fails on Solaris modify_test.symlink_directory('g-s', 02744, 00744) unless is_solaris modify_test.symlink_directory('u-t', 01744, 00744) modify_test.create_starting_state modify_test.puppet_apply modify_test.puppet_reapply # these raise # test.assert_raises('') # test.assert_raises(' ') # test.assert_raises('u=X') # test.assert_raises('u-X') # test.assert_raises('+l') # test.assert_raises('-l') end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/ticket_6448_file_with_utf8_source.rb000066400000000000000000000067531527241624000336550ustar00rootroot00000000000000test_name 'Ensure a file resource can have a UTF-8 source attribute, content, and path when served via a module' do tag 'audit:high', 'broken:images', 'audit:acceptance', 'server', 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/agent_fqdn_utils' extend Puppet::Acceptance::AgentFqdnUtils tmp_environment = mk_tmp_environment_with_teardown(master, File.basename(__FILE__, '.*')) agent_tmp_dirs = {} agents.each do |agent| agent_tmp_dirs[agent_to_fqdn(agent)] = agent.tmpdir(tmp_environment) end teardown do # note - master teardown is registered by #mk_tmp_environment_with_teardown step 'remove all test files on agents' do agents.each do |agent| on(agent, "rm -r '#{agent_tmp_dirs[agent_to_fqdn(agent)]}'", :accept_all_exit_codes => true) on(agent, puppet('config print lastrunfile')) do |command_result| agent.rm_rf(command_result.stdout) end end end end step 'create unicode source file served via module on master' do # é�™ \u9759 0xE9 0x9D 0x99 http://www.fileformat.info/info/unicode/char/9759/index.htm # çš„ \u7684 0xE7 0x9A 0x84 http://www.fileformat.info/info/unicode/char/7684/index.htm # ☃ \2603 0xE2 0x98 0x83 http://www.fileformat.info/info/unicode/char/2603/index.htm setup_module_on_master = <<-MASTER_MANIFEST File { ensure => directory, mode => "0755", } file { '#{environmentpath}/#{tmp_environment}/modules/utf8_file_module':; '#{environmentpath}/#{tmp_environment}/modules/utf8_file_module/files':; } file { '#{environmentpath}/#{tmp_environment}/modules/utf8_file_module/files/\u9759\u7684': ensure => file, content => "\u2603" } MASTER_MANIFEST apply_manifest_on(master, setup_module_on_master, :expect_changes => true) end step 'create a site.pp on master containing a unicode file resource' do site_pp_contents = <<-SITE_PP \$test_path = \$facts['networking']['fqdn'] ? #{agent_tmp_dirs} file { "\$test_path/\uff72\uff67\u30d5\u30eb": ensure => present, source => "puppet:///modules/utf8_file_module/\u9759\u7684", } SITE_PP create_site_pp = <<-CREATE_SITE_PP file { "#{environmentpath}/#{tmp_environment}/manifests/site.pp": ensure => file, content => @(UTF8) #{site_pp_contents} | UTF8 } CREATE_SITE_PP apply_manifest_on(master, create_site_pp, :expect_changes => true) end step 'ensure agent can manage unicode file resource' do # イ \uff72 0xEF 0xBD 0xB2 http://www.fileformat.info/info/unicode/char/ff72/index.htm # ã‚¡ \uff67 0xEF 0xBD 0xA7 http://www.fileformat.info/info/unicode/char/ff67/index.htm # フ \u30d5 0xE3 0x83 0x95 http://www.fileformat.info/info/unicode/char/30d5/index.htm # ル \u30eb 0xE3 0x83 0xAB http://www.fileformat.info/info/unicode/char/30eb/index.htm with_puppet_running_on(master, {}) do agents.each do |agent| on(agent, puppet("agent -t --environment '#{tmp_environment}'"), :acceptable_exit_codes => 2) on(agent, "cat '#{agent_tmp_dirs[agent_to_fqdn(agent)]}/\uff72\uff67\u30d5\u30eb'") do |result| assert_match("\u2603", result.stdout, "managed UTF-8 file contents '#{result.stdout}' did not match expected value '\u2603'") end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/file/ticket_7680-follow-symlinks.rb000066400000000000000000000024621527241624000324340ustar00rootroot00000000000000test_name "#7680: 'links => follow' should use the file source content" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group3' # For splitting out groups of tests for slow test runners agents.each do |agent| step "Create file content" real_source = agent.tmpfile('follow_links_source') dest = agent.tmpfile('follow_links_dest') symlink = agent.tmpfile('follow_links_symlink') on agent, "echo 'This is the real content' > #{real_source}" if agent['platform'].include?('windows') # cygwin ln doesn't behave properly, fallback to mklink, # but that requires backslashes, that need to be escaped, # and the link cannot exist prior. on agent, "rm -f #{symlink}" on agent, "cmd /c mklink #{symlink.gsub('/', '\\\\\\\\')} #{real_source.gsub('/', '\\\\\\\\')}" else on agent, "ln -sf #{real_source} #{symlink}" end manifest = <<-MANIFEST file { '#{dest}': ensure => file, source => '#{symlink}', links => follow, } MANIFEST apply_manifest_on(agent, manifest, :trace => true) on(agent, "cat #{dest}") do |result| assert_match(/This is the real content/, result.stdout) end step "Cleanup" [real_source, dest, symlink].each do |file| on agent, "rm -f '#{file}'" end end ticket_8740_should_not_enumerate_root_directory.rb000066400000000000000000000031341527241624000366330ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/filetest_name "#8740: should not enumerate root directory" confine :except, :platform => 'windows' confine :except, :platform => 'osx' tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance', 'shard:group4' # For splitting out groups of tests for slow test runners target = "/test-socket-#{$$}" require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::CommandUtils agents.each do |agent| step "clean up the system before we begin" on(agent, "rm -f #{target}") step "create UNIX domain socket" on(agent, "#{ruby_command(agent)} -e \"require 'socket'; UNIXServer::new('#{target}').close\"") step "query for all files, which should return nothing" on(agent, puppet_resource('file'), :acceptable_exit_codes => [1]) do |result| assert_match(%r{Listing all file instances is not supported. Please specify a file or directory, e.g. puppet resource file /etc}, result.stderr) end ["/", "/etc"].each do |file| step "query '#{file}' directory, which should return single entry" on(agent, puppet_resource('file', file)) do |result| files = result.stdout.scan(/^file \{ '([^']+)'/).flatten assert_equal(1, files.size, "puppet returned multiple files: #{files.join(', ')}") assert_match(file, files[0], "puppet did not return file") end end step "query file that does not exist, which should report the file is absent" on(agent, puppet_resource('file', '/this/does/notexist')) do |result| assert_match(/ensure\s+=>\s+'absent'/, result.stdout) end step "remove UNIX domain socket" on(agent, "rm -f #{target}") end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/000077500000000000000000000000001527241624000252025ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/should_create.rb000066400000000000000000000013561527241624000303550ustar00rootroot00000000000000test_name "should create a group" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group1' # For splitting out groups of tests for slow test runners name = "pl#{rand(999999).to_i}" agents.each do |agent| step "ensure the group does not exist" agent.group_absent(name) step "create the group" on agent, puppet_resource('group', name, 'ensure=present') step "verify the group exists" agent.group_get(name) step "delete the group" agent.group_absent(name) end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/should_destroy.rb000066400000000000000000000012751527241624000306030ustar00rootroot00000000000000test_name "should destroy a group" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group2' # For splitting out groups of tests for slow test runners name = "pl#{rand(999999).to_i}" agents.each do |agent| step "ensure the group is present" agent.group_present(name) step "delete the group" on agent, puppet_resource('group', name, 'ensure=absent') step "verify the group was deleted" agent.group_absent(name) end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/should_manage_attributes_aix.rb000066400000000000000000000014241527241624000334450ustar00rootroot00000000000000test_name "should correctly manage the attributes property for the Group (AIX only)" do confine :to, :platform => /aix/ tag 'audit:high', 'audit:acceptance',# Could be done as integration tests, but would # require changing the system running the test # in ways that might require special permissions # or be harmful to the system running the test 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/aix_util' extend Puppet::Acceptance::AixUtil initial_attributes = { 'admin' => true } changed_attributes = { 'admin' => false } run_attribute_management_tests('group', :gid, initial_attributes, changed_attributes) end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/should_manage_members.rb000066400000000000000000000174301527241624000320540ustar00rootroot00000000000000test_name "should correctly manage the members property for the Group resource" do # These are the only platforms whose group providers manage the members # property confine :to, :platform => /windows|osx|aix|^el-|fedora/ tag 'audit:high', 'audit:acceptance',# Could be done as integration tests, but would # require changing the system running the test # in ways that might require special permissions # or be harmful to the system running the test 'shard:group4' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::BeakerUtils def random_name "pl#{rand(999999).to_i}" end def group_manifest(user, params) params_str = params.map do |param, value| value_str = value.to_s value_str = "\"#{value_str}\"" if value.is_a?(String) " #{param} => #{value_str}" end.join(",\n") <<-MANIFEST group { '#{user}': #{params_str} } MANIFEST end def members_of(host, group) case host['platform'] when /windows/ # More verbose than 'net localgroup ', but more programmatic # because it does not require us to parse stdout get_group_members = <<-PS1 # Adapted from https://github.com/RamblingCookieMonster/PowerShell/blob/master/Get-ADGroupMembers.ps1 function Get-Members([string] $group) { $ErrorActionPreference = 'Stop' Add-Type -AssemblyName 'System.DirectoryServices.AccountManagement' -ErrorAction Stop $contextType = [System.DirectoryServices.AccountManagement.ContextType]::Machine $groupObject = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity( $contextType, $group ) if (-Not $groupObject) { throw "Could not find the group '$group'!" } $members = $groupObject.GetMembers($false) | ForEach-Object { "'$($_.Name)'" } write-output "[$([string]::join(',', $members))]" } Get-Members #{group} PS1 Kernel.eval( execute_powershell_script_on(host, get_group_members).stdout.chomp ) else # This reads the group members from the /etc/group file get_group_members = <<-RUBY require 'etc' group_struct = nil Etc.group do |g| if g.name == '#{group}' group_struct = g break end end unless group_struct raise "Could not find the group '#{group}'!" end puts(group_struct.mem.to_s) RUBY script_path = "#{host.tmpfile("get_group_members")}.rb" create_remote_file(host, script_path, get_group_members) # The setup step should have already set :privatebindir on the # host. We only include the default here to make this routine # work for local testing, which sometimes skips the setup step. privatebindir = host.has_key?(:privatebindir) ? host[:privatebindir] : '/opt/puppetlabs/puppet/bin' result = on(host, "#{privatebindir}/ruby #{script_path}") Kernel.eval(result.stdout.chomp) end end agents.each do |agent| users = 6.times.collect { random_name } users.each { |user| agent.user_absent(user) } group = random_name agent.group_absent(group) teardown { agent.group_absent(group) } step 'Creating the Users' do users.each do |user| agent.user_present(user) teardown { agent.user_absent(user) } end end group_members = [users[0], users[1]] step 'Ensure that the group is created with the specified members' do manifest = group_manifest(group, members: group_members) apply_manifest_on(agent, manifest) assert_matching_arrays(group_members, members_of(agent, group), "The group was not successfully created with the specified members!") end step "Verify that Puppet errors when one of the members does not exist" do manifest = group_manifest(group, members: ['nonexistent_member']) apply_manifest_on(agent, manifest, :acceptable_exit_codes => [0, 1]) do |result| assert_match(/Error:.*#{group}/, result.stderr, "Puppet fails to report an error when one of the members in the members property does not exist") end end step "Verify that Puppet noops when the group's members are already set after creating the group" do manifest = group_manifest(group, members: group_members) apply_manifest_on(agent, manifest, catch_changes: true) assert_matching_arrays(group_members, members_of(agent, group), "The group's members somehow changed despite Puppet reporting a noop") end step "Verify that Puppet enforces minimum user membership when auth_membership == false" do new_members = [users[2], users[4]] manifest = group_manifest(group, members: new_members, auth_membership: false) apply_manifest_on(agent, manifest) group_members += new_members assert_matching_arrays(group_members, members_of(agent, group), "Puppet fails to enforce minimum user membership when auth_membership == false") end step "Verify that Puppet noops when the group's members are already set after enforcing minimum user membership" do manifest = group_manifest(group, members: group_members) apply_manifest_on(agent, manifest, catch_changes: true) assert_matching_arrays(group_members, members_of(agent, group), "The group's members somehow changed despite Puppet reporting a noop") end # Run some special, platform-specific tests. If these get too large, then # we should consider placing them in a separate file. case agent['platform'] when /windows/ domain = on(agent, 'hostname').stdout.chomp.upcase step "(Windows) Verify that Puppet prints each group member as DOMAIN\\" do new_members = [users[3]] manifest = group_manifest(group, members: new_members, auth_membership: false) apply_manifest_on(agent, manifest) do |result| group_members += new_members stdout = result.stdout.chomp group_members.each do |user| assert_match(/#{domain}\\#{user}/, stdout, "Puppet fails to print the group member #{user} as #{domain}\\#{user}") end end end step "(Windows) Verify that `puppet resource` prints each group member as DOMAIN\\" do on(agent, puppet('resource', 'group', group)) do |result| stdout = result.stdout.chomp group_members.each do |user| assert_match(/#{domain}\\#{user}/, stdout, "`puppet resource` fails to print the group member #{user} as #{domain}\\#{user}") end end end when /aix/ step "(AIX) Verify that Puppet accepts a comma-separated list of members for backwards compatibility" do new_members = [users[3], users[5]] manifest = group_manifest(group, members: new_members.join(','), auth_membership: false) apply_manifest_on(agent, manifest) group_members += new_members assert_matching_arrays(group_members, members_of(agent, group), "Puppet cannot manage the members property when the members are provided as a comma-separated list") end end step "Verify that Puppet enforces inclusive user membership when auth_membership == true" do group_members = [users[0]] manifest = group_manifest(group, members: group_members, auth_membership: true) apply_manifest_on(agent, manifest) assert_matching_arrays(group_members, members_of(agent, group), "Puppet fails to enforce inclusive group membership when auth_membership == true") end step "Verify that Puppet noops when the group's members are already set after enforcing inclusive user membership" do manifest = group_manifest(group, members: group_members) apply_manifest_on(agent, manifest, catch_changes: true) assert_matching_arrays(group_members, members_of(agent, group), "The group's members somehow changed despite Puppet reporting a noop") end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/should_modify_gid.rb000066400000000000000000000026121527241624000312200ustar00rootroot00000000000000test_name "should modify gid of existing group" confine :except, :platform => 'windows' tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group1' # For splitting out groups of tests for slow test runners name = "pl#{rand(999999).to_i}" gid1 = (rand(989999).to_i + 10000) gid2 = (rand(989999).to_i + 10000) agents.each do |agent| # AIX group provider returns quoted gids step "ensure that the group exists with gid #{gid1}" on(agent, puppet_resource('group', name, 'ensure=present', "gid=#{gid1}")) do |result| fail_test "missing gid notice" unless result.stdout =~ /gid +=> +'?#{gid1}'?/ end step "ensure that we can modify the GID of the group to #{gid2}" on(agent, puppet_resource('group', name, 'ensure=present', "gid=#{gid2}")) do |result| fail_test "missing gid notice" unless result.stdout =~ /gid +=> +'?#{gid2}'?/ end step "verify that the GID changed" gid_output = agent.group_gid(name).to_i fail_test "gid #{gid_output} does not match expected value of: #{gid2}" unless gid_output == gid2 step "clean up the system after the test run" on(agent, puppet_resource('group', name, 'ensure=absent')) end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/should_not_create_existing.rb000066400000000000000000000016221527241624000331430ustar00rootroot00000000000000test_name "group should not create existing group" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group2' # For splitting out groups of tests for slow test runners name = "gr#{rand(999999).to_i}" agents.each do |agent| step "ensure the group exists on the target node" agent.group_present(name) step "verify that we don't try and create the existing group" on(agent, puppet_resource('group', name, 'ensure=present')) do |result| fail_test "looks like we created the group" if result.stdout.include? "/Group[#{name}]/ensure: created" end step "clean up the system after the test run" agent.group_absent(name) end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/should_not_destroy_unexisting.rb000066400000000000000000000015231527241624000337340ustar00rootroot00000000000000test_name "should not destroy a group that doesn't exist" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group3' # For splitting out groups of tests for slow test runners name = "test-group-#{Time.new.to_i}" step "verify the group does not already exist" agents.each do |agent| agent.group_absent(name) end step "verify that we don't remove the group when it doesn't exist" on(agents, puppet_resource('group', name, 'ensure=absent')) do |result| fail_test "it looks like we tried to remove the group" if result.stdout.include? "/Group[#{name}]/ensure: removed" end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/should_query.rb000066400000000000000000000017641527241624000302620ustar00rootroot00000000000000test_name "test that we can query and find a group that exists." tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group4' # For splitting out groups of tests for slow test runners name = "pl#{rand(999999).to_i}" agents.each do |agent| skip_test('this test fails on windows French due to Cygwin/UTF Issues - PUP-8319,IMAGES-492') if agent['platform'] =~ /windows/ && agent['locale'] == 'fr' step "ensure that our test group exists" agent.group_present(name) step "query for the resource and verify it was found" on(agent, puppet_resource('group', name)) do |result| fail_test "didn't find the group #{name}" unless result.stdout.include? 'present' end step "clean up the group we added" agent.group_absent(name) end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/group/should_query_all.rb000066400000000000000000000016741527241624000311120ustar00rootroot00000000000000test_name "should query all groups" tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:integration',# Does not modify system running test 'shard:group1' # For splitting out groups of tests for slow test runners agents.each do |agent| skip_test('this test fails on windows French due to Cygwin/UTF Issues - PUP-8319,IMAGES-492') if agent['platform'] =~ /windows/ && agent['locale'] == 'fr' step "query natively" groups = agent.group_list fail_test("No groups found") unless groups step "query with puppet" on(agent, puppet_resource('group')) do |result| result.stdout.each_line do |line| name = ( line.match(/^group \{ '([^']+)'/) or next )[1] unless groups.delete(name) fail_test "group #{name} found by puppet, not natively" end end end if groups.length > 0 then fail_test "#{groups.length} groups found natively, not puppet: #{groups.join(', ')}" end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/000077500000000000000000000000001527241624000254415ustar00rootroot00000000000000common_package_name_in_different_providers.rb000066400000000000000000000110041527241624000364570ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/packagetest_name "ticket 1073: common package name in two different providers should be allowed" do confine :to, {:platform => /(?:centos|el-|fedora)/}, agents # Skipping tests if facter finds this is an ec2 host, PUP-7774 agents.each do |agent| skip_test('Skipping EC2 Hosts') if fact_on(agent, 'ec2_metadata') end # Upgrade the AlmaLinux release package for newer keys until our image is updated (RE-16096) agents.each do |agent| on(agent, 'dnf -y upgrade almalinux-release') if fact_on(agent, 'os.name') == 'AlmaLinux' end tag 'audit:high', 'audit:acceptance',# Uses a provider that depends on AIO packaging 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/rpm_util' extend Puppet::Acceptance::RpmUtils require 'puppet/acceptance/common_utils' extend Puppet::Acceptance::CommandUtils rpm_options = {:pkg => 'guid', :version => '1.0'} teardown do step "cleanup" agents.each do |agent| clean_rpm agent, rpm_options end end step "Verify gem and ruby-devel on fedora-22 and above if not aio" do if @options[:type] != 'aio' then agents.each do |agent| if agent[:platform] =~ /fedora-2[2-9]/ then unless check_for_package agent, 'rubygems' install_package agent, 'rubygems' end unless check_for_package agent, 'ruby-devel' install_package agent, 'ruby-devel' end end end end end def gem_provider if @options[:type] == 'aio' 'puppet_gem' else 'gem' end end def verify_state(hosts, pkg, state, match) hosts.each do |agent| cmd = rpm_provider(agent) # Note yum lists packages as . on(agent, "#{cmd} list installed") do |result| method(match).call(/^#{pkg}\./, result.stdout) end on(agent, "#{gem_command(agent, @options[:type])} list --local") do |result| method(match).call(/^#{pkg} /, result.stdout) end end end def verify_present(hosts, pkg) verify_state(hosts, pkg, '(?!purged|absent)[^\']+', :assert_match) end def verify_absent(hosts, pkg) verify_state(hosts, pkg, '(?:purged|absent)', :refute_match) end # Setup repo and package agents.each do |agent| clean_rpm agent, rpm_options setup_rpm agent, rpm_options send_rpm agent, rpm_options end verify_absent agents, 'guid' # Test error trying to install duplicate packages collide1_manifest = <<-MANIFEST package {'guid': ensure => installed} package {'other-guid': name => 'guid', ensure => present} MANIFEST apply_manifest_on(agents, collide1_manifest, :acceptable_exit_codes => [1]) do |result| assert_match(/Error while evaluating a Resource Statement, Cannot alias Package\[other-guid\] to \[nil, "guid", nil\]/, "#{result.host}: #{result.stderr}") end verify_absent agents, 'guid' gem_source = if ENV['GEM_SOURCE'] then "source => '#{ENV['GEM_SOURCE']}'," else '' end collide2_manifest = <<-MANIFEST package {'guid': ensure => '0.1.0', provider => #{gem_provider}, #{gem_source}} package {'other-guid': name => 'guid', ensure => installed, provider => #{gem_provider}, #{gem_source}} MANIFEST apply_manifest_on(agents, collide2_manifest, :acceptable_exit_codes => [1]) do |result| assert_match(/Error while evaluating a Resource Statement, Cannot alias Package\[other-guid\] to \[nil, "guid", "#{gem_provider}"\]/, "#{result.host}: #{result.stderr}") end verify_absent agents, 'guid' # Test successful parallel installation install_manifest = <<-MANIFEST package {'guid': ensure => installed} package {'gem-guid': provider => #{gem_provider}, name => 'guid', ensure => installed, #{gem_source} } MANIFEST apply_manifest_on(agents, install_manifest) do |result| assert_match('Package[guid]/ensure: created', "#{result.host}: #{result.stdout}") assert_match('Package[gem-guid]/ensure: created', "#{result.host}: #{result.stdout}") end verify_present agents, 'guid' # Test removal remove_manifest = <<-MANIFEST package {'gem-guid': provider => #{gem_provider}, name => 'guid', ensure => absent, #{gem_source} } package {'guid': ensure => absent} MANIFEST apply_manifest_on(agents, remove_manifest) do |result| assert_match('Package[guid]/ensure: removed', "#{result.host}: #{result.stdout}") assert_match('Package[gem-guid]/ensure: removed', "#{result.host}: #{result.stdout}") end verify_absent agents, 'guid' end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/does_not_exist.rb000066400000000000000000000023701527241624000310160ustar00rootroot00000000000000# Redmine (#22529) test_name "Puppet returns only resource package declaration when querying an uninstalled package" do tag 'audit:high', 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group3' # For splitting out groups of tests for slow test runners agents.each do |agent| step "test puppet resource package" do on(agent, puppet('resource', 'package', 'not-installed-on-this-host')) do |result| assert_match(/package.*not-installed-on-this-host.*\n.*ensure.*(?:absent|purged).*\n.*provider/, result.stdout) end end end # Until #3707 is fixed and purged rpm/yum packages no longer give spurious creation notices # Also skipping solaris, windows whose providers do not have purgeable implemented. confine_block(:to, :platform => /debian|ubuntu/) do agents.each do |agent| step "test puppet apply" do on(agent, puppet('apply', '-e', %Q|"package {'not-installed-on-this-host': ensure => purged }"|)) do |result| refute_match(/warning/i, result.stdout) end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ips/000077500000000000000000000000001527241624000262345ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ips/basic_tests.rb000066400000000000000000000051601527241624000310660ustar00rootroot00000000000000test_name "Package:IPS basic tests" confine :to, :platform => 'solaris-11' tag 'audit:medium', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group4' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/solaris_util' extend Puppet::Acceptance::IPSUtils teardown do step "cleanup" agents.each do |agent| clean agent end end agents.each do |agent| step "IPS: clean slate" clean agent step "IPS: setup" setup agent setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.1' set_publisher agent step "IPS: basic ensure we are clean" apply_manifest_on(agent, 'package {mypkg : ensure=>absent}') on(agent, "pkg list -v mypkg", :acceptable_exit_codes => [1]) do refute_match( /mypkg@0.0.1/, result.stdout, "err: #{agent}") end step "IPS: basic - it should create" apply_manifest_on(agent, 'package {mypkg : ensure=>present}') do assert_match( /ensure: created/, result.stdout, "err: #{agent}") end step "IPS: check it was created" on(agent, puppet("resource package mypkg")) do assert_match( /ensure\s+=> '0\.0\.1[,:]?.*'/, result.stdout, "err: #{agent}") end step "IPS: do not upgrade until latest is mentioned" send_pkg agent,:pkg => 'mypkg@0.0.2' apply_manifest_on(agent, 'package {mypkg : ensure=>present}') do refute_match( /ensure: created/, result.stdout, "err: #{agent}") end step "IPS: verify it was not upgraded" on(agent, puppet("resource package mypkg")) do assert_match( /ensure\s+=> '0\.0\.1[,:]?.*'/, result.stdout, "err: #{agent}") end step "IPS: ask to be latest" apply_manifest_on(agent, 'package {mypkg : ensure=>latest}') step "IPS: ensure it was upgraded" on(agent, puppet("resource package mypkg")) do assert_match( /ensure\s+=> '0\.0\.2[,:]?.*'/, result.stdout, "err: #{agent}") end step "IPS: when there are more than one option, choose latest." send_pkg agent,:pkg => 'mypkg@0.0.3' send_pkg agent,:pkg => 'mypkg@0.0.4' apply_manifest_on(agent, 'package {mypkg : ensure=>latest}') on(agent, puppet("resource package mypkg")) do assert_match( /ensure\s+=> '0\.0\.4[,:]?.*'/, result.stdout, "err: #{agent}") end step "IPS: ensure removed." apply_manifest_on(agent, 'package {mypkg : ensure=>absent}') on(agent, "pkg list -v mypkg", :acceptable_exit_codes => [1]) do refute_match( /mypkg@0.0.1/, result.stdout, "err: #{agent}") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ips/should_be_holdable.rb000066400000000000000000000062101527241624000323560ustar00rootroot00000000000000test_name "Package:IPS versionable" confine :to, :platform => 'solaris-11' tag 'audit:medium', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/solaris_util' extend Puppet::Acceptance::IPSUtils teardown do step "cleanup" agents.each do |agent| clean agent, :pkg => 'mypkg2' clean agent, :pkg => 'mypkg' end end agents.each do |agent| step "IPS: setup" setup agent setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.1' setup_fakeroot2 agent send_pkg2 agent, :pkg => 'mypkg2@0.0.1' set_publisher agent step "IPS: basic - it should create a specific version and install dependent package" apply_manifest_on(agent, 'package {mypkg2 : ensure=>"0.0.1"}') do assert_match( /ensure: created/, result.stdout, "err: #{agent}") end on agent, "pkg list -v mypkg" do assert_match( /mypkg@0.0.1/, result.stdout, "err: #{agent}") end on agent, "pkg list -v mypkg2" do assert_match( /mypkg2@0.0.1/, result.stdout, "err: #{agent}") end step "IPS: it should upgrade current and dependent package" setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.2' setup_fakeroot2 agent send_pkg2 agent, :pkg => 'mypkg2@0.0.2', :pkgdep => 'mypkg@0.0.2' apply_manifest_on(agent, 'package {mypkg2 : ensure=>"0.0.2"}') do assert_match( /changed/, result.stdout, "err: #{agent}") end on agent, "pkg list -v mypkg" do assert_match( /mypkg@0.0.2/, result.stdout, "err: #{agent}") end on agent, "pkg list -v mypkg2" do assert_match( /mypkg2@0.0.2/, result.stdout, "err: #{agent}") end step "IPS: it should not upgrade current and dependent package if dependent package is hold" apply_manifest_on(agent, 'package {mypkg : ensure=>"present", mark=>"hold", provider=>"pkg"}') do assert_match( //, result.stdout, "err: #{agent}") end setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.3' setup_fakeroot2 agent send_pkg2 agent, :pkg => 'mypkg2@0.0.3', :pkgdep => 'mypkg@0.0.3' apply_manifest_on(agent, 'package {mypkg2 : ensure=>"0.0.2"}') do refute_match( /changed/, result.stdout, "err: #{agent}") end on agent, "pkg list -v mypkg" do assert_match( /mypkg@0.0.2/, result.stdout, "err: #{agent}") end on agent, "pkg list -v mypkg2" do assert_match( /mypkg2@0.0.2/, result.stdout, "err: #{agent}") end step "IPS: it should upgrade if hold was released." apply_manifest_on(agent, 'package {mypkg : ensure=>"0.0.3", provider=>"pkg"}') do assert_match( //, result.stdout, "err: #{agent}") end apply_manifest_on(agent, 'package {mypkg2 : ensure=>"0.0.3"}') do assert_match( /changed/, result.stdout, "err: #{agent}") end on agent, "pkg list -v mypkg" do assert_match( /mypkg@0.0.3/, result.stdout, "err: #{agent}") end on agent, "pkg list -v mypkg2" do assert_match( /mypkg2@0.0.3/, result.stdout, "err: #{agent}") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ips/should_be_idempotent.rb000066400000000000000000000043101527241624000327530ustar00rootroot00000000000000test_name "Package:IPS idempotency" confine :to, :platform => 'solaris-11' tag 'audit:medium', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/solaris_util' extend Puppet::Acceptance::IPSUtils teardown do step "cleanup" agents.each do |agent| clean agent end end agents.each do |agent| step "IPS: setup" setup agent setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.1' set_publisher agent step "IPS: it should create" apply_manifest_on(agent, 'package {mypkg : ensure=>present}') do assert_match( /ensure: created/, result.stdout, "err: #{agent}") end step "IPS: should be idempotent (present)" apply_manifest_on(agent, 'package {mypkg : ensure=>present}') do refute_match( /created/, result.stdout, "err: #{agent}") refute_match( /changed/, result.stdout, "err: #{agent}") end send_pkg agent, :pkg => 'mypkg@0.0.2' step "IPS: ask for latest version" apply_manifest_on(agent, 'package {mypkg : ensure=>latest}') step "IPS: ask for latest version again: should be idempotent (latest)" apply_manifest_on(agent, 'package {mypkg : ensure=>latest}') do refute_match( /created/, result.stdout, "err: #{agent}") end step "IPS: ask for specific version" send_pkg agent,:pkg => 'mypkg@0.0.3' apply_manifest_on(agent, 'package {mypkg : ensure=>"0.0.3"}') do assert_match( /changed/, result.stdout, "err: #{agent}") end step "IPS: ask for specific version again: should be idempotent (version)" apply_manifest_on(agent, 'package {mypkg : ensure=>"0.0.3"}') do refute_match( /created/, result.stdout, "err: #{agent}") refute_match( /changed/, result.stdout, "err: #{agent}") end step "IPS: ensure removed." apply_manifest_on(agent, 'package {mypkg : ensure=>absent}') on(agent, "pkg list -v mypkg", :acceptable_exit_codes => [1]) do refute_match( /mypkg/, result.stdout, "err: #{agent}") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ips/should_be_updatable.rb000066400000000000000000000030421527241624000325450ustar00rootroot00000000000000test_name "Package:IPS test for updatable (update, latest)" confine :to, :platform => 'solaris-11' tag 'audit:medium', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/solaris_util' extend Puppet::Acceptance::IPSUtils teardown do step "cleanup" agents.each do |agent| clean agent end end agents.each do |agent| step "IPS: setup" setup agent setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.1' set_publisher agent step "IPS: basic - it should create" apply_manifest_on(agent, 'package {mypkg : ensure=>present}') do assert_match( /ensure: created/, result.stdout, "err: #{agent}") end step "IPS: ask to be latest" send_pkg agent, :pkg => 'mypkg@0.0.2' apply_manifest_on(agent, 'package {mypkg : ensure=>latest}') step "IPS: ensure it was upgraded" on agent, "pkg list -v mypkg" do assert_match( /mypkg@0.0.2/, result.stdout, "err: #{agent}") end step "IPS: when there are more than one option, choose latest." send_pkg agent,:pkg => 'mypkg@0.0.3' send_pkg agent,:pkg => 'mypkg@0.0.4' apply_manifest_on(agent, 'package {mypkg : ensure=>latest}') on agent, "pkg list -v mypkg" do assert_match( /mypkg@0.0.4/, result.stdout, "err: #{agent}") end end should_be_updateable_and_unholdable_at_same_time.rb000066400000000000000000000021561527241624000403660ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ipstest_name "Package:IPS test for updatable holded package" do confine :to, :platform => 'solaris-11' tag 'audit:high', 'shard:group4' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/solaris_util' extend Puppet::Acceptance::IPSUtils agents.each do |agent| teardown do clean agent end step "IPS: setup" do setup agent setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.1' set_publisher agent end step "IPS: it should create and hold in same manifest" do apply_manifest_on(agent, 'package {mypkg : ensure=>"0.0.1", mark=>hold}') do |result| assert_match( /ensure: created/, result.stdout, "err: #{agent}") end end step "IPS: it should update and unhold in same manifest" do send_pkg agent, :pkg => 'mypkg@0.0.2' apply_manifest_on(agent, 'package {mypkg : ensure=>"0.0.2", mark=>"none"}') end step "IPS: ensure it was upgraded" do on agent, "pkg list -v mypkg" do |result| assert_match( /mypkg@0.0.2/, result.stdout, "err: #{agent}") end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ips/should_be_versionable.rb000066400000000000000000000034421527241624000331210ustar00rootroot00000000000000test_name "Package:IPS versionable" confine :to, :platform => 'solaris-11' tag 'audit:medium', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/solaris_util' extend Puppet::Acceptance::IPSUtils teardown do step "cleanup" agents.each do |agent| clean agent end end agents.each do |agent| step "IPS: setup" setup agent setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.1' send_pkg agent, :pkg => 'mypkg@0.0.2' set_publisher agent step "IPS: basic - it should create a specific version" apply_manifest_on(agent, 'package {mypkg : ensure=>"0.0.1"}') do assert_match( /ensure: created/, result.stdout, "err: #{agent}") end on agent, "pkg list mypkg" do assert_match( /0.0.1/, result.stdout, "err: #{agent}") end step "IPS: it should upgrade if asked for next version" apply_manifest_on(agent, 'package {mypkg : ensure=>"0.0.2"}') do assert_match( /ensure changed/, result.stdout, "err: #{agent}") end on agent, "pkg list mypkg" do refute_match( /0.0.1/, result.stdout, "err: #{agent}") assert_match( /0.0.2/, result.stdout, "err: #{agent}") end step "IPS: it should downpgrade if asked for previous version" apply_manifest_on(agent, 'package {mypkg : ensure=>"0.0.1"}') do assert_match( /ensure changed/, result.stdout, "err: #{agent}") end on agent, "pkg list mypkg" do refute_match( /0.0.2/, result.stdout, "err: #{agent}") assert_match( /0.0.1/, result.stdout, "err: #{agent}") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ips/should_create.rb000066400000000000000000000023661527241624000314110ustar00rootroot00000000000000test_name "Package:IPS basic tests" confine :to, :platform => 'solaris-11' tag 'audit:medium', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/solaris_util' extend Puppet::Acceptance::IPSUtils teardown do step "cleanup" agents.each do |agent| clean agent end end agents.each do |agent| step "IPS: clean slate" clean agent step "IPS: setup" setup agent setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.1' set_publisher agent step "IPS: basic - it should create" apply_manifest_on(agent, 'package {mypkg : ensure=>present}') do assert_match( /ensure: created/, result.stdout, "err: #{agent}") end step "IPS: check it was created" on(agent, puppet("resource package mypkg")) do assert_match( /ensure\s+=> '0\.0\.1[,:]?.*'/, result.stdout, "err: #{agent}") end on agent, "pkg list -v mypkg" do assert_match( /mypkg@0.0.1/, result.stdout, "err: #{agent}") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ips/should_query.rb000066400000000000000000000022241527241624000313040ustar00rootroot00000000000000test_name "Package:IPS query" confine :to, :platform => 'solaris-11' tag 'audit:medium', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group3' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/solaris_util' extend Puppet::Acceptance::IPSUtils teardown do step "cleanup" agents.each do |agent| clean agent end end agents.each do |agent| step "IPS: setup" setup agent setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.1' set_publisher agent step "IPS: basic - it should create" apply_manifest_on(agent, 'package {mypkg : ensure=>"present"}') do assert_match( /ensure: created/, result.stdout, "err: #{agent}") end on(agent, puppet("resource package mypkg")) do assert_match( /0.0.1/, result.stdout, "err: #{agent}") end on(agent, puppet("resource package")) do assert_match( /0.0.1/, result.stdout, "err: #{agent}") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/ips/should_remove.rb000066400000000000000000000021671527241624000314420ustar00rootroot00000000000000test_name "Package:IPS basic tests" confine :to, :platform => 'solaris-11' tag 'audit:medium', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group4' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/solaris_util' extend Puppet::Acceptance::IPSUtils teardown do step "cleanup" agents.each do |agent| clean agent end end agents.each do |agent| step "IPS: setup" setup agent setup_fakeroot agent send_pkg agent, :pkg => 'mypkg@0.0.1' set_publisher agent on agent, "pkg install mypkg" on agent, "pkg list -v mypkg" do assert_match( /mypkg@0.0.1/, result.stdout, "err: #{agent}") end step "IPS: ensure removed." apply_manifest_on(agent, 'package {mypkg : ensure=>absent}') on(agent, "pkg list -v mypkg", :acceptable_exit_codes => [1]) do refute_match( /mypkg@0.0.1/, result.stdout, "err: #{agent}") end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/windows.rb000066400000000000000000000054271527241624000274700ustar00rootroot00000000000000test_name "Windows Package Provider" do confine :to, :platform => 'windows' tag 'audit:high', 'audit:acceptance', 'shard:group1' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/windows_utils' extend Puppet::Acceptance::WindowsUtils def package_manifest(name, params, installer_source) params_str = params.map do |param, value| value_str = value.to_s value_str = "\"#{value_str}\"" if value.is_a?(String) " #{param} => #{value_str}" end.join(",\n") <<-MANIFEST package { '#{name}': source => '#{installer_source}', #{params_str} } MANIFEST end mock_package = { :name => "MockPackage" } agents.each do |agent| tmpdir = agent.tmpdir("mock_installer") installer_location = create_mock_package(agent, tmpdir, mock_package) step 'Verify that ensure = present installs the package' do apply_manifest_on(agent, package_manifest(mock_package[:name], {ensure: :present}, installer_location)) assert(package_installed?(agent, mock_package[:name]), 'Package succesfully installed') end step 'Verify that ensure = absent removes the package' do apply_manifest_on(agent, package_manifest(mock_package[:name], {ensure: :absent}, installer_location)) assert_equal(false, package_installed?(agent, mock_package[:name]), 'Package successfully Uninstalled') end tmpdir = agent.tmpdir("mock_installer") mock_package[:name] = "MockPackageWithFile" mock_package[:install_commands] = 'System.IO.File.ReadAllLines("install.txt");' installer_location = create_mock_package(agent, tmpdir, mock_package) # Since we didn't add the install.txt package the installation should fail with code 1004 step 'Verify that ensure = present fails when an installer fails with a non-zero exit code' do apply_manifest_on(agent, package_manifest(mock_package[:name], {ensure: :present}, installer_location)) do |result| assert_match(/#{mock_package[:name]}/, result.stderr, 'Windows package provider did not fail when the package install failed') end end step 'Verify that ensure = present installs a package that requires additional resources' do create_remote_file(agent, "#{tmpdir}/install.txt", 'foobar') apply_manifest_on(agent, package_manifest(mock_package[:name], {ensure: :present}, installer_location)) assert(package_installed?(agent, mock_package[:name]), 'Package succesfully installed') end step 'Verify that ensure = absent removes the package that required additional resources' do apply_manifest_on(agent, package_manifest(mock_package[:name], {ensure: :absent}, installer_location)) assert_equal(false, package_installed?(agent, mock_package[:name]), 'Package successfully Uninstalled') end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/package/yum.rb000066400000000000000000000203111527241624000265750ustar00rootroot00000000000000test_name "test the yum package provider" do confine :to, {:platform => /(?:centos|el-|fedora)/}, agents # Skipping tests if facter finds this is an ec2 host, PUP-7774 agents.each do |agent| skip_test('Skipping EC2 Hosts') if fact_on(agent, 'ec2_metadata') end # Upgrade the AlmaLinux release package for newer keys until our image is updated (RE-16096) agents.each do |agent| on(agent, 'dnf -y upgrade almalinux-release') if fact_on(agent, 'os.name') == 'AlmaLinux' end tag 'audit:high', 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group2' # For splitting out groups of tests for slow test runners require 'puppet/acceptance/rpm_util' extend Puppet::Acceptance::RpmUtils epoch_rpm_options = {:pkg => 'epoch', :version => '1.1', :epoch => '1'} no_epoch_rpm_options = {:pkg => 'guid', :version => '1.0'} teardown do step "cleanup" agents.each do |agent| clean_rpm agent, epoch_rpm_options clean_rpm agent, no_epoch_rpm_options end end def verify_state(hosts, pkg, state, match) hosts.each do |agent| cmd = rpm_provider(agent) # Note yum and dnf list packages as . on(agent, "#{cmd} list installed") do |result| method(match).call(/^#{pkg}\./, result.stdout) end end end def verify_present(hosts, pkg) verify_state(hosts, pkg, '(?!purged|absent)[^\']+', :assert_match) end def verify_absent(hosts, pkg) verify_state(hosts, pkg, '(?:purged|absent)', :refute_match) end step "Managing a package which does not include an epoch in its version" do step 'Setup repo and package' agents.each do |agent| clean_rpm agent, no_epoch_rpm_options setup_rpm agent, no_epoch_rpm_options send_rpm agent, no_epoch_rpm_options end step 'Installing a known package succeeds' do verify_absent agents, 'guid' apply_manifest_on(agents, 'package {"guid": ensure => installed}') do |result| assert_match('Package[guid]/ensure: created', "#{result.host}: #{result.stdout}") end end step 'Removing a known package succeeds' do verify_present agents, 'guid' apply_manifest_on(agents, 'package {"guid": ensure => absent}') do |result| assert_match('Package[guid]/ensure: removed', "#{result.host}: #{result.stdout}") end end step 'Installing a specific version of a known package succeeds' do verify_absent agents, 'guid' apply_manifest_on(agents, 'package {"guid": ensure => "1.0"}') do |result| assert_match('Package[guid]/ensure: created', "#{result.host}: #{result.stdout}") end end step 'Removing a specific version of a known package succeeds' do verify_present agents, 'guid' apply_manifest_on(agents, 'package {"guid": ensure => absent}') do |result| assert_match('Package[guid]/ensure: removed', "#{result.host}: #{result.stdout}") end end step 'Installing a non-existent version of a known package fails' do verify_absent agents, 'guid' apply_manifest_on(agents, 'package {"guid": ensure => "1.1"}') do |result| refute_match(/Package\[guid\]\/ensure: created/, "#{result.host}: #{result.stdout}") assert_match("Package[guid]/ensure: change from 'purged' to '1.1' failed", "#{result.host}: #{result.stderr}") end verify_absent agents, 'guid' end step 'Installing a non-existent package fails' do verify_absent agents, 'not_a_package' apply_manifest_on(agents, 'package {"not_a_package": ensure => present}') do |result| refute_match(/Package\[not_a_package\]\/ensure: created/, "#{result.host}: #{result.stdout}") assert_match("Package[not_a_package]/ensure: change from 'purged' to 'present' failed", "#{result.host}: #{result.stderr}") end verify_absent agents, 'not_a_package' end step 'Removing a non-existent package succeeds' do verify_absent agents, 'not_a_package' apply_manifest_on(agents, 'package {"not_a_package": ensure => absent}') do |result| refute_match(/Package\[not_a_package\]\/ensure/, "#{result.host}: #{result.stdout}") assert_match('Applied catalog', "#{result.host}: #{result.stdout}") end verify_absent agents, 'not_a_package' end step 'Installing a known package using source succeeds' do verify_absent agents, 'guid' apply_manifest_on(agents, "package { 'guid': ensure => installed, install_options => '--nogpgcheck', source=>'/tmp/rpmrepo/RPMS/noarch/guid-1.0-1.noarch.rpm' }") do |result| assert_match('Package[guid]/ensure: created', "#{result.host}: #{result.stdout}") end end end ### Epoch tests ### agents.each do |agent| step "Managing a package which includes an epoch in its version" do step "Setup repo and package" do clean_rpm agent, no_epoch_rpm_options setup_rpm agent, epoch_rpm_options send_rpm agent, epoch_rpm_options end step 'Installing a known package with an epoch succeeds' do verify_absent [agent], 'epoch' apply_manifest_on(agent, 'package {"epoch": ensure => installed}') do |result| assert_match('Package[epoch]/ensure: created', "#{result.host}: #{result.stdout}") end end step 'Removing a known package with an epoch succeeds' do verify_present [agent], 'epoch' apply_manifest_on(agent, 'package {"epoch": ensure => absent}') do |result| assert_match('Package[epoch]/ensure: removed', "#{result.host}: #{result.stdout}") end end step "Installing a specific version of a known package with an epoch succeeds when epoch and arch are specified" do verify_absent [agent], 'epoch' apply_manifest_on(agent, "package {'epoch': ensure => '1:1.1-1.noarch'}") do |result| assert_match('Package[epoch]/ensure: created', "#{result.host}: #{result.stdout}") end apply_manifest_on(agent, "package {'epoch': ensure => '1:1.1-1.noarch'}") do |result| refute_match(/epoch/, result.stdout) end end if rpm_provider(agent) == 'dnf' # Yum requires the arch to be specified whenever epoch is specified. This step is only # expected to work in DNF. step "Installing a specific version of a known package with an epoch succeeds when epoch is specified and arch is not" do step "Remove the package" do apply_manifest_on(agent, 'package {"epoch": ensure => absent}') verify_absent [agent], 'epoch' end apply_manifest_on(agent, 'package {"epoch": ensure => "1:1.1-1"}') do |result| assert_match('Package[epoch]/ensure: created', "#{result.host}: #{result.stdout}") end apply_manifest_on(agent, 'package {"epoch": ensure => "1:1.1-1"}') do |result| refute_match(/epoch/, result.stdout) end apply_manifest_on(agent, "package {'epoch': ensure => '1:1.1-1.noarch'}") do |result| refute_match(/epoch/, result.stdout) end end end if rpm_provider(agent) == 'yum' step "Installing a specified version of a known package with an epoch succeeds without epoch or arch provided" do # Due to a bug in DNF, epoch is required. This step is only expected to work in Yum. # See https://bugzilla.redhat.com/show_bug.cgi?id=1286877 step "Remove the package" do apply_manifest_on(agent, 'package {"epoch": ensure => absent}') verify_absent [agent], 'epoch' end apply_manifest_on(agent, 'package {"epoch": ensure => "1.1-1"}') do |result| assert_match('Package[epoch]/ensure: created', "#{result.host}: #{result.stdout}") end apply_manifest_on(agent, 'package {"epoch": ensure => "1.1-1"}') do |result| refute_match(/epoch/, result.stdout) end apply_manifest_on(agent, "package {'epoch': ensure => '1:1.1-1.noarch'}") do |result| refute_match(/epoch/, result.stdout) end end end end end end OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/service/000077500000000000000000000000001527241624000255065ustar00rootroot00000000000000OpenVoxProject-openvox-ebcec1e/acceptance/tests/resource/service/AIX_service_provider.rb000066400000000000000000000065321527241624000321140ustar00rootroot00000000000000test_name 'AIX Service Provider Testing' tag 'audit:high', 'audit:refactor', # Use block style `test_name` 'audit:acceptance',# Could be done at the integration (or unit) layer though # actual changing of resources could irreparably damage a # host running this, or require special permissions. 'shard:group3' # For splitting out groups of tests for slow test runners confine :to, :platform => 'aix' require 'puppet/acceptance/service_utils' extend Puppet::Acceptance::ServiceUtils sloth_daemon_script = <