diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index d59437a..4021da7 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,230 +1,217 @@ name: "nightly" on: schedule: - cron: '0 0 * * *' env: HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6 HONEYCOMB_DATASET: litmus tests jobs: setup_matrix: name: "Setup Test Matrix" runs-on: ubuntu-20.04 outputs: matrix: ${{ steps.get-matrix.outputs.matrix }} steps: - name: "Honeycomb: Start recording" - uses: kvrhdn/gha-buildevents@v1.0.2 + uses: kvrhdn/gha-buildevents@5be4636b81803713c94d7cb7e3a4b85d759df112 # pin@v1.0.2 with: apikey: ${{ env.HONEYCOMB_WRITEKEY }} dataset: ${{ env.HONEYCOMB_DATASET }} job-status: ${{ job.status }} - name: "Honeycomb: Start first step" run: | echo STEP_ID=0 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Checkout Source uses: actions/checkout@v2 if: ${{ github.repository_owner == 'puppetlabs' }} - name: Activate Ruby 2.7 uses: actions/setup-ruby@v1 if: ${{ github.repository_owner == 'puppetlabs' }} with: ruby-version: "2.7" - name: Cache gems uses: actions/cache@v2 if: ${{ github.repository_owner == 'puppetlabs' }} with: path: vendor/gems key: ${{ runner.os }}-${{ github.event_name }}-${{ hashFiles('**/Gemfile') }} restore-keys: | ${{ runner.os }}-${{ github.event_name }}- ${{ runner.os }}- - name: Install gems if: ${{ github.repository_owner == 'puppetlabs' }} run: | buildevents cmd $TRACE_ID $STEP_ID 'bundle config path vendor/gems' -- bundle config path vendor/gems buildevents cmd $TRACE_ID $STEP_ID 'bundle config jobs 8' -- bundle config jobs 8 buildevents cmd $TRACE_ID $STEP_ID 'bundle config retry 3' -- bundle config retry 3 buildevents cmd $TRACE_ID $STEP_ID 'bundle install' -- bundle install buildevents cmd $TRACE_ID $STEP_ID 'bundle clean' -- bundle clean - name: Setup Acceptance Test Matrix id: get-matrix if: ${{ github.repository_owner == 'puppetlabs' }} run: | if [ '${{ github.repository_owner }}' == 'puppetlabs' ]; then buildevents cmd $TRACE_ID $STEP_ID matrix_from_metadata -- bundle exec matrix_from_metadata else echo "::set-output name=matrix::{}" fi - name: "Honeycomb: Record setup time" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Test Matrix' Acceptance: needs: - setup_matrix runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: ${{fromJson(needs.setup_matrix.outputs.matrix)}} env: BUILDEVENT_FILE: '../buildevents.txt' steps: - run: | echo 'platform=${{ matrix.platform }}' >> $BUILDEVENT_FILE echo 'collection=${{ matrix.collection }}' >> $BUILDEVENT_FILE - name: "Honeycomb: Start recording" - uses: kvrhdn/gha-buildevents@v1.0.2 + uses: kvrhdn/gha-buildevents@5be4636b81803713c94d7cb7e3a4b85d759df112 # pin@v1.0.2 with: apikey: ${{ env.HONEYCOMB_WRITEKEY }} dataset: ${{ env.HONEYCOMB_DATASET }} job-status: ${{ job.status }} matrix-key: ${{ matrix.platform }}-${{ matrix.collection }} - name: "Honeycomb: start first step" run: | echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-1 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Checkout Source uses: actions/checkout@v2 - name: Activate Ruby 2.7 uses: actions/setup-ruby@v1 with: ruby-version: "2.7" - name: Cache gems uses: actions/cache@v2 with: path: vendor/gems key: ${{ runner.os }}-${{ github.event_name }}-${{ hashFiles('**/Gemfile') }} restore-keys: | ${{ runner.os }}-${{ github.event_name }}- ${{ runner.os }}- - name: "Honeycomb: Record cache setup time" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Cache retrieval' echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-2 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Bundler Setup run: | buildevents cmd $TRACE_ID $STEP_ID 'bundle config path vendor/gems' -- bundle config path vendor/gems buildevents cmd $TRACE_ID $STEP_ID 'bundle config jobs 8' -- bundle config jobs 8 buildevents cmd $TRACE_ID $STEP_ID 'bundle config retry 3' -- bundle config retry 3 buildevents cmd $TRACE_ID $STEP_ID 'bundle install' -- bundle install buildevents cmd $TRACE_ID $STEP_ID 'bundle clean' -- bundle clean echo ::group::bundler environment buildevents cmd $TRACE_ID $STEP_ID 'bundle env' -- bundle env echo ::endgroup:: - name: "Honeycomb: Record Bundler Setup time" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Bundler Setup' echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-3 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Provision test environment run: | buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:provision ${{ matrix.platform }}' -- bundle exec rake 'litmus:provision[provision::provision_service,${{ matrix.platform }}]' echo ::group::=== REQUEST === cat request.json || true echo echo ::endgroup:: echo ::group::=== INVENTORY === sed -e 's/password: .*/password: "[redacted]"/' < inventory.yaml || true echo ::endgroup:: - # The provision service hands out machines as soon as they're provisioned. - # The GCP VMs might still take a while to spool up and configure themselves fully. - # This retry loop spins until all agents have been installed successfully. - name: Install agent - uses: nick-invision/retry@v1 - with: - timeout_minutes: 30 - max_attempts: 5 - retry_wait_seconds: 60 - command: buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_agent ${{ matrix.collection }}' -- bundle exec rake 'litmus:install_agent[${{ matrix.collection }}]' + run: | + buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_agent ${{ matrix.collection }}' -- bundle exec rake 'litmus:install_agent[${{ matrix.collection }}]' - # The agent installer on windows does not finish in time for this to work. To - # work around this for now, retry after a minute if installing the module failed. - name: Install module - uses: nick-invision/retry@v1 - with: - timeout_minutes: 30 - max_attempts: 2 - retry_wait_seconds: 60 - command: buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_module' -- bundle exec rake 'litmus:install_module' + run: | + buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_module' -- bundle exec rake 'litmus:install_module' - name: "Honeycomb: Record deployment times" if: ${{ always() }} run: | echo ::group::honeycomb step buildevents step $TRACE_ID $STEP_ID $STEP_START 'Deploy test system' echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-4 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV echo ::endgroup:: - name: Run acceptance tests run: | buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:acceptance:parallel' -- bundle exec rake 'litmus:acceptance:parallel' - name: "Honeycomb: Record acceptance testing times" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Run acceptance tests' echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-5 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Remove test environment if: ${{ always() }} run: | if [ -f inventory.yaml ]; then buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:tear_down' -- bundle exec rake 'litmus:tear_down' echo ::group::=== REQUEST === cat request.json || true echo echo ::endgroup:: fi - name: "Honeycomb: Record removal times" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Remove test environment' slack-workflow-status: if: always() name: Post Workflow Status To Slack needs: - Acceptance runs-on: ubuntu-20.04 steps: - name: Slack Workflow Notification - uses: Gamesight/slack-workflow-status@master + uses: Gamesight/slack-workflow-status@88ee95b73b4669825883ddf22747966204663e58 # pin@master with: # Required Input repo_token: ${{ secrets.GITHUB_TOKEN }} slack_webhook_url: ${{ secrets.SLACK_WEBHOOK }} # Optional Input channel: '#team-ia-bots' name: 'GABot' diff --git a/.github/workflows/pr_test.yml b/.github/workflows/pr_test.yml index 17f5a64..2b5ab1f 100644 --- a/.github/workflows/pr_test.yml +++ b/.github/workflows/pr_test.yml @@ -1,211 +1,198 @@ name: "PR Testing" on: [pull_request] env: HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6 HONEYCOMB_DATASET: litmus tests jobs: setup_matrix: name: "Setup Test Matrix" runs-on: ubuntu-20.04 outputs: matrix: ${{ steps.get-matrix.outputs.matrix }} steps: - name: "Honeycomb: Start recording" - uses: kvrhdn/gha-buildevents@v1.0.2 + uses: kvrhdn/gha-buildevents@5be4636b81803713c94d7cb7e3a4b85d759df112 # pin@v1.0.2 with: apikey: ${{ env.HONEYCOMB_WRITEKEY }} dataset: ${{ env.HONEYCOMB_DATASET }} job-status: ${{ job.status }} - name: "Honeycomb: Start first step" run: | echo STEP_ID=0 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Checkout Source uses: actions/checkout@v2 if: ${{ github.repository_owner == 'puppetlabs' }} - name: Activate Ruby 2.7 uses: actions/setup-ruby@v1 if: ${{ github.repository_owner == 'puppetlabs' }} with: ruby-version: "2.7" - name: Cache gems uses: actions/cache@v2 if: ${{ github.repository_owner == 'puppetlabs' }} with: path: vendor/gems key: ${{ runner.os }}-${{ github.event_name }}-${{ hashFiles('**/Gemfile') }} restore-keys: | ${{ runner.os }}-${{ github.event_name }}- ${{ runner.os }}- - name: Install gems if: ${{ github.repository_owner == 'puppetlabs' }} run: | buildevents cmd $TRACE_ID $STEP_ID 'bundle config path vendor/gems' -- bundle config path vendor/gems buildevents cmd $TRACE_ID $STEP_ID 'bundle config jobs 8' -- bundle config jobs 8 buildevents cmd $TRACE_ID $STEP_ID 'bundle config retry 3' -- bundle config retry 3 buildevents cmd $TRACE_ID $STEP_ID 'bundle install' -- bundle install buildevents cmd $TRACE_ID $STEP_ID 'bundle clean' -- bundle clean - name: Setup Acceptance Test Matrix id: get-matrix if: ${{ github.repository_owner == 'puppetlabs' }} run: | if [ '${{ github.repository_owner }}' == 'puppetlabs' ]; then buildevents cmd $TRACE_ID $STEP_ID matrix_from_metadata -- bundle exec matrix_from_metadata else echo "::set-output name=matrix::{}" fi - name: "Honeycomb: Record setup time" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Test Matrix' Acceptance: needs: - setup_matrix runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: ${{fromJson(needs.setup_matrix.outputs.matrix)}} env: BUILDEVENT_FILE: '../buildevents.txt' steps: - run: | echo 'platform=${{ matrix.platform }}' >> $BUILDEVENT_FILE echo 'collection=${{ matrix.collection }}' >> $BUILDEVENT_FILE - name: "Honeycomb: Start recording" - uses: kvrhdn/gha-buildevents@v1.0.2 + uses: kvrhdn/gha-buildevents@5be4636b81803713c94d7cb7e3a4b85d759df112 # pin@v1.0.2 with: apikey: ${{ env.HONEYCOMB_WRITEKEY }} dataset: ${{ env.HONEYCOMB_DATASET }} job-status: ${{ job.status }} matrix-key: ${{ matrix.platform }}-${{ matrix.collection }} - name: "Honeycomb: start first step" run: | echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-1 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Checkout Source uses: actions/checkout@v2 - name: Activate Ruby 2.7 uses: actions/setup-ruby@v1 with: ruby-version: "2.7" - name: Cache gems uses: actions/cache@v2 with: path: vendor/gems key: ${{ runner.os }}-${{ github.event_name }}-${{ hashFiles('**/Gemfile') }} restore-keys: | ${{ runner.os }}-${{ github.event_name }}- ${{ runner.os }}- - name: "Honeycomb: Record cache setup time" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Cache retrieval' echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-2 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Bundler Setup run: | buildevents cmd $TRACE_ID $STEP_ID 'bundle config path vendor/gems' -- bundle config path vendor/gems buildevents cmd $TRACE_ID $STEP_ID 'bundle config jobs 8' -- bundle config jobs 8 buildevents cmd $TRACE_ID $STEP_ID 'bundle config retry 3' -- bundle config retry 3 buildevents cmd $TRACE_ID $STEP_ID 'bundle install' -- bundle install buildevents cmd $TRACE_ID $STEP_ID 'bundle clean' -- bundle clean echo ::group::bundler environment buildevents cmd $TRACE_ID $STEP_ID 'bundle env' -- bundle env echo ::endgroup:: - name: "Honeycomb: Record Bundler Setup time" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Bundler Setup' echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-3 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Provision test environment run: | buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:provision ${{ matrix.platform }}' -- bundle exec rake 'litmus:provision[provision::provision_service,${{ matrix.platform }}]' echo ::group::=== REQUEST === cat request.json || true echo echo ::endgroup:: echo ::group::=== INVENTORY === sed -e 's/password: .*/password: "[redacted]"/' < inventory.yaml || true echo ::endgroup:: - # The provision service hands out machines as soon as they're provisioned. - # The GCP VMs might still take a while to spool up and configure themselves fully. - # This retry loop spins until all agents have been installed successfully. - name: Install agent - uses: nick-invision/retry@v1 - with: - timeout_minutes: 30 - max_attempts: 5 - retry_wait_seconds: 60 - command: buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_agent ${{ matrix.collection }}' -- bundle exec rake 'litmus:install_agent[${{ matrix.collection }}]' + run: | + buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_agent ${{ matrix.collection }}' -- bundle exec rake 'litmus:install_agent[${{ matrix.collection }}]' - # The agent installer on windows does not finish in time for this to work. To - # work around this for now, retry after a minute if installing the module failed. - name: Install module - uses: nick-invision/retry@v1 - with: - timeout_minutes: 30 - max_attempts: 2 - retry_wait_seconds: 60 - command: buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_module' -- bundle exec rake 'litmus:install_module' + run: | + buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_module' -- bundle exec rake 'litmus:install_module' - name: "Honeycomb: Record deployment times" if: ${{ always() }} run: | echo ::group::honeycomb step buildevents step $TRACE_ID $STEP_ID $STEP_START 'Deploy test system' echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-4 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV echo ::endgroup:: - name: Run acceptance tests run: | buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:acceptance:parallel' -- bundle exec rake 'litmus:acceptance:parallel' - name: "Honeycomb: Record acceptance testing times" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Run acceptance tests' echo STEP_ID=${{ matrix.platform }}-${{ matrix.collection }}-5 >> $GITHUB_ENV echo STEP_START=$(date +%s) >> $GITHUB_ENV - name: Remove test environment if: ${{ always() }} run: | if [ -f inventory.yaml ]; then buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:tear_down' -- bundle exec rake 'litmus:tear_down' echo ::group::=== REQUEST === cat request.json || true echo echo ::endgroup:: fi - name: "Honeycomb: Record removal times" if: ${{ always() }} run: | buildevents step $TRACE_ID $STEP_ID $STEP_START 'Remove test environment' diff --git a/.rubocop.yml b/.rubocop.yml index b7c972b..1823837 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,138 +1,538 @@ --- require: +- rubocop-performance - rubocop-rspec -- rubocop-i18n AllCops: DisplayCopNames: true - TargetRubyVersion: '2.1' + TargetRubyVersion: '2.4' Include: - - "./**/*.rb" + - "**/*.rb" Exclude: - bin/* - ".vendor/**/*" - "**/Gemfile" - "**/Rakefile" - pkg/**/* - spec/fixtures/**/* - vendor/**/* - "**/Puppetfile" - "**/Vagrantfile" - "**/Guardfile" -Metrics/LineLength: +Layout/LineLength: Description: People have wide screens, use them. Max: 200 -GetText: - Enabled: false -GetText/DecorateString: - Description: We don't want to decorate test output. - Exclude: - - spec/**/* - Enabled: false RSpec/BeforeAfterAll: Description: Beware of using after(:all) as it may cause state to leak between tests. A necessary evil in acceptance testing. Exclude: - spec/acceptance/**/*.rb RSpec/HookArgument: Description: Prefer explicit :each argument, matching existing module's style EnforcedStyle: each Style/BlockDelimiters: Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to be consistent then. EnforcedStyle: braces_for_chaining -Style/BracesAroundHashParameters: - Description: Braces are required by Ruby 2.7. Cop removed from RuboCop v0.80.0. - See https://github.com/rubocop-hq/rubocop/pull/7643 - Enabled: false Style/ClassAndModuleChildren: Description: Compact style reduces the required amount of indentation. EnforcedStyle: compact Style/EmptyElse: Description: Enforce against empty else clauses, but allow `nil` for clarity. EnforcedStyle: empty Style/FormatString: Description: Following the main puppet project's style, prefer the % format format. EnforcedStyle: percent Style/FormatStringToken: Description: Following the main puppet project's style, prefer the simpler template tokens over annotated ones. EnforcedStyle: template Style/Lambda: Description: Prefer the keyword for easier discoverability. EnforcedStyle: literal Style/RegexpLiteral: Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 EnforcedStyle: percent_r Style/TernaryParentheses: Description: Checks for use of parentheses around ternary conditions. Enforce parentheses on complex expressions for better readability, but seriously consider breaking it up. EnforcedStyle: require_parentheses_when_complex Style/TrailingCommaInArguments: Description: Prefer always trailing comma on multiline argument lists. This makes diffs, and re-ordering nicer. EnforcedStyleForMultiline: comma -Style/TrailingCommaInLiteral: +Style/TrailingCommaInArrayLiteral: Description: Prefer always trailing comma on multiline literals. This makes diffs, and re-ordering nicer. EnforcedStyleForMultiline: comma Style/SymbolArray: Description: Using percent style obscures symbolic intent of array's contents. EnforcedStyle: brackets -inherit_from: ".rubocop_todo.yml" RSpec/MessageSpies: EnforcedStyle: receive Style/Documentation: Exclude: - lib/puppet/parser/functions/**/* - spec/**/* Style/WordArray: EnforcedStyle: brackets +Performance/AncestorsInclude: + Enabled: true +Performance/BigDecimalWithNumericArgument: + Enabled: true +Performance/BlockGivenWithExplicitBlock: + Enabled: true +Performance/Caller: + Enabled: true +Performance/CaseWhenSplat: + Enabled: true +Performance/Casecmp: + Enabled: true +Performance/CollectionLiteralInLoop: + Exclude: + - spec/**/* + Enabled: true +Performance/CompareWithBlock: + Enabled: true +Performance/ConstantRegexp: + Enabled: true +Performance/Count: + Enabled: true +Performance/Detect: + Enabled: true +Performance/DoubleStartEndWith: + Enabled: true +Performance/EndWith: + Enabled: true +Performance/FixedSize: + Enabled: true +Performance/FlatMap: + Enabled: true +Performance/MethodObjectAsBlock: + Enabled: true +Performance/RangeInclude: + Enabled: true +Performance/RedundantBlockCall: + Enabled: true +Performance/RedundantMatch: + Enabled: true +Performance/RedundantMerge: + Enabled: true +Performance/RedundantSortBlock: + Enabled: true +Performance/RedundantStringChars: + Enabled: true +Performance/RegexpMatch: + Enabled: true +Performance/ReverseEach: + Enabled: true +Performance/ReverseFirst: + Enabled: true +Performance/Size: + Enabled: true +Performance/SortReverse: + Enabled: true +Performance/Squeeze: + Enabled: true +Performance/StartWith: + Enabled: true +Performance/StringInclude: + Enabled: true +Performance/StringReplacement: + Enabled: true +Performance/Sum: + Enabled: true +Performance/TimesMap: + Enabled: true Style/CollectionMethods: Enabled: true Style/MethodCalledOnDoEndBlock: Enabled: true Style/StringMethods: Enabled: true -GetText/DecorateFunctionMessage: +Bundler/InsecureProtocolSource: Enabled: false -GetText/DecorateStringFormattingUsingInterpolation: +Gemspec/DuplicatedAssignment: Enabled: false -GetText/DecorateStringFormattingUsingPercent: +Gemspec/OrderedDependencies: + Enabled: false +Gemspec/RequiredRubyVersion: + Enabled: false +Gemspec/RubyVersionGlobalsUsage: + Enabled: false +Layout/ArgumentAlignment: + Enabled: false +Layout/BeginEndAlignment: + Enabled: false +Layout/ClosingHeredocIndentation: + Enabled: false +Layout/EmptyComment: + Enabled: false +Layout/EmptyLineAfterGuardClause: + Enabled: false +Layout/EmptyLinesAroundArguments: + Enabled: false +Layout/EmptyLinesAroundAttributeAccessor: Enabled: false Layout/EndOfLine: Enabled: false -Layout/IndentHeredoc: +Layout/FirstArgumentIndentation: + Enabled: false +Layout/HashAlignment: + Enabled: false +Layout/HeredocIndentation: + Enabled: false +Layout/LeadingEmptyLines: + Enabled: false +Layout/SpaceAroundMethodCallOperator: + Enabled: false +Layout/SpaceInsideArrayLiteralBrackets: + Enabled: false +Layout/SpaceInsideReferenceBrackets: + Enabled: false +Lint/BigDecimalNew: + Enabled: false +Lint/BooleanSymbol: + Enabled: false +Lint/ConstantDefinitionInBlock: + Enabled: false +Lint/DeprecatedOpenSSLConstant: + Enabled: false +Lint/DisjunctiveAssignmentInConstructor: + Enabled: false +Lint/DuplicateBranch: + Enabled: false +Lint/DuplicateElsifCondition: + Enabled: false +Lint/DuplicateRegexpCharacterClassElement: + Enabled: false +Lint/DuplicateRequire: + Enabled: false +Lint/DuplicateRescueException: + Enabled: false +Lint/EmptyBlock: + Enabled: false +Lint/EmptyClass: + Enabled: false +Lint/EmptyConditionalBody: + Enabled: false +Lint/EmptyFile: + Enabled: false +Lint/ErbNewArguments: + Enabled: false +Lint/FloatComparison: + Enabled: false +Lint/HashCompareByIdentity: + Enabled: false +Lint/IdentityComparison: + Enabled: false +Lint/InterpolationCheck: + Enabled: false +Lint/MissingCopEnableDirective: + Enabled: false +Lint/MixedRegexpCaptureTypes: + Enabled: false +Lint/NestedPercentLiteral: + Enabled: false +Lint/NoReturnInBeginEndBlocks: + Enabled: false +Lint/NonDeterministicRequireOrder: + Enabled: false +Lint/OrderedMagicComments: + Enabled: false +Lint/OutOfRangeRegexpRef: + Enabled: false +Lint/RaiseException: + Enabled: false +Lint/RedundantCopEnableDirective: + Enabled: false +Lint/RedundantRequireStatement: + Enabled: false +Lint/RedundantSafeNavigation: + Enabled: false +Lint/RedundantWithIndex: + Enabled: false +Lint/RedundantWithObject: + Enabled: false +Lint/RegexpAsCondition: + Enabled: false +Lint/ReturnInVoidContext: + Enabled: false +Lint/SafeNavigationConsistency: + Enabled: false +Lint/SafeNavigationWithEmpty: + Enabled: false +Lint/SelfAssignment: + Enabled: false +Lint/SendWithMixinArgument: + Enabled: false +Lint/ShadowedArgument: + Enabled: false +Lint/StructNewOverride: + Enabled: false +Lint/ToEnumArguments: + Enabled: false +Lint/ToJSON: + Enabled: false +Lint/TopLevelReturnWithArgument: + Enabled: false +Lint/TrailingCommaInAttributeDeclaration: + Enabled: false +Lint/UnexpectedBlockArity: + Enabled: false +Lint/UnmodifiedReduceAccumulator: + Enabled: false +Lint/UnreachableLoop: + Enabled: false +Lint/UriEscapeUnescape: + Enabled: false +Lint/UriRegexp: + Enabled: false +Lint/UselessMethodDefinition: + Enabled: false +Lint/UselessTimes: Enabled: false Metrics/AbcSize: Enabled: false Metrics/BlockLength: 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 +Migration/DepartmentName: + Enabled: false +Naming/AccessorMethodName: + Enabled: false +Naming/BlockParameterName: + Enabled: false +Naming/HeredocDelimiterCase: + Enabled: false +Naming/HeredocDelimiterNaming: + Enabled: false +Naming/MemoizedInstanceVariableName: + Enabled: false +Naming/MethodParameterName: + Enabled: false +Naming/RescuedExceptionsVariableName: + Enabled: false +RSpec/Be: + Enabled: false +RSpec/Capybara/CurrentPathExpectation: + Enabled: false +RSpec/Capybara/FeatureMethods: + Enabled: false +RSpec/Capybara/VisibilityMatcher: + Enabled: false +RSpec/ContextMethod: + Enabled: false +RSpec/ContextWording: + Enabled: false RSpec/DescribeClass: Enabled: false +RSpec/EmptyHook: + Enabled: false +RSpec/EmptyLineAfterExample: + Enabled: false +RSpec/EmptyLineAfterExampleGroup: + Enabled: false +RSpec/EmptyLineAfterHook: + Enabled: false RSpec/ExampleLength: Enabled: false -RSpec/MessageExpectation: +RSpec/ExampleWithoutDescription: + Enabled: false +RSpec/ExpectChange: + Enabled: false +RSpec/ExpectInHook: + Enabled: false +RSpec/FactoryBot/AttributeDefinedStatically: + Enabled: false +RSpec/FactoryBot/CreateList: + Enabled: false +RSpec/FactoryBot/FactoryClassName: + Enabled: false +RSpec/HooksBeforeExamples: + Enabled: false +RSpec/ImplicitBlockExpectation: + Enabled: false +RSpec/ImplicitSubject: + Enabled: false +RSpec/LeakyConstantDeclaration: + Enabled: false +RSpec/LetBeforeExamples: + Enabled: false +RSpec/MissingExampleGroupArgument: Enabled: false RSpec/MultipleExpectations: Enabled: false +RSpec/MultipleMemoizedHelpers: + Enabled: false +RSpec/MultipleSubjects: + Enabled: false RSpec/NestedGroups: Enabled: false +RSpec/PredicateMatcher: + Enabled: false +RSpec/ReceiveCounts: + Enabled: false +RSpec/ReceiveNever: + Enabled: false +RSpec/RepeatedExampleGroupBody: + Enabled: false +RSpec/RepeatedExampleGroupDescription: + Enabled: false +RSpec/RepeatedIncludeExample: + Enabled: false +RSpec/ReturnFromStub: + Enabled: false +RSpec/SharedExamples: + Enabled: false +RSpec/StubbedMock: + Enabled: false +RSpec/UnspecifiedException: + Enabled: false +RSpec/VariableDefinition: + Enabled: false +RSpec/VoidExpect: + Enabled: false +RSpec/Yield: + Enabled: false +Security/Open: + Enabled: false +Style/AccessModifierDeclarations: + Enabled: false +Style/AccessorGrouping: + Enabled: false +Style/ArgumentsForwarding: + Enabled: false Style/AsciiComments: Enabled: false +Style/BisectedAttrAccessor: + Enabled: false +Style/CaseLikeIf: + Enabled: false +Style/ClassEqualityComparison: + Enabled: false +Style/CollectionCompact: + Enabled: false +Style/ColonMethodDefinition: + Enabled: false +Style/CombinableLoops: + Enabled: false +Style/CommentedKeyword: + Enabled: false +Style/Dir: + Enabled: false +Style/DocumentDynamicEvalDefinition: + Enabled: false +Style/DoubleCopDisableDirective: + Enabled: false +Style/EmptyBlockParameter: + Enabled: false +Style/EmptyLambdaParameter: + Enabled: false +Style/Encoding: + Enabled: false +Style/EvalWithLocation: + Enabled: false +Style/ExpandPathArguments: + Enabled: false +Style/ExplicitBlockArgument: + Enabled: false +Style/ExponentialNotation: + Enabled: false +Style/FloatDivision: + Enabled: false +Style/GlobalStdStream: + Enabled: false +Style/HashAsLastArrayItem: + Enabled: false +Style/HashLikeCase: + Enabled: false +Style/HashTransformKeys: + Enabled: false +Style/HashTransformValues: + Enabled: false Style/IfUnlessModifier: Enabled: false +Style/KeywordParametersOrder: + Enabled: false +Style/MinMax: + Enabled: false +Style/MixinUsage: + Enabled: false +Style/MultilineWhenThen: + Enabled: false +Style/NegatedIfElseCondition: + Enabled: false +Style/NegatedUnless: + Enabled: false +Style/NilLambda: + Enabled: false +Style/NumericPredicate: + Enabled: false +Style/OptionalBooleanParameter: + Enabled: false +Style/OrAssignment: + Enabled: false +Style/RandomWithOffset: + Enabled: false +Style/RedundantArgument: + Enabled: false +Style/RedundantAssignment: + Enabled: false +Style/RedundantCondition: + Enabled: false +Style/RedundantConditional: + Enabled: false +Style/RedundantFetchBlock: + Enabled: false +Style/RedundantFileExtensionInRequire: + Enabled: false +Style/RedundantRegexpCharacterClass: + Enabled: false +Style/RedundantRegexpEscape: + Enabled: false +Style/RedundantSelfAssignment: + Enabled: false +Style/RedundantSort: + Enabled: false +Style/RescueStandardError: + Enabled: false +Style/SingleArgumentDig: + Enabled: false +Style/SlicingWithRange: + Enabled: false +Style/SoleNestedConditional: + Enabled: false +Style/StderrPuts: + Enabled: false +Style/StringConcatenation: + Enabled: false +Style/Strip: + Enabled: false +Style/SwapValues: + Enabled: false Style/SymbolProc: Enabled: false +Style/TrailingBodyOnClass: + Enabled: false +Style/TrailingBodyOnMethodDefinition: + Enabled: false +Style/TrailingBodyOnModule: + Enabled: false +Style/TrailingCommaInHashLiteral: + Enabled: false +Style/TrailingMethodEndStatement: + Enabled: false +Style/UnpackFirst: + Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml deleted file mode 100644 index 36d6b1b..0000000 --- a/.rubocop_todo.yml +++ /dev/null @@ -1,7 +0,0 @@ -GetText/DecorateString: - Enabled: false - -RSpec/InstanceVariable: - Enabled: true - Exclude: - - spec/acceptance/* \ No newline at end of file diff --git a/.sync.yml b/.sync.yml index 0732cde..96d2050 100644 --- a/.sync.yml +++ b/.sync.yml @@ -1,79 +1,63 @@ --- ".gitlab-ci.yml": delete: true -".rubocop.yml": - default_configs: - inherit_from: ".rubocop_todo.yml" - require: - - rubocop-i18n - - rubocop-rspec ".travis.yml": - global_env: + global_env: - HONEYCOMB_WRITEKEY="7f3c63a70eecc61d635917de46bea4e6",HONEYCOMB_DATASET="litmus tests" deploy_to_forge: enabled: false branches: - release user: puppet secure: '' use_litmus: true litmus: provision_list: - ---travis_el - travis_deb - travis_el7 - travis_el8 complex: - collection: puppet_collection: - puppet6 provision_list: - travis_ub_6 - collection: puppet_collection: - puppet5 provision_list: - travis_ub_5 simplecov: true notifications: slack: secure: nNKMeWyQAjfWxXkNjP9RCSZQaCsuEYB1r2v+HMNMOmoEqmUoJDXYO5Cvy3p3BC4uyN5u94BkcOQWlZ9vJVdW526WNbNmk1UrKKNz6wVa8ssAH2+2Us2Ybx96+oboiiko2ZX7Pku1KAXn0mrEOFQo/ESeXCt25Q2P6MWhKTLQUXg= appveyor.yml: environment: HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6 HONEYCOMB_DATASET: litmus tests use_litmus: true matrix_extras: - RUBY_VERSION: 25-x64 ACCEPTANCE: 'yes' TARGET_HOST: localhost - RUBY_VERSION: 25-x64 ACCEPTANCE: 'yes' TARGET_HOST: localhost APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 simplecov: true Gemfile: - use_litmus: true - required: - ":development": - - gem: puppet-lint-i18n optional: ":development": - gem: github_changelog_generator - git: https://github.com/skywinder/github-changelog-generator - ref: 20ee04ba1234e9e83eb2ffb5056e23d641c7a018 - condition: Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.2.2') -Rakefile: - requires: - - puppet_pot_generator/rake_tasks spec/spec_helper.rb: mock_with: ":rspec" coverage_report: true .gitpod.Dockerfile: unmanaged: false .gitpod.yml: unmanaged: false .github/workflows/nightly.yml: unmanaged: false .github/workflows/pr_test.yml: unmanaged: false diff --git a/.travis.yml b/.travis.yml index ee3e94f..6b17bf6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,146 +1,138 @@ --- os: linux dist: xenial language: ruby cache: bundler before_install: - bundle -v - rm -f Gemfile.lock - "# Update system gems if requested. This is useful to temporarily workaround troubles in the test runner" - "# See https://github.com/puppetlabs/pdk-templates/commit/705154d5c437796b821691b707156e1b056d244f for an example of how this was used" - "# Ignore exit code of SIGPIPE'd yes to not fail with shell's pipefail set" - '[ -z "$RUBYGEMS_VERSION" ] || (yes || true) | gem update --system $RUBYGEMS_VERSION' - gem --version - bundle -v script: - 'SIMPLECOV=yes bundle exec rake $CHECK' bundler_args: --without system_tests rvm: - 2.5.7 env: global: - HONEYCOMB_WRITEKEY="7f3c63a70eecc61d635917de46bea4e6",HONEYCOMB_DATASET="litmus tests" stages: - static - spec - acceptance jobs: fast_finish: true include: - - + - bundler_args: --with system_tests before_script: - "bundle exec rake 'litmus:provision_list[travis_ub_6]'" - "bundle exec rake 'litmus:install_agent[puppet6]'" - "bundle exec rake litmus:install_module" - bundler_args: env: PLATFORMS=travis_ub_6_puppet6 rvm: 2.5.7 script: ["travis_wait 45 bundle exec rake litmus:acceptance:parallel"] services: docker stage: acceptance - - + - bundler_args: --with system_tests before_script: - "bundle exec rake 'litmus:provision_list[travis_ub_5]'" - "bundle exec rake 'litmus:install_agent[puppet5]'" - "bundle exec rake litmus:install_module" - bundler_args: env: PLATFORMS=travis_ub_5_puppet5 rvm: 2.5.7 script: ["travis_wait 45 bundle exec rake litmus:acceptance:parallel"] services: docker stage: acceptance - - + - bundler_args: --with system_tests before_script: - "bundle exec rake 'litmus:provision_list[travis_deb]'" - "bundle exec rake 'litmus:install_agent[puppet5]'" - "bundle exec rake litmus:install_module" - bundler_args: env: PLATFORMS=travis_deb_puppet5 rvm: 2.5.7 script: ["travis_wait 45 bundle exec rake litmus:acceptance:parallel"] services: docker stage: acceptance - - + - bundler_args: --with system_tests before_script: - "bundle exec rake 'litmus:provision_list[travis_el7]'" - "bundle exec rake 'litmus:install_agent[puppet5]'" - "bundle exec rake litmus:install_module" - bundler_args: env: PLATFORMS=travis_el7_puppet5 rvm: 2.5.7 script: ["travis_wait 45 bundle exec rake litmus:acceptance:parallel"] services: docker stage: acceptance - - + - bundler_args: --with system_tests before_script: - "bundle exec rake 'litmus:provision_list[travis_el8]'" - "bundle exec rake 'litmus:install_agent[puppet5]'" - "bundle exec rake litmus:install_module" - bundler_args: env: PLATFORMS=travis_el8_puppet5 rvm: 2.5.7 script: ["travis_wait 45 bundle exec rake litmus:acceptance:parallel"] services: docker stage: acceptance - - + - bundler_args: --with system_tests before_script: - "bundle exec rake 'litmus:provision_list[travis_deb]'" - "bundle exec rake 'litmus:install_agent[puppet6]'" - "bundle exec rake litmus:install_module" - bundler_args: env: PLATFORMS=travis_deb_puppet6 rvm: 2.5.7 script: ["travis_wait 45 bundle exec rake litmus:acceptance:parallel"] services: docker stage: acceptance - - + - bundler_args: --with system_tests before_script: - "bundle exec rake 'litmus:provision_list[travis_el7]'" - "bundle exec rake 'litmus:install_agent[puppet6]'" - "bundle exec rake litmus:install_module" - bundler_args: env: PLATFORMS=travis_el7_puppet6 rvm: 2.5.7 script: ["travis_wait 45 bundle exec rake litmus:acceptance:parallel"] services: docker stage: acceptance - - + - bundler_args: --with system_tests before_script: - "bundle exec rake 'litmus:provision_list[travis_el8]'" - "bundle exec rake 'litmus:install_agent[puppet6]'" - "bundle exec rake litmus:install_module" - bundler_args: env: PLATFORMS=travis_el8_puppet6 rvm: 2.5.7 script: ["travis_wait 45 bundle exec rake litmus:acceptance:parallel"] services: docker stage: acceptance - env: CHECK="check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop syntax lint metadata_lint" stage: static - env: PUPPET_GEM_VERSION="~> 5.0" CHECK=parallel_spec rvm: 2.4.5 stage: spec - env: PUPPET_GEM_VERSION="~> 6.0" CHECK=parallel_spec rvm: 2.5.7 stage: spec branches: only: - main - /^v\d/ - release notifications: email: false slack: secure: nNKMeWyQAjfWxXkNjP9RCSZQaCsuEYB1r2v+HMNMOmoEqmUoJDXYO5Cvy3p3BC4uyN5u94BkcOQWlZ9vJVdW526WNbNmk1UrKKNz6wVa8ssAH2+2Us2Ybx96+oboiiko2ZX7Pku1KAXn0mrEOFQo/ESeXCt25Q2P6MWhKTLQUXg= deploy: provider: puppetforge username: puppet password: secure: "" on: tags: true all_branches: true condition: "$DEPLOY_TO_FORGE = yes" diff --git a/Gemfile b/Gemfile index 815331e..ae2b430 100644 --- a/Gemfile +++ b/Gemfile @@ -1,75 +1,73 @@ source ENV['GEM_SOURCE'] || 'https://rubygems.org' def location_for(place_or_version, fake_version = nil) git_url_regex = %r{\A(?(https?|git)[:@][^#]*)(#(?.*))?} file_url_regex = %r{\Afile:\/\/(?.*)} if place_or_version && (git_url = place_or_version.match(git_url_regex)) [fake_version, { git: git_url[:url], branch: git_url[:branch], require: false }].compact elsif place_or_version && (file_url = place_or_version.match(file_url_regex)) ['>= 0', { path: File.expand_path(file_url[:path]), require: false }] else [place_or_version, { require: false }] end end ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments minor_version = ruby_version_segments[0..1].join('.') group :development do - gem "fast_gettext", '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') - gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') - gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9') gem "json", '= 2.0.4', require: false if Gem::Requirement.create('~> 2.4.2').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) gem "json", '= 2.3.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 2.8.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "rb-readline", '= 0.5.5', require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "puppet-module-posix-default-r#{minor_version}", '~> 0.4', require: false, platforms: [:ruby] - gem "puppet-module-posix-dev-r#{minor_version}", '~> 0.4', require: false, platforms: [:ruby] - gem "puppet-module-win-default-r#{minor_version}", '~> 0.4', require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "puppet-module-win-dev-r#{minor_version}", '~> 0.4', require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "puppet-lint-i18n", require: false - gem "github_changelog_generator", require: false, git: 'https://github.com/skywinder/github-changelog-generator', ref: '20ee04ba1234e9e83eb2ffb5056e23d641c7a018' if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.2.2') + gem "puppet-module-posix-default-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby] + gem "puppet-module-posix-dev-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby] + gem "puppet-module-win-default-r#{minor_version}", '~> 1.0', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "puppet-module-win-dev-r#{minor_version}", '~> 1.0', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "github_changelog_generator", require: false +end +group :system_tests do + gem "puppet-module-posix-system-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby] + gem "puppet-module-win-system-r#{minor_version}", '~> 1.0', require: false, platforms: [:mswin, :mingw, :x64_mingw] end puppet_version = ENV['PUPPET_GEM_VERSION'] facter_version = ENV['FACTER_GEM_VERSION'] hiera_version = ENV['HIERA_GEM_VERSION'] gems = {} gems['puppet'] = location_for(puppet_version) # If facter or hiera versions have been specified via the environment # variables gems['facter'] = location_for(facter_version) if facter_version gems['hiera'] = location_for(hiera_version) if hiera_version if Gem.win_platform? && puppet_version =~ %r{^(file:///|git://)} # If we're using a Puppet gem on Windows which handles its own win32-xxx gem # dependencies (>= 3.5.0), set the maximum versions (see PUP-6445). gems['win32-dir'] = ['<= 0.4.9', require: false] gems['win32-eventlog'] = ['<= 0.6.5', require: false] gems['win32-process'] = ['<= 0.7.5', require: false] gems['win32-security'] = ['<= 0.2.5', require: false] gems['win32-service'] = ['0.8.8', require: false] end gems.each do |gem_name, gem_params| gem gem_name, *gem_params end # Evaluate Gemfile.local and ~/.gemfile if they exist extra_gemfiles = [ "#{__FILE__}.local", File.join(Dir.home, '.gemfile'), ] extra_gemfiles.each do |gemfile| if File.file?(gemfile) && File.readable?(gemfile) eval(File.read(gemfile), binding) end end # vim: syntax=ruby diff --git a/Rakefile b/Rakefile index f8ec754..0a5093b 100644 --- a/Rakefile +++ b/Rakefile @@ -1,88 +1,87 @@ # frozen_string_literal: true require 'puppet_litmus/rake_tasks' if Bundler.rubygems.find_name('puppet_litmus').any? require 'puppetlabs_spec_helper/rake_tasks' require 'puppet-syntax/tasks/puppet-syntax' require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any? require 'github_changelog_generator/task' if Bundler.rubygems.find_name('github_changelog_generator').any? require 'puppet-strings/tasks' if Bundler.rubygems.find_name('puppet-strings').any? -require 'puppet_pot_generator/rake_tasks' def changelog_user return unless Rake.application.top_level_tasks.include? "changelog" returnVal = nil || JSON.load(File.read('metadata.json'))['author'] raise "unable to find the changelog_user in .sync.yml, or the author in metadata.json" if returnVal.nil? puts "GitHubChangelogGenerator user:#{returnVal}" returnVal end def changelog_project return unless Rake.application.top_level_tasks.include? "changelog" returnVal = nil returnVal ||= begin metadata_source = JSON.load(File.read('metadata.json'))['source'] metadata_source_match = metadata_source && metadata_source.match(%r{.*\/([^\/]*?)(?:\.git)?\Z}) metadata_source_match && metadata_source_match[1] end raise "unable to find the changelog_project in .sync.yml or calculate it from the source in metadata.json" if returnVal.nil? puts "GitHubChangelogGenerator project:#{returnVal}" returnVal end def changelog_future_release return unless Rake.application.top_level_tasks.include? "changelog" returnVal = "v%s" % JSON.load(File.read('metadata.json'))['version'] raise "unable to find the future_release (version) in metadata.json" if returnVal.nil? puts "GitHubChangelogGenerator future_release:#{returnVal}" returnVal end PuppetLint.configuration.send('disable_relative') if Bundler.rubygems.find_name('github_changelog_generator').any? GitHubChangelogGenerator::RakeTask.new :changelog do |config| raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil? config.user = "#{changelog_user}" config.project = "#{changelog_project}" config.future_release = "#{changelog_future_release}" config.exclude_labels = ['maintenance'] config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)." config.add_pr_wo_labels = true config.issues = false config.merge_prefix = "### UNCATEGORIZED PRS; LABEL THEM ON GITHUB" config.configure_sections = { "Changed" => { "prefix" => "### Changed", "labels" => ["backwards-incompatible"], }, "Added" => { "prefix" => "### Added", "labels" => ["enhancement", "feature"], }, "Fixed" => { "prefix" => "### Fixed", "labels" => ["bug", "documentation", "bugfix"], }, } end else desc 'Generate a Changelog from GitHub' task :changelog do raise < 1.15' condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')" EOM end end diff --git a/appveyor.yml b/appveyor.yml index eb3dcfb..d69b461 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,84 +1,84 @@ --- version: 1.1.x.{build} branches: only: - main - release skip_commits: message: /^\(?doc\)?.*/ clone_depth: 10 init: - SET - 'mkdir C:\ProgramData\PuppetLabs\code && exit 0' - 'mkdir C:\ProgramData\PuppetLabs\facter && exit 0' - 'mkdir C:\ProgramData\PuppetLabs\hiera && exit 0' - 'mkdir C:\ProgramData\PuppetLabs\puppet\var && exit 0' environment: HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6 HONEYCOMB_DATASET: litmus tests SIMPLECOV: yes matrix: - - RUBY_VERSION: 24-x64 + RUBY_VERSION: 25-x64 CHECK: syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop - PUPPET_GEM_VERSION: ~> 5.0 RUBY_VERSION: 24 CHECK: parallel_spec - PUPPET_GEM_VERSION: ~> 5.0 RUBY_VERSION: 24-x64 CHECK: parallel_spec - PUPPET_GEM_VERSION: ~> 6.0 RUBY_VERSION: 25 CHECK: parallel_spec - PUPPET_GEM_VERSION: ~> 6.0 RUBY_VERSION: 25-x64 CHECK: parallel_spec - RUBY_VERSION: 25-x64 ACCEPTANCE: yes TARGET_HOST: localhost - RUBY_VERSION: 25-x64 ACCEPTANCE: yes TARGET_HOST: localhost APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 for: - matrix: only: - ACCEPTANCE: yes install: - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% - bundle install --jobs 4 --retry 2 - type Gemfile.lock test_script: - bundle exec puppet -V - ruby -v - gem -v - bundle -v - bundle exec rake spec_prep - bundle exec rake litmus:acceptance:localhost matrix: fast_finish: true install: - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% - bundle install --jobs 4 --retry 2 --without system_tests - type Gemfile.lock build: off test_script: - bundle exec puppet -V - ruby -v - gem -v - bundle -v - bundle exec rake %CHECK% notifications: - provider: Email to: - nobody@nowhere.com on_build_success: false on_build_failure: false on_build_status_changed: false diff --git a/lib/puppet/type/concat_file.rb b/lib/puppet/type/concat_file.rb index 1c005c6..7165b81 100644 --- a/lib/puppet/type/concat_file.rb +++ b/lib/puppet/type/concat_file.rb @@ -1,363 +1,365 @@ +# frozen_string_literal: true + require 'puppet/type/file/owner' require 'puppet/type/file/group' require 'puppet/type/file/mode' require 'puppet/util/checksums' Puppet::Type.newtype(:concat_file) do @doc = <<-DOC @summary Generates a file with content from fragments sharing a common unique tag. @example Concat_fragment <<| tag == 'unique_tag' |>> concat_file { '/tmp/file': tag => 'unique_tag', # Optional. Default to undef path => '/tmp/file', # Optional. If given it overrides the resource name owner => 'root', # Optional. Default to undef group => 'root', # Optional. Default to undef mode => '0644' # Optional. Default to undef order => 'numeric' # Optional, Default to 'numeric' ensure_newline => false # Optional, Defaults to false } DOC ensurable do desc <<-DOC Specifies whether the destination file should exist. Setting to 'absent' tells Puppet to delete the destination file if it exists, and negates the effect of any other parameters. DOC defaultvalues defaultto { :present } end def exists? self[:ensure] == :present end newparam(:tag) do desc 'Required. Specifies a unique tag reference to collect all concat_fragments with the same tag.' end newparam(:path, namevar: true) do desc <<-DOC Specifies a destination file for the combined fragments. Valid options: a string containing an absolute path. Default value: the title of your declared resource. DOC validate do |value| unless Puppet::Util.absolute_path?(value, :posix) || Puppet::Util.absolute_path?(value, :windows) raise ArgumentError, _("File paths must be fully qualified, not '%{_value}'") % { _value: value } end end end newparam(:owner, parent: Puppet::Type::File::Owner) do desc <<-DOC Specifies the owner of the destination file. Valid options: a string containing a username or integer containing a uid. DOC end newparam(:group, parent: Puppet::Type::File::Group) do desc <<-DOC Specifies a permissions group for the destination file. Valid options: a string containing a group name or integer containing a gid. DOC end newparam(:mode, parent: Puppet::Type::File::Mode) do desc <<-DOC Specifies the permissions mode of the destination file. Valid options: a string containing a permission mode value in octal notation. DOC end newparam(:order) do desc <<-DOC Specifies a method for sorting your fragments by name within the destination file. You can override this setting for individual fragments by adjusting the order parameter in their concat::fragment declarations. DOC newvalues(:alpha, :numeric) defaultto :numeric end newparam(:backup) do desc <<-DOC Specifies whether (and how) to back up the destination file before overwriting it. Your value gets passed on to Puppet's native file resource for execution. Valid options: true, false, or a string representing either a target filebucket or a filename extension beginning with ".".' DOC validate do |value| unless [TrueClass, FalseClass, String].include?(value.class) raise ArgumentError, _('Backup must be a Boolean or String') end end end newparam(:replace, boolean: true, parent: Puppet::Parameter::Boolean) do desc 'Specifies whether to overwrite the destination file if it already exists.' defaultto true end newparam(:validate_cmd) do desc <<-DOC Specifies a validation command to apply to the destination file. Requires Puppet version 3.5 or newer. Valid options: a string to be passed to a file resource. DOC validate do |value| unless value.is_a?(String) raise ArgumentError, _('Validate_cmd must be a String') end end end newparam(:ensure_newline, boolean: true, parent: Puppet::Parameter::Boolean) do desc "Specifies whether to add a line break at the end of each fragment that doesn't already end in one." defaultto false end newparam(:format) do desc <<-DOC Specify what data type to merge the fragments as. Valid options: 'plain', 'yaml', 'json', 'json-array', 'json-pretty', 'json-array-pretty'. DOC newvalues(:plain, :yaml, :json, :'json-array', :'json-pretty', :'json-array-pretty') defaultto :plain end newparam(:force, boolean: true, parent: Puppet::Parameter::Boolean) do desc 'Specifies whether to merge data structures, keeping the values with higher order.' defaultto false end newparam(:selinux_ignore_defaults, boolean: true, parent: Puppet::Parameter::Boolean) do desc <<-DOC See the file type's selinux_ignore_defaults documentention: https://docs.puppetlabs.com/references/latest/type.html#file-attribute-selinux_ignore_defaults. DOC end newparam(:selrange) do desc "See the file type's selrange documentation: https://docs.puppetlabs.com/references/latest/type.html#file-attribute-selrange" validate do |value| raise ArgumentError, _('Selrange must be a String') unless value.is_a?(String) end end newparam(:selrole) do desc "See the file type's selrole documentation: https://docs.puppetlabs.com/references/latest/type.html#file-attribute-selrole" validate do |value| raise ArgumentError, _('Selrole must be a String') unless value.is_a?(String) end end newparam(:seltype) do desc "See the file type's seltype documentation: https://docs.puppetlabs.com/references/latest/type.html#file-attribute-seltype" validate do |value| raise ArgumentError, _('Seltype must be a String') unless value.is_a?(String) end end newparam(:seluser) do desc "See the file type's seluser documentation: https://docs.puppetlabs.com/references/latest/type.html#file-attribute-seluser" validate do |value| raise ArgumentError, _('Seluser must be a String') unless value.is_a?(String) end end newparam(:show_diff, boolean: true, parent: Puppet::Parameter::Boolean) do desc <<-DOC Specifies whether to set the show_diff parameter for the file resource. Useful for hiding secrets stored in hiera from insecure reporting methods. DOC end # Autorequire the file we are generating below # Why is this necessary ? autorequire(:file) do [self[:path]] end def fragments # Collect fragments that target this resource by path, title or tag. @fragments ||= catalog.resources.map { |resource| next unless resource.is_a?(Puppet::Type.type(:concat_fragment)) if resource[:target] == self[:path] || resource[:target] == title || (resource[:tag] && resource[:tag] == self[:tag]) resource end }.compact end def decompound(d) d.split('___', 2).map { |v| (v =~ %r{^\d+$}) ? v.to_i : v } end def should_content return @generated_content if @generated_content @generated_content = '' content_fragments = [] fragments.each do |r| content_fragments << ["#{r[:order]}___#{r[:name]}", fragment_content(r)] end sorted = if self[:order] == :numeric content_fragments.sort do |a, b| decompound(a[0]) <=> decompound(b[0]) end else content_fragments.sort_by do |a| a_order, a_name = a[0].split('__', 2) [a_order, a_name] end end case self[:format] when :plain @generated_content = sorted.map { |cf| cf[1] }.join when :yaml content_array = sorted.map do |cf| YAML.safe_load(cf[1]) end content_hash = content_array.reduce({}) do |memo, current| nested_merge(memo, current) end @generated_content = content_hash.to_yaml when :json, :'json-array', :'json-pretty', :'json-array-pretty' content_array = sorted.map do |cf| JSON.parse(cf[1]) end if [:json, :'json-pretty'].include?(self[:format]) content_hash = content_array.reduce({}) do |memo, current| nested_merge(memo, current) end @generated_content = if self[:format] == :json content_hash.to_json else JSON.pretty_generate(content_hash) end else @generated_content = if self[:format] == :'json-array' content_array.to_json else JSON.pretty_generate(content_array) end end end @generated_content end def nested_merge(hash1, hash2) # If a hash is empty, simply return the other return hash1 if hash2.empty? return hash2 if hash1.empty? # Unique merge for arrays if hash1.is_a?(Array) && hash2.is_a?(Array) return (hash1 + hash2).uniq end # Deep-merge Hashes; higher order value is kept hash1.merge(hash2) do |k, v1, v2| if v1.is_a?(Hash) && v2.is_a?(Hash) nested_merge(v1, v2) elsif v1.is_a?(Array) && v2.is_a?(Array) nested_merge(v1, v2) else # Fail if there are duplicate keys without force unless v1 == v2 unless self[:force] err_message = [ "Duplicate key '#{k}' found with values '#{v1}' and #{v2}'.", "Use 'force' attribute to merge keys.", ] raise(_(err_message.join(' '))) end Puppet.debug("Key '#{k}': replacing '#{v2}' with '#{v1}'.") end v1 end end end def fragment_content(r) if r[:content].nil? == false fragment_content = r[:content] elsif r[:source].nil? == false @source = nil Array(r[:source]).each do |source| if Puppet::FileServing::Metadata.indirection.find(source) @source = source break end end raise _('Could not retrieve source(s) %{_array}') % { _array: Array(r[:source]).join(', ') } unless @source tmp = Puppet::FileServing::Content.indirection.find(@source) fragment_content = tmp.content unless tmp.nil? end if self[:ensure_newline] newline = Puppet::Util::Platform.windows? ? "\r\n" : "\n" - fragment_content << newline unless fragment_content =~ %r{#{newline}\Z} + fragment_content << newline unless %r{#{newline}\Z}.match?(fragment_content) end fragment_content end def generate file_opts = { ensure: (self[:ensure] == :absent) ? :absent : :file, } [:path, :owner, :group, :mode, :replace, :backup, :selinux_ignore_defaults, :selrange, :selrole, :seltype, :seluser, :validate_cmd, :show_diff].each do |param| file_opts[param] = self[param] unless self[param].nil? end metaparams = Puppet::Type.metaparams excluded_metaparams = [:before, :notify, :require, :subscribe, :tag] metaparams.reject! { |param| excluded_metaparams.include? param } metaparams.each do |metaparam| file_opts[metaparam] = self[metaparam] unless self[metaparam].nil? end [Puppet::Type.type(:file).new(file_opts)] end def eval_generate content = should_content unless content.nil? catalog.resource("File[#{self[:path]}]")[:content] = content end [catalog.resource("File[#{self[:path]}]")] end end diff --git a/lib/puppet/type/concat_fragment.rb b/lib/puppet/type/concat_fragment.rb index c66a557..37a8d18 100644 --- a/lib/puppet/type/concat_fragment.rb +++ b/lib/puppet/type/concat_fragment.rb @@ -1,95 +1,97 @@ +# frozen_string_literal: true + Puppet::Type.newtype(:concat_fragment) do @doc = <<-DOC @summary Manages the fragment. @example # The example is based on exported resources. concat_fragment { \"uniqe_name_${::fqdn}\": tag => 'unique_name', order => 10, # Optional. Default to 10 content => 'some content' # OR # content => template('template.erb') source => 'puppet:///path/to/file' } DOC newparam(:name, namevar: true) do desc 'Name of resource.' end newparam(:target) do desc <<-DOC Required. Specifies the destination file of the fragment. Valid options: a string containing the path or title of the parent concat_file resource. DOC validate do |value| raise ArgumentError, _('Target must be a String') unless value.is_a?(String) end end newparam(:content) do desc <<-DOC Supplies the content of the fragment. Note: You must supply either a content parameter or a source parameter. Valid options: a string DOC validate do |value| raise ArgumentError, _('Content must be a String') unless value.is_a?(String) end end newparam(:source) do desc <<-DOC Specifies a file to read into the content of the fragment. Note: You must supply either a content parameter or a source parameter. Valid options: a string or an array, containing one or more Puppet URLs. DOC validate do |value| raise ArgumentError, _('Content must be a String or Array') unless [String, Array].include?(value.class) end end newparam(:order) do desc <<-DOC Reorders your fragments within the destination file. Fragments that share the same order number are ordered by name. The string option is recommended. DOC defaultto '10' validate do |val| raise Puppet::ParseError, _('$order is not a string or integer.') unless val.is_a?(String) || val.is_a?(Integer) - raise Puppet::ParseError, _('Order cannot contain \'/\', \':\', or \'\\n\'.') if val.to_s =~ %r{[:\n\/]} + raise Puppet::ParseError, _('Order cannot contain \'/\', \':\', or \'\\n\'.') if %r{[:\n\/]}.match?(val.to_s) end end newparam(:tag) do desc 'Specifies a unique tag to be used by concat_file to reference and collect content.' end autorequire(:file) do found = catalog.resources.select do |resource| next unless resource.is_a?(Puppet::Type.type(:concat_file)) resource[:path] == self[:target] || resource.title == self[:target] || (resource[:tag] && resource[:tag] == self[:tag]) end if found.empty? tag_message = (self[:tag]) ? "or tag '#{self[:tag]} " : '' warning "Target Concat_file with path or title '#{self[:target]}' #{tag_message}not found in the catalog" end end validate do # Check if target is set raise Puppet::ParseError, _("No 'target' or 'tag' set") unless self[:target] || self[:tag] # Check if either source or content is set. raise error if none is set raise Puppet::ParseError, _("Set either 'source' or 'content'") if self[:source].nil? && self[:content].nil? # Check if both are set, if so rais error raise Puppet::ParseError, _("Can't use 'source' and 'content' at the same time") if !self[:source].nil? && !self[:content].nil? end end diff --git a/metadata.json b/metadata.json index ca72146..90f8382 100644 --- a/metadata.json +++ b/metadata.json @@ -1,117 +1,117 @@ { "name": "puppetlabs-concat", "version": "6.4.0", "author": "puppetlabs", "summary": "Construct files from multiple fragments.", "license": "Apache-2.0", "source": "https://github.com/puppetlabs/puppetlabs-concat", "project_page": "https://github.com/puppetlabs/puppetlabs-concat", "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", "dependencies": [ { "name": "puppetlabs/stdlib", "version_requirement": ">= 4.13.1 < 7.0.0" }, { "name": "puppetlabs/translate", "version_requirement": ">= 1.0.0 < 3.0.0" } ], "operatingsystem_support": [ { "operatingsystem": "RedHat", "operatingsystemrelease": [ "5", "6", "7", "8" ] }, { "operatingsystem": "CentOS", "operatingsystemrelease": [ "5", "6", "7", "8" ] }, { "operatingsystem": "OracleLinux", "operatingsystemrelease": [ "5", "6", "7" ] }, { "operatingsystem": "Scientific", "operatingsystemrelease": [ "6", "7" ] }, { "operatingsystem": "SLES", "operatingsystemrelease": [ "11 SP1", "12", "15" ] }, { "operatingsystem": "Debian", "operatingsystemrelease": [ "8", "9", "10" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ "14.04", "16.04", "18.04", "20.04" ] }, { "operatingsystem": "Solaris", "operatingsystemrelease": [ "10", "11" ] }, { "operatingsystem": "Windows", "operatingsystemrelease": [ "2008 R2", "2012", "2012 R2", "2016", "2012 R2 Core", "7", "8.1", "10" ] }, { "operatingsystem": "AIX", "operatingsystemrelease": [ "5.3", "6.1", "7.1" ] } ], "requirements": [ { "name": "puppet", "version_requirement": ">= 5.5.10 < 8.0.0" } ], "template-url": "https://github.com/puppetlabs/pdk-templates#main", - "template-ref": "heads/main-0-g5afcd3d", + "template-ref": "heads/main-0-g4543421", "pdk-version": "1.18.1" } diff --git a/spec/acceptance/backup_spec.rb b/spec/acceptance/backup_spec.rb index 80a9879..a50c4d3 100644 --- a/spec/acceptance/backup_spec.rb +++ b/spec/acceptance/backup_spec.rb @@ -1,77 +1,81 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'concat backup parameter' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'when puppet' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': backup => 'puppet', } concat::fragment { 'new file': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => 'new contents', } MANIFEST end it 'applies the manifest twice with "Filebucketed" stdout and no stderr' do expect(apply_manifest(pp, catch_failures: true, debug: true).stdout).to match(%r{Filebucketed.*to puppet with sum.*}) apply_manifest(pp, catch_changes: true) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match %r{new contents} + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match %r{new contents} end end describe 'when .backup' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': backup => '.backup', } concat::fragment { 'new file': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => 'backup extension', } MANIFEST end # XXX Puppet doesn't mention anything about filebucketing with a given # extension like .backup it 'applies the manifest twice no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match %r{backup extension} - expect(file("#{@basedir}/file.backup")).to be_file - expect(file("#{@basedir}/file.backup").content).to match %r{new contents} + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match %r{backup extension} + expect(file("#{basedir}/file.backup")).to be_file + expect(file("#{basedir}/file.backup").content).to match %r{new contents} end end # XXX The backup parameter uses validate_string() and thus can't be the # boolean false value, but the string 'false' has the same effect in Puppet 3 describe "when 'false'" do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': backup => '.backup', } concat::fragment { 'new file': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => 'new contents', } MANIFEST end it 'applies the manifest twice with no "Filebucketed" stdout and no stderr' do apply_manifest(pp, catch_failures: true) do |r| expect(r.stdout).not_to match(%r{Filebucketed}) end apply_manifest(pp, catch_changes: true) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match %r{new contents} + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match %r{new contents} end end end diff --git a/spec/acceptance/concat_spec.rb b/spec/acceptance/concat_spec.rb index 1e6e752..bfaf801 100644 --- a/spec/acceptance/concat_spec.rb +++ b/spec/acceptance/concat_spec.rb @@ -1,169 +1,173 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' case os[:family] when 'aix' username = 'root' groupname = 'system' when 'darwin' username = 'root' groupname = 'wheel' when 'windows' username = 'Administrator' groupname = 'Administrators' else username = 'root' groupname = 'root' end describe 'basic concat test' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'with owner/group root' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '1', order => '01', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '2', order => '02', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file")).to be_owned_by username unless os[:family] == 'windows' - expect(file("#{@basedir}/file")).to be_grouped_into groupname unless os[:family] == 'windows' || os[:family] == 'darwin' - expect(file("#{@basedir}/file")).to be_mode 644 unless os[:family] == 'aix' || os[:family] == 'windows' - expect(file("#{@basedir}/file").content).to match '1' - expect(file("#{@basedir}/file").content).to match '2' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file")).to be_owned_by username unless os[:family] == 'windows' + expect(file("#{basedir}/file")).to be_grouped_into groupname unless os[:family] == 'windows' || os[:family] == 'darwin' + expect(file("#{basedir}/file")).to be_mode 644 unless os[:family] == 'aix' || os[:family] == 'windows' + expect(file("#{basedir}/file").content).to match '1' + expect(file("#{basedir}/file").content).to match '2' end end describe 'when present with path set' do let(:pp) do <<-MANIFEST concat { 'file': ensure => present, - path => '#{@basedir}/file', + path => '#{basedir}/file', mode => '0644', } concat::fragment { '1': target => 'file', content => '1', order => '01', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file")).to be_mode 644 unless os[:family] == 'aix' || os[:family] == 'windows' - expect(file("#{@basedir}/file").content).to match '1' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file")).to be_mode 644 unless os[:family] == 'aix' || os[:family] == 'windows' + expect(file("#{basedir}/file").content).to match '1' end end describe 'with no fragments declared' do let(:pp) do <<-MANIFEST concat { 'file': ensure => present, - path => '#{@basedir}/file', + path => '#{basedir}/file', mode => '0644', } MANIFEST end it 'applies manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to eq '' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to eq '' end end describe 'when absent with path set' do let(:pp) do <<-MANIFEST concat { 'file': ensure => absent, - path => '#{@basedir}/file', + path => '#{basedir}/file', mode => '0644', } concat::fragment { '1': target => 'file', content => '1', order => '01', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).not_to be_file + expect(file("#{basedir}/file")).not_to be_file end end describe 'when present with path that has special characters' do filename = (os[:family] == 'windows') ? 'file(1)' : 'file(1:2)' let(:pp) do <<-MANIFEST concat { '#{filename}': ensure => present, - path => '#{@basedir}/#{filename}', + path => '#{basedir}/#{filename}', mode => '0644', } concat::fragment { '1': target => '#{filename}', content => '1', order => '01', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/#{filename}")).to be_file - expect(file("#{@basedir}/#{filename}")).to be_mode 644 unless os[:family] == 'aix' || os[:family] == 'windows' - expect(file("#{@basedir}/#{filename}").content).to match '1' + expect(file("#{basedir}/#{filename}")).to be_file + expect(file("#{basedir}/#{filename}")).to be_mode 644 unless os[:family] == 'aix' || os[:family] == 'windows' + expect(file("#{basedir}/#{filename}").content).to match '1' end end describe 'with noop properly' do let(:pp) do <<-MANIFEST concat { 'file': ensure => present, - path => '#{@basedir}/file', + path => '#{basedir}/file', mode => '0644', noop => true, } concat::fragment { '1': target => 'file', content => '1', order => '01', } MANIFEST end it 'applies manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).not_to be_file + expect(file("#{basedir}/file")).not_to be_file end end end diff --git a/spec/acceptance/concurrency_spec.rb b/spec/acceptance/concurrency_spec.rb index 49d39e4..2c86fc8 100644 --- a/spec/acceptance/concurrency_spec.rb +++ b/spec/acceptance/concurrency_spec.rb @@ -1,35 +1,39 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'concurrency, with file recursive purge' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'when run should still create concat file' do let(:pp) do <<-MANIFEST - file { '#{@basedir}/bar': + file { '#{basedir}/bar': ensure => directory, purge => true, recurse => true, } concat { "foobar": ensure => 'present', - path => '#{@basedir}/bar/foobar', + path => '#{basedir}/bar/foobar', } concat::fragment { 'foo': target => 'foobar', content => 'foo', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/bar/foobar")).to be_file - expect(file("#{@basedir}/bar/foobar").content).to match 'foo' + expect(file("#{basedir}/bar/foobar")).to be_file + expect(file("#{basedir}/bar/foobar").content).to match 'foo' end end end diff --git a/spec/acceptance/force_spec.rb b/spec/acceptance/force_spec.rb index 6785606..d6fd0d4 100644 --- a/spec/acceptance/force_spec.rb +++ b/spec/acceptance/force_spec.rb @@ -1,147 +1,151 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'force merge of file' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'when run should not force' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'yaml', force => false, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST end it 'applies manifest twice with stderr check' do expect(apply_manifest(pp, catch_failures: true).stderr).to match("Duplicate key 'one' found with values 'foo' and bar'. Use 'force' attribute to merge keys.") expect(apply_manifest(pp, catch_failures: true).stderr).to match("Duplicate key 'one' found with values 'foo' and bar'. Use 'force' attribute to merge keys.") - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match 'file exists' - expect(file("#{@basedir}/file").content).not_to match 'one: foo' - expect(file("#{@basedir}/file").content).not_to match 'one: bar' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match 'file exists' + expect(file("#{basedir}/file").content).not_to match 'one: foo' + expect(file("#{basedir}/file").content).not_to match 'one: bar' end end describe 'when run should not force by default' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'yaml', } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST end it 'applies manifest twice with stderr check' do expect(apply_manifest(pp, catch_failures: true).stderr).to match("Duplicate key 'one' found with values 'foo' and bar'. Use 'force' attribute to merge keys.") expect(apply_manifest(pp, catch_failures: true).stderr).to match("Duplicate key 'one' found with values 'foo' and bar'. Use 'force' attribute to merge keys.") - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match 'file exists' - expect(file("#{@basedir}/file").content).not_to match 'one: foo' - expect(file("#{@basedir}/file").content).not_to match 'one: bar' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match 'file exists' + expect(file("#{basedir}/file").content).not_to match 'one: foo' + expect(file("#{basedir}/file").content).not_to match 'one: bar' end end describe 'when run should force' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'yaml', force => true, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match 'one: foo' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match 'one: foo' end end describe 'when run should force merge nested arrays' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'json', force => true, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": [1]}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": [2]}', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to contain '{"one":\[1,2\]}' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to contain '{"one":\[1,2\]}' end end describe 'when run should not force on plain' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': force => true, format => plain, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '{"one": "foo"}{"one": "bar"}' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '{"one": "foo"}{"one": "bar"}' end end end diff --git a/spec/acceptance/format_spec.rb b/spec/acceptance/format_spec.rb index 7bd1994..f0fa429 100644 --- a/spec/acceptance/format_spec.rb +++ b/spec/acceptance/format_spec.rb @@ -1,214 +1,218 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'format of file' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'when run should default to plain' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '{"one": "foo"}{"one": "bar"}' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '{"one": "foo"}{"one": "bar"}' end end describe 'when run should output to plain format' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => plain, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '{"one": "foo"}{"one": "bar"}' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '{"one": "foo"}{"one": "bar"}' end end describe 'when run should output to yaml format' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'yaml', } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"two": "bar"}', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match 'one: foo\Rtwo: bar' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match 'one: foo\Rtwo: bar' end end describe 'when run should output yaml arrays to yaml format' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'yaml', } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => to_yaml([{ 'one.a' => 'foo', 'one.b' => 'bar' }]), } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => to_yaml([{ 'two.a' => 'dip', 'two.b' => 'doot' }]), } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '- one.a: foo\R one.b: bar\R- two.a: dip\R two.b: doot' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '- one.a: foo\R one.b: bar\R- two.a: dip\R two.b: doot' end end describe 'when run should output to json format' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'json', } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"two": "bar"}', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '{"one":"foo","two":"bar"}' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '{"one":"foo","two":"bar"}' end end describe 'when run should output to json-array format' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'json-array', } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"two": "bar"}', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '[{"one":"foo"},{"two":"bar"}]' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '[{"one":"foo"},{"two":"bar"}]' end end describe 'when run should output to json-pretty format' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'json-pretty', } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"two": "bar"}', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '{\R "one": "foo",\R "two": "bar"\R}' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '{\R "one": "foo",\R "two": "bar"\R}' end end describe 'when run should output to json-array-pretty format' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': format => 'json-array-pretty', } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '{"two": "bar"}', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '[\n {\n "one": "foo"\n },\n {\n "two": "bar"\n }\n]' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '[\n {\n "one": "foo"\n },\n {\n "two": "bar"\n }\n]' end end end diff --git a/spec/acceptance/fragment_order_spec.rb b/spec/acceptance/fragment_order_spec.rb index 2e2e39a..e9533f0 100644 --- a/spec/acceptance/fragment_order_spec.rb +++ b/spec/acceptance/fragment_order_spec.rb @@ -1,98 +1,102 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'concat::fragment order' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'with reverse order, alphabetical' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/foo': + concat { '#{basedir}/foo': order => 'alpha' } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string1', order => '15', } concat::fragment { '2': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string2', # default order 10 } concat::fragment { '3': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string3', order => '1', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/foo")).to be_file - expect(file("#{@basedir}/foo").content).to match %r{string3string2string1} + expect(file("#{basedir}/foo")).to be_file + expect(file("#{basedir}/foo").content).to match %r{string3string2string1} end end describe 'with reverse order, numeric' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/foo': + concat { '#{basedir}/foo': order => 'numeric' } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string1', order => '15', } concat::fragment { '2': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string2', # default order 10 } concat::fragment { '3': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string3', order => '1', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/foo")).to be_file - expect(file("#{@basedir}/foo").content).to match %r{string3string2string1} + expect(file("#{basedir}/foo")).to be_file + expect(file("#{basedir}/foo").content).to match %r{string3string2string1} end end describe 'with normal order' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/foo': } + concat { '#{basedir}/foo': } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string1', order => '01', } concat::fragment { '2': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string2', order => '02' } concat::fragment { '3': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string3', order => '03', } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/foo")).to be_file - expect(file("#{@basedir}/foo").content).to match %r{string1string2string3} + expect(file("#{basedir}/foo")).to be_file + expect(file("#{basedir}/foo").content).to match %r{string1string2string3} end end end diff --git a/spec/acceptance/fragment_replace_spec.rb b/spec/acceptance/fragment_replace_spec.rb index f552f7b..600198c 100644 --- a/spec/acceptance/fragment_replace_spec.rb +++ b/spec/acceptance/fragment_replace_spec.rb @@ -1,182 +1,186 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'replacement of' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'file' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': replace => false, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '1', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '2', } - concat { '#{@basedir}/file2': + concat { '#{basedir}/file2': replace => true, } concat::fragment { 'file2_1': - target => '#{@basedir}/file2', + target => '#{basedir}/file2', content => '1', } concat::fragment { 'file2_2': - target => '#{@basedir}/file2', + target => '#{basedir}/file2', content => '2', } MANIFEST end it 'when file should not succeed' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match 'file exists' - expect(file("#{@basedir}/file").content).not_to match '1' - expect(file("#{@basedir}/file").content).not_to match '2' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match 'file exists' + expect(file("#{basedir}/file").content).not_to match '1' + expect(file("#{basedir}/file").content).not_to match '2' end it 'when file should succeed' do - expect(file("#{@basedir}/file2")).to be_file - expect(file("#{@basedir}/file2").content).not_to match 'file exists' - expect(file("#{@basedir}/file2").content).to match '1' - expect(file("#{@basedir}/file2").content).to match '2' + expect(file("#{basedir}/file2")).to be_file + expect(file("#{basedir}/file2").content).not_to match 'file exists' + expect(file("#{basedir}/file2").content).to match '1' + expect(file("#{basedir}/file2").content).to match '2' end end describe 'symlink', unless: (os[:family] == 'windows') do # XXX the core puppet file type will replace a symlink with a plain file # when using ensure => present and source => ... but it will not when using # ensure => present and content => ...; this is somewhat confusing behavior before(:all) do pp = <<-MANIFEST - file { '#{@basedir}': + file { '#{basedir}': ensure => directory, } - file { '#{@basedir}/file': + file { '#{basedir}/file': ensure => link, - target => '#{@basedir}/dangling', + target => '#{basedir}/dangling', } MANIFEST apply_manifest(pp) end let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': replace => false, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '1', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '2', } - concat { '#{@basedir}/file2': + concat { '#{basedir}/file2': replace => true, } concat::fragment { 'file2_1': - target => '#{@basedir}/file2', + target => '#{basedir}/file2', content => '1', } concat::fragment { 'file2_2': - target => '#{@basedir}/file2', + target => '#{basedir}/file2', content => '2', } MANIFEST end it 'when symlink should not succeed' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_linked_to "#{@basedir}/dangling" unless os[:family] == 'aix' || os[:family] == 'windows' - expect(file("#{@basedir}/dangling")).not_to be_file - expect(file("#{@basedir}/dangling")).not_to be_directory + expect(file("#{basedir}/file")).to be_linked_to "#{basedir}/dangling" unless os[:family] == 'aix' || os[:family] == 'windows' + expect(file("#{basedir}/dangling")).not_to be_file + expect(file("#{basedir}/dangling")).not_to be_directory end it 'when symlink should succeed' do - expect(file("#{@basedir}/file2")).to be_file - expect(file("#{@basedir}/file2").content).to match '1' - expect(file("#{@basedir}/file2").content).to match '2' + expect(file("#{basedir}/file2")).to be_file + expect(file("#{basedir}/file2").content).to match '1' + expect(file("#{basedir}/file2").content).to match '2' end end describe 'when directory should not succeed' do before(:all) do pp = <<-MANIFEST - file { '#{@basedir}': + file { '#{basedir}': ensure => directory, } - file { '#{@basedir}/file': + file { '#{basedir}/file': ensure => directory, } MANIFEST apply_manifest(pp) end let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': } + concat { '#{basedir}/file': } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '1', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '2', } MANIFEST end it 'applies the manifest twice with stderr' do expect(apply_manifest(pp, expect_failures: true).stderr).to match(%r{change from '?directory'? to '?file'? failed}) expect(apply_manifest(pp, expect_failures: true).stderr).to match(%r{change from '?directory'? to '?file'? failed}) - expect(file("#{@basedir}/file")).to be_directory + expect(file("#{basedir}/file")).to be_directory end end # XXX # when there are no fragments, and the replace param will only replace # files and symlinks, not directories. The semantics either need to be # changed, extended, or a new param introduced to control directory # replacement. describe 'when directory should succeed', pending: 'not yet implemented' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '1', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '2', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '1' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '1' end end end diff --git a/spec/acceptance/fragment_source_spec.rb b/spec/acceptance/fragment_source_spec.rb index 38f5167..f364d37 100644 --- a/spec/acceptance/fragment_source_spec.rb +++ b/spec/acceptance/fragment_source_spec.rb @@ -1,143 +1,147 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' case os[:family] when 'aix' username = 'root' groupname = 'system' when 'darwin' username = 'root' groupname = 'wheel' when 'windows' username = 'Administrator' groupname = 'Administrators' else username = 'root' groupname = 'root' end describe 'concat::fragment source' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'when run should read file fragments from local system' do let(:pp) do <<-MANIFEST - file { '#{@basedir}/file1': + file { '#{basedir}/file1': content => "file1 contents\n" } - file { '#{@basedir}/file2': + file { '#{basedir}/file2': content => "file2 contents\n" } - concat { '#{@basedir}/foo': } + concat { '#{basedir}/foo': } concat::fragment { '1': - target => '#{@basedir}/foo', - source => '#{@basedir}/file1', - require => File['#{@basedir}/file1'], + target => '#{basedir}/foo', + source => '#{basedir}/file1', + require => File['#{basedir}/file1'], } concat::fragment { '2': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string1 contents', } concat::fragment { '3': - target => '#{@basedir}/foo', - source => '#{@basedir}/file2', - require => File['#{@basedir}/file2'], + target => '#{basedir}/foo', + source => '#{basedir}/file2', + require => File['#{basedir}/file2'], } MANIFEST end it 'idempotent, file matches' do idempotent_apply(pp) - expect(file("#{@basedir}/foo")).to be_file - expect(file("#{@basedir}/foo").content).to match 'file1 contents' - expect(file("#{@basedir}/foo").content).to match 'file2 contents' + expect(file("#{basedir}/foo")).to be_file + expect(file("#{basedir}/foo").content).to match 'file1 contents' + expect(file("#{basedir}/foo").content).to match 'file2 contents' end end describe 'when run should create files containing first match only.' do let(:pp) do <<-MANIFEST - file { '#{@basedir}/file1': + file { '#{basedir}/file1': content => "file1 contents\n" } - file { '#{@basedir}/file2': + file { '#{basedir}/file2': content => "file2 contents\n" } - concat { '#{@basedir}/result_file1': + concat { '#{basedir}/result_file1': owner => '#{username}', group => '#{groupname}', mode => '0644', } - concat { '#{@basedir}/result_file2': + concat { '#{basedir}/result_file2': owner => '#{username}', group => '#{groupname}', mode => '0644', } - concat { '#{@basedir}/result_file3': + concat { '#{basedir}/result_file3': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat::fragment { '1': - target => '#{@basedir}/result_file1', - source => [ '#{@basedir}/file1', '#{@basedir}/file2' ], - require => [ File['#{@basedir}/file1'], File['#{@basedir}/file2'] ], + target => '#{basedir}/result_file1', + source => [ '#{basedir}/file1', '#{basedir}/file2' ], + require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ], order => '01', } concat::fragment { '2': - target => '#{@basedir}/result_file2', - source => [ '#{@basedir}/file2', '#{@basedir}/file1' ], - require => [ File['#{@basedir}/file1'], File['#{@basedir}/file2'] ], + target => '#{basedir}/result_file2', + source => [ '#{basedir}/file2', '#{basedir}/file1' ], + require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ], order => '01', } concat::fragment { '3': - target => '#{@basedir}/result_file3', - source => [ '#{@basedir}/file1', '#{@basedir}/file2' ], - require => [ File['#{@basedir}/file1'], File['#{@basedir}/file2'] ], + target => '#{basedir}/result_file3', + source => [ '#{basedir}/file1', '#{basedir}/file2' ], + require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ], order => '01', } MANIFEST end it 'idempotent, files match' do idempotent_apply(pp) - expect(file("#{@basedir}/result_file1")).to be_file - expect(file("#{@basedir}/result_file1").content).to match 'file1 contents' - expect(file("#{@basedir}/result_file1").content).not_to match 'file2 contents' + expect(file("#{basedir}/result_file1")).to be_file + expect(file("#{basedir}/result_file1").content).to match 'file1 contents' + expect(file("#{basedir}/result_file1").content).not_to match 'file2 contents' - expect(file("#{@basedir}/result_file2")).to be_file - expect(file("#{@basedir}/result_file2").content).to match 'file2 contents' - expect(file("#{@basedir}/result_file2").content).not_to match 'file1 contents' + expect(file("#{basedir}/result_file2")).to be_file + expect(file("#{basedir}/result_file2").content).to match 'file2 contents' + expect(file("#{basedir}/result_file2").content).not_to match 'file1 contents' - expect(file("#{@basedir}/result_file3")).to be_file - expect(file("#{@basedir}/result_file3").content).to match 'file1 contents' - expect(file("#{@basedir}/result_file3").content).not_to match 'file2 contents' + expect(file("#{basedir}/result_file3")).to be_file + expect(file("#{basedir}/result_file3").content).to match 'file1 contents' + expect(file("#{basedir}/result_file3").content).not_to match 'file2 contents' end end describe 'when run should fail if no match on source.' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/fail_no_source': + concat { '#{basedir}/fail_no_source': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat::fragment { '1': - target => '#{@basedir}/fail_no_source', - source => [ '#{@basedir}/nofilehere', '#{@basedir}/nothereeither' ], + target => '#{basedir}/fail_no_source', + source => [ '#{basedir}/nofilehere', '#{basedir}/nothereeither' ], order => '01', } MANIFEST end it 'applies the manifest with resource failures' do expect(apply_manifest(pp, catch_failures: true).stderr).to match(%r{Failed to generate additional resources using 'eval_generate'}) - expect(file("#{@basedir}/fail_no_source")).not_to be_directory + expect(file("#{basedir}/fail_no_source")).not_to be_directory end end end diff --git a/spec/acceptance/fragments_are_always_replaced_spec.rb b/spec/acceptance/fragments_are_always_replaced_spec.rb index fc3f96a..a86bd0b 100644 --- a/spec/acceptance/fragments_are_always_replaced_spec.rb +++ b/spec/acceptance/fragments_are_always_replaced_spec.rb @@ -1,101 +1,105 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'concat::fragment replace' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'when run should create fragment files' do let(:pp1) do <<-MANIFEST - concat { '#{@basedir}/foo': } + concat { '#{basedir}/foo': } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'caller has replace unset run 1', } MANIFEST end let(:pp2) do <<-MANIFEST - concat { '#{@basedir}/foo': } + concat { '#{basedir}/foo': } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'caller has replace unset run 2', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp1) idempotent_apply(pp2) - expect(file("#{@basedir}/foo")).to be_file - expect(file("#{@basedir}/foo").content).not_to match 'caller has replace unset run 1' - expect(file("#{@basedir}/foo").content).to match 'caller has replace unset run 2' + expect(file("#{basedir}/foo")).to be_file + expect(file("#{basedir}/foo").content).not_to match 'caller has replace unset run 1' + expect(file("#{basedir}/foo").content).to match 'caller has replace unset run 2' end end # should create fragment files describe 'when run should replace its own fragment files when caller has File { replace=>true } set' do let(:pp1) do <<-MANIFEST File { replace=>true } - concat { '#{@basedir}/foo': } + concat { '#{basedir}/foo': } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'caller has replace true set run 1', } MANIFEST end let(:pp2) do <<-MANIFEST File { replace=>true } - concat { '#{@basedir}/foo': } + concat { '#{basedir}/foo': } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'caller has replace true set run 2', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp1) idempotent_apply(pp2) - expect(file("#{@basedir}/foo")).to be_file - expect(file("#{@basedir}/foo").content).not_to match 'caller has replace true set run 1' - expect(file("#{@basedir}/foo").content).to match 'caller has replace true set run 2' + expect(file("#{basedir}/foo")).to be_file + expect(file("#{basedir}/foo").content).not_to match 'caller has replace true set run 1' + expect(file("#{basedir}/foo").content).to match 'caller has replace true set run 2' end end # should replace its own fragment files when caller has File(replace=>true) set describe 'when run should replace its own fragment files even when caller has File { replace=>false } set' do let(:pp1) do <<-MANIFEST File { replace=>false } - concat { '#{@basedir}/foo': } + concat { '#{basedir}/foo': } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'caller has replace false set run 1', } MANIFEST end let(:pp2) do <<-MANIFEST File { replace=>false } - concat { '#{@basedir}/foo': } + concat { '#{basedir}/foo': } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'caller has replace false set run 2', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp1) idempotent_apply(pp2) - expect(file("#{@basedir}/foo")).to be_file - expect(file("#{@basedir}/foo").content).not_to match 'caller has replace false set run 1' - expect(file("#{@basedir}/foo").content).to match 'caller has replace false set run 2' + expect(file("#{basedir}/foo")).to be_file + expect(file("#{basedir}/foo").content).not_to match 'caller has replace false set run 1' + expect(file("#{basedir}/foo").content).to match 'caller has replace false set run 2' end end # should replace its own fragment files even when caller has File(replace=>false) set end diff --git a/spec/acceptance/newline_spec.rb b/spec/acceptance/newline_spec.rb index 7a8bfdf..9aeca47 100644 --- a/spec/acceptance/newline_spec.rb +++ b/spec/acceptance/newline_spec.rb @@ -1,54 +1,59 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'concat ensure_newline parameter' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end + describe 'when false' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': ensure_newline => false, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '1', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '2', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '12' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '12' end end describe 'when true' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': ensure_newline => true, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '1', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '2', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match %r{1\r?\n2\r?\n} + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match %r{1\r?\n2\r?\n} end end end diff --git a/spec/acceptance/noop_spec.rb b/spec/acceptance/noop_spec.rb index 3432ae7..53824cd 100644 --- a/spec/acceptance/noop_spec.rb +++ b/spec/acceptance/noop_spec.rb @@ -1,26 +1,31 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'concat noop parameter', if: ['debian', 'redhat', 'ubuntu'].include?(os[:family]) do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end + describe 'with "/usr/bin/test -e %"' do let(:pp) do <<-MANIFEST - concat_file { '#{@basedir}/file': + concat_file { '#{basedir}/file': noop => false, } concat_fragment { 'content': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => 'content', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to contain 'content' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to contain 'content' end end end diff --git a/spec/acceptance/order_spec.rb b/spec/acceptance/order_spec.rb index 307502b..5ff94bf 100644 --- a/spec/acceptance/order_spec.rb +++ b/spec/acceptance/order_spec.rb @@ -1,66 +1,71 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'concat order' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end + describe 'sortby alpha' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/foo': + concat { '#{basedir}/foo': order => 'alpha' } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string1', order => '1', } concat::fragment { '2': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string2', order => '2', } concat::fragment { '10': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string10', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/foo")).to be_file - expect(file("#{@basedir}/foo").content).to match %r{string1string10string2} + expect(file("#{basedir}/foo")).to be_file + expect(file("#{basedir}/foo").content).to match %r{string1string10string2} end end describe 'sortby numeric' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/foo': + concat { '#{basedir}/foo': order => 'numeric' } concat::fragment { '1': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string1', order => '1', } concat::fragment { '2': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string2', order => '2', } concat::fragment { '10': - target => '#{@basedir}/foo', + target => '#{basedir}/foo', content => 'string10', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/foo")).to be_file - expect(file("#{@basedir}/foo").content).to match %r{string1string2string10} + expect(file("#{basedir}/foo")).to be_file + expect(file("#{basedir}/foo").content).to match %r{string1string2string10} end end end diff --git a/spec/acceptance/pup_1963_spec.rb b/spec/acceptance/pup_1963_spec.rb index c42e3fc..b7181c3 100644 --- a/spec/acceptance/pup_1963_spec.rb +++ b/spec/acceptance/pup_1963_spec.rb @@ -1,70 +1,74 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' command = case os[:family] when 'windows' 'cmd.exe /c echo triggered' else 'echo triggered' end describe 'with metaparameters' do + attr_reader :basedir + before(:each) do @basedir = setup_test_directory end describe 'with subscribed resources' do let(:pp) do <<-MANIFEST concat { "foobar": ensure => 'present', - path => '#{@basedir}/foobar', + path => '#{basedir}/foobar', } concat::fragment { 'foo': target => 'foobar', content => 'foo', } exec { 'trigger': path => $::path, command => "#{command}", subscribe => Concat['foobar'], refreshonly => true, } MANIFEST end it 'applies the manifest twice with no changes second apply' do expect(apply_manifest(pp, catch_failures: true).stdout).to match(%r{Triggered 'refresh'}) expect(apply_manifest(pp, catch_changes: true).stdout).not_to match(%r{Triggered 'refresh'}) end end describe 'with resources to notify' do let(:pp) do <<-MANIFEST exec { 'trigger': path => $::path, command => "#{command}", refreshonly => true, } concat { "foobar": ensure => 'present', - path => '#{@basedir}/foobar', + path => '#{basedir}/foobar', notify => Exec['trigger'], } concat::fragment { 'foo': target => 'foobar', content => 'foo', } MANIFEST end it 'applies the manifest twice with no changes second apply' do expect(apply_manifest(pp, catch_failures: true).stdout).to match(%r{Triggered 'refresh'}) expect(apply_manifest(pp, catch_changes: true).stdout).not_to match(%r{Triggered 'refresh'}) end end end diff --git a/spec/acceptance/quoted_paths_spec.rb b/spec/acceptance/quoted_paths_spec.rb index e331c08..8aaa20a 100644 --- a/spec/acceptance/quoted_paths_spec.rb +++ b/spec/acceptance/quoted_paths_spec.rb @@ -1,33 +1,37 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'quoted paths' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'with path with blanks' do let(:pp) do <<-MANIFEST - file { '#{@basedir}/concat test': + file { '#{basedir}/concat test': ensure => directory, } - concat { '#{@basedir}/concat test/foo': + concat { '#{basedir}/concat test/foo': } concat::fragment { '1': - target => '#{@basedir}/concat test/foo', + target => '#{basedir}/concat test/foo', content => 'string1', } concat::fragment { '2': - target => '#{@basedir}/concat test/foo', + target => '#{basedir}/concat test/foo', content => 'string2', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/concat test/foo")).to be_file - expect(file("#{@basedir}/concat test/foo").content).to match %r{string1string2} + expect(file("#{basedir}/concat test/foo")).to be_file + expect(file("#{basedir}/concat test/foo").content).to match %r{string1string2} end end end diff --git a/spec/acceptance/specinfra_stubs.rb b/spec/acceptance/specinfra_stubs.rb index 94622ca..02d3f66 100644 --- a/spec/acceptance/specinfra_stubs.rb +++ b/spec/acceptance/specinfra_stubs.rb @@ -1,19 +1,22 @@ +# frozen_string_literal: true + # class Specinfra::Command::Windows::Base::File class Specinfra::Command::Windows::Base::File < Specinfra::Command::Windows::Base class << self def check_is_owned_by(file, owner) Backend::PowerShell::Command.new do exec "if((Get-Item '#{file}').GetAccessControl().Owner -match '#{owner}' -or ((Get-Item '#{file}').GetAccessControl().Owner -match '#{owner}').Length -gt 0){ exit 0 } else { exit 1 }" end end end end + # class Specinfra::Command::Base::File class Specinfra::Command::Base::File < Specinfra::Command::Base class << self def get_content(file) "cat '#{file}' 2> /dev/null || echo -n" end end end diff --git a/spec/acceptance/symbolic_name_spec.rb b/spec/acceptance/symbolic_name_spec.rb index 1a55a84..c8ee063 100644 --- a/spec/acceptance/symbolic_name_spec.rb +++ b/spec/acceptance/symbolic_name_spec.rb @@ -1,34 +1,38 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'symbolic name' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end let(:pp) do <<-MANIFEST concat { 'not_abs_path': - path => '#{@basedir}/file', + path => '#{basedir}/file', } concat::fragment { '1': target => 'not_abs_path', content => '1', order => '01', } concat::fragment { '2': target => 'not_abs_path', content => '2', order => '02', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match '1' - expect(file("#{@basedir}/file").content).to match '2' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match '1' + expect(file("#{basedir}/file").content).to match '2' end end diff --git a/spec/acceptance/validation_spec.rb b/spec/acceptance/validation_spec.rb index 7a3641a..6254540 100644 --- a/spec/acceptance/validation_spec.rb +++ b/spec/acceptance/validation_spec.rb @@ -1,27 +1,31 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'validation, concat validate_cmd parameter', if: ['debian', 'redhat', 'ubuntu'].include?(os[:family]) do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end context 'with "/usr/bin/test -e %"' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': validate_cmd => '/usr/bin/test -e %', } concat::fragment { 'content': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => 'content', } MANIFEST end it 'applies the manifest twice with no stderr' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to contain 'content' + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to contain 'content' end end end diff --git a/spec/acceptance/warn_header_spec.rb b/spec/acceptance/warn_header_spec.rb index 84894b4..f7ecfb4 100644 --- a/spec/acceptance/warn_header_spec.rb +++ b/spec/acceptance/warn_header_spec.rb @@ -1,84 +1,88 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'concat warn_header =>' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end describe 'applies the manifest twice with no stderr' do let(:pp) do <<-MANIFEST - concat { '#{@basedir}/file': + concat { '#{basedir}/file': warn => true, } concat::fragment { '1': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '1', order => '01', } concat::fragment { '2': - target => '#{@basedir}/file', + target => '#{basedir}/file', content => '2', order => '02', } - concat { '#{@basedir}/file2': + concat { '#{basedir}/file2': warn => false, } concat::fragment { 'file2_1': - target => '#{@basedir}/file2', + target => '#{basedir}/file2', content => '1', order => '01', } concat::fragment { 'file2_2': - target => '#{@basedir}/file2', + target => '#{basedir}/file2', content => '2', order => '02', } - concat { '#{@basedir}/file3': + concat { '#{basedir}/file3': warn => "# foo\n", } concat::fragment { 'file3_1': - target => '#{@basedir}/file3', + target => '#{basedir}/file3', content => '1', order => '01', } concat::fragment { 'file3_2': - target => '#{@basedir}/file3', + target => '#{basedir}/file3', content => '2', order => '02', } MANIFEST end it 'when true should enable default warning message' do idempotent_apply(pp) - expect(file("#{@basedir}/file")).to be_file - expect(file("#{@basedir}/file").content).to match %r{# This file is managed by Puppet\. DO NOT EDIT\.} - expect(file("#{@basedir}/file").content).to match %r{1} - expect(file("#{@basedir}/file").content).to match %r{2} + expect(file("#{basedir}/file")).to be_file + expect(file("#{basedir}/file").content).to match %r{# This file is managed by Puppet\. DO NOT EDIT\.} + expect(file("#{basedir}/file").content).to match %r{1} + expect(file("#{basedir}/file").content).to match %r{2} end it 'when false should not enable default warning message' do - expect(file("#{@basedir}/file2")).to be_file - expect(file("#{@basedir}/file2").content).not_to match %r{# This file is managed by Puppet\. DO NOT EDIT\.} - expect(file("#{@basedir}/file2").content).to match %r{1} - expect(file("#{@basedir}/file2").content).to match %r{2} + expect(file("#{basedir}/file2")).to be_file + expect(file("#{basedir}/file2").content).not_to match %r{# This file is managed by Puppet\. DO NOT EDIT\.} + expect(file("#{basedir}/file2").content).to match %r{1} + expect(file("#{basedir}/file2").content).to match %r{2} end it 'when foo should overide default warning message' do - expect(file("#{@basedir}/file3")).to be_file - expect(file("#{@basedir}/file3").content).to match %r{# foo} - expect(file("#{@basedir}/file3").content).to match %r{1} - expect(file("#{@basedir}/file3").content).to match %r{2} + expect(file("#{basedir}/file3")).to be_file + expect(file("#{basedir}/file3").content).to match %r{# foo} + expect(file("#{basedir}/file3").content).to match %r{1} + expect(file("#{basedir}/file3").content).to match %r{2} end end end diff --git a/spec/acceptance/warnings_spec.rb b/spec/acceptance/warnings_spec.rb index 46b984d..5224275 100644 --- a/spec/acceptance/warnings_spec.rb +++ b/spec/acceptance/warnings_spec.rb @@ -1,26 +1,30 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'warnings' do + attr_reader :basedir + before(:all) do @basedir = setup_test_directory end context 'when concat::fragment target not found' do let(:pp) do <<-MANIFEST concat { 'file': - path => '#{@basedir}/file', + path => '#{basedir}/file', } concat::fragment { 'foo': - target => '#{@basedir}/bar', + target => '#{basedir}/bar', content => 'bar', } MANIFEST end it 'applies manifests, check stderr' do expect(apply_manifest(pp, catch_failures: true).stderr).to match 'not found in the catalog' expect(apply_manifest(pp, catch_failures: true).stderr).to match 'not found in the catalog' end end end diff --git a/spec/defines/concat_fragment_spec.rb b/spec/defines/concat_fragment_spec.rb index 71c7d06..85a90f3 100644 --- a/spec/defines/concat_fragment_spec.rb +++ b/spec/defines/concat_fragment_spec.rb @@ -1,156 +1,158 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'concat::fragment' do shared_examples 'fragment' do |title, params| params = {} if params.nil? p = { content: nil, source: nil, order: 10, }.merge(params) let(:title) { title } let(:params) { params } let(:pre_condition) do "concat{ '#{p[:target]}': }" end it do is_expected.to contain_concat(p[:target]) end it do is_expected.to contain_concat_file(p[:target]) end it do is_expected.to contain_concat_fragment(title) end end context 'when title' do ['0', '1', 'a', 'z'].each do |title| it_behaves_like 'fragment', title, target: '/etc/motd', content: "content for #{title}" end end # title context 'when target =>' do ['./etc/motd', 'etc/motd', 'motd_header'].each do |target| context target do it_behaves_like 'fragment', target, target: '/etc/motd', content: "content for #{target}" end end context 'when false' do let(:title) { 'motd_header' } let(:params) { { target: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'target' expects a .*String.*}) end end end # target => context 'when content =>' do ['', 'ashp is our hero'].each do |content| context content do it_behaves_like 'fragment', 'motd_header', content: content, target: '/etc/motd' end end context 'when false' do let(:title) { 'motd_header' } let(:params) { { content: false, target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{expects a value of type Undef( or String|, String, or Deferred), got Boolean}) end end end # content => context 'when source =>' do ['', '/foo/bar', ['/foo/bar', '/foo/baz']].each do |source| context source do it_behaves_like 'fragment', 'motd_header', source: source, target: '/etc/motd' end end context 'when false' do let(:title) { 'motd_header' } let(:params) { { source: false, target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'source' expects a .*String.*Array.*}) end end end # source => context 'when order =>' do ['', '42', 'a', 'z'].each do |order| context "'#{order}'" do it_behaves_like 'fragment', 'motd_header', order: order, target: '/etc/motd' end end context 'when false' do let(:title) { 'motd_header' } let(:params) { { order: false, target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Evaluation Error.*expects.*Boolean.*}) end end context 'when 123:456' do let(:title) { 'motd_header' } let(:params) { { order: '123:456', target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{cannot contain}) end end context 'when 23/456' do let(:title) { 'motd_header' } let(:params) { { order: '123/456', target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{cannot contain}) end end context 'when 123\n456' do let(:title) { 'motd_header' } let(:params) { { order: "123\n456", target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{cannot contain}) end end end # order => context 'with more than one content source' do context 'with source and content' do let(:title) { 'motd_header' } let(:params) do { target: '/etc/motd', source: '/foo', content: 'bar', } end it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Can\'t use \'source\' and \'content\' at the same time}m) end end end # more than one content source end diff --git a/spec/defines/concat_spec.rb b/spec/defines/concat_spec.rb index 4adcd01..840cd44 100644 --- a/spec/defines/concat_spec.rb +++ b/spec/defines/concat_spec.rb @@ -1,402 +1,404 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'concat' do shared_examples 'concat' do |title, params, id| params = {} if params.nil? id = 'root' if id.nil? # default param values p = { ensure: 'present', path: title, owner: nil, group: nil, mode: '0644', warn: false, backup: 'puppet', replace: true, force: false, }.merge(params) file_defaults = { backup: p[:backup], } present_expect = { ensure: 'present', owner: p[:owner], group: p[:group], mode: p[:mode], path: p[:path], backup: p[:backup], replace: p[:replace], selinux_ignore_defaults: p[:selinux_ignore_defaults], selrange: p[:selrange], selrole: p[:selrole], seltype: p[:seltype], seluser: p[:seluser], force: p[:force], } let(:title) { title } let(:params) { params } let(:facts) do { id: id, osfamily: 'Debian', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', kernel: 'Linux', is_pe: false, } end if p[:ensure] == 'present' it do is_expected.to contain_concat(title).with(file_defaults.merge(present_expect)) end else it do is_expected.to contain_concat(title).with(file_defaults.merge(ensure: 'absent', backup: p[:backup])) end end end context 'when title without path param' do # title/name is the default value for the path param. therefore, the # title must be an absolute path unless path is specified ['/foo', '/foo/bar', '/foo/bar/baz'].each do |title| context title do it_behaves_like 'concat', '/etc/foo.bar' end end ['./foo', 'foo', 'foo/bar'].each do |title| context title do let(:title) { title } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Stdlib::Unixpath}) end end end end context 'when title with path param' do ['/foo', 'foo', 'foo/bar'].each do |title| context title do it_behaves_like 'concat', title, path: '/etc/foo.bar' end end end context 'when title with special characters in title' do ['foo:bar', 'foo*bar', 'foo(bar)', 'foo@bar'].each do |title| context title do it_behaves_like 'concat', title, path: '/etc/foo.bar' end end end context 'when as non-root user' do it_behaves_like 'concat', '/etc/foo.bar', {}, 'bob' end context 'when ensure =>' do ['present', 'absent'].each do |ens| context ens do it_behaves_like 'concat', '/etc/foo.bar', ensure: ens end end context 'when invalid' do let(:title) { '/etc/foo.bar' } let(:params) { { ensure: 'invalid' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{expects a match for Enum\['absent', 'present'\]}) end end end # ensure => context 'when path =>' do context 'when /foo' do it_behaves_like 'concat', '/etc/foo.bar', path: '/foo' end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { path: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Stdlib::Unixpath}) end end ['./foo', 'foo', 'foo/bar'].each do |path| context path do let(:title) { '/etc/foo.bar' } let(:params) { { path: path } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Stdlib::Unixpath}) end end end end # path => context 'when owner =>' do ['apenney', 1000, '1001'].each do |owner| context owner do it_behaves_like 'concat', '/etc/foo.bar', owner: owner end end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { owner: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Evaluation Error.*expects.*String.*Boolean.*}) end end end # owner => context 'when group =>' do ['apenney', 1000, '1001'].each do |group| context group do it_behaves_like 'concat', '/etc/foo.bar', group: group end end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { group: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Evaluation Error.*expects.*String.*Boolean.*}) end end end # group => context 'when mode =>' do context 'when 1755' do it_behaves_like 'concat', '/etc/foo.bar', mode: '1755' end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { mode: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'mode' expects .*String.*}) end end end # mode => context 'when warn =>' do [true, false, '# foo'].each do |warn| context warn do it_behaves_like 'concat', '/etc/foo.bar', warn: warn end end context 'when (stringified boolean)' do ['true', 'yes', 'on', 'false', 'no', 'off'].each do |warn| define warn do it_behaves_like 'concat', '/etc/foo.bar', warn: warn it 'creates a warning' do skip('rspec-puppet support for testing warning()') end end end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { warn: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'warn' expects .*Boolean.*String.*}) end end end # warn => context 'when show_diff =>' do [true, false].each do |show_diff| context show_diff do it_behaves_like 'concat', '/etc/foo.bar', show_diff: show_diff end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { show_diff: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'show_diff' expects .*Boolean.*}) end end end # show_diff => context 'when backup =>' do ['reverse', false, true].each do |backup| context backup.to_s do it_behaves_like 'concat', '/etc/foo.bar', backup: backup end end context 'when true' do let(:title) { '/etc/foo.bar' } let(:params) { { backup: [] } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'backup' expects .*Boolean.*String.*}) end end end # backup => context 'when replace =>' do [true, false].each do |replace| context replace do it_behaves_like 'concat', '/etc/foo.bar', replace: replace end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { replace: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'replace' expects .*Boolean.*}) end end end # replace => context 'when force =>' do [true, false].each do |force| context force do it_behaves_like 'concat', '/etc/foo.bar', force: force end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { force: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'force' expects .*Boolean.*}) end end end # force => context 'when order =>' do ['alpha', 'numeric'].each do |order| context order do it_behaves_like 'concat', '/etc/foo.bar', order: order end end context 'when invalid' do let(:title) { '/etc/foo.bar' } let(:params) { { order: 'invalid' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{expects a match for Enum\['alpha', 'numeric'\]}) end end end # order => context 'when ensure_newline =>' do [true, false].each do |ensure_newline| context 'when true' do it_behaves_like 'concat', '/etc/foo.bar', ensure_newline: ensure_newline end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { ensure_newline: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'ensure_newline' expects a Boolean value}) end end end # ensure_newline => context 'when validate_cmd =>' do context 'when /usr/bin/test -e %' do it_behaves_like 'concat', '/etc/foo.bar', validate_cmd: '/usr/bin/test -e %' end [1234, true].each do |cmd| context cmd do let(:title) { '/etc/foo.bar' } let(:params) { { validate_cmd: cmd } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'validate_cmd' expects.*String.*}) end end end end # validate_cmd => context 'when selinux_ignore_defaults =>' do let(:title) { '/etc/foo.bar' } [true, false].each do |v| context v do it_behaves_like 'concat', '/etc/foo.bar', selinux_ignore_defaults: v end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { selinux_ignore_defaults: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Evaluation Error.*expects.*Boolean.*}) end end end # selinux_ignore_defaults => [ :selrange, :selrole, :seltype, :seluser, ].each do |p| context " #{p} =>" do let(:title) { '/etc/foo.bar' } context 'when foo' do it_behaves_like 'concat', '/etc/foo.bar', p => 'foo' end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { p => false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter '#{p}' expects.*String.*}) end end end # #{p} => end end diff --git a/spec/spec_helper_local.rb b/spec/spec_helper_local.rb index fc29827..abac766 100644 --- a/spec/spec_helper_local.rb +++ b/spec/spec_helper_local.rb @@ -1,75 +1,77 @@ +# frozen_string_literal: true + if ENV['COVERAGE'] == 'yes' require 'simplecov' require 'simplecov-console' require 'codecov' SimpleCov.formatters = [ SimpleCov::Formatter::HTMLFormatter, SimpleCov::Formatter::Console, SimpleCov::Formatter::Codecov, ] SimpleCov.start do track_files 'lib/**/*.rb' add_filter '/spec' # do not track vendored files add_filter '/vendor' add_filter '/.vendor' # do not track gitignored files # this adds about 4 seconds to the coverage check # this could definitely be optimized add_filter do |f| # system returns true if exit status is 0, which with git-check-ignore means file is ignored system("git check-ignore --quiet #{f.filename}") end end end shared_examples 'Puppet::Parameter::Boolean' do |parameter| [true, :true, 'true', :yes, 'yes'].each do |value| it "accepts #{value} (#{value.class}) as a value" do resource[parameter] = value expect(resource[parameter]).to eq(true) end end [false, :false, 'false', :no, 'no'].each do |value| it "accepts #{value} (#{value.class}) as a value" do resource[parameter] = value expect(resource[parameter]).to eq(false) end end it 'does not accept "foo" as a value' do expect { resource[parameter] = 'foo' }.to raise_error(%r{Invalid value "foo"}) end end shared_examples 'a parameter that accepts only string values' do |parameter| it 'accepts a string value' do resource[parameter] = 'foo' expect(resource[parameter]).to eq('foo') end it 'does not accept an array value' do expect { resource[parameter] = ['foo', 'bar'] }.to raise_error(%r{must be a String}) end it 'does not accept a hash value' do expect { resource[parameter] = { foo: 'bar' } }.to raise_error(%r{must be a String}) end it 'does not accept an integer value' do expect { resource[parameter] = 9001 }.to raise_error(%r{must be a String}) end it 'does not accept a boolean true value' do expect { resource[parameter] = true }.to raise_error(%r{must be a String}) end it 'does not accept a boolean false value' do expect { resource[parameter] = false }.to raise_error(%r{must be a String}) end end diff --git a/spec/unit/type/concat_file_spec.rb b/spec/unit/type/concat_file_spec.rb index 892ff4f..6df9177 100644 --- a/spec/unit/type/concat_file_spec.rb +++ b/spec/unit/type/concat_file_spec.rb @@ -1,150 +1,152 @@ +# frozen_string_literal: true + require 'spec_helper' describe Puppet::Type.type(:concat_file) do let(:resource) { described_class.new(name: '/foo/bar') } describe 'key attributes' do let(:subject) { described_class.key_attributes } it 'contain only :path' do is_expected.to eq([:path]) end end describe 'parameter :path' do it 'does not accept unqualified paths' do expect { resource[:path] = 'foo' }.to raise_error( %r{File paths must be fully qualified}, ) end end describe 'parameter :owner' do subject { described_class.attrclass(:owner) } it 'inherits Puppet::Type::File::Owner' do is_expected.to be < Puppet::Type::File::Owner end end describe 'parameter :group' do subject { described_class.attrclass(:group) } it 'inherits Puppet::Type::File::Group' do is_expected.to be < Puppet::Type::File::Group end end describe 'parameter :mode' do subject { described_class.attrclass(:mode) } it 'inherits Puppet::Type::File::Mode' do is_expected.to be < Puppet::Type::File::Mode end end describe 'parameter :order' do it 'accepts "alpha" as a value' do resource[:order] = 'alpha' expect(resource[:order]).to eq(:alpha) end it 'accepts "numeric" as a value' do resource[:order] = 'numeric' expect(resource[:order]).to eq(:numeric) end it 'does not accept "bar" as a value' do expect { resource[:order] = 'bar' }.to raise_error(%r{Invalid value "bar"}) end end describe 'parameter :backup' do it 'accepts true (TrueClass) as a value' do resource[:backup] = true expect(resource[:backup]).to eq(true) end it 'accepts false (FalseClass) as a value' do resource[:backup] = false expect(resource[:backup]).to eq(false) end it 'accepts "foo" as a value' do resource[:backup] = 'foo' expect(resource[:backup]).to eq('foo') end end describe 'parameter :selrange' do it_behaves_like 'a parameter that accepts only string values', :selrange end describe 'parameter :selrole' do it_behaves_like 'a parameter that accepts only string values', :selrole end describe 'parameter :seltype' do it_behaves_like 'a parameter that accepts only string values', :seltype end describe 'parameter :seluser' do it_behaves_like 'a parameter that accepts only string values', :seluser end describe 'parameter :replace' do it_behaves_like 'Puppet::Parameter::Boolean', :replace end describe 'parameter :ensure_newline' do it_behaves_like 'Puppet::Parameter::Boolean', :ensure_newline end describe 'parameter :show_diff' do it_behaves_like 'Puppet::Parameter::Boolean', :show_diff end describe 'parameter :selinux_ignore_defaults' do it_behaves_like 'Puppet::Parameter::Boolean', :selinux_ignore_defaults end describe 'parameter :force' do it_behaves_like 'Puppet::Parameter::Boolean', :force end describe 'parameter :format' do it 'accepts "plain" as a value' do resource[:format] = 'plain' expect(resource[:format]).to eq(:plain) end it 'accepts "yaml" as a value' do resource[:format] = 'yaml' expect(resource[:format]).to eq(:yaml) end it 'accepts "json" as a value' do resource[:format] = 'json' expect(resource[:format]).to eq(:json) end it 'accepts "json-array" as a value' do resource[:format] = 'json-array' expect(resource[:format]).to eq(:'json-array') end it 'accepts "json-pretty" as a value' do resource[:format] = 'json-pretty' expect(resource[:format]).to eq(:'json-pretty') end it 'accepts "json-array-pretty" as a value' do resource[:format] = 'json-array-pretty' expect(resource[:format]).to eq(:'json-array-pretty') end it 'does not accept "bar" as a value' do expect { resource[:format] = 'bar' }.to raise_error(%r{Invalid value "bar"}) end end end diff --git a/spec/unit/type/concat_fragment_spec.rb b/spec/unit/type/concat_fragment_spec.rb index 5a2700c..991472d 100644 --- a/spec/unit/type/concat_fragment_spec.rb +++ b/spec/unit/type/concat_fragment_spec.rb @@ -1,111 +1,113 @@ +# frozen_string_literal: true + require 'spec_helper' describe Puppet::Type.type(:concat_fragment) do let(:resource) do described_class.new(name: 'foo', target: 'bar', content: 'baz') end describe 'key attributes' do let(:subject) { described_class.key_attributes } it 'contain only :name' do is_expected.to eq([:name]) end end describe 'parameter :target' do it_behaves_like 'a parameter that accepts only string values', :target end describe 'parameter :content' do it_behaves_like 'a parameter that accepts only string values', :content end describe 'parameter :source' do it 'accepts a string value' do resource[:source] = 'foo' expect(resource[:source]).to eq('foo') end it 'accepts an array value' do resource[:source] = ['foo', 'bar'] expect(resource[:source]).to eq(['foo', 'bar']) end it 'does not accept a hash value' do expect { resource[:source] = { foo: 'bar' } }.to raise_error(%r{must be a String or Array}) end it 'does not accept an integer value' do expect { resource[:source] = 9001 }.to raise_error(%r{must be a String or Array}) end it 'does not accept a boolean true value' do expect { resource[:source] = true }.to raise_error(%r{must be a String or Array}) end it 'does not accept a boolean false value' do expect { resource[:source] = false }.to raise_error(%r{must be a String or Array}) end end describe 'parameter :order' do it 'accepts a string value' do resource[:order] = 'foo' expect(resource[:order]).to eq('foo') end it 'accepts an integer value' do resource[:order] = 9001 expect(resource[:order]).to eq(9001) end it 'does not accept an array value' do expect { resource[:order] = ['foo', 'bar'] }.to raise_error(%r{is not a string or integer}) end it 'does not accept a hash value' do expect { resource[:order] = { foo: 'bar' } }.to raise_error(%r{is not a string or integer}) end it 'does not accept a boolean true value' do expect { resource[:order] = true }.to raise_error(%r{is not a string or integer}) end it 'does not accept a boolean false value' do expect { resource[:order] = false }.to raise_error(%r{is not a string or integer}) end it 'does not accept a string with ":" in it/' do expect { resource[:order] = ':foo' }.to raise_error(%r{Order cannot contain}) end it 'does not accept a string with "\n" in it/' do expect { resource[:order] = "\nfoo" }.to raise_error(%r{Order cannot contain}) end it 'does not accept a string with "/" in it/' do expect { resource[:order] = '/foo' }.to raise_error(%r{Order cannot contain}) end end context 'without a value set for :target or :tag' do it 'throws an error' do expect { described_class.new(name: 'foo', content: 'baz') }.to raise_error(%r{No 'target' or 'tag' set}) end end context 'without a value set for both :content and :source' do it 'throws an error' do expect { described_class.new(name: 'foo', target: 'bar') }.to raise_error(%r{Set either 'source' or 'content'}) end end context 'with a value set for both :content and :source' do it 'throws an error' do expect { described_class.new(name: 'foo', target: 'bar', content: 'baz', source: 'qux') }.to raise_error(%r{Can't use 'source' and 'content' at the same time}) end end end