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..8a313f4 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,138 +1,542 @@ +inherit_from: .rubocop_todo.yml + --- 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 +Gemspec/DuplicatedAssignment: Enabled: false -GetText/DecorateStringFormattingUsingInterpolation: +Gemspec/OrderedDependencies: Enabled: false -GetText/DecorateStringFormattingUsingPercent: +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/BlockNesting: + Enabled: false Metrics/ClassLength: Enabled: false Metrics/CyclomaticComplexity: Enabled: false Metrics/MethodLength: Enabled: false Metrics/ModuleLength: Enabled: false Metrics/ParameterLists: Enabled: false Metrics/PerceivedComplexity: Enabled: false +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 index bb1d59c..9fb474c 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,44 +1,478 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2020-11-18 11:06:43 +0000 using RuboCop version 0.49.1. +# on 2020-12-16 17:04:12 UTC using RuboCop version 1.6.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 55 -Lint/UnderscorePrefixedVariableName: +# Offense count: 2 +# Configuration parameters: Include. +# Include: **/*.gemfile, **/Gemfile, **/gems.rb +Bundler/DuplicatedGem: + Exclude: + - 'Gemfile' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. +# Include: **/*.gemfile, **/Gemfile, **/gems.rb +Bundler/OrderedGems: + Exclude: + - 'Gemfile' + +# Offense count: 24 +# Cop supports --auto-correct. +Layout/ClosingHeredocIndentation: + Exclude: + - 'spec/acceptance/docker_custom_source_spec.rb' + - 'spec/acceptance/docker_full_spec.rb' + - 'spec/acceptance/docker_spec.rb' + - 'spec/acceptance/stack_spec.rb' + - 'spec/spec_helper_acceptance_local.rb' + +# Offense count: 24 +# Cop supports --auto-correct. +Layout/EmptyLineAfterGuardClause: + Enabled: false + +# Offense count: 667 +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. +# SupportedHashRocketStyles: key, separator, table +# SupportedColonStyles: key, separator, table +# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit +Layout/HashAlignment: Enabled: false -# Offense count: 38 +# Offense count: 10 +# Cop supports --auto-correct. +Layout/HeredocIndentation: + Exclude: + - 'Rakefile' + - 'spec/spec_helper_acceptance_local.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: normal, indented_internal_methods +Layout/IndentationConsistency: + Exclude: + - 'Guardfile' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: IndentationWidth, EnforcedStyle. +# SupportedStyles: spaces, tabs +Layout/IndentationStyle: + Exclude: + - 'Guardfile' + +# Offense count: 2 +# Cop supports --auto-correct. +Layout/SpaceAroundMethodCallOperator: + Exclude: + - 'spec/shared_examples/install.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: final_newline, final_blank_line +Layout/TrailingEmptyLines: + Exclude: + - 'Guardfile' + - 'Rakefile' + +# Offense count: 1 +# Cop supports --auto-correct. +Lint/InterpolationCheck: + Exclude: + - 'spec/acceptance/docker_full_spec.rb' + +# Offense count: 1 +# Configuration parameters: MaximumRangeSize. +Lint/MissingCopEnableDirective: + Exclude: + - 'lib/puppet/provider/docker_compose/ruby.rb' + +# Offense count: 1 +Lint/MixedRegexpCaptureTypes: + Exclude: + - 'Gemfile' + +# Offense count: 22 +# Configuration parameters: AllowKeywordBlockArguments. +Lint/UnderscorePrefixedVariableName: + Exclude: + - 'spec/helper/get_defaults.rb' + - 'spec/helper/get_values_init.rb' + - 'spec/shared_examples/compose.rb' + - 'spec/shared_examples/config.rb' + - 'spec/shared_examples/exec.rb' + - 'spec/shared_examples/image.rb' + - 'spec/shared_examples/install.rb' + - 'spec/shared_examples/machine.rb' + - 'spec/shared_examples/params.rb' + - 'spec/shared_examples/plugin.rb' + - 'spec/shared_examples/registry.rb' + +# Offense count: 7 Lint/UselessAssignment: Exclude: - 'spec/classes/networks_spec.rb' - 'spec/defines/run_spec.rb' - 'spec/helper/get_defaults.rb' - 'spec/shared_examples/compose.rb' - 'spec/shared_examples/image.rb' - 'spec/shared_examples/machine.rb' - - 'spec/shared_examples/run.rb' - - 'spec/shared_examples/service.rb' - - 'spec/shared_examples/services.rb' -# Offense count: 6 +# Offense count: 18 +# Configuration parameters: IgnoredMethods, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 309 + +# Offense count: 131 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. +# IgnoredMethods: refine +Metrics/BlockLength: + Max: 712 + +# Offense count: 7 # Configuration parameters: CountBlocks. Metrics/BlockNesting: Max: 7 +# Offense count: 15 +# Configuration parameters: IgnoredMethods. +Metrics/CyclomaticComplexity: + Max: 36 + +# Offense count: 20 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. +Metrics/MethodLength: + Max: 485 + +# Offense count: 2 +# Configuration parameters: CountKeywordArgs, MaxOptionalParameters. +Metrics/ParameterLists: + Max: 9 + +# Offense count: 12 +# Configuration parameters: IgnoredMethods. +Metrics/PerceivedComplexity: + Max: 39 + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: lowercase, uppercase +Naming/HeredocDelimiterCase: + Exclude: + - 'spec/acceptance/compose_v3_spec.rb' + - 'spec/acceptance_swarm/swarm_spec.rb' + +# Offense count: 48 +# Configuration parameters: ForbiddenDelimiters. +# ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$)) +Naming/HeredocDelimiterNaming: + Exclude: + - 'Rakefile' + - 'spec/acceptance/docker_custom_source_spec.rb' + - 'spec/acceptance/docker_full_spec.rb' + - 'spec/acceptance/machine_spec.rb' + - 'spec/spec_helper_acceptance_local.rb' + +# Offense count: 13 +# Configuration parameters: EnforcedStyle. +# SupportedStyles: snake_case, camelCase +Naming/VariableName: + Exclude: + - 'Rakefile' + +# Offense count: 1 +Security/Eval: + Exclude: + - 'Gemfile' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect. +Security/JSONLoad: + Exclude: + - 'Rakefile' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, conditionals +Style/AndOr: + Exclude: + - 'Rakefile' + +# Offense count: 5 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. +# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces +# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object +# FunctionalMethods: let, let!, subject, watch +# IgnoredMethods: lambda, proc, it +Style/BlockDelimiters: + Exclude: + - 'lib/puppet/provider/docker_compose/ruby.rb' + - 'lib/puppet/provider/docker_stack/ruby.rb' + - 'spec/spec_helper.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +Style/CaseLikeIf: + Exclude: + - 'lib/puppet/parser/functions/docker_run_flags.rb' + - 'lib/puppet/provider/docker_network/ruby.rb' + - 'spec/shared_examples/plugin.rb' + - 'spec/shared_examples/registry.rb' + +# Offense count: 11 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: nested, compact +Style/ClassAndModuleChildren: + Exclude: + - 'lib/puppet/parser/functions/docker_exec_flags.rb' + - 'lib/puppet/parser/functions/docker_params_changed.rb' + - 'lib/puppet/parser/functions/docker_plugin_enable_flags.rb' + - 'lib/puppet/parser/functions/docker_plugin_install_flags.rb' + - 'lib/puppet/parser/functions/docker_plugin_remove_flags.rb' + - 'lib/puppet/parser/functions/docker_run_flags.rb' + - 'lib/puppet/parser/functions/docker_secrets_flags.rb' + - 'lib/puppet/parser/functions/docker_service_flags.rb' + - 'lib/puppet/parser/functions/docker_stack_flags.rb' + - 'lib/puppet/parser/functions/docker_swarm_init_flags.rb' + - 'lib/puppet/parser/functions/docker_swarm_join_flags.rb' + +# Offense count: 1 +Style/Documentation: + Exclude: + - 'spec/**/*' + - 'test/**/*' + - 'lib/puppet/parser/functions/docker_params_changed.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty, nil, both +Style/EmptyElse: + Exclude: + - 'lib/facter/docker.rb' + - 'spec/shared_examples/service.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: format, sprintf, percent +Style/FormatString: + Exclude: + - 'Rakefile' + - 'lib/puppet/parser/functions/docker_secrets_flags.rb' + - 'spec/helper/get_docker_secrets_flags.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Exclude: + - 'Gemfile' + - 'Guardfile' + +# Offense count: 12 +# Cop supports --auto-correct. +Style/GlobalStdStream: + Exclude: + - 'tasks/node_ls.rb' + - 'tasks/node_rm.rb' + - 'tasks/node_update.rb' + - 'tasks/service_create.rb' + - 'tasks/service_rm.rb' + - 'tasks/service_scale.rb' + - 'tasks/service_update.rb' + - 'tasks/swarm_init.rb' + - 'tasks/swarm_join.rb' + - 'tasks/swarm_leave.rb' + - 'tasks/swarm_token.rb' + - 'tasks/swarm_update.rb' + +# Offense count: 5 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: braces, no_braces +Style/HashAsLastArrayItem: + Exclude: + - 'Gemfile' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. +# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys +Style/HashSyntax: + Exclude: + - 'Guardfile' + # Offense count: 5 Style/IdenticalConditionalBranches: Exclude: - 'spec/helper/get_defaults.rb' - 'spec/helper/get_values_init.rb' +# Offense count: 95 +# Cop supports --auto-correct. +Style/IfUnlessModifier: + Enabled: false + # Offense count: 6 -Style/IfInsideElse: +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: line_count_dependent, lambda, literal +Style/Lambda: Exclude: - - 'lib/puppet/parser/functions/docker_service_flags.rb' - - 'spec/helper/get_docker_service_flags.rb' - - 'spec/shared_examples/image.rb' - - 'spec/shared_examples/install.rb' - - 'spec/shared_examples/service.rb' + - 'lib/puppet/parser/functions/docker_run_flags.rb' + - 'lib/puppet/parser/functions/docker_secrets_flags.rb' + - 'lib/puppet/provider/docker_network/ruby.rb' + - 'lib/puppet/provider/docker_volume/ruby.rb' + - 'spec/helper/get_docker_run_flags.rb' + - 'spec/helper/get_docker_secrets_flags.rb' + +# Offense count: 2 +Style/MixinUsage: + Exclude: + - 'spec/spec_helper.rb' + - 'spec/spec_helper_acceptance_local.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantCondition: + Exclude: + - 'spec/shared_examples/run.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantConditional: + Exclude: + - 'spec/helper/get_defaults.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Style/RedundantInterpolation: + Exclude: + - 'Rakefile' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/RedundantRegexpCharacterClass: + Exclude: + - 'spec/classes/compose_spec.rb' + +# Offense count: 53 +# Cop supports --auto-correct. +Style/RedundantRegexpEscape: + Exclude: + - 'Gemfile' + - 'Guardfile' + - 'Rakefile' + - 'spec/acceptance/docker_custom_source_spec.rb' + - 'spec/acceptance/docker_full_spec.rb' + - 'spec/acceptance/docker_spec.rb' + - 'spec/classes/compose_spec.rb' + +# Offense count: 123 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, AllowInnerSlashes. +# SupportedStyles: slashes, percent_r, mixed +Style/RegexpLiteral: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, explicit +Style/RescueStandardError: + Exclude: + - 'spec/spec_helper.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. +# AllowedMethods: present?, blank?, presence, try, try! +Style/SafeNavigation: + Exclude: + - 'Rakefile' + +# Offense count: 5 +# Cop supports --auto-correct. +# Configuration parameters: AllowModifier. +Style/SoleNestedConditional: + Exclude: + - 'lib/facter/docker.rb' + - 'lib/puppet/provider/docker_network/ruby.rb' + - 'spec/classes/compose_spec.rb' + - 'spec/classes/machine_spec.rb' + - 'spec/defines/services_spec.rb' + +# Offense count: 34 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Exclude: + - 'Gemfile' + - 'Rakefile' + +# Offense count: 9 +# Cop supports --auto-correct. +# Configuration parameters: MinSize. +# SupportedStyles: percent, brackets +Style/SymbolArray: + EnforcedStyle: brackets + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, AllowSafeAssignment. +# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex +Style/TernaryParentheses: + Exclude: + - 'lib/puppet/provider/docker_compose/ruby.rb' + - 'lib/puppet/provider/docker_stack/ruby.rb' + +# Offense count: 156 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInArguments: + Enabled: false + +# Offense count: 44 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInArrayLiteral: + Enabled: false + +# Offense count: 189 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInHashLiteral: + Enabled: false + +# Offense count: 21 +# Cop supports --auto-correct. +# Configuration parameters: MinSize, WordRegex. +# SupportedStyles: percent, brackets +Style/WordArray: + EnforcedStyle: brackets + +# Offense count: 85 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# URISchemes: http, https +Layout/LineLength: + Max: 255 diff --git a/.sync.yml b/.sync.yml index a219c9f..b9be5c4 100644 --- a/.sync.yml +++ b/.sync.yml @@ -1,57 +1,41 @@ --- ".gitlab-ci.yml": delete: true -".rubocop.yml": - default_configs: - inherit_from: ".rubocop_todo.yml" - require: - - rubocop-rspec ".travis.yml": deploy_to_forge: enabled: false docker_sets: - set: docker/debian-8 - set: docker/ubuntu-14.04 docker_defaults: bundler_args: '' secure: '' branches: - release simplecov: true notifications: slack: secure: >- hvYQAWaLeSyzyWeryph15CXqYFmy/jszkW13fhsteTwQjiVpuW950Z+hO0us7z1+G34wLvUC8uMrQw7F64h8qq6o2GR98r5HS4XvhkkuIymXdQoFWwsuMzh6EkKsLqYbw8Th+b1Wy8jQprZulAssfiV+r1FlSuyj4uvxkge/oheENgfs77tQOK0yCdvOyNtZeBS+hfbd26eAHZCkzPaJQJ0brZIg73B86w4Lu5+JtD5bys7NDq69jmXWzYHDGx4A0d7uI880L0tjDdcZxxlsLFYm0sESpWPHitWx/XaQwCbif6OOM59c0/W7yBwMTim3++C2BpVjD0pq0cRVgqNvqRpe0xSQ8rZ4RNZdkmdjZdz+ZX7HADJh1nKwmlzv0YYpUQNZoWcyTikkYKeHQjgwxPutxMFSioMcZFXYjo49Y5601VlKOkWI+afyrbh0s4nJnHinmk0cvyIK8svlltrUO/oXpONODJv5AJvGVp7/EeeGlYWz4yfV11+nwIbSpLM+VZdLCoULC08N1jCAoLVmSiGkZDdjuC1+jNuDjnaPKFKgTOjf6FWGN6mElrtyitYvvrw23LAvHBs49uVKOYEhUlCIM4dTqg5kapMLcJg8CTTjBXaWIzJHwlCUMwTh3CLBkOf5WFi5/gzKVFFvbamaqIFpv2K4Cf8DqB6mOgGAlrI= appveyor.yml: delete: true Gemfile: optional: ":development": - gem: ruby-pwsh - 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') - required: ":system_tests": - - gem: puppet-module-posix-system-r#{minor_version} - platforms: ruby - - gem: puppet-module-win-system-r#{minor_version} - platforms: - - mswin - - mingw - - x64_mingw - gem: rspec-retry Rakefile: changelog_since_tag: 3.5.0 spec/spec_helper.rb: unmanaged: true 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/Gemfile b/Gemfile index 636c4ef..4f9a7bd 100644 --- a/Gemfile +++ b/Gemfile @@ -1,80 +1,75 @@ 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-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 "ruby-pwsh", 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 "github_changelog_generator", require: false end group :system_tests do - gem "puppet-module-posix-system-r#{minor_version}", require: false, platforms: [:ruby] - gem "puppet-module-win-system-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "rspec-retry", require: false + 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] + gem "rspec-retry", require: false 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/lib/facter/docker.rb b/lib/facter/docker.rb index dee0370..a6479b0 100644 --- a/lib/facter/docker.rb +++ b/lib/facter/docker.rb @@ -1,135 +1,135 @@ # frozen_string_literal: true require 'facter' require 'json' Facter.add(:docker_systemroot) do confine osfamily: :windows setcode do Puppet::Util.get_env('SystemRoot') end end Facter.add(:docker_program_files_path) do confine osfamily: :windows setcode do Puppet::Util.get_env('ProgramFiles') end end Facter.add(:docker_program_data_path) do confine osfamily: :windows setcode do Puppet::Util.get_env('ProgramData') end end Facter.add(:docker_user_temp_path) do confine osfamily: :windows setcode do Puppet::Util.get_env('TEMP') end end docker_command = if Facter.value(:kernel) == 'windows' 'powershell -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -c docker' else 'docker' end def interfaces Facter.value(:interfaces).split(',') end Facter.add(:docker_client_version) do setcode do docker_version = Facter.value(:docker_version) if docker_version if !docker_version['Client'].nil? docker_version['Client']['Version'] else docker_version['Version'] end end end end Facter.add(:docker_server_version) do setcode do docker_version = Facter.value(:docker_version) if docker_version && !docker_version['Server'].nil? && docker_version['Server'].is_a?(Hash) docker_version['Server']['Version'] else nil end end end Facter.add(:docker_version) do setcode do if Facter::Util::Resolution.which('docker') value = Facter::Util::Resolution.exec( "#{docker_command} version --format '{{json .}}'", ) val = JSON.parse(value) end val end end Facter.add(:docker_worker_join_token) do setcode do if Facter::Util::Resolution.which('docker') val = Facter::Util::Resolution.exec( "#{docker_command} swarm join-token worker -q", ) end val end end Facter.add(:docker_manager_join_token) do setcode do if Facter::Util::Resolution.which('docker') val = Facter::Util::Resolution.exec( "#{docker_command} swarm join-token manager -q", ) end val end end Facter.add(:docker) do setcode do docker_version = Facter.value(:docker_client_version) - if docker_version !~ %r{1[.][0-9][0-2]?[.]\w+} + unless %r{1[.][0-9][0-2]?[.]\w+}.match?(docker_version) if Facter::Util::Resolution.which('docker') docker_json_str = Facter::Util::Resolution.exec( "#{docker_command} info --format '{{json .}}'", ) begin docker = JSON.parse(docker_json_str) docker['network'] = {} docker['network']['managed_interfaces'] = {} network_list = Facter::Util::Resolution.exec("#{docker_command} network ls | tail -n +2") docker_network_names = [] network_list.each_line { |line| docker_network_names.push line.split[1] } docker_network_ids = [] network_list.each_line { |line| docker_network_ids.push line.split[0] } docker_network_names.each do |network| inspect = JSON.parse(Facter::Util::Resolution.exec("#{docker_command} network inspect #{network}")) docker['network'][network] = inspect[0] network_id = docker['network'][network]['Id'][0..11] interfaces.each do |iface| - docker['network']['managed_interfaces'][iface] = network if iface =~ %r{#{network_id}} + docker['network']['managed_interfaces'][iface] = network if %r{#{network_id}}.match?(iface) end end docker rescue JSON::ParserError nil end end end end end diff --git a/lib/puppet/parser/functions/docker_exec_flags.rb b/lib/puppet/parser/functions/docker_exec_flags.rb index 416c96d..809675b 100644 --- a/lib/puppet/parser/functions/docker_exec_flags.rb +++ b/lib/puppet/parser/functions/docker_exec_flags.rb @@ -1,33 +1,31 @@ # frozen_string_literal: true require 'shellwords' # # docker_exec_flags.rb # module Puppet::Parser::Functions # Transforms a hash into a string of docker exec flags newfunction(:docker_exec_flags, type: :rvalue) do |args| opts = args[0] || {} flags = [] if opts['detach'] flags << '--detach=true' end if opts['interactive'] flags << '--interactive=true' end if opts['tty'] flags << '--tty=true' end - if opts['env'] - opts['env'].each do |namevaluepair| - flags << "--env #{namevaluepair}" - end + opts['env']&.each do |namevaluepair| + flags << "--env #{namevaluepair}" end flags.flatten.join(' ') end end diff --git a/lib/puppet/parser/functions/docker_params_changed.rb b/lib/puppet/parser/functions/docker_params_changed.rb index 894dac8..325cbc7 100644 --- a/lib/puppet/parser/functions/docker_params_changed.rb +++ b/lib/puppet/parser/functions/docker_params_changed.rb @@ -1,76 +1,78 @@ +# frozen_string_literal: true + require 'open3' require 'json' module Puppet::Parser::Functions # Checks if at least one parammeter is changed newfunction(:docker_params_changed, type: :rvalue) do |args| opts = args[0] || {} return_value = [] if opts['sanitised_title'] && opts['osfamily'] stdout, stderr, status = Open3.capture3("docker inspect #{opts['sanitised_title']}") if stderr.to_s == '' && status.to_s.include?('exit 0') param_changed = false inspect_hash = JSON.parse(stdout)[0] # check if the image was changed param_changed = true if opts['image'] && opts['image'] != inspect_hash['Config']['Image'] # check if something on volumes or mounts was changed(a new volume/mount was added or removed) param_changed = true if opts['volumes'].is_a?(String) && opts['volumes'].include?(':') && opts['volumes'] != inspect_hash['Mounts'].to_a[0] && opts['osfamily'] != 'windows' param_changed = true if opts['volumes'].is_a?(String) && !opts['volumes'].include?(':') && opts['volumes'] != inspect_hash['Config']['Volumes'].to_a[0] && opts['osfamily'] != 'windows' param_changed = true if opts['volumes'].is_a?(String) && opts['volumes'].scan(%r{(?=:)}).count == 2 && opts['volumes'] != inspect_hash['Mounts'].to_a[0] && opts['osfamily'] == 'windows' param_changed = if opts['volumes'].is_a?(String) && opts['volumes'].scan(%r{(?=:)}).count == 1 && opts['volumes'] != inspect_hash['Config']['Volumes'].to_a[0] && opts['osfamily'] == 'windows' true else param_changed end pp_paths = opts['volumes'].reject { |item| item.include?(':') } if opts['volumes'].is_a?(Array) && opts['osfamily'] != 'windows' pp_mounts = opts['volumes'].select { |item| item.include?(':') } if opts['volumes'].is_a?(Array) && opts['osfamily'] != 'windows' pp_paths = opts['volumes'].select { |item| item.scan(%r{(?=:)}).count == 1 } if opts['volumes'].is_a?(Array) && opts['osfamily'] == 'windows' pp_mounts = opts['volumes'].select { |item| item.scan(%r{(?=:)}).count == 2 } if opts['volumes'].is_a?(Array) && opts['osfamily'] == 'windows' inspect_paths = if inspect_hash['Config']['Volumes'] inspect_hash['Config']['Volumes'].keys else [] end param_changed = true if pp_paths != inspect_paths names = inspect_hash['Mounts'].map { |item| item.values[1] } if inspect_hash['Mounts'] pp_names = pp_mounts.map { |item| item.split(':')[0] } if pp_mounts names = names.select { |item| pp_names.include?(item) } if names && pp_names destinations = inspect_hash['Mounts'].map { |item| item.values[3] } if inspect_hash['Mounts'] pp_destinations = pp_mounts.map { |item| item.split(':')[1] } if pp_mounts && opts['osfamily'] != 'windows' pp_destinations = pp_mounts.map { |item| "#{item.split(':')[1].downcase}:#{item.split(':')[2]}" } if pp_mounts && opts['osfamily'] == 'windows' destinations = destinations.select { |item| pp_destinations.include?(item) } if destinations && pp_destinations param_changed = true if pp_names != names param_changed = true if pp_destinations != destinations param_changed = true if pp_mounts != [] && inspect_hash['Mounts'].nil? # check if something on ports was changed(some ports were added or removed) ports = inspect_hash['HostConfig']['PortBindings'].keys ports = ports.map { |item| item.split('/')[0] } pp_ports = opts['ports'].sort if opts['ports'].is_a?(Array) pp_ports = [opts['ports']] if opts['ports'].is_a?(String) param_changed = true if pp_ports && pp_ports != ports return_value << if param_changed 'PARAM_CHANGED' else 'NO_CHANGE' end else return_value << 'CONTAINER_NOT_FOUND' end else return_value << 'ARG_REQUIRED_MISSING' end return_value.flatten.join(' ') end end diff --git a/lib/puppet/parser/functions/docker_service_flags.rb b/lib/puppet/parser/functions/docker_service_flags.rb index 72f1e6b..7ee5255 100644 --- a/lib/puppet/parser/functions/docker_service_flags.rb +++ b/lib/puppet/parser/functions/docker_service_flags.rb @@ -1,101 +1,99 @@ # frozen_string_literal: true require 'shellwords' # # docker_service_flags.rb # module Puppet::Parser::Functions # Transforms a hash into a string of docker swarm init flags newfunction(:docker_service_flags, type: :rvalue) do |args| opts = args[0] || {} flags = [] if opts['service_name'] && opts['service_name'].to_s != 'undef' flags << "'#{opts['service_name']}'" end if opts['detach'].to_s != 'false' flags << '--detach' end if opts['env'].is_a? Array opts['env'].each do |env| flags << "--env #{env}" end end if opts['label'].is_a? Array opts['label'].each do |label| flags << "--label #{label}" end end if opts['mounts'].is_a? Array opts['mounts'].each do |mount| flags << "--mount #{mount}" end end if opts['networks'].is_a? Array opts['networks'].each do |network| flags << "--network #{network}" end end if opts['publish'].is_a? Array opts['publish'].each do |port| flags << "--publish #{port}" end elsif opts['publish'] && opts['publish'].to_s != 'undef' flags << "--publish '#{opts['publish']}'" end if opts['replicas'] && opts['replicas'].to_s != 'undef' flags << "--replicas '#{opts['replicas']}'" end if opts['tty'].to_s != 'false' flags << '--tty' end if opts['user'] && opts['user'].to_s != 'undef' flags << "--user '#{opts['user']}'" end if opts['workdir'] && opts['workdir'].to_s != 'undef' flags << "--workdir '#{opts['workdir']}'" end if opts['extra_params'].is_a? Array opts['extra_params'].each do |param| flags << param end end if opts['host_socket'] && opts['host_socket'].to_s != 'undef' flags << "-H '#{opts['host_socket']}'" end if opts['registry_mirror'].is_a? Array opts['registry_mirror'].each do |param| flags << "--registry-mirror='#{param}'" end - else - if opts['registry_mirror'] && opts['registry_mirror'].to_s != 'undef' - flags << "--registry-mirror='#{opts['registry_mirror']}'" - end + elsif opts['registry_mirror'] && opts['registry_mirror'].to_s != 'undef' + flags << "--registry-mirror='#{opts['registry_mirror']}'" end if opts['image'] && opts['image'].to_s != 'undef' flags << "'#{opts['image']}'" end if opts['command'].is_a? Array flags << opts['command'].join(' ') elsif opts['command'] && opts['command'].to_s != 'undef' flags << opts['command'].to_s end flags.flatten.join(' ') end end diff --git a/lib/puppet/provider/docker_compose/ruby.rb b/lib/puppet/provider/docker_compose/ruby.rb index bfcca81..02c8792 100644 --- a/lib/puppet/provider/docker_compose/ruby.rb +++ b/lib/puppet/provider/docker_compose/ruby.rb @@ -1,106 +1,104 @@ # frozen_string_literal: true require 'deep_merge' Puppet::Type.type(:docker_compose).provide(:ruby) do desc 'Support for Puppet running Docker Compose' mk_resource_methods commands dockercompose: 'docker-compose' commands dockercmd: 'docker' has_command(:docker, command(:dockercmd)) do environment(HOME: '/root') end def exists? Puppet.info("Checking for compose project #{name}") compose_services = {} compose_containers = [] # get merged config using docker-compose config args = [compose_files, '-p', name, 'config'].insert(3, resource[:options]).compact compose_output = YAML.safe_load(execute([command(:dockercompose)] + args, combine: false)) # rubocop:disable Style/StringLiterals containers = docker([ 'ps', '--format', "{{.Label \"com.docker.compose.service\"}}-{{.Image}}", '--filter', "label=com.docker.compose.project=#{name}", ]).split("\n") compose_containers.push(*containers) compose_containers.uniq! compose_services = compose_output['services'] if compose_services.count != compose_containers.count return false end counts = Hash[*compose_services.each.map { |key, array| image = (array['image']) ? array['image'] : get_image(key, compose_services) Puppet.info("Checking for compose service #{key} #{image}") ["#{key}-#{image}", compose_containers.count("#{key}-#{image}")] }.flatten] # No containers found for the project if counts.empty? || # Containers described in the compose file are not running counts.any? { |_k, v| v.zero? } || # The scaling factors in the resource do not match the number of running containers resource[:scale] && counts.merge(resource[:scale]) != counts false else true end end def get_image(service_name, compose_services) image = compose_services[service_name]['image'] unless image if compose_services[service_name]['extends'] image = get_image(compose_services[service_name]['extends'], compose_services) elsif compose_services[service_name]['build'] image = "#{name}_#{service_name}" end end image end def create Puppet.info("Running compose project #{name}") args = [compose_files, '-p', name, 'up', '-d', '--remove-orphans'].insert(3, resource[:options]).insert(5, resource[:up_args]).compact dockercompose(args) return unless resource[:scale] instructions = resource[:scale].map { |k, v| "#{k}=#{v}" } Puppet.info("Scaling compose project #{name}: #{instructions.join(' ')}") args = [compose_files, '-p', name, 'scale'].insert(3, resource[:options]).compact + instructions dockercompose(args) end def destroy Puppet.info("Removing all containers for compose project #{name}") kill_args = [compose_files, '-p', name, 'kill'].insert(3, resource[:options]).compact dockercompose(kill_args) rm_args = [compose_files, '-p', name, 'rm', '--force', '-v'].insert(3, resource[:options]).compact dockercompose(rm_args) end def restart return unless exists? Puppet.info("Rebuilding and Restarting all containers for compose project #{name}") kill_args = [compose_files, '-p', name, 'kill'].insert(3, resource[:options]).compact dockercompose(kill_args) build_args = [compose_files, '-p', name, 'build'].insert(3, resource[:options]).compact dockercompose(build_args) create end def compose_files resource[:compose_files].map { |x| ['-f', x] }.flatten end - - private end diff --git a/lib/puppet/provider/docker_stack/ruby.rb b/lib/puppet/provider/docker_stack/ruby.rb index b1fc55d..c493859 100644 --- a/lib/puppet/provider/docker_stack/ruby.rb +++ b/lib/puppet/provider/docker_stack/ruby.rb @@ -1,94 +1,92 @@ # frozen_string_literal: true require 'deep_merge' Puppet::Type.type(:docker_stack).provide(:ruby) do desc 'Support for Puppet running Docker Stacks' mk_resource_methods commands dockercmd: 'docker' has_command(:docker, command(:dockercmd)) do environment(HOME: '/root') end def exists? Puppet.info("Checking for stack #{name}") stack_services = {} stack_containers = [] resource[:compose_files].each do |file| compose_file = YAML.safe_load(File.read(file), [], [], true) # rubocop:disable Style/StringLiterals containers = docker([ 'ps', '--format', "{{.Label \"com.docker.swarm.service.name\"}}-{{.Image}}", '--filter', "label=com.docker.stack.namespace=#{name}", ]).split("\n").each do |c| c.slice!("#{name}_") end stack_containers.push(*containers) stack_containers.uniq! # rubocop:enable Style/StringLiterals case compose_file['version'] when %r{^3(\.[0-7])?$} stack_services.merge!(compose_file['services']) else raise(Puppet::Error, "Unsupported docker compose file syntax version \"#{compose_file['version']}\"!") end end if stack_services.count != stack_containers.count return false end counts = Hash[*stack_services.each.map { |key, array| image = (array['image']) ? array['image'] : get_image(key, stack_services) image = "#{image}:latest" unless image.include?(':') Puppet.info("Checking for compose service #{key} #{image}") ["#{key}-#{image}", stack_containers.count("#{key}-#{image}")] }.flatten] # No containers found for the project if counts.empty? || # Containers described in the compose file are not running counts.any? { |_k, v| v.zero? } false else true end end def get_image(service_name, stack_services) image = stack_services[service_name]['image'] unless image if stack_services[service_name]['extends'] image = get_image(stack_services[service_name]['extends'], stack_services) elsif stack_services[service_name]['build'] image = "#{name}_#{service_name}" end end image end def create Puppet.info("Running stack #{name}") args = ['stack', 'deploy', compose_files, name].insert(1, bundle_file).insert(4, resource[:up_args]).compact docker(args) end def destroy Puppet.info("Removing docker stack #{name}") rm_args = ['stack', 'rm', name] docker(rm_args) end def bundle_file return resource[:bundle_file].map { |x| ['-c', x] }.flatten unless resource[:bundle_file].nil? end def compose_files resource[:compose_files].map { |x| ['-c', x] }.flatten end - - private end diff --git a/metadata.json b/metadata.json index e6b9812..9a361cf 100644 --- a/metadata.json +++ b/metadata.json @@ -1,73 +1,73 @@ { "name": "puppetlabs-docker", "version": "3.13.0", "author": "puppetlabs", "summary": "Module for installing and managing docker", "license": "Apache-2.0", "source": "git://github.com/puppetlabs/puppetlabs-docker", "project_page": "https://github.com/puppetlabs/puppetlabs-docker", "issues_url": "https://github.com/puppetlabs/puppetlabs-docker/issues", "dependencies": [ { "name": "puppetlabs/stdlib", "version_requirement": ">= 4.24.0 < 7.0.0" }, { "name": "puppetlabs/apt", "version_requirement": ">= 4.4.1 < 8.0.0" }, { "name": "puppetlabs/translate", "version_requirement": ">= 0.0.1 < 3.0.0" }, { "name": "puppetlabs/powershell", "version_requirement": ">= 2.1.4 < 4.0.0" }, { "name": "puppetlabs/reboot", "version_requirement": ">=2.0.0 < 3.0.0" } ], "operatingsystem_support": [ { "operatingsystem": "CentOS", "operatingsystemrelease": [ "7" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ "14.04", "16.04", "18.04", "20.04" ] }, { "operatingsystem": "Debian", "operatingsystemrelease": [ "8", "9", "10" ] }, { "operatingsystem": "Windows", "operatingsystemrelease": [ "2016", "2019" ] } ], "requirements": [ { "name": "puppet", "version_requirement": ">= 5.5.10 < 8.0.0" } ], "pdk-version": "1.18.1", "template-url": "https://github.com/puppetlabs/pdk-templates#main", - "template-ref": "heads/main-0-g5afcd3d" + "template-ref": "heads/main-0-g4543421" } diff --git a/spec/acceptance/compose_v3_spec.rb b/spec/acceptance/compose_v3_spec.rb index 29c8d88..bf2dfcf 100644 --- a/spec/acceptance/compose_v3_spec.rb +++ b/spec/acceptance/compose_v3_spec.rb @@ -1,157 +1,159 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:family] == 'windows' install_dir = '/cygdrive/c/Program Files/Docker' file_extension = '.exe' docker_args = 'docker_ee => true' tmp_path = 'C:/cygwin64/tmp' - test_container = if os[:release] =~ %r{2019} + test_container = if %r{2019}.match?(os[:release]) 'nanoserver' else 'nanoserver-sac2016' end else docker_args = if os[:name] == 'ubuntu' && os[:release][:full] == '14.04' "version => '18.06.1~ce~3-0~ubuntu'" else '' end install_dir = '/usr/local/bin' file_extension = '' tmp_path = '/tmp' test_container = 'debian' end describe 'docker compose' do before(:all) do retry_on_error_matching(60, 5, %r{connection failure running}) do install_code = <<-code class { 'docker': #{docker_args} } class { 'docker::compose': version => '1.23.2', } code apply_manifest(install_code, catch_failures: true) end end context 'Creating compose v3 projects', win_broken: true do let(:install_pp) do <<-MANIFEST docker_compose { 'web': compose_files => ['#{tmp_path}/docker-compose-v3.yml'], ensure => present, } MANIFEST end it 'is idempotent' do idempotent_apply(install_pp) end it 'has docker compose installed' do run_shell('docker-compose --help', expect_failures: false) end it 'finds a docker container' do run_shell('docker inspect web_compose_test_1', expect_failures: false) end end context 'creating compose projects with multi compose files', win_broken: true do before(:all) do install_pp = <<-MANIFEST docker_compose { 'web1': compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], ensure => present, } MANIFEST apply_manifest(install_pp, catch_failures: true) end - it "should find container with #{test_container} tag" do + it "finds container with #{test_container} tag" do run_shell("docker inspect web1_compose_test_1 | grep #{test_container}", acceptable_exit_codes: [0]) end end context 'Destroying project with multiple compose files', win_broken: true do let(:destroy_pp) do <<-MANIFEST docker_compose { 'web1': compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], ensure => absent, } MANIFEST end before(:all) do install_pp = <<-MANIFEST docker_compose { 'web1': compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], ensure => present, } MANIFEST apply_manifest(install_pp, catch_failures: true) end it 'is idempotent' do idempotent_apply(destroy_pp) end it 'does not find a docker container' do run_shell('docker inspect web1_compose_test_1', expect_failures: true) end end context 'Requesting a specific version of compose' do let(:version) do '1.21.2' end it 'is idempotent' do pp = <<-MANIFEST class { 'docker::compose': version => '#{version}', } MANIFEST idempotent_apply(pp) end it 'has installed the requested version' do run_shell('docker-compose --version', expect_failures: false) do |r| expect(r.stdout).to match(%r{#{version}}) end end end context 'Removing docker compose' do let(:version) do '1.21.2' end it 'is idempotent' do pp = <<-MANIFEST class { 'docker::compose': ensure => absent, version => '#{version}', } MANIFEST idempotent_apply(pp) end it 'has removed the relevant files' do run_shell("test -e \"#{install_dir}/docker-compose#{file_extension}\"", expect_failures: true) run_shell("test -e \"#{install_dir}/docker-compose-#{version}#{file_extension}\"", expect_failures: true) end after(:all) do install_pp = <<-MANIFEST class { 'docker': #{docker_args}} class { 'docker::compose': } MANIFEST apply_manifest(install_pp, catch_failures: true) end end end diff --git a/spec/acceptance/docker_custom_source_spec.rb b/spec/acceptance/docker_custom_source_spec.rb index fd1c0cf..0f0f27c 100644 --- a/spec/acceptance/docker_custom_source_spec.rb +++ b/spec/acceptance/docker_custom_source_spec.rb @@ -1,105 +1,107 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:family] == 'windows' docker_args = 'docker_ee => true, docker_ee_source_location => "https://download.docker.com/components/engine/windows-server/17.06/docker-17.06.2-ee-14.zip"' default_image = 'winamd64/hello-seattle' # The default args are set because: # restart => 'always' - there is no service created to manage containers # net => 'nat' - docker uses bridged by default when running a container. When installing docker on windows the default network is NAT. default_docker_run_arg = "restart => 'always', net => 'nat'," default_run_command = 'ping 127.0.0.1 -t' docker_command = '"/cygdrive/c/Program Files/Docker/docker"' skip = false elsif os[:name] == 'Ubuntu' && os[:release][:full] == '14.04' docker_args = "version => '18.06.1~ce~3-0~ubuntu'" default_image = 'busybox' skip = true else docker_args = '' default_image = 'busybox' skip = false end describe 'the Puppet Docker module' do context 'with download location', skip: skip do let(:pp) do "class { 'docker': #{docker_args} }" end it 'runs successfully' do apply_manifest(pp, catch_failures: true) end it 'runs idempotently' do apply_manifest(pp, catch_changes: true) unless selinux == 'true' end it 'is start a docker process' do if os[:family] == 'windows' run_shell('powershell Get-Process -Name dockerd') do |r| expect(r.stdout).to match(%r{ProcessName}) end else run_shell('ps aux | grep docker') do |r| expect(r.stdout).to match %r{dockerd -H unix:\/\/\/var\/run\/docker.sock} end end end it 'installs a working docker client' do run_shell("#{docker_command} ps", expect_failures: false) end it 'stops a running container and remove container' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': ensure => 'absent', image => '#{default_image}', require => Docker::Image['#{default_image}'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} ps", expect_failures: false) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} inspect container-3-6", expect_failures: true) if os[:family] == 'windows' run_shell('test -f /cygdrive/c/Users/Administrator/AppData/Local/Temp/container-3-6.service', expect_failures: true) else run_shell('test -f /etc/systemd/system/container-3-6.service', expect_failures: true) end end end end diff --git a/spec/acceptance/docker_full_spec.rb b/spec/acceptance/docker_full_spec.rb index 3019325..1f356e8 100644 --- a/spec/acceptance/docker_full_spec.rb +++ b/spec/acceptance/docker_full_spec.rb @@ -1,996 +1,998 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:kernel] == 'windows' docker_args = 'docker_ee => true' default_image = 'winamd64/hello-seattle' default_image_tag = if os[:release][:major] == '2019' 'nanoserver' else 'nanoserver-sac2016' end default_digest = 'sha256:dcba85354678b50608b8c40ec6d17cce063a224aa0e12b6a55dc47b67f039e75' default_local_digest = 'sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10' second_image = 'winamd64/hola-mundo' default_dockerfile = 'C:/Users/Administrator/AppData/Local/Temp/Dockerfile' dockerfile_test = 'C:/Windows/Dockerfile_test.txt' # The default args are set because: # restart => 'always' - there is no service created to manage containers # net => 'nat' - docker uses bridged by default when running a container. When installing docker on windows the default network is NAT. default_docker_run_arg = "restart => 'always', net => 'nat'," default_run_command = 'ping 127.0.0.1 -t' docker_command = '"/cygdrive/c/Program Files/Docker/docker"' default_docker_exec_lr_command = 'cmd /c "ping 127.0.0.1 -t > C:\Users\Public\test_file.txt"' default_docker_exec_command = 'cmd /c "echo test > C:\Users\Public\test_file.txt"' docker_mount_path = 'C:/Users/Public/DockerVolume' storage_driver = 'windowsfilter' else docker_args = if os[:name] == 'ubuntu' && os[:release][:full] == '14.04' "version => '18.06.1~ce~3-0~ubuntu'" else '' end default_image = 'alpine' second_image = 'busybox' default_image_tag = '3.7' default_digest = 'sha256:3dcdb92d7432d56604d4545cbd324b14e647b313626d99b889d0626de158f73a' default_local_digest = 'sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10' default_dockerfile = '/root/Dockerfile' dockerfile_test = "#{default_dockerfile}_test.txt" docker_command = 'docker' default_docker_run_arg = '' default_run_command = 'init' default_docker_exec_lr_command = '/bin/sh -c "touch /root/test_file.txt; while true; do echo hello world; sleep 1; done"' default_docker_exec_command = 'touch /root/test_file.txt' docker_mount_path = '/root' storage_driver = 'devicemapper' storage_driver = if os[:family] == 'Debian' && os[:release][:major] =~ %r{14.04|^8$} 'aufs' elsif os[:family] == 'RedHat' 'devicemapper' else 'overlay2' end end describe 'the Puppet Docker module' do context 'clean up before each test', win_broken: true do before(:each) do retry_on_error_matching(60, 5, %r{connection failure running}) do # Stop all container using systemd run_shell('ls -D -1 /etc/systemd/system/docker-container* | sed \'s/\/etc\/systemd\/system\///g\' | sed \'s/\.service//g\' | while read container; do service $container stop; done') # Delete all running containers run_shell("#{docker_command} rm -f $(#{docker_command} ps -a -q) || true") # Delete all existing images run_shell("#{docker_command} rmi -f $(#{docker_command} images -q) || true") # Check to make sure no images are present run_shell("#{docker_command} images | wc -l") do |r| - expect(r.stdout).to match(%r{^0|1$}) # rubocop:disable RSpec/ExpectInHook: + expect(r.stdout).to match(%r{^0|1$}) end # Check to make sure no running containers are present run_shell("#{docker_command} ps | wc -l") do |r| - expect(r.stdout).to match(%r{^0|1$}) # rubocop:disable RSpec/ExpectInHook: + expect(r.stdout).to match(%r{^0|1$}) end end end describe 'docker class' do context 'without any parameters', win_broken: true do let(:pp) { "class { 'docker': #{docker_args} }" } it 'runs successfully' do apply_manifest(pp, catch_failures: true) end it 'runs idempotently' do apply_manifest(pp, catch_changes: true) unless selinux == 'true' end it 'is start a docker process' do if os[:family] == 'windows' run_shell('powershell Get-Process -Name dockerd') do |r| expect(r.stdout).to match(%r{ProcessName}) end else run_shell('ps aux | grep docker') do |r| expect(r.stdout).to match(%r{dockerd -H unix:\/\/\/var\/run\/docker.sock}) end end end it 'installs a working docker client' do run_shell("#{docker_command} ps", expect_failures: false) end it 'stops a running container and remove container' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': ensure => 'absent', image => '#{default_image}', require => Docker::Image['#{default_image}'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} ps", expect_failures: false) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} inspect container-3-6", expect_failures: true) if os[:family] == 'windows' run_shell('test -f /cygdrive/c/Users/Administrator/AppData/Local/Temp/container-3-6.service', expect_failures: true) else run_shell('test -f /etc/systemd/system/container-3-6.service', expect_failures: true) end end end context 'passing a storage driver' do let(:pp) do <<-MANIFEST class {'docker': #{docker_args}, storage_driver => "#{storage_driver}", } MANIFEST end it 'applies manifest' do apply_manifest(pp, catch_failures: true) sleep 15 end it 'results in the docker daemon being configured with the specified storage driver' do run_shell("#{docker_command} info -f \"{{ .Driver}}\"") do |r| expect(r.stdout).to match %r{#{storage_driver}} end end end context 'passing a TCP address to bind to' do let(:pp) do <<-MANIFEST class { 'docker': tcp_bind => 'tcp://127.0.0.1:4444', #{docker_args} } MANIFEST end it 'runs idempotently' do idempotent_apply(pp) unless selinux == 'true' sleep 4 end it 'results in docker listening on the specified address' do if os[:family] == 'windows' run_shell('netstat -a -b') do |r| expect(r.stdout).to match(%r{127.0.0.1:4444}) end else run_shell('netstat -tulpn | grep docker') do |r| expect(r.stdout).to match(%r{tcp\s+0\s+0\s+127.0.0.1:4444\s+0.0.0.0\:\*\s+LISTEN\s+\d+\/docker}) end end end end context 'bound to a particular unix socket' do let(:pp) do <<-MANIFEST class { 'docker': socket_bind => 'unix:///var/run/docker.sock', #{docker_args} } MANIFEST end it 'runs idempotently' do idempotent_apply(pp) unless selinux == 'true' sleep 4 end it 'shows docker listening on the specified unix socket' do if os[:family] != 'windows' run_shell('ps aux | grep docker') do |r| expect(r.stdout).to match(%r{unix:\/\/\/var\/run\/docker.sock}) end end end end context 'uninstall docker' do after(:all) do pp = <<-EOS class {'docker': #{docker_args}, ensure => 'present' } EOS apply_manifest(pp, catch_failures: true) # Wait for reboot if windows sleep 300 if os[:family] == 'windows' end it 'uninstalls successfully' do pp = <<-EOS class {'docker': #{docker_args}, ensure => 'absent' } EOS apply_manifest(pp, catch_failures: true) sleep 4 run_shell('docker ps', expect_failures: true) end end end describe 'docker::image' do it 'successfullies download an image from the Docker Hub' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => present, require => Class['docker'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} images") do |r| expect(r.stdout).to match(%r{#{default_image}}) end end it 'successfullies download an image based on a tag from the Docker Hub' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => present, image_tag => '#{default_image_tag}', require => Class['docker'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} images") do |r| expect(r.stdout).to match(%r{#{default_image}\s+#{default_image_tag}}) end end it 'successfullies download an image based on a digest from the Docker Hub' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => present, image_digest => '#{default_digest}', require => Class['docker'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} images --digests") do |r| expect(r.stdout).to match(%r{#{default_image}.*#{default_digest}}) end end it 'creates a new image based on a Dockerfile' do run_cmd = if os[:family] == 'windows' 'RUN echo test > C:\\Users\\Public\\Dockerfile_test.txt' else "RUN echo test > #{dockerfile_test}" end pp = <<-EOS class { 'docker': #{docker_args} } docker::image { 'alpine_with_file': docker_file => "#{default_dockerfile}", require => Class['docker'], } file { '#{default_dockerfile}': ensure => present, content => "FROM #{default_image}\n#{run_cmd}", before => Docker::Image['alpine_with_file'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 if os[:family] == 'windows' run_shell("#{docker_command} run alpine_with_file cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{_test.txt}) end else run_shell("#{docker_command} run alpine_with_file ls #{dockerfile_test}") do |r| expect(r.stdout).to match(%r{#{dockerfile_test}}) end end end it 'creates a new image based on a tar', win_broken: true do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], ensure => present, } docker::run { 'container_2_4': image => '#{default_image}', command => '/bin/sh -c "touch /root/test_file_for_tar_test.txt; while true; do echo hello world; sleep 1; done"', require => Docker::Image['alpine'], } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { 'alpine_from_commit': docker_tar => "/root/rootfs.tar" } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 # Commit currently running container as an image container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") run_shell("#{docker_command} commit #{container_id.stdout.strip} alpine_from_commit") # Stop all container using systemd run_shell('ls -D -1 /etc/systemd/system/docker-container* | sed \'s/\/etc\/systemd\/system\///g\' | sed \'s/\.service//g\' | while read container; do service $container stop; done') # Stop all running containers run_shell("#{docker_command} rm -f $(docker ps -a -q) || true") # Make sure no other containers are running run_shell("#{docker_command} ps | wc -l") do |r| expect(r.stdout).to match(%r{^1$}) end # Export new to a tar file run_shell("#{docker_command} save alpine_from_commit > /root/rootfs.tar") # Remove all images run_shell("#{docker_command} rmi $(docker images -q) || true") # Make sure no other images are present run_shell("#{docker_command} images | wc -l") do |r| expect(r.stdout).to match(%r{^1$}) end apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} run alpine_from_commit ls /root") do |r| expect(r.stdout).to match(%r{test_file_for_tar_test.txt}) end end it 'successfullies delete the image' do pp1 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => present, require => Class['docker'], } EOS apply_manifest(pp1, catch_failures: true) pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => absent, } EOS apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} images") do |r| expect(r.stdout).not_to match(%r{#{default_image}}) end end end describe 'docker::run' do it 'starts a container with a configurable command' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_1': image => '#{default_image}', command => '#{default_docker_exec_lr_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{test_file.txt}) end else run_shell("#{docker_command} exec #{container_id.stdout.strip} ls /root") do |r| expect(r.stdout).to match(%r{test_file.txt}) end end container_name = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") expect(container_name.stdout.strip.to_s).to match(%r{(container-3-1|container_3_1)}) end it 'starts a container with port configuration' do pp = <<-EOS class { 'docker': #{docker_args}} docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_2': image => '#{default_image}', command => '#{default_run_command}', ports => ['4444'], expose => ['5555'], require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} ps") do |r| expect(r.stdout).to match(%r{#{default_run_command}.+5555\/tcp\, 0\.0\.0.0\:\d+\-\>4444\/tcp}) end end it 'starts a container with the hostname set' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_3': image => '#{default_image}', command => '#{default_run_command}', hostname => 'testdomain.com', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") run_shell("#{docker_command} exec #{container_id.stdout.strip} hostname") do |r| expect(r.stdout).to match(%r{testdomain.com}) end end it 'starts a container while mounting local volumes' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_4': image => '#{default_image}', command => '#{default_run_command}', volumes => ["#{docker_mount_path}:#{docker_mount_path}/mnt:rw"], require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } file { '#{docker_mount_path}': ensure => directory, before => File['#{docker_mount_path}/test_mount.txt'], } file { '#{docker_mount_path}/test_mount.txt': ensure => present, before => Docker::Run['container_3_4'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Users\\\\Public\\\\DockerVolume\\\\mnt") do |r| expect(r.stdout).to match(%r{test_mount.txt}) end else run_shell("#{docker_command} exec #{container_id.stdout.strip} ls /root/mnt") do |r| expect(r.stdout).to match(%r{test_mount.txt}) end end end # cpuset is not supported on Docker Windows # STDERR: C:/Program Files/Docker/docker.exe: Error response from daemon: invalid option: Windows does not support CpusetCpus. it 'starts a container with cpuset paramater set', win_broken: true do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_5_5': image => '#{default_image}', command => '#{default_run_command}', cpuset => ['0'], require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell('#{docker_command} inspect container_3_5_5') do |r| expect(r.stdout).to match(%r{"CpusetCpus"\: "0"}) end end # leagacy container linking was not implemented on Windows. --link is a legacy Docker feature: https://docs.docker.com/network/links/ it 'starts multiple linked containers', win_broken: true do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_5_1': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container1 = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_5_2': image => '#{default_image}', command => '#{default_run_command}', depends => ['#{container1.stdout.strip}'], links => "#{container1.stdout.strip}:the_link", require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container2 = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") run_shell("#{docker_command} inspect -f \"{{ .HostConfig.Links }}\" #{container_id.stdout.strip}") do |r| expect(r.stdout).to match("/#{container1.stdout.strip}:/#{container2.stdout.strip}/the_link") end end it 'stops a running container', win_broken: true do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': image => '#{default_image}', running => false, require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} ps | wc -l") do |r| expect(r.stdout).to match(%r{^2$}) end apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} ps | wc -l") do |r| expect(r.stdout).to match(%r{^1$}) end end it 'stops a running container and remove container' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6_1': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6_1': ensure => 'absent', image => '#{default_image}', require => Docker::Image['#{default_image}'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} inspect container_3_6_1", expect_failures: false) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} inspect container_3_6_1", expect_failures: true) end it 'allows dependency for ordering of independent run and image' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': } docker::run { 'container_3_7_1': image => '#{default_image}', command => '#{default_run_command}', #{default_docker_run_arg} } docker::image { '#{second_image}': require => Docker::Run['container_3_7_1'], } docker::run { 'container_3_7_2': image => '#{second_image}', command => '#{default_run_command}', #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' end it 'restarts a unhealthy container' do pp5 = <<-EOS class { 'docker': #{docker_args} } docker::run { 'container_3_7_3': image => '#{default_image}', command => '#{default_run_command}', health_check_cmd => 'echo', restart_on_unhealthy => true, #{default_docker_run_arg} } EOS pp_delete = <<-EOS class { 'docker': #{docker_args} } docker::run { 'container_3_7_3': image => '#{default_image}', ensure => absent, } EOS if os[:family] == 'windows' apply_manifest(pp5, catch_failures: true) - elsif os[:release] =~ %r{14.04|^8$} + elsif %r{14.04|^8$}.match?(os[:release]) apply_manifest(pp5, catch_failures: true) do |r| expect(r.stdout).to match(%r{container_3_7_3}) end else apply_manifest(pp5, catch_failures: true) do |r| expect(r.stdout).to match(%r{docker-container_3_7_3-systemd-reload}) end end apply_manifest(pp_delete, catch_failures: true) end end it 'run with verify_digest' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}:#{default_image_tag}': require => Class['docker'], } docker::run { '#{default_image}': image => '#{default_image}:#{default_image_tag}', verify_digest => '#{default_local_digest}', } EOS pp_invalid = <<-EOS docker::run { '#{default_image}': image => '#{default_image}:#{default_image_tag}', verify_digest => 'sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc000', } EOS apply_manifest(pp, catch_failures: true) run_shell('/usr/local/bin/docker-run-alpine-start.sh', expect_failures: false) do |r| expect(r.stdout.include?('Digest verify failed!')).to be false end apply_manifest(pp_invalid, catch_failures: true) run_shell('/usr/local/bin/docker-run-alpine-start.sh', expect_failures: true) do |r| expect(r.stdout.include?('Digest verify failed!')).to be true end end end describe 'docker::exec', win_broken: true do it 'runs a command inside an already running container' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_4_1': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 container1 = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") pp2 = <<-EOS class { 'docker': #{docker_args} } docker::exec { 'test_command': container => '#{container1.stdout.strip}', command => '#{default_docker_exec_command}', tty => true, } EOS pp_delete = <<-EOS docker::run { 'container_4_1': image => '#{default_image}', ensure => absent, } EOS apply_manifest(pp2, catch_failures: true) # A sleep to give docker time to execute properly sleep 4 container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{test_file.txt}) end else run_shell("#{docker_command} exec #{container_id.stdout.strip} ls /root") do |r| expect(r.stdout).to match(%r{test_file.txt}) end end apply_manifest(pp_delete, catch_failures: true) end it 'onlies run if notified when refreshonly is true', win_broken: true do container_name = 'container_4_2' pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': } docker::run { '#{container_name}': image => '#{default_image}', command => '#{default_run_command}', #{default_docker_run_arg} } docker::exec { 'test_command': container => '#{container_name}', command => '#{default_docker_exec_command}', refreshonly => true, } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_name} cmd /c dir Users\\\\Public") do |r| expect(r.stdout).not_to match(%r{test_file.txt}) end else run_shell("#{docker_command} exec #{container_name} ls /root") do |r| expect(r.stdout).not_to match(%r{test_file.txt}) end end pp_extra = <<-EOS file { '#{default_dockerfile}_dummy_file': ensure => 'present', notify => Docker::Exec['test_command'], } EOS pp_delete = <<-EOS docker::run { '#{container_name}': image => '#{default_image}', ensure => absent, } EOS pp2 = pp + pp_extra apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_name} cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{home}) end else run_shell("#{docker_command} exec #{container_name} ls /") do |r| expect(r.stdout).to match(%r{home}) end end apply_manifest(pp_delete, catch_failures: true) end end end diff --git a/spec/acceptance/docker_params_changed_spec.rb b/spec/acceptance/docker_params_changed_spec.rb index e464fed..622a702 100644 --- a/spec/acceptance/docker_params_changed_spec.rb +++ b/spec/acceptance/docker_params_changed_spec.rb @@ -1,141 +1,143 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:family] == 'windows' os_name = run_shell('systeminfo | findstr /R /C:"OS Name"') raise 'Could not retrieve systeminfo for Windows box' if os_name.exit_code != 0 os_name = os_name.stdout.split(%r{\s}).include?('2016') ? 'win-2016' : 'win-2019' docker_args = 'docker_ee => true' docker_network = 'nat' volume_location = 'C:\\' docker_image = if os_name == 'win-2016' 'stefanscherer/nanoserver:sac2016' else 'stefanscherer/nanoserver:10.0.17763.1040' end else docker_args = '' docker_network = 'bridge' volume_location = '/opt' docker_image = 'hello-world:linux' end describe 'docker trigger parammeters change' do before(:all) do if os[:family] != 'windows' install_pp = "class { 'docker': #{docker_args}}" apply_manifest(install_pp) end run_shell("mkdir #{volume_location}/volume_1") run_shell("mkdir #{volume_location}/volume_2") end context 'when image is changed' do image_changed = if os[:family] == 'windows' if os_name == 'win-2016' 'stefanscherer/nanoserver:10.0.14393.2551' else 'stefanscherer/nanoserver:1809' end else 'hello-world:latest' end let(:pp1) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}' } " end let(:pp2) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{image_changed}', restart => 'always', net => '#{docker_network}' } " end it 'creates servercore with first image' do idempotent_apply(pp1) end it 'detect image change and apply the change' do apply_manifest(pp2, catch_failures: true) run_shell('docker inspect --format="{{ .Config.Image }}" servercore') do |r| expect(r.stdout).to match(%r{#{image_changed}}) end end end context 'when volumes parameter is changed' do if os[:family] == 'windows' volumes1 = "volumes => ['volume-1:C:\\volume_1']" volumes2 = "volumes => ['volume-1:C:\\volume_1', 'volume-2:C:\\volume_2']" else volumes1 = "volumes => ['volume-1:#{volume_location}/volume_1']" volumes2 = "volumes => ['volume-1:#{volume_location}/volume_1', 'volume-2:#{volume_location}/volume_2']" end let(:pp1) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}', #{volumes1}} " end let(:pp2) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}', #{volumes2}} " end it "creates servercore with #{volumes1}" do idempotent_apply(pp1) end it "creates servercore with #{volumes2}" do apply_manifest(pp2, catch_failures: true) run_shell('docker inspect servercore --format="{{ json .Mounts }}"') do |r| inspect_result = JSON.parse(r.stdout) inspect_result = inspect_result.map { |item| item['Name'] }.sort expect(inspect_result).to eq(['volume-1', 'volume-2']) end end end context 'when ports parameter is changed' do ports1 = "ports => ['4444']" ports2 = "ports => ['4444', '4445']" let(:pp1) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}', #{ports1}} " end let(:pp2) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}', #{ports2}} " end it 'creates servercore with ports => ["4444"]' do idempotent_apply(pp1) end it 'creates servercore with ports => ["4444", "4445"]' do apply_manifest(pp2, catch_failures: true) run_shell('docker inspect servercore --format="{{ json .HostConfig.PortBindings }}"') do |r| inspect_result = JSON.parse(r.stdout) inspect_result = inspect_result.keys.map { |item| item.split('/')[0] }.sort expect(inspect_result).to eq(['4444', '4445']) end end end after(:all) do run_shell("rm -r #{volume_location}/volume_1") run_shell("rm -r #{volume_location}/volume_2") end end diff --git a/spec/acceptance/docker_spec.rb b/spec/acceptance/docker_spec.rb index 8d99917..cbcbd94 100644 --- a/spec/acceptance/docker_spec.rb +++ b/spec/acceptance/docker_spec.rb @@ -1,318 +1,320 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' broken = false registry_port = 5000 if os[:family] == 'windows' result = run_shell("ipconfig | findstr /i 'ipv4'") raise 'Could not retrieve ip address for Windows box' if result.exit_code != 0 ip = result.stdout.split("\n")[0].split(':')[1].strip @windows_ip = ip docker_args = "docker_ee => true, extra_parameters => '\"insecure-registries\": [ \"#{@windows_ip}:5000\" ]'" root_dir = 'C:/Users/Administrator/AppData/Local/Temp' docker_registry_image = 'stefanscherer/registry-windows' docker_network = 'nat' registry_host = @windows_ip config_file = '/cygdrive/c/Users/Administrator/.docker/config.json' server_strip = "#{registry_host}_#{registry_port}" bad_server_strip = "#{registry_host}_5001" broken = true else docker_args = if os[:name] == 'ubuntu' && os[:release][:full] == '14.04' "version => '18.06.1~ce~3-0~ubuntu'" else '' end docker_registry_image = 'registry' docker_network = 'bridge' registry_host = '127.0.0.1' server_strip = "#{registry_host}:#{registry_port}" bad_server_strip = "#{registry_host}:5001" config_file = '/root/.docker/config.json' root_dir = '/root' end describe 'docker' do package_name = 'docker-ce' service_name = 'docker' command = 'docker' context 'When adding system user', win_broken: broken do let(:pp) do " class { 'docker': #{docker_args}, docker_users => ['user1'] } " end it 'the docker daemon' do apply_manifest(pp, catch_failures: true) do |r| expect(r.stdout).not_to match(%r{docker-systemd-reload-before-service}) end end end context 'When prepare_service_only param is set(prepare_service_only => true)', win_broken: broken do let(:pp) do " class { 'docker': #{docker_args} } docker::run { 'servercore': image => 'hello-world:latest', prepare_service_only => true, } " end it 'creates the service without starting it' do apply_manifest(pp, catch_failures: true) end it 'not start the service' do run_shell('systemctl status docker-servercore', expect_failures: true) do |r| expect(r.stdout.include?('Main PID')).to be false end end end context 'When prepare_service_only param is not set(prepare_service_only => false)', win_broken: broken do let(:pp) do " class { 'docker': #{docker_args} } docker::run { 'servercore': image => 'hello-world:latest', } " end it 'creates the service and start it' do apply_manifest(pp, catch_failures: true) end it 'start the service' do run_shell('systemctl status docker-servercore', expect_failures: true) do |r| expect(r.stdout.include?('Main PID')).to be true end end end context 'When root_dir is set' do let(:pp) do "class { 'docker': #{docker_args}, root_dir => \"#{root_dir}\"}" end let(:shell_command) do if os[:family] == 'windows' 'cat C:/ProgramData/docker/config/daemon.json' else 'systemctl status docker' end end it 'works' do apply_manifest(pp, catch_failures: true) run_shell(shell_command) do |r| if os[:family] == 'windows' expect(r.stdout).to match(%r{\"data-root\": \"#{root_dir}\"}) else expect(r.stdout).to match(%r{--data-root #{root_dir}}) end end end end context 'with default parameters', win_broken: broken do let(:pp) do " class { 'docker': docker_users => [ 'testuser' ], #{docker_args} } docker::image { 'nginx': } docker::run { 'nginx': image => 'nginx', net => 'host', require => Docker::Image['nginx'], } docker::run { 'nginx2': image => 'nginx', restart => 'always', require => Docker::Image['nginx'], } " end it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'is idempotent' do apply_manifest(pp, catch_changes: true) end describe package(package_name) do it { is_expected.to be_installed } end describe service(service_name) do it { is_expected.to be_enabled } it { is_expected.to be_running } end it "#{command} version" do run_shell("#{command} version", expect_failures: false) end it "#{command} images" do result = run_shell("sudo #{command} images", expect_failures: false) expect(result[:exit_code]).to eq 0 expect(result[:stdout]).to match %r{nginx} end it "#{command} inspect nginx" do run_shell("sudo #{command} inspect nginx", expect_failures: false) end it "#{command} inspect nginx2" do run_shell("sudo #{command} inspect nginx2", expect_failures: false) end it "#{command} ps --no-trunc | grep `cat /var/run/docker-nginx2.cid`" do result = run_shell("sudo #{command} ps --no-trunc | grep `cat /var/run/docker-nginx2.cid`", expect_failures: false) expect(result[:exit_code]).to eq 0 expect(result[:stdout]).to match %r{nginx -g 'daemon off;'} end it 'netstat -tlndp' do result = run_shell('netstat -tlndp') expect(result[:exit_code]).to eq 0 expect(result[:stdout]).to match %r{0\.0\.0\.0\:80} end it 'id testuser | grep docker' do result = run_shell('id testuser | grep docker') expect(result[:exit_code]).to eq 0 expect(result[:stdout]).to match %r{docker} end end context 'When asked to have the latest image of something', win_broken: broken do let(:pp) do " class { 'docker': docker_users => [ 'testuser' ] } docker::image { 'busybox': ensure => latest } " end it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end end context 'When registry_mirror is set', win_broken: broken do let(:pp) do " class { 'docker': registry_mirror => 'http://testmirror.io' } " end it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'has a registry mirror set' do run_shell('ps -aux | grep docker') do |r| expect(r.stdout).to match(%r{--registry-mirror=http:\/\/testmirror.io}) end end end context 'When registry_mirror is array', win_broken: broken do let(:pp) do " class { 'docker': registry_mirror => ['http://testmirror1.io', 'http://testmirror2.io'] } " end it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'has all registry mirrors set' do run_shell('ps -aux | grep docker') do |r| expect(r.stdout).to match(%r{--registry-mirror=http:\/\/testmirror1.io}) expect(r.stdout).to match(%r{--registry-mirror=http:\/\/testmirror2.io}) end end end context 'registry' do let(:registry_address) do "#{registry_host}:#{registry_port}" end let(:registry_bad_address) do "#{registry_host}:5001" end it 'is able to run registry' do pp = <<-MANIFEST class { 'docker': #{docker_args}} docker::run { 'registry': image => '#{docker_registry_image}', pull_on_start => true, restart => 'always', net => '#{docker_network}', ports => '#{registry_port}:#{registry_port}', } MANIFEST retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest(pp, catch_failures: true) end # avoid a race condition with the registry taking time to start # on some operating systems sleep 10 end it 'is able to login to the registry', retry: 3, retry_wait: 10, win_broken: true do pp = <<-MANIFEST docker::registry { '#{registry_address}': username => 'username', password => 'password', } MANIFEST apply_manifest(pp, catch_failures: true) run_shell("grep #{registry_address} #{config_file}", expect_failures: false) run_shell("test -e \"#{root_dir}/registry-auth-puppet_receipt_#{server_strip}_root\"", expect_failures: false) end it 'is able to logout from the registry', win_broken: true do pp = <<-MANIFEST docker::registry { '#{registry_address}': ensure=> absent, } MANIFEST apply_manifest(pp, catch_failures: true) run_shell("grep #{registry_address} #{config_file}", expect_failures: true) end it 'does not create receipt if registry login fails', win_broken: true do pp = <<-MANIFEST docker::registry { '#{registry_bad_address}': username => 'username', password => 'password', } MANIFEST apply_manifest(pp, catch_failures: false) run_shell("grep #{registry_bad_address} #{config_file}", expect_failures: true) run_shell("test -e \"#{root_dir}/registry-auth-puppet_receipt_#{bad_server_strip}_root\"", expect_failures: true) end end end diff --git a/spec/acceptance/machine_spec.rb b/spec/acceptance/machine_spec.rb index 5ee89bf..975a2a6 100644 --- a/spec/acceptance/machine_spec.rb +++ b/spec/acceptance/machine_spec.rb @@ -1,64 +1,66 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'docker::machine', win_broken: true do context 'with default parameters' do pp = <<-EOS include docker::machine EOS it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'is idempotent' do apply_manifest(pp, catch_changes: true) end it 'machine configurable check of docker-machine-0.16.1' do expect(file('/usr/local/bin/docker-machine-0.16.1')).to be_file expect(file('/usr/local/bin/docker-machine-0.16.1')).to be_owned_by 'root' expect(file('/usr/local/bin/docker-machine-0.16.1')).to be_mode 755 end it 'machine configurable check of docker-machine' do expect(file('/usr/local/bin/docker-machine')).to be_linked_to '/usr/local/bin/docker-machine-0.16.1' expect(file('/usr/local/bin/docker-machine')).to be_symlink end it 'is installed and working' do run_shell('docker-machine --help', expect_failures: false) end end context 'with url => https://gitlab-docker-machine-downloads.s3.amazonaws.com/v0.16.2-gitlab.3/docker-machine' do pp = <<-EOS class { 'docker::machine': version => '0.16.2-gitlab.3', url => 'https://gitlab-docker-machine-downloads.s3.amazonaws.com/v0.16.2-gitlab.3/docker-machine', } EOS it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'is idempotent' do apply_manifest(pp, catch_changes: true) end it 'machine configurable check of docker-machine-0.16.2-gitlab.3' do expect(file('/usr/local/bin/docker-machine-0.16.2-gitlab.3')).to be_file expect(file('/usr/local/bin/docker-machine-0.16.2-gitlab.3')).to be_owned_by 'root' expect(file('/usr/local/bin/docker-machine-0.16.2-gitlab.3')).to be_mode 755 end it 'machine configurable check of docker-machine' do expect(file('/usr/local/bin/docker-machine')).to be_linked_to '/usr/local/bin/docker-machine-0.16.2-gitlab.3' expect(file('/usr/local/bin/docker-machine')).to be_symlink end it 'is installed and working' do run_shell('docker-machine --help', expect_failures: false) end end end diff --git a/spec/acceptance/network_spec.rb b/spec/acceptance/network_spec.rb index 174e5d1..3de738f 100644 --- a/spec/acceptance/network_spec.rb +++ b/spec/acceptance/network_spec.rb @@ -1,44 +1,46 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' broken = false command = 'docker' network_name = 'test-network' if os[:family] == 'windows' puts 'Not implemented on Windows' broken = true elsif os[:name] == 'ubuntu' && os[:release][:full] == '14.04' docker_args = "version => '18.06.1~ce~3-0~ubuntu'" else docker_args = '' end describe 'docker network', win_broken: broken do before(:all) do install_pp = "class { 'docker': #{docker_args}}" apply_manifest(install_pp, catch_failures: true) end it "#{command} network --help" do run_shell("#{command} network --help", expect_failures: false) end context 'with a local bridge network described in Puppet' do after(:all) do run_shell("#{command} network rm #{network_name}") end it 'is idempotent' do pp = <<-MANIFEST docker_network { '#{network_name}': ensure => present, } MANIFEST idempotent_apply(pp) end it 'has created a network' do run_shell("#{command} network inspect #{network_name}", expect_failures: false) end end end diff --git a/spec/acceptance/plugin_spec.rb b/spec/acceptance/plugin_spec.rb index b9f2c74..29290b1 100644 --- a/spec/acceptance/plugin_spec.rb +++ b/spec/acceptance/plugin_spec.rb @@ -1,42 +1,44 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' broken = false command = 'docker' plugin_name = 'vieux/sshfs' if os[:family] == 'windows' puts 'Not implemented on Windows' broken = true elsif os[:name] == 'ubuntu' && os[:release][:full] == '14.04' docker_args = "version => '18.06.1~ce~3-0~ubuntu'" else docker_args = '' end describe 'docker plugin', win_broken: broken do before(:all) do install_code = "class { 'docker': #{docker_args}}" apply_manifest(install_code, catch_failures: true) end it "#{command} plugin --help" do run_shell("#{command} plugin --help", expect_failures: false) end context 'manage a plugin' do after(:all) do run_shell("#{command} plugin rm -f #{plugin_name}") end it 'is idempotent' do pp = <<-MANIFEST docker::plugin { '#{plugin_name}':} MANIFEST idempotent_apply(pp) end it 'has installed a plugin' do run_shell("#{command} plugin inspect #{plugin_name}", expect_failures: false) end end end diff --git a/spec/acceptance/stack_spec.rb b/spec/acceptance/stack_spec.rb index 817dcd5..6cc8d0c 100644 --- a/spec/acceptance/stack_spec.rb +++ b/spec/acceptance/stack_spec.rb @@ -1,168 +1,170 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:family] == 'windows' docker_args = 'docker_ee => true' tmp_path = 'C:\\tmp\\' wait_for_container_seconds = 120 else docker_args = if os[:name] == 'ubuntu' && os[:release][:full] == '14.04' "version => '18.06.1~ce~3-0~ubuntu'" else '' end tmp_path = '/tmp/' wait_for_container_seconds = 10 end describe 'docker stack', win_broken: true do before(:all) do retry_on_error_matching(60, 5, %r{connection failure running}) do install_pp = <<-MANIFEST class { 'docker': #{docker_args} } docker::swarm {'cluster_manager': init => true, ensure => 'present', advertise_addr => $facts['networking']['ip'], listen_addr => $facts['networking']['ip'], require => Class['docker'], } MANIFEST apply_manifest(install_pp, catch_failures: true) end end context 'Creating stack' do let(:install_pp) do <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml'], ensure => present, } MANIFEST end it 'deploys stack' do apply_manifest(install_pp, catch_failures: true) sleep wait_for_container_seconds end it 'is idempotent' do apply_manifest(install_pp, catch_changes: true) end it 'finds a stack' do run_shell('docker stack ls') do |r| expect(r.stdout).to match(%r{web}) end end it 'does not find a docker container' do run_shell('docker ps -a -q -f "name=web_compose_test"', expect_failures: false) end end context 'Destroying stack' do let(:install) do <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml'], ensure => present, } MANIFEST end let(:destroy) do <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml'], ensure => absent, } MANIFEST end it 'runs successfully' do apply_manifest(destroy, catch_failures: true) sleep 10 end it 'is idempotent' do retry_on_error_matching(10, 3, %r{Removing network web_default}) do apply_manifest(destroy, catch_changes: true) end end it 'does not find a docker stack' do run_shell('docker stack ls') do |r| expect(r.stdout).not_to match(%r{web}) end end end context 'creating stack with multi compose files' do before(:all) do install_pp = <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml', '#{tmp_path}docker-stack-override.yml'], ensure => present, } MANIFEST apply_manifest(install_pp, catch_failures: true) end it 'finds container with web_compose_test tag' do sleep wait_for_container_seconds run_shell('docker ps | grep web_compose_test', expect_failures: false) end end context 'Destroying project with multiple compose files' do let(:destroy_pp) do <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml', '#{tmp_path}docker-stack-override.yml'], ensure => absent, } MANIFEST end before(:all) do install_pp = <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml', '#{tmp_path}docker-stack-override.yml'], ensure => present, } MANIFEST apply_manifest(install_pp, catch_failures: true) destroy_pp = <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml', '#{tmp_path}docker-stack-override.yml'], ensure => absent, } MANIFEST retry_on_error_matching(10, 3, %r{Removing network web_default}) do apply_manifest(destroy_pp, catch_failures: true) end sleep 15 # Wait for containers to stop and be destroyed end it 'is idempotent' do retry_on_error_matching(10, 3, %r{Removing network web_default}) do apply_manifest(destroy_pp, catch_changes: true) end end it 'does not find a docker stack' do run_shell('docker stack ls') do |r| expect(r.stdout).not_to match(%r{web}) end end it 'does not find a docker container' do run_shell('docker ps', expect_failures: false) do |r| expect(r.stdout).not_to match(%r{web_compose_test}) end end end end diff --git a/spec/acceptance/volume_spec.rb b/spec/acceptance/volume_spec.rb index b9974ce..c8e67a1 100644 --- a/spec/acceptance/volume_spec.rb +++ b/spec/acceptance/volume_spec.rb @@ -1,47 +1,49 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' volume_name = 'test-volume' if os[:family] == 'windows' docker_args = 'docker_ee => true' command = '"/cygdrive/c/Program Files/Docker/docker"' elsif os[:name] == 'ubuntu' && os[:release][:full] == '14.04' docker_args = "version => '18.06.1~ce~3-0~ubuntu'" command = 'docker' else docker_args = '' command = 'docker' end describe 'docker volume' do before(:all) do retry_on_error_matching(60, 5, %r{connection failure running}) do install_pp = "class { 'docker': #{docker_args} }" apply_manifest(install_pp, catch_failures: true) end end it 'exposes volume subcommand' do run_shell("#{command} volume --help", expect_failures: false) end context 'with a local volume described in Puppet' do it 'applies idempotently' do pp = <<-MANIFEST docker_volume { '#{volume_name}': ensure => present, } MANIFEST idempotent_apply(pp) end it 'has created a volume' do run_shell("#{command} volume inspect #{volume_name}", expect_failures: false) end after(:all) do run_shell("#{command} volume rm #{volume_name}") end end end diff --git a/spec/acceptance_swarm/swarm_spec.rb b/spec/acceptance_swarm/swarm_spec.rb index f39a6c8..9268618 100644 --- a/spec/acceptance_swarm/swarm_spec.rb +++ b/spec/acceptance_swarm/swarm_spec.rb @@ -1,146 +1,148 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if fact('osfamily') == 'windows' docker_args = 'docker_ee => true' test_docker_image = 'hello-seattle:nanoserver' test_docker_command = 'cmd.exe /C "ping /t 8.8.8.8"' else docker_args = '' test_docker_image = 'ubuntu:16.04' test_docker_command = '/bin/sh -c "while true; do echo hello world; sleep 1; done"' end skip_tests = false begin swarm_manager = only_host_with_role(hosts, 'swarm-manager') swarm_worker = only_host_with_role(hosts, 'swarm-worker') manager_ip = swarm_manager.ip rescue ArgumentError skip_tests = true end describe 'docker swarm', skip: skip_tests do before(:each) do retry_on_error_matching(60, 5, %r{connection failure running}) do install_code = <<-code class { 'docker': #{docker_args} } code apply_manifest_on(swarm_manager, install_code, catch_failures: true) end retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_worker, install_code, catch_failures: true) end setup_manager_pp = <<-MANIFEST docker::swarm {'cluster_manager': init => true, advertise_addr => '#{manager_ip}', listen_addr => '#{manager_ip}', ensure => 'present', } MANIFEST retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_manager, setup_manager_pp, catch_failures: true) end if fact('osfamily') == 'windows' on swarm_manager, 'netsh advfirewall firewall add rule name="Swarm mgmgt" dir=in action=allow protocol=TCP localport=2377', acceptable_exit_codes: [0] on swarm_manager, 'netsh advfirewall firewall add rule name="Swarm comm tcp" dir=in action=allow protocol=TCP localport=7946', acceptable_exit_codes: [0] on swarm_manager, 'netsh advfirewall firewall add rule name="Swarm comm udp" dir=in action=allow protocol=UDP localport=7946', acceptable_exit_codes: [0] on swarm_manager, 'netsh advfirewall firewall add rule name="Swarm network" dir=in action=allow protocol=UDP localport=4789', acceptable_exit_codes: [0] end end after(:each) do remove_worker = <<-code docker::swarm {'cluster_worker': ensure => 'absent', } code retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_worker, remove_worker, catch_failures: true) end remove_mgr_pp = <<-MANIFEST docker::swarm {'cluster_manager': ensure => 'absent', } MANIFEST retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_manager, remove_mgr_pp, catch_failures: true) end end context 'Creating a swarm server' do let(:token) { shell('docker swarm join-token -q worker').stdout.strip } it 'is idempotent' do setup_manager_pp = <<-MANIFEST docker::swarm {'cluster_manager': init => true, advertise_addr => '#{manager_ip}', listen_addr => '#{manager_ip}', ensure => 'present', } MANIFEST apply_manifest_on(swarm_manager, setup_manager_pp, catch_failures: true) end it 'displays nodes' do on swarm_manager, 'docker node ls', acceptable_exit_codes: [0] do |result| expect(result.stdout).to match(%r{Leader}) end end it 'joins a node' do setup_slave_pp = <<-MANIFEST docker::swarm {'cluster_worker': join => true, advertise_addr => '#{swarm_worker.ip}', listen_addr => '#{swarm_worker.ip}', manager_ip => '#{manager_ip}', token => '#{token}', } MANIFEST retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_worker, setup_slave_pp, catch_failures: true) end retry_on_error_matching(60, 5, %r{connection failure running}) do on swarm_worker, 'docker info' do |result| expect(result.stdout).to match(%r{Swarm: active}) end end if fact('osfamily') == 'windows' on swarm_worker, 'netsh advfirewall firewall add rule name="Swarm mgmgt" dir=in action=allow protocol=TCP localport=2377', acceptable_exit_codes: [0] on swarm_worker, 'netsh advfirewall firewall add rule name="Swarm comm tcp" dir=in action=allow protocol=TCP localport=7946', acceptable_exit_codes: [0] on swarm_worker, 'netsh advfirewall firewall add rule name="Swarm comm udp" dir=in action=allow protocol=UDP localport=7946', acceptable_exit_codes: [0] on swarm_worker, 'netsh advfirewall firewall add rule name="Swarm network" dir=in action=allow protocol=UDP localport=4789', acceptable_exit_codes: [0] end end it 'starts a container' do start_service = <<-MANIFEST docker::services {'helloworld': create => true, service_name => 'helloworld', image => '#{test_docker_image}', extra_params => ['--endpoint-mode dnsrr'], command => '#{test_docker_command}', replicas => '2', } MANIFEST apply_manifest_on(swarm_manager, start_service, catch_failures: true) # on swarm_manager, "docker service create --name=helloworld --endpoint-mode dnsrr --network=swarmnet #{test_docker_image} #{test_docker_command}", :acceptable_exit_codes => [0] on swarm_manager, 'docker service ps helloworld', acceptable_exit_codes: [0] do |result| expect(result.stdout).to match(%r{Running}) end end end end diff --git a/spec/classes/compose_spec.rb b/spec/classes/compose_spec.rb index ed17da8..3b0d7a9 100644 --- a/spec/classes/compose_spec.rb +++ b/spec/classes/compose_spec.rb @@ -1,90 +1,92 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default valus' => { }, 'with ensure => absent' => { 'ensure' => 'absent', }, 'with version => 1.7.0' => { 'version' => '1.7.0', }, 'when proxy is provided' => { 'version' => '1.7.0', 'proxy' => 'http://proxy.example.org:3128/', }, 'when proxy is not a http proxy' => { 'proxy' => 'this is not a URL', }, 'when proxy contains username and password' => { 'version' => '1.7.0', 'proxy' => 'http://user:password@proxy.example.org:3128/', }, 'when proxy IP is provided' => { 'version' => '1.7.0', 'proxy' => 'http://10.10.10.10:3128/', }, 'when base_url is provided' => { 'version' => '1.7.0', 'base_url' => 'http://example.org', }, 'when raw_url is provided' => { 'version' => '1.7.0', 'raw_url' => 'http://example.org', }, } describe 'docker::compose', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'version' => defaults['compose_version'], 'install_path' => defaults['compose_install_path'], 'symlink_name' => defaults['compose_symlink_name'], 'proxy' => :undef, 'base_url' => defaults['compose_base_url'], 'raw_url' => :undef, 'curl_ensure' => defaults['curl_ensure'], }.merge(local_params) let(:facts) do facts end let(:params) do params end if params['proxy'] != :undef - if params['proxy'] !~ %r{^((http[s]?)?:\/\/)?([^:^@]+:[^:^@]+@|)([\da-z\.-]+)\.([\da-z\.]{2,6})(:[\d])?([\/\w \.-]*)*\/?$} + unless %r{^((http[s]?)?:\/\/)?([^:^@]+:[^:^@]+@|)([\da-z\.-]+)\.([\da-z\.]{2,6})(:[\d])?([\/\w \.-]*)*\/?$}.match?(params['proxy']) it { is_expected.to compile.and_raise_error(%r{does not match}) } next end end include_examples 'compose', params, facts end end end end end diff --git a/spec/classes/images_spec.rb b/spec/classes/images_spec.rb index 99fcb2a..8d5255f 100644 --- a/spec/classes/images_spec.rb +++ b/spec/classes/images_spec.rb @@ -1,68 +1,70 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure => present' => { 'ensure' => 'present', }, 'with ensure => absent' => { 'ensure' => 'absent', }, } describe 'docker::images', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'base' => { 'ensure' => 'present', 'image_tag' => :undef, 'image_digest' => :undef, 'force' => false, 'docker_file' => :undef, 'docker_dir' => :undef, 'docker_tar' => :undef, }, } params.each do |key, values| values.merge!(local_params.merge('image' => key)) let(:facts) do facts end let(:params) do { 'images' => { key => values, }, } end include_examples 'image', values, facts, defaults it { is_expected.to contain_docker__image(key) } end end end end end end diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 0a557f7..ee1521e 100755 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1,222 +1,224 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default values' => { }, 'with docker_users set' => { 'docker_users' => [ 'some_random_user', 'foo', 'bar', ], }, 'with package_source set to docker-engine' => { 'package_source' => 'docker-engine', }, 'with package_source set to docker-ce' => { 'package_source' => 'docker-ce', }, 'with ensure set to absent' => { 'ensure' => 'absent', }, 'with ensure set to absent and given version' => { 'ensure' => 'absent', 'version' => '16', }, 'with ms parameter set' => { 'version' => '16', 'docker_msft_provider_version' => '123', 'nuget_package_provider_version' => '41', }, } describe 'docker', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - if os =~ %r{windows} + if %r{windows}.match?(os) facts = windows_facts.merge(os_facts) default_params = { 'docker_ee' => true, 'docker_users' => [], } else facts = os_facts default_params = { 'docker_users' => [], } end ## ## get default values based on facts ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'acknowledge_unsupported_os' => false, 'apt_source_pin_level' => defaults['apt_source_pin_level'], 'bip' => defaults['bip'], 'bridge' => defaults['bridge'], 'daemon_environment_files' => [], 'default_gateway_ipv6' => defaults['default_gateway_ipv6'], 'default_gateway' => defaults['default_gateway'], 'dependent_packages' => defaults['dependent_packages'], 'dm_basesize' => defaults['dm_basesize'], 'dm_blkdiscard' => defaults['dm_blkdiscard'], 'dm_blocksize' => defaults['dm_blocksize'], 'dm_datadev' => defaults['dm_datadev'], 'dm_fs' => defaults['dm_fs'], 'dm_loopdatasize' => defaults['dm_loopdatasize'], 'dm_loopmetadatasize' => defaults['dm_loopmetadatasize'], 'dm_metadatadev' => defaults['dm_metadatadev'], 'dm_mkfsarg' => defaults['dm_mkfsarg'], 'dm_mountopt' => defaults['dm_mountopt'], 'dm_override_udev_sync_check' => defaults['dm_override_udev_sync_check'], 'dm_thinpooldev' => defaults['dm_thinpooldev'], 'dm_use_deferred_deletion' => defaults['dm_use_deferred_deletion'], 'dm_use_deferred_removal' => defaults['dm_use_deferred_removal'], 'dns_search' => defaults['dns_search'], 'dns' => defaults['dns'], 'docker_ce_channel' => defaults['docker_ce_channel'], 'docker_ce_key_id' => defaults['package_ce_key_id'], 'docker_ce_key_source' => defaults['package_ce_key_source'], 'docker_ce_package_name' => defaults['docker_ce_package_name'], 'docker_ce_release' => defaults['package_ce_release'], 'docker_ce_source_location' => defaults['package_ce_source_location'], 'docker_ce_start_command' => defaults['docker_ce_start_command'], 'docker_ee_key_id' => defaults['package_ee_key_id'], 'docker_ee_key_source' => defaults['package_ee_key_source'], 'docker_ee_package_name' => defaults['package_ee_package_name'], 'docker_ee_release' => defaults['package_ee_release'], 'docker_ee_repos' => defaults['package_ee_repos'], 'docker_ee_source_location' => defaults['package_ee_source_location'], 'docker_ee' => defaults['docker_ee'], 'docker_engine_package_name' => defaults['docker_engine_package_name'], 'docker_engine_start_command' => defaults['docker_engine_start_command'], 'docker_group' => defaults['docker_group'], 'docker_msft_provider_version' => defaults['docker_msft_provider_version'], 'docker_package_key_check_source' => defaults['package_key_check_source'], 'docker_package_key_id' => defaults['package_key_id'], 'docker_package_key_source' => defaults['package_key_source'], 'docker_package_location' => defaults['package_source_location'], 'docker_package_release' => defaults['package_release'], 'docker_users' => [], 'ensure' => defaults['package_ensure'], 'execdriver' => defaults['execdriver'], 'extra_parameters' => :undef, 'fixed_cidr' => defaults['fixed_cidr'], 'icc' => defaults['icc'], 'ip_forward' => defaults['ip_forward'], 'ip_masq' => defaults['ip_masq'], 'iptables' => defaults['iptables'], 'ipv6_cidr' => defaults['ipv6_cidr'], 'ipv6' => defaults['ipv6'], 'labels' => defaults['labels'], 'log_driver' => defaults['log_driver'], 'log_level' => defaults['log_level'], 'log_opt' => defaults['log_opt'], 'manage_package' => defaults['manage_package'], 'manage_service' => defaults['manage_service'], 'mtu' => defaults['mtu'], 'no_proxy' => defaults['no_proxy'], 'nuget_package_provider_version' => defaults['nuget_package_provider_version'], 'os_lc' => defaults['os_lc'], 'overlay2_override_kernel_check' => defaults['overlay2_override_kernel_check'], 'package_release' => defaults['package_release'], 'package_source' => defaults['package_source'], 'pin_upstream_package_source' => defaults['pin_upstream_package_source'], 'prerequired_packages' => defaults['prerequired_packages'], 'proxy' => defaults['proxy'], 'registry_mirror' => defaults['registry_mirror'], 'repo_opt' => defaults['repo_opt'], 'root_dir' => defaults['root_dir'], 'selinux_enabled' => defaults['selinux_enabled'], 'service_after_override' => defaults['service_after_override'], 'service_config_template' => defaults['service_config_template'], 'service_config' => defaults['service_config'], 'service_enable' => defaults['service_enable'], 'service_hasrestart' => defaults['service_hasrestart'], 'service_hasstatus' => defaults['service_hasstatus'], 'service_name' => defaults['service_name'], 'service_overrides_template' => defaults['service_overrides_template'], 'service_provider' => defaults['service_provider'], 'service_state' => defaults['service_state'], 'shell_values' => :undef, 'socket_bind' => defaults['socket_bind'], 'socket_group' => defaults['socket_group'], 'socket_override' => defaults['socket_override'], 'socket_overrides_template' => defaults['socket_overrides_template'], 'storage_auto_extend_pool' => defaults['storage_auto_extend_pool'], 'storage_chunk_size' => defaults['storage_chunk_size'], 'storage_config_template' => defaults['storage_config_template'], 'storage_config' => defaults['storage_config'], 'storage_data_size' => defaults['storage_data_size'], 'storage_devs' => defaults['storage_devs'], 'storage_driver' => defaults['storage_driver'], 'storage_growpart' => defaults['storage_growpart'], 'storage_min_data_size' => defaults['storage_min_data_size'], 'storage_pool_autoextend_percent' => defaults['storage_pool_autoextend_percent'], 'storage_pool_autoextend_threshold' => defaults['storage_pool_autoextend_threshold'], 'storage_root_size' => defaults['storage_root_size'], 'storage_setup_file' => defaults['storage_setup_file'], 'storage_vg' => defaults['storage_vg'], 'tcp_bind' => defaults['tcp_bind'], 'tls_cacert' => defaults['tls_cacert'], 'tls_cert' => defaults['tls_cert'], 'tls_enable' => defaults['tls_enable'], 'tls_key' => defaults['tls_key'], 'tls_verify' => defaults['tls_verify'], 'tmp_dir_config' => defaults['tmp_dir_config'], 'tmp_dir' => defaults['tmp_dir'], 'use_upstream_package_source' => defaults['use_upstream_package_source'], 'version' => defaults['version'], }.merge(default_params).merge(local_params) let(:facts) do facts end let(:params) do params end if params['ensure'] != 'absent' if params['package_source'] != :undef && facts[:os]['family'] =~ %r{windows} it { is_expected.to compile.and_raise_error(%r{Custom package source is currently not implemented on windows.}) } else it { is_expected.to contain_class('docker::repos').that_comes_before('Class[docker::install]') is_expected.to contain_class('docker::install').that_comes_before('Class[docker::config]') is_expected.to contain_class('docker::config').that_comes_before('Class[docker::service]') is_expected.to contain_class('docker::service') } include_examples 'params', facts include_examples 'repos', params, facts include_examples 'install', params, facts include_examples 'config', params, facts include_examples 'service', params, facts end else it { is_expected.to contain_class('docker::repos').that_comes_before('Class[docker::install]') is_expected.to contain_class('docker::install') } include_examples 'params', facts include_examples 'repos', params, facts include_examples 'install', params, facts end end end end end end diff --git a/spec/classes/machine_spec.rb b/spec/classes/machine_spec.rb index 9d49732..6283473 100644 --- a/spec/classes/machine_spec.rb +++ b/spec/classes/machine_spec.rb @@ -1,59 +1,61 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default value' => { }, } describe 'docker::machine', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'version' => defaults['machine_version'], 'install_path' => defaults['machine_install_path'], 'proxy' => :undef, 'url' => :undef, 'curl_ensure' => defaults['curl_ensure'], }.merge(local_params) let(:facts) do facts end let(:params) do params end if params['proxy'] != :undef - if params['proxy'] !~ '^((http[s]?)?:\/\/)?([^:^@]+:[^:^@]+@|)([\da-z\.-]+)\.([\da-z\.]{2,6})(:[\d])?([\/\w \.-]*)*\/?$' + unless '^((http[s]?)?:\/\/)?([^:^@]+:[^:^@]+@|)([\da-z\.-]+)\.([\da-z\.]{2,6})(:[\d])?([\/\w \.-]*)*\/?$'.match?(params['proxy']) it { is_expected.to compile.and_raise_error(%r{}) } next end end include_examples 'machine', params, facts, defaults end end end end end diff --git a/spec/classes/networks_spec.rb b/spec/classes/networks_spec.rb index 6542c34..53ec229 100644 --- a/spec/classes/networks_spec.rb +++ b/spec/classes/networks_spec.rb @@ -1,66 +1,68 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'network-present' => { 'ensure' => 'present', 'driver' => 'overlay', 'subnet' => '192.168.1.0/24', 'gateway' => '192.168.1.1', 'ip_range' => '192.168.1.4/32', }, 'network-absent' => { 'ensure' => 'absent', 'driver' => 'overlay', 'subnet' => '192.168.1.0/24', 'gateway' => '192.168.1.1', 'ip_range' => '192.168.1.4/32', }, } describe 'docker::networks', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = local_params let(:facts) do facts end let(:params) do { 'networks' => { title => local_params, }, } end it { is_expected.to contain_docker_network(title).with( 'ensure' => params['ensure'], 'driver' => params['driver'], 'subnet' => params['subnet'], 'gateway' => params['gateway'], 'ip_range' => params['ip_range'], ) } end end end end end diff --git a/spec/classes/plugins_spec.rb b/spec/classes/plugins_spec.rb index 6c84369..012fda0 100644 --- a/spec/classes/plugins_spec.rb +++ b/spec/classes/plugins_spec.rb @@ -1,78 +1,80 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'foo/enabled:latest' => { 'enabled' => true, }, 'foo/disabled:latest' => { 'enabled' => false, }, } describe 'docker::plugins', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'base' => { 'ensure' => 'present', 'enabled' => true, 'timeout' => :undef, 'plugin_alias' => :undef, 'disable_on_install' => false, 'disable_content_trust' => true, 'grant_all_permissions' => true, 'force_remove' => true, 'settings' => [], }, } params.each do |key, values| values.merge!(local_params.merge('plugin_name' => key)) let(:facts) do facts end let(:params) do { 'plugins' => { key => values, }, } end if facts[:os]['family'] == 'windows' it { is_expected.to compile.and_raise_error(%r{Feature not implemented on windows.}) } next end include_examples 'plugin', values, facts, defaults it { is_expected.to contain_docker__plugin(key) } end end end end end end diff --git a/spec/defines/exec_spec.rb b/spec/defines/exec_spec.rb index c17102f..b33051c 100644 --- a/spec/defines/exec_spec.rb +++ b/spec/defines/exec_spec.rb @@ -1,94 +1,96 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default values' => { }, 'when running detached' => { 'detach' => true, }, 'when running with tty' => { 'tty' => true, }, 'when running with interactive' => { 'interactive' => true, }, 'when running with onlyif "running"' => { 'interactive' => true, 'onlyif' => 'running', }, 'when running without onlyif custom command' => { 'interactive' => true, 'onlyif' => 'custom', }, 'when running without onlyif' => { 'interactive' => true, }, 'when running with unless' => { 'interactive' => true, 'unless' => 'some_command arg1', }, 'when running without unless' => { 'interactive' => true, }, 'with title that need sanitisation' => { 'detach' => true, 'sanitise_name' => true, }, 'with environment variables passed to exec' => { 'env' => [ 'FOO=BAR', 'FOO2=BAR2', ], }, } describe 'docker::exec', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'command' => '/bin/echo foo', 'container' => 'some_conainer_name', 'detach' => false, 'env' => [], 'interactive' => false, 'onlyif' => :undef, 'refreshonly' => false, 'sanitise_name' => true, 'tty' => false, 'unless' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do title end include_examples 'exec', params, facts, defaults end end end end end diff --git a/spec/defines/image_spec.rb b/spec/defines/image_spec.rb index 93c6b83..08cd7d3 100644 --- a/spec/defines/image_spec.rb +++ b/spec/defines/image_spec.rb @@ -1,180 +1,182 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default value' => { }, 'with ensure => absent' => { 'ensure' => 'absent', }, 'with ensure => absent and force => true' => { 'ensure' => 'absent', 'force' => true, }, 'with ensure => absent and image_tag => precise' => { 'ensure' => 'absent', 'image_tag' => 'precise', }, 'with docker_file => Dockerfile' => { 'docker_file' => 'Dockerfile', }, 'with ensure => present and docker_file => Dockerfile' => { 'ensure' => 'present', 'docker_file' => 'Dockerfile', }, 'with docker_dir => /tmp/docker_images/test1 and docker_file => /tmp/docker_images/test1/Dockerfile_altbuild' => { 'docker_dir' => '/tmp/docker_images/test1', 'docker_file' => '/tmp/docker_images/test1/Dockerfile_altbuild', }, 'with docker_dir => /tmp/docker_images/test1' => { 'docker_dir' => '/tmp/docker_images/test1', }, 'with ensure => present and docker_dir => /tmp/docker_images/test1' => { 'ensure' => 'present', 'docker_dir' => '/tmp/docker_images/test1', }, 'with ensure => present and image_tag => precise' => { 'ensure' => 'present', 'image_tag' => 'precise', }, 'with ensure => present and image_digest => sha256:deadbeef' => { 'ensure' => 'present', 'image_digest' => 'sha256:deadbeef', }, 'with ensure => present and image_tag => precise and docker_file => Dockerfile' => { 'ensure' => 'present', 'image_tag' => 'precise', 'docker_file' => 'Dockerfile', }, 'with ensure => present and image_tag => precise and docker_dir => /tmp/docker_images/test1' => { 'ensure' => 'present', 'image_tag' => 'precise', 'docker_dir' => '/tmp/docker_images/test1', }, 'with docker_tar => /tmp/docker_tars/test1.tar' => { 'docker_tar' => '/tmp/docker_tars/test1.tar', }, 'with ensure => present and docker_tar => /tmp/docker_tars/test1.tar' => { 'ensure' => 'present', 'docker_tar' => '/tmp/docker_tars/test1.tar', }, 'with docker_file => Dockerfile and docker_tar => /tmp/docker_tars/test1.tar' => { 'docker_file' => 'Dockerfile', 'docker_tar' => '/tmp/docker_tars/test1.tar', }, 'with docker_tar => /tmp/docker_tars/test1.tar and docker_dir => /tmp/docker_images/test1' => { 'docker_tar' => '/tmp/docker_tars/test1.tar', 'docker_dir' => '/tmp/docker_images/test1', }, 'with image_digest => sha256:deadbeef and docker_file => Dockerfile' => { 'image_digest' => 'sha256:deadbeef', 'docker_file' => 'Dockerfile', }, 'with image_digest => sha256:deadbeef and docker_dir => /tmp/docker_images/test1' => { 'image_digest' => 'sha256:deadbeef', 'docker_dir' => '/tmp/docker_images/test1', }, 'with image_digest => sha256:deadbeef and docker_tar => /tmp/docker_tars/test1.tar' => { 'image_digest' => 'sha256:deadbeef', 'docker_tar' => '/tmp/docker_tars/test1.tar', }, 'with ensure => latest' => { 'ensure' => 'latest', }, 'with ensure => latest and image_tag => precise' => { 'ensure' => 'latest', 'image_tag' => 'precise', }, 'with ensure => latest and image_digest => sha256:deadbeef' => { 'ensure' => 'latest', 'image_digest' => 'sha256:deadbeef', }, } describe 'docker::image', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'image' => 'base', 'image_tag' => :undef, 'image_digest' => :undef, 'force' => false, 'docker_file' => :undef, 'docker_dir' => :undef, 'docker_tar' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do params['image'] end if params['docker_file'] != :undef && params['docker_tar'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$docker_file and \$docker_tar set}) } next end if params['docker_dir'] != :undef && params['docker_tar'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$docker_dir and \$docker_tar set}) } next end if params['image_digest'] != :undef && params['docker_file'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$image_digest and \$docker_file set}) } next end if params['image_digest'] != :undef && params['docker_dir'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$image_digest and \$docker_dir set}) } next end if params['image_digest'] != :undef && params['docker_tar'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$image_digest and \$docker_tar set}) } next end include_examples 'image', params, facts, defaults end end end end end diff --git a/spec/defines/plugin_spec.rb b/spec/defines/plugin_spec.rb index 7968eb3..1d4fc1b 100644 --- a/spec/defines/plugin_spec.rb +++ b/spec/defines/plugin_spec.rb @@ -1,76 +1,78 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'foo/setting:latest' => { 'settings' => [ 'VAR1=test', 'VAR2=value', ], }, 'foo/disabled:latest' => { 'enabled' => false, }, 'foo/force_remove:latest' => { 'ensure' => 'absent', 'force_remove' => true, }, } describe 'docker::plugin', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'plugin_name' => title, 'enabled' => true, 'timeout' => :undef, 'plugin_alias' => :undef, 'disable_on_install' => false, 'disable_content_trust' => true, 'grant_all_permissions' => true, 'force_remove' => true, 'settings' => [], }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do title end if facts[:os]['family'] == 'windows' it { is_expected.to compile.and_raise_error(%r{Feature not implemented on windows.}) } next end include_examples 'plugin', params, facts, defaults end end end end end diff --git a/spec/defines/registry_spec.rb b/spec/defines/registry_spec.rb index 84b24ac..bae0e0d 100644 --- a/spec/defines/registry_spec.rb +++ b/spec/defines/registry_spec.rb @@ -1,150 +1,152 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure => absent' => { 'ensure' => 'absent', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present' => { 'ensure' => 'present', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and username => user1' => { 'ensure' => 'present', 'username' => 'user1', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and password => secret' => { 'ensure' => 'present', 'password' => 'secret', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and email => user1@example.io' => { 'ensure' => 'present', 'email' => 'user1@example.io', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and username => user1, and password => secret and email => user1@example.io' => { 'ensure' => 'present', 'username' => 'user1', 'password' => 'secret', 'email' => 'user1@example.io', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and username => user1, and password => secret and email => user1@example.io and version < 1.11.0' => { 'ensure' => 'present', 'username' => 'user1', 'password' => 'secret', 'email' => 'user1@example.io', 'version' => '1.9.0', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with username => user1, and password => secret' => { 'username' => 'user1', 'password' => 'secret', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with username => user1, and password => secret and local_user => testuser' => { 'username' => 'user1', 'password' => 'secret', 'local_user' => 'testuser', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, } describe 'docker::registry', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - if os =~ %r{windows} + if %r{windows}.match?(os) facts = windows_facts.merge( 'docker_home_dirs' => { 'user' => '/home/user', 'root' => '/root', }, ).merge(os_facts) docker_params = { 'docker_ee' => true, } else facts = { docker_home_dirs: { 'user' => '/home/user', 'root' => '/root', }, }.merge(os_facts) docker_params = {} end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'server' => title, 'ensure' => 'present', 'username' => :undef, 'password' => :undef, 'pass_hash' => :undef, 'email' => :undef, 'local_user' => 'root', 'version' => defaults['version'], 'receipt' => true, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do title end let :pre_condition do <<-MANIFEST function pw_hash($foo, $bar, $asdf) { return '$6$foobar$v8j5roVj0D8t.Ipwvk0RrMHiZfZRoBMeVQDywxUKFtdRI2EFRi2X6tbOigjpOsa9UDVzgIBtcl2ZEGcM.jnZZ.' } class { 'docker': version => "#{params['version']}", * => #{docker_params}, } MANIFEST end include_examples 'registry', title, params, facts, defaults end end end end end diff --git a/spec/defines/run_spec.rb b/spec/defines/run_spec.rb index 9087023..81fa35c 100644 --- a/spec/defines/run_spec.rb +++ b/spec/defines/run_spec.rb @@ -1,363 +1,365 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'default values' => {}, 'when passing depends containers' => { 'depends' => [ 'foo', 'bar', 'foo_bar/baz', ], }, 'when passing after containers' => { 'after' => [ 'foo', 'bar', 'foo_bar/baz', ], }, 'when use_name is true' => { 'use_name' => true, }, 'when stopping the service' => { 'running' => false, }, 'when passing a cpuset' => { 'cpuset' => '3', }, 'when passing a multiple cpu cpuset' => { 'cpuset' => [ '0', '3', ], }, 'when passing a links option' => { 'links' => [ 'example:one', 'example:two', ], }, 'when passing a hostname' => { 'hostname' => 'example.com', }, 'when passing a username' => { 'username' => 'bob', }, 'when passing a port number' => { 'ports' => '4444', }, 'when passing a port to expose' => { 'expose' => '4666', }, 'when passing a label' => { 'labels' => 'key=value', }, 'when passing a hostentry' => { 'hostentries' => 'dummyhost:127.0.0.2', }, 'when connecting to shared data volumes' => { 'volumes_from' => '6446ea52fbc9', }, 'when connecting to several shared data volumes' => { 'volumes_from' => [ 'sample-linked-container-1', 'sample-linked-container-2', ], }, 'when passing several port numbers' => { 'ports' => [ '4444', '4555', ], }, 'when passing several labels' => { 'labels' => [ 'key1=value1', 'key2=value2', ], }, 'when passing several ports to expose' => { 'expose' => [ '4666', '4777', ], }, 'when passing serveral environment variables' => { 'env' => [ 'FOO=BAR', 'FOO2=BAR2', ], }, 'when passing an environment variable' => { 'env' => 'FOO=BAR', }, 'when passing serveral environment files' => { 'env_file' => [ '/etc/foo.env', '/etc/bar.env', ], }, 'when passing an environment file' => { 'env_file' => '/etc/foo.env', }, 'when passing serveral dns addresses' => { 'dns' => [ '8.8.8.8', '8.8.4.4', ], }, 'when passing a dns address' => { 'dns' => '8.8.8.8', }, 'when passing serveral sockets to connect to' => { 'socket_connect' => [ 'tcp://127.0.0.1:4567', 'tcp://127.0.0.2:4567', ], }, 'when passing a socket to connect to' => { 'socket_connect' => 'tcp://127.0.0.1:4567', }, 'when passing serveral dns search domains' => { 'dns_search' => [ 'my.domain.local', 'other-domain.de', ], }, 'when passing a dns search domain' => { 'dns_search' => 'my.domain.local', }, 'when disabling network' => { 'disable_network' => true, }, 'when running privileged' => { 'privileged' => true, }, 'when passing serveral extra parameters' => { 'extra_parameters' => ['--rm', '-w /tmp'], }, 'when passing an extra parameter' => { 'extra_parameters' => '-c 4', }, 'when passing a data volume' => { 'volumes' => '/var/log', }, 'when passing serveral data volume' => { 'volumes' => [ '/var/lib/couchdb', '/var/log', ], }, 'when pull_on_start is true' => { 'pull_on_start' => true, }, 'when pull_on_start is false' => { 'pull_on_start' => false, }, 'when before_start is set' => { 'before_start' => 'echo before_start', }, 'when before_start is not set' => { 'before_start' => false, }, 'when before_stop is set' => { 'before_stop' => 'echo before_stop', }, 'when before_stop is not set' => { 'before_stop' => false, }, 'when after_start is set' => { 'after_start' => 'echo after_start', }, 'when after_start is not set' => { 'after_start' => false, }, 'when after_stop is set' => { 'after_stop' => 'echo after_stop', }, 'when after_stop is not set' => { 'after_stop' => false, }, 'when docker_service is false' => { 'docker_service' => false, }, 'when docker_service is true' => { 'docker_service' => true, }, 'when docker_service is true and restart_service_on_docker_refresh is false' => { 'docker_service' => true, 'restart_service_on_docker_refresh' => false, }, 'when docker_service is my-docker' => { 'docker_service' => 'my-docker', }, 'when docker_service is my-docker and restart_service_on_docker_refresh is false' => { 'docker_service' => 'my-docker', 'restart_service_on_docker_refresh' => false, }, } describe 'docker::run', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - if os =~ %r{windows} + if %r{windows}.match?(os) facts = windows_facts.merge(os_facts) os_params = { 'restart' => 'no', 'extra_parameters' => '-c 4', } docker_params = { 'docker_ee' => true, } else facts = {}.merge(os_facts) os_params = {} docker_params = {} end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'after_create' => :undef, 'after_service' => [], 'after_start' => false, 'after_stop' => false, 'after' => [], 'before_start' => false, 'before_stop' => false, 'command' => 'command', 'cpuset' => [], 'custom_unless' => [], 'depend_services' => ['docker.service'], 'depends' => [], 'detach' => :undef, 'disable_network' => false, 'dns_search' => [], 'dns' => [], 'docker_service' => false, 'ensure' => 'present', 'env_file' => [], 'env' => [], 'expose' => [], 'extra_parameters' => :undef, 'extra_systemd_parameters' => {}, 'health_check_cmd' => :undef, 'health_check_interval' => :undef, 'hostentries' => [], 'hostname' => false, 'image' => 'base', 'labels' => [], 'links' => [], 'lxc_conf' => [], 'manage_service' => true, 'memory_limit' => '0b', 'net' => 'bridge', 'ports' => [], 'privileged' => false, 'pull_on_start' => false, 'read_only' => false, 'remain_after_exit' => :undef, 'remove_container_on_start' => true, 'remove_container_on_stop' => true, 'remove_volume_on_start' => false, 'remove_volume_on_stop' => false, 'restart_on_unhealthy' => false, 'restart_service_on_docker_refresh' => true, 'restart_service' => true, 'restart' => :undef, 'running' => true, 'service_prefix' => 'docker-', 'service_provider' => :undef, 'socket_connect' => [], 'stop_wait_time' => 0, 'syslog_identifier' => :undef, 'systemd_restart' => 'on-failure', 'tty' => false, 'use_name' => false, 'username' => false, 'volumes_from' => [], 'volumes' => [], }.merge(os_params).merge(local_params) if params['docker_service'] && params['docker_service'].to_s != 'true' docker_params['service_name'] = params['docker_service'] end let(:facts) do facts end let(:params) do params end let(:title) do params['command'] end let :pre_condition do <<-MANIFEST class { 'docker': version => "#{params['version']}", * => #{docker_params}, } MANIFEST end if params['remove_volume_on_start'] && !params['remove_container_on_start'] it { is_expected.to compile.and_raise_error("In order to remove the volume on start for #{_title} you need to also remove the container") } next end if params['remove_volume_on_stop'] && !params['remove_container_on_stop'] it { is_expected.to compile.and_raise_error("In order to remove the volume on stop for #{_title} you need to also remove the container") } next end service_provider_real = case params['service_provider'] when :undef defaults['service_provider'] else params['service_provider'] end if !params['service_provider_real'] == 'systemd' && !params['service_provider_real'] == 'upstart' if facts[:os]['family'] != 'windows' it { is_expected.to compile.and_raise_error('Docker needs a Debian or RedHat based system.') } next elsif params['ensure'] == 'present' it { is_expected.to compile.and_raise_error('Restart parameter is required for Windows') } next end end include_examples 'run', params['command'], params, facts, defaults end end end end end diff --git a/spec/defines/secrets_spec.rb b/spec/defines/secrets_spec.rb index c260d4a..e0a23d5 100644 --- a/spec/defines/secrets_spec.rb +++ b/spec/defines/secrets_spec.rb @@ -1,58 +1,60 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure present' => { 'secret_name' => 'test_secret', 'secret_path' => '/root/secret.txt', 'label' => ['test'], }, 'with ensure absent' => { 'ensure' => 'absent', 'secret_name' => 'test_secret', }, } describe 'docker::secrets', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'label' => [], 'secret_name' => :undef, 'secret_path' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do title end include_examples 'secrets', title, params, facts, defaults end end end end end diff --git a/spec/defines/services_spec.rb b/spec/defines/services_spec.rb index e7f9651..0f5603e 100644 --- a/spec/defines/services_spec.rb +++ b/spec/defines/services_spec.rb @@ -1,118 +1,120 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure => present and service create' => { 'create' => true, 'service_name' => 'foo', 'image' => 'foo:bar', 'publish' => '80:80', 'replicas' => '5', 'extra_params' => ['--update-delay 1m', '--restart-window 30s'], 'env' => ['MY_ENV=1', 'MY_ENV2=2'], 'label' => ['com.example.foo="bar"', 'bar=baz'], 'mounts' => ['type=bind,src=/tmp/a,dst=/tmp/a', 'type=bind,src=/tmp/b,dst=/tmp/b,readonly'], 'networks' => ['overlay'], 'command' => 'echo hello world', }, 'multiple services declaration' => { 'service_name' => 'foo_2', 'image' => 'foo:bar', 'command' => ['echo', 'hello', 'world'], }, 'multiple publish ports and multiple networks' => { 'service_name' => 'foo_3', 'image' => 'foo:bar', 'publish' => ['80:8080', '9000:9000'], 'networks' => ['foo_1', 'foo_2'], }, 'with ensure => present and service update' => { 'create' => false, 'update' => true, 'service_name' => 'foo', 'image' => 'bar:latest', }, 'with ensure => present and service scale' => { 'create' => false, 'scale' => true, 'service_name' => 'bar', 'replicas' => '5', }, 'with ensure => absent' => { 'ensure' => 'absent', 'service_name' => 'foo', }, 'when adding a system user' => { 'user' => ['user1'], }, } describe 'docker::services', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'create' => true, 'update' => false, 'scale' => false, 'detach' => true, 'tty' => false, 'env' => [], 'label' => [], 'extra_params' => [], 'image' => :undef, 'service_name' => :undef, 'publish' => :undef, 'replicas' => :undef, 'user' => :undef, 'workdir' => :undef, 'host_socket' => :undef, 'registry_mirror' => :undef, 'mounts' => :undef, 'networks' => :undef, 'command' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do 'rspec_services' end if params['ensure'] == 'absent' if params['update'] || params['scale'] it { is_expected.to compile.and_raise_error('When removing a service you can not update it.') } next end end include_examples 'services', 'rspec_services', params, facts, defaults end end end end end diff --git a/spec/defines/stack_spec.rb b/spec/defines/stack_spec.rb index a429431..5504d8c 100644 --- a/spec/defines/stack_spec.rb +++ b/spec/defines/stack_spec.rb @@ -1,71 +1,73 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'create stack with compose file' => { 'stack_name' => 'foo', 'compose_files' => ['/tmp/docker-compose.yaml'], 'resolve_image' => 'always', }, 'create stack with multiple compose files' => { 'stack_name' => 'foo', 'compose_files' => ['/tmp/docker-compose.yaml', '/tmp/docker-compose-2.yaml'], 'resolve_image' => 'always', }, 'with prune' => { 'stack_name' => 'foo', 'compose_files' => ['/tmp/docker-compose.yaml'], 'prune' => true, }, 'with ensure => absent' => { 'ensure' => 'absent', 'stack_name' => 'foo', }, } describe 'docker::stack', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'stack_name' => :undef, 'bundle_file' => :undef, 'compose_files' => :undef, 'prune' => false, 'with_registry_auth' => false, 'resolve_image' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do 'rspec_stack' end include_examples 'stack', 'rspec_stack', params, facts, defaults end end end end end diff --git a/spec/defines/swarm_spec.rb b/spec/defines/swarm_spec.rb index 816694c..4338922 100644 --- a/spec/defines/swarm_spec.rb +++ b/spec/defines/swarm_spec.rb @@ -1,88 +1,90 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure => present and swarm init' => { 'init' => true, 'advertise_addr' => '192.168.1.1', 'listen_addr' => '192.168.1.1', }, 'with ensure => present and swarm init and default-addr-pool and default_addr_pool_mask_length' => { 'init' => true, 'advertise_addr' => '192.168.1.1', 'listen_addr' => '192.168.1.1', 'default_addr_pool' => ['30.30.0.0/16', '40.40.0.0/16'], 'default_addr_pool_mask_length' => '24', }, 'with ensure => present and swarm join' => { 'join' => true, 'advertise_addr' => '192.168.1.1', 'listen_addr' => '192.168.1.1', 'token' => 'foo', 'manager_ip' => '192.168.1.2', }, 'with ensure => absent' => { 'ensure' => 'absent', 'join' => true, 'advertise_addr' => '192.168.1.1', 'listen_addr' => '192.168.1.1', 'token' => 'foo', 'manager_ip' => '192.168.1.2', }, } describe 'docker::swarm', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## - facts = if os =~ %r{windows} + facts = if %r{windows}.match?(os) windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'init' => false, 'join' => false, 'advertise_addr' => :undef, 'autolock' => false, 'cert_expiry' => :undef, 'default_addr_pool' => :undef, 'default_addr_pool_mask_length' => :undef, 'dispatcher_heartbeat' => :undef, 'external_ca' => :undef, 'force_new_cluster' => false, 'listen_addr' => :undef, 'max_snapshots' => :undef, 'snapshot_interval' => :undef, 'token' => :undef, 'manager_ip' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do 'rspec_swarm' end include_examples 'swarm', 'rspec_swarm', params, facts, defaults end end end end end diff --git a/spec/helper/get_defaults.rb b/spec/helper/get_defaults.rb index bb455df..ec5f6a5 100644 --- a/spec/helper/get_defaults.rb +++ b/spec/helper/get_defaults.rb @@ -1,500 +1,502 @@ +# frozen_string_literal: true + def get_defaults(_facts) bip = :undef bridge = :undef compose_base_url = 'https://github.com/docker/compose/releases/download' compose_symlink_name = 'docker-compose' curl_ensure = true default_gateway = :undef default_gateway_ipv6 = :undef dm_basesize = :undef dm_blkdiscard = :undef dm_blocksize = :undef dm_datadev = :undef dm_fs = :undef dm_loopdatasize = :undef dm_loopmetadatasize = :undef dm_metadatadev = :undef dm_mkfsarg = :undef dm_mountopt = :undef dm_override_udev_sync_check = :undef dm_thinpooldev = :undef dm_use_deferred_deletion = :undef dm_use_deferred_removal = :undef dns = :undef dns_search = :undef docker_ce_channel = 'stable' docker_ce_package_name = 'docker-ce' docker_ce_start_command = 'dockerd' docker_command = 'docker' docker_ee = false docker_ee_key_id = :undef docker_ee_key_source = :undef docker_ee_repos = 'stable' docker_ee_source_location = :undef docker_ee_start_command = 'dockerd' docker_engine_package_name = 'docker-engine' docker_engine_start_command = 'docker daemon' docker_group_default = 'docker' docker_msft_provider_version = :undef package_ensure = 'present' execdriver = :undef fixed_cidr = :undef icc = :undef ip_forward = true ip_masq = true iptables = true ipv6 = false ipv6_cidr = :undef labels = [] log_driver = :undef log_level = :undef log_opt = [] machine_version = '0.16.1' manage_package = true manage_service = true mtu = :undef no_proxy = :undef nuget_package_provider_version = :undef os_lc = _facts[:os]['name'] overlay2_override_kernel_check = false package_source = :undef proxy = :undef registry_mirror = :undef root_dir = :undef selinux_enabled = :undef service_enable = true service_name_default = 'docker' service_state = 'running' socket_bind = 'unix:///var/run/docker.sock' socket_group_default = 'docker' storage_auto_extend_pool = :undef storage_chunk_size = :undef storage_config_template = 'docker/etc/sysconfig/docker-storage.erb' storage_data_size = :undef storage_devs = :undef storage_driver = :undef storage_growpart = :undef storage_min_data_size = :undef storage_pool_autoextend_percent = :undef storage_pool_autoextend_threshold = :undef storage_root_size = :undef storage_vg = :undef tcp_bind = :undef tls_enable = false tls_verify = true tmp_dir = '/tmp/' tmp_dir_config = true version = :undef if _facts[:os]['family'] == 'windows' compose_install_path = "#{_facts['docker_program_files_path']}/Docker" compose_version = '1.21.2' docker_ee_package_name = 'Docker' machine_install_path = "#{_facts['docker_program_files_path']}/Docker" tls_cacert = "#{_facts['docker_program_data_path']}/docker/certs.d/ca.pem" tls_cert = "#{_facts['docker_program_data_path']}/docker/certs.d/server-cert.pem" tls_key = "#{_facts['docker_program_data_path']}/docker/certs.d/server-key.pem" else compose_install_path = '/usr/local/bin' compose_version = '1.9.0' docker_ee_package_name = 'docker-ee' machine_install_path = '/usr/local/bin' tls_cacert = '/etc/docker/tls/ca.pem' tls_cert = '/etc/docker/tls/cert.pem' tls_key = '/etc/docker/tls/key.pem' end case _facts[:os]['family'] when 'Debian' case _facts[:os]['name'] when 'Ubuntu' package_release = "ubuntu-#{_facts[:os]['distro']['codename']}" if _facts[:os]['release']['full'] != '14.04' service_after_override = :undef service_config_template = 'docker/etc/sysconfig/docker.systemd.erb' service_hasrestart = true service_hasstatus = true service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb' service_provider = 'systemd' socket_override = false socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' storage_config = '/etc/default/docker-storage' else service_after_override = :undef service_config_template = 'docker/etc/default/docker.erb' service_hasrestart = false service_hasstatus = true service_overrides_template = :undef service_provider = 'upstart' socket_override = false socket_overrides_template = :undef storage_config = :undef end else package_release = "debian-#{_facts[:os]['distro']['codename']}" service_after_override = :undef service_config_template = 'docker/etc/sysconfig/docker.systemd.erb' service_hasrestart = true service_hasstatus = true service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb' service_provider = 'systemd' socket_override = false socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' storage_config = '/etc/default/docker-storage' end apt_source_pin_level = 500 docker_group = docker_group_default pin_upstream_package_source = true repo_opt = :undef service_config = :undef service_name = service_name_default socket_group = socket_group_default storage_setup_file = :undef use_upstream_package_source = true package_ce_key_id = '9DC858229FC7DD38854AE2D88D81803C0EBFCD88' package_ce_key_source = "https://download.docker.com/linux/#{os_lc}/gpg" package_ce_release = _facts[:os]['distro']['codename'] package_ce_source_location = "https://download.docker.com/linux/#{os_lc}" package_ee_key_id = docker_ee_key_id package_ee_key_source = docker_ee_key_source package_ee_package_name = docker_ee_package_name package_ee_release = _facts[:os]['distro']['codename'] package_ee_repos = docker_ee_repos package_ee_source_location = docker_ee_source_location package_key_check_source = :undef package_key_id = '58118E89F3A912897C070ADBF76221572C52609D' package_key_source = 'https://apt.dockerproject.org/gpg' package_source_location = 'http://apt.dockerproject.org/repo' detach_service_in_init = if service_provider == 'systemd' false else true end when 'RedHat' service_after_override = :undef service_config = '/etc/sysconfig/docker' service_config_template = 'docker/etc/sysconfig/docker.systemd.erb' service_hasrestart = true service_hasstatus = true service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-rhel.conf.erb' service_provider = 'systemd' socket_override = false socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' storage_config = '/etc/sysconfig/docker-storage' storage_setup_file = '/etc/sysconfig/docker-storage-setup' use_upstream_package_source = true apt_source_pin_level = :undef detach_service_in_init = false package_ce_key_id = :undef package_ce_key_source = 'https://download.docker.com/linux/centos/gpg' package_ce_release = :undef package_ce_source_location = "https://download.docker.com/linux/centos/#{_facts[:os]['release']['major']}/#{_facts[:os]['architecture']}/#{docker_ce_channel}" package_ee_key_id = docker_ee_key_id package_ee_key_source = docker_ee_key_source package_ee_package_name = docker_ee_package_name package_ee_release = :undef package_ee_repos = docker_ee_repos package_ee_source_location = docker_ee_source_location package_key_check_source = true package_key_id = :undef package_key_source = 'https://yum.dockerproject.org/gpg' package_release = :undef package_source_location = "https://yum.dockerproject.org/repo/main/centos/#{_facts[:os]['release']['major']}" pin_upstream_package_source = :undef service_name = service_name_default if use_upstream_package_source docker_group = docker_group_default socket_group = socket_group_default else docker_group = 'dockerroot' socket_group = 'dockerroot' end # repo_opt to specify install_options for docker package repo_opt = if _facts[:os]['name'] == 'RedHat' '--enablerepo=rhel-7-server-extras-rpms' else :undef end when 'windows' msft_nuget_package_provider_version = nuget_package_provider_version msft_provider_version = docker_msft_provider_version msft_package_version = version service_config_template = 'docker/windows/config/daemon.json.erb' service_config = "#{_facts['docker_program_data_path']}/docker/config/daemon.json" docker_group = 'docker' package_ce_source_location = :undef package_ce_key_source = :undef package_ce_key_id = :undef package_ce_repos = :undef package_ce_release = :undef package_key_id = :undef package_release = :undef package_source_location = :undef package_key_source = :undef package_key_check_source = :undef package_ee_source_location = :undef package_ee_package_name = docker_ee_package_name package_ee_key_source = :undef package_ee_key_id = :undef package_ee_repos = :undef package_ee_release = :undef use_upstream_package_source = :undef pin_upstream_package_source = :undef apt_source_pin_level = :undef socket_group = :undef service_name = service_name_default repo_opt = :undef storage_config = :undef storage_setup_file = :undef service_provider = :undef service_overrides_template = :undef socket_overrides_template = :undef socket_override = false service_after_override = :undef service_hasstatus = :undef service_hasrestart = :undef detach_service_in_init = true when 'Suse' docker_group = docker_group_default socket_group = socket_group_default package_key_source = :undef package_key_check_source = :undef package_source_location = :undef package_key_id = :undef package_repos = :undef package_release = :undef package_ce_key_source = :undef package_ce_source_location = :undef package_ce_key_id = :undef package_ce_repos = :undef package_ce_release = :undef package_ee_source_location = :undef package_ee_key_source = :undef package_ee_key_id = :undef package_ee_release = :undef package_ee_repos = :undef package_ee_package_name = :undef use_upstream_package_source = true service_overrides_template = :undef socket_overrides_template = :undef socket_override = false service_after_override = :undef service_hasstatus = :undef service_hasrestart = :undef service_provider = 'systemd' package_name = docker_ce_package_name service_name = service_name_default detach_service_in_init = true repo_opt = :undef nowarn_kernel = false service_config = :undef storage_config = :undef storage_setup_file = :undef service_config_template = :undef pin_upstream_package_source = :undef apt_source_pin_level = :undef else docker_group = docker_group_default socket_group = socket_group_default package_key_source = :undef package_key_check_source = :undef package_source_location = :undef package_key_id = :undef package_repos = :undef package_release = :undef package_ce_key_source = :undef package_ce_source_location = :undef package_ce_key_id = :undef package_ce_repos = :undef package_ce_release = :undef package_ee_source_location = :undef package_ee_key_source = :undef package_ee_key_id = :undef package_ee_release = :undef package_ee_repos = :undef package_ee_package_name = :undef use_upstream_package_source = true service_overrides_template = :undef socket_overrides_template = :undef socket_override = false service_after_override = :undef service_hasstatus = :undef service_hasrestart = :undef service_provider = :undef package_name = docker_ce_package_name service_name = service_name_default detach_service_in_init = true repo_opt = :undef nowarn_kernel = false service_config = :undef storage_config = :undef storage_setup_file = :undef service_config_template = :undef pin_upstream_package_source = :undef apt_source_pin_level = :undef end dependent_packages = ['docker-ce-cli', 'containerd.io'] prerequired_packages = case _facts[:os]['family'] when 'Debian' case _facts[:os]['name'] when 'Debian' ['cgroupfs-mount'] when 'Ubuntu' ['cgroup-lite', 'apparmor'] else [] end when 'RedHat' ['device-mapper'] else [] end { 'apt_source_pin_level' => apt_source_pin_level, 'bip' => bip, 'bridge' => bridge, 'compose_base_url' => compose_base_url, 'compose_install_path' => compose_install_path, 'compose_symlink_name' => compose_symlink_name, 'compose_version' => compose_version, 'curl_ensure' => curl_ensure, 'default_gateway' => default_gateway, 'default_gateway_ipv6' => default_gateway_ipv6, 'dependent_packages' => dependent_packages, 'detach_service_in_init' => detach_service_in_init, 'dm_basesize' => dm_basesize, 'dm_blkdiscard' => dm_blkdiscard, 'dm_blocksize' => dm_blocksize, 'dm_datadev' => dm_datadev, 'dm_fs' => dm_fs, 'dm_loopdatasize' => dm_loopdatasize, 'dm_loopmetadatasize' => dm_loopmetadatasize, 'dm_metadatadev' => dm_metadatadev, 'dm_mkfsarg' => dm_mkfsarg, 'dm_mountopt' => dm_mountopt, 'dm_override_udev_sync_check' => dm_override_udev_sync_check, 'dm_thinpooldev' => dm_thinpooldev, 'dm_use_deferred_deletion' => dm_use_deferred_deletion, 'dm_use_deferred_removal' => dm_use_deferred_removal, 'dns' => dns, 'dns_search' => dns_search, 'docker_ce_channel' => docker_ce_channel, 'docker_ce_package_name' => docker_ce_package_name, 'docker_ce_start_command' => docker_ce_start_command, 'docker_command' => docker_command, 'docker_ee' => docker_ee, 'docker_ee_key_id' => docker_ee_key_id, 'docker_ee_key_source' => docker_ee_key_source, 'docker_ee_package_name' => docker_ee_package_name, 'docker_ee_repos' => docker_ee_repos, 'docker_ee_source_location' => docker_ee_source_location, 'docker_ee_start_command' => docker_ee_start_command, 'docker_engine_package_name' => docker_engine_package_name, 'docker_engine_start_command' => docker_engine_start_command, 'docker_group' => docker_group, 'docker_group_default' => docker_group_default, 'docker_msft_provider_version' => docker_msft_provider_version, 'execdriver' => execdriver, 'fixed_cidr' => fixed_cidr, 'icc' => icc, 'ip_forward' => ip_forward, 'ip_masq' => ip_masq, 'iptables' => iptables, 'ipv6' => ipv6, 'ipv6_cidr' => ipv6_cidr, 'labels' => labels, 'log_driver' => log_driver, 'log_level' => log_level, 'log_opt' => log_opt, 'machine_install_path' => machine_install_path, 'machine_version' => machine_version, 'manage_package' => manage_package, 'manage_service' => manage_service, 'msft_nuget_package_provider_version' => msft_nuget_package_provider_version, 'msft_package_version' => msft_package_version, 'msft_provider_version' => msft_provider_version, 'mtu' => mtu, 'no_proxy' => no_proxy, 'nowarn_kernel' => nowarn_kernel, 'nuget_package_provider_version' => nuget_package_provider_version, 'os_lc' => os_lc, 'overlay2_override_kernel_check' => overlay2_override_kernel_check, 'package_ce_key_id' => package_ce_key_id, 'package_ce_key_source' => package_ce_key_source, 'package_ce_release' => package_ce_release, 'package_ce_repos' => package_ce_repos, 'package_ce_source_location' => package_ce_source_location, 'package_ee_key_id' => package_ee_key_id, 'package_ee_key_source' => package_ee_key_source, 'package_ee_package_name' => package_ee_package_name, 'package_ee_release' => package_ee_release, 'package_ee_repos' => package_ee_repos, 'package_ee_source_location' => package_ee_source_location, 'package_ensure' => package_ensure, 'package_key_check_source' => package_key_check_source, 'package_key_id' => package_key_id, 'package_key_source' => package_key_source, 'package_name' => package_name, 'package_release' => package_release, 'package_repos' => package_repos, 'package_source' => package_source, 'package_source_location' => package_source_location, 'pin_upstream_package_source' => pin_upstream_package_source, 'prerequired_packages' => prerequired_packages, 'proxy' => proxy, 'registry_mirror' => registry_mirror, 'repo_opt' => repo_opt, 'root_dir' => root_dir, 'selinux_enabled' => selinux_enabled, 'service_after_override' => service_after_override, 'service_config' => service_config, 'service_config_template' => service_config_template, 'service_enable' => service_enable, 'service_hasrestart' => service_hasrestart, 'service_hasstatus' => service_hasstatus, 'service_name' => service_name, 'service_name_default' => service_name_default, 'service_overrides_template' => service_overrides_template, 'service_provider' => service_provider, 'service_state' => service_state, 'socket_bind' => socket_bind, 'socket_group' => socket_group, 'socket_group_default' => socket_group_default, 'socket_override' => socket_override, 'socket_overrides_template' => socket_overrides_template, 'storage_auto_extend_pool' => storage_auto_extend_pool, 'storage_chunk_size' => storage_chunk_size, 'storage_config' => storage_config, 'storage_config_template' => storage_config_template, 'storage_data_size' => storage_data_size, 'storage_devs' => storage_devs, 'storage_driver' => storage_driver, 'storage_growpart' => storage_growpart, 'storage_min_data_size' => storage_min_data_size, 'storage_pool_autoextend_threshold' => storage_pool_autoextend_percent, 'storage_pool_autoextend_percent' => storage_pool_autoextend_percent, 'storage_root_size' => storage_root_size, 'storage_setup_file' => storage_setup_file, 'storage_vg' => storage_vg, 'tcp_bind' => tcp_bind, 'tls_cacert' => tls_cacert, 'tls_cert' => tls_cert, 'tls_enable' => tls_enable, 'tls_key' => tls_key, 'tls_verify' => tls_verify, 'tmp_dir' => tmp_dir, 'tmp_dir_config' => tmp_dir_config, 'use_upstream_package_source' => use_upstream_package_source, 'version' => version, } end diff --git a/spec/helper/get_docker_exec_flags.rb b/spec/helper/get_docker_exec_flags.rb index 2c0d863..6fe692a 100644 --- a/spec/helper/get_docker_exec_flags.rb +++ b/spec/helper/get_docker_exec_flags.rb @@ -1,23 +1,25 @@ +# frozen_string_literal: true + def get_docker_exec_flags(args) flags = [] if args['detach'] flags << '--detach=true' end if args['interactive'] flags << '--interactive=true' end if args['tty'] flags << '--tty=true' end unless args['env'].empty? args['env'].each do |namevaluepair| flags << "--env #{namevaluepair}" end end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_plugin_enable_flags.rb b/spec/helper/get_docker_plugin_enable_flags.rb index 9bc4b8a..9fd2166 100644 --- a/spec/helper/get_docker_plugin_enable_flags.rb +++ b/spec/helper/get_docker_plugin_enable_flags.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + def get_docker_plugin_enable_flags(args) flags = [] flags << '--force' if args['force_remove'] == true if args['plugin_alias'] && args['plugin_alias'].to_s != 'undef' flags << "'#{args['plugin_alias']}'" elsif args['plugin_name'] && args['plugin_name'].to_s != 'undef' flags << "'#{args['plugin_name']}'" end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_plugin_install_flags.rb b/spec/helper/get_docker_plugin_install_flags.rb index 6986c5d..fcdd58f 100644 --- a/spec/helper/get_docker_plugin_install_flags.rb +++ b/spec/helper/get_docker_plugin_install_flags.rb @@ -1,16 +1,18 @@ +# frozen_string_literal: true + def get_docker_plugin_install_flags(args) flags = [] flags << "--alias #{args['plugin_alias']}" if args['plugin_alias'] && args['plugin_alias'].to_s != 'undef' flags << '--disable' if args['disable_on_install'] == true flags << '--disable-content-trust' if args['disable_content_trust'] == true flags << '--grant-all-permissions' if args['grant_all_permissions'] == true flags << "'#{args['plugin_name']}'" if args['plugin_name'] && args['plugin_name'].to_s != 'undef' if args['settings'].is_a? Array args['settings'].each do |setting| flags << setting.to_s end end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_plugin_remove_flags.rb b/spec/helper/get_docker_plugin_remove_flags.rb index f97c48b..3bfcf44 100644 --- a/spec/helper/get_docker_plugin_remove_flags.rb +++ b/spec/helper/get_docker_plugin_remove_flags.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + def get_docker_plugin_remove_flags(args) flags = [] flags << '--force' if args['force_remove'] == true flags << "'#{args['plugin_name']}'" if args['plugin_name'] && args['plugin_name'].to_s != 'undef' flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_run_flags.rb b/spec/helper/get_docker_run_flags.rb index f27435d..eaa4519 100644 --- a/spec/helper/get_docker_run_flags.rb +++ b/spec/helper/get_docker_run_flags.rb @@ -1,94 +1,96 @@ +# frozen_string_literal: true + require 'shellwords' def get_docker_run_flags(args) flags = [] if args['username'] flags << "-u '#{args['username'].shellescape}'" end if args['hostname'] flags << "-h '#{args['hostname'].shellescape}'" end if args['restart'] flags << "--restart '#{args['restart']}'" end if args['net'].is_a? String flags << "--net #{args['net']}" end if args['memory_limit'] flags << "-m #{args['memory_limit']}" end cpusets = [args['cpuset']].flatten.compact unless cpusets.empty? value = cpusets.join(',') flags << "--cpuset-cpus=#{value}" end if args['disable_network'] flags << '-n false' end if args['privileged'] flags << '--privileged' end if args['health_check_cmd'] && args['health_check_cmd'].to_s != 'undef' flags << "--health-cmd='#{args['health_check_cmd']}'" end if args['health_check_interval'] && args['health_check_interval'].to_s != 'undef' flags << "--health-interval=#{args['health_check_interval']}s" end if args['tty'] flags << '-t' end if args['read_only'] flags << '--read-only=true' end params_join_char = if args['osfamily'] && args['osfamily'].to_s != 'undef' args['osfamily'].casecmp('windows').zero? ? " `\n" : " \\\n" else " \\\n" end multi_flags = ->(values, fmt) { filtered = [values].flatten.compact filtered.map { |val| (fmt + params_join_char) % val } } [ ['--dns %s', 'dns'], ['--dns-search %s', 'dns_search'], ['--expose=%s', 'expose'], ['--link %s', 'links'], ['--lxc-conf="%s"', 'lxc_conf'], ['--volumes-from %s', 'volumes_from'], ['-e "%s"', 'env'], ['--env-file %s', 'env_file'], ['-p %s', 'ports'], ['-l %s', 'labels'], ['--add-host %s', 'hostentries'], ['-v %s', 'volumes'], ].each do |format, key| values = args[key] new_flags = multi_flags.call(values, format) flags << new_flags end args['extra_params'].each do |param| flags << param if args['param'].to_s != 'undef' end # Some software (inc systemd) will truncate very long lines using glibc's # max line length. Wrap options across multiple lines with '\' to avoid flags.flatten.reject { |val| val.to_s == 'undef' }.join(params_join_char) end diff --git a/spec/helper/get_docker_secrets_flags.rb b/spec/helper/get_docker_secrets_flags.rb index 07ac105..a617362 100644 --- a/spec/helper/get_docker_secrets_flags.rb +++ b/spec/helper/get_docker_secrets_flags.rb @@ -1,31 +1,33 @@ +# frozen_string_literal: true + require 'shellwords' def get_docker_secrets_flags(args) flags = [] if args['ensure'].to_s == 'present' flags << 'create' end if args['secret_name'] && args['secret_name'].to_s != 'undef' flags << "'#{args['secret_name']}'" end if args['secret_path'] && args['secret_path'].to_s != 'undef' flags << "'#{args['secret_path']}'" end multi_flags = ->(values, format) { filtered = [values].flatten.compact filtered.map { |val| format + " \\\n" % val } } [ ['-l %s', 'label'], ].each do |(format, key)| values = args[key] new_flags = multi_flags.call(values, format) flags.concat(new_flags) end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_service_flags.rb b/spec/helper/get_docker_service_flags.rb index 9ee6e47..07b493c 100644 --- a/spec/helper/get_docker_service_flags.rb +++ b/spec/helper/get_docker_service_flags.rb @@ -1,93 +1,93 @@ +# frozen_string_literal: true + require 'shellwords' def get_docker_service_flags(args) flags = [] if args['service_name'] && args['service_name'].to_s != 'undef' flags << "'#{args['service_name']}'" end if args['detach'].to_s != 'false' flags << '--detach' end if args['env'].is_a? Array args['env'].each do |env| flags << "--env #{env}" end end if args['label'].is_a? Array args['label'].each do |label| flags << "--label #{label}" end end if args['mounts'].is_a? Array args['mounts'].each do |mount| flags << "--mount #{mount}" end end if args['networks'].is_a? Array args['networks'].each do |network| flags << "--network #{network}" end end if args['publish'].is_a? Array args['publish'].each do |port| flags << "--publish #{port}" end elsif args['publish'] && args['publish'].to_s != 'undef' flags << "--publish '#{args['publish']}'" end if args['replicas'] && args['replicas'].to_s != 'undef' flags << "--replicas '#{args['replicas']}'" end if args['tty'].to_s != 'false' flags << '--tty' end if args['user'] && args['user'].to_s != 'undef' flags << "--user '#{args['user']}'" end if args['workdir'] && args['workdir'].to_s != 'undef' flags << "--workdir '#{args['workdir']}'" end if args['extra_params'].is_a? Array args['extra_params'].each do |param| flags << param end end if args['host_socket'] && args['host_socket'].to_s != 'undef' flags << "-H '#{args['host_socket']}'" end if args['registry_mirror'].is_a? Array args['registry_mirror'].each do |param| flags << "--registry-mirror='#{param}'" end - else - if args['registry_mirror'] && args['registry_mirror'].to_s != 'undef' - flags << "--registry-mirror='#{args['registry_mirror']}'" - end + elsif args['registry_mirror'] && args['registry_mirror'].to_s != 'undef' + flags << "--registry-mirror='#{args['registry_mirror']}'" end if args['image'] && args['image'].to_s != 'undef' flags << "'#{args['image']}'" end if args['command'].is_a? Array flags << args['command'].join(' ') elsif args['command'] && args['command'].to_s != 'undef' flags << args['command'].to_s end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_stack_flags.rb b/spec/helper/get_docker_stack_flags.rb index b2769d2..2aa873e 100644 --- a/spec/helper/get_docker_stack_flags.rb +++ b/spec/helper/get_docker_stack_flags.rb @@ -1,27 +1,29 @@ +# frozen_string_literal: true + def get_docker_stack_flags(args) flags = [] if args['bundle_file'] && args['bundle_file'].to_s != 'undef' flags << "--bundle-file '#{args['bundle_file']}'" end if args['compose_files'] && args['compose_files'].to_s != 'undef' args['compose_files'].each do |file| flags << "--compose-file '#{file}'" end end if args['resolve_image'] && args['resolve_image'].to_s != 'undef' flags << "--resolve-image '#{args['resolve_image']}'" end if args['prune'] && args['prune'].to_s != 'undef' flags << '--prune' end if args['with_registry_auth'] && args['with_registry_auth'].to_s != 'undef' flags << '--with-registry-auth' end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_swarm_init_flags.rb b/spec/helper/get_docker_swarm_init_flags.rb index a290fc8..f496e5b 100644 --- a/spec/helper/get_docker_swarm_init_flags.rb +++ b/spec/helper/get_docker_swarm_init_flags.rb @@ -1,55 +1,57 @@ +# frozen_string_literal: true + def get_docker_swarm_init_flags(args) flags = [] if args['init'].to_s != 'false' flags << 'init' end if args['advertise_addr'] && args['advertise_addr'].to_s != 'undef' flags << "--advertise-addr '#{args['advertise_addr']}'" end if args['autolock'].to_s != 'false' flags << '--autolock' end if args['cert_expiry'] && args['cert_expiry'].to_s != 'undef' flags << "--cert-expiry '#{args['cert_expiry']}'" end if args['default_addr_pool'].is_a? Array args['default_addr_pool'].each do |default_addr_pool| flags << "--default-addr-pool #{default_addr_pool}" end end if args['default_addr_pool_mask_length'] && args['default_addr_pool_mask_length'].to_s != 'undef' flags << "--default-addr-pool-mask-length '#{args['default_addr_pool_mask_length']}'" end if args['dispatcher_heartbeat'] && args['dispatcher_heartbeat'].to_s != 'undef' flags << "--dispatcher-heartbeat '#{args['dispatcher_heartbeat']}'" end if args['external_ca'] && args['external_ca'].to_s != 'undef' flags << "--external-ca '#{args['external_ca']}'" end if args['force_new_cluster'].to_s != 'false' flags << '--force-new-cluster' end if args['listen_addr'] && args['listen_addr'].to_s != 'undef' flags << "--listen-addr '#{args['listen_addr']}'" end if args['max_snapshots'] && args['max_snapshots'].to_s != 'undef' flags << "--max-snapshots '#{args['max_snapshots']}'" end if args['snapshot_interval'] && args['snapshot_interval'].to_s != 'undef' flags << "--snapshot-interval '#{args['snapshot_interval']}'" end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_swarm_join_flags.rb b/spec/helper/get_docker_swarm_join_flags.rb index cbb00fd..4794eaa 100644 --- a/spec/helper/get_docker_swarm_join_flags.rb +++ b/spec/helper/get_docker_swarm_join_flags.rb @@ -1,21 +1,23 @@ +# frozen_string_literal: true + def get_docker_swarm_join_flags(args) flags = [] if args['join'].to_s != 'false' flags << 'join' end if args['advertise_addr'] && args['advertise_addr'].to_s != 'undef' flags << "--advertise-addr '#{args['advertise_addr']}'" end if args['listen_addr'] && args['listen_addr'].to_s != 'undef' flags << "--listen-addr \"#{args['listen_addr']}\"" end if args['token'] && args['token'].to_s != 'undef' flags << "--token '#{args['token']}'" end flags.flatten.join(' ') end diff --git a/spec/helper/get_values_init.rb b/spec/helper/get_values_init.rb index bd2a64c..42e75a0 100644 --- a/spec/helper/get_values_init.rb +++ b/spec/helper/get_values_init.rb @@ -1,75 +1,77 @@ +# frozen_string_literal: true + def get_values_init(_params, _facts) if _params['version'] == :undef || _params['version'] !~ %r{^(17[.][0-1][0-9][.][0-1](~|-|\.)ce|1.\d+)} if _params['docker_ee'] package_location = _params['docker_ee_source_location'] package_key_source = _params['docker_ee_key_source'] package_key_check_source = true package_key = _params['docker_ee_key_id'] package_repos = _params['docker_ee_repos'] release = _params['docker_ee_release'] docker_start_command = _params['docker_ee_start_command'] docker_package_name = _params['docker_ee_package_name'] else case _facts[:os]['family'] when 'Debian' package_location = _params['docker_ce_source_location'] package_key_source = _params['docker_ce_key_source'] package_key = _params['docker_ce_key_id'] package_repos = _params['docker_ce_channel'] release = _params['docker_ce_release'] when 'RedHat' package_location = _params['docker_ce_source_location'] package_key_source = _params['docker_ce_key_source'] package_key_check_source = true # when 'windows' # fail(translate('This module only work for Docker Enterprise Edition on Windows.')) else package_location = _params['docker_package_location'] package_key_source = _params['docker_package_key_source'] package_key_check_source = _params['docker_package_key_check_source'] end docker_start_command = _params['docker_ce_start_command'] docker_package_name = _params['docker_ce_package_name'] end else case _facts[:os]['family'] when 'Debian' package_location = _params['docker_package_location'] package_key_source = _params['docker_package_key_source'] package_key_check_source = _params['docker_package_key_check_source'] package_key = _params['docker_package_key_id'] package_repos = 'main' release = _params['docker_package_release'] when 'RedHat' package_location = _params['docker_package_location'] package_key_source = _params['docker_package_key_source'] package_key_check_source = _params['docker_package_key_check_source'] else package_location = _params['docker_package_location'] package_key_source = _params['docker_package_key_source'] package_key_check_source = _params['docker_package_key_check_source'] end docker_start_command = _params['docker_engine_start_command'] docker_package_name = _params['docker_engine_package_name'] end root_dir_flag = if _params['version'] != :undef && _params['version'] =~ %r{^(17[.]0[0-4]|1.\d+)} '-g' else '--data-root' end { 'docker_package_name' => docker_package_name, 'docker_start_command' => docker_start_command, 'package_key' => package_key, 'package_key_check_source' => package_key_check_source, 'package_key_source' => package_key_source, 'package_location' => package_location, 'package_repos' => package_repos, 'release' => release, 'root_dir_flag' => root_dir_flag, } end diff --git a/spec/helper/pw_hash.rb b/spec/helper/pw_hash.rb index daed8b1..b4a5c9c 100644 --- a/spec/helper/pw_hash.rb +++ b/spec/helper/pw_hash.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + def pw_hash(_foo, _bar, _asdf) '$6$foobar$v8j5roVj0D8t.Ipwvk0RrMHiZfZRoBMeVQDywxUKFtdRI2EFRi2X6tbOigjpOsa9UDVzgIBtcl2ZEGcM.jnZZ.' end diff --git a/spec/helper/windows_facts.rb b/spec/helper/windows_facts.rb index bff7be0..b32359b 100644 --- a/spec/helper/windows_facts.rb +++ b/spec/helper/windows_facts.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + def windows_facts { 'docker_program_data_path' => 'C:/ProgramData', 'docker_program_files_path' => 'C:/Program Files', 'docker_systemroot' => 'C:/Windows', 'docker_user_temp_path' => 'C:/Users/Administrator/AppData/Local/Temp', } end diff --git a/spec/shared_examples.rb b/spec/shared_examples.rb index 96fb1f3..44e5143 100644 --- a/spec/shared_examples.rb +++ b/spec/shared_examples.rb @@ -1,32 +1,34 @@ +# frozen_string_literal: true + require 'helper/get_defaults' require 'helper/get_docker_exec_flags' require 'helper/get_docker_plugin_enable_flags' require 'helper/get_docker_plugin_install_flags' require 'helper/get_docker_plugin_remove_flags' require 'helper/get_docker_run_flags' require 'helper/get_docker_secrets_flags' require 'helper/get_docker_service_flags' require 'helper/get_docker_stack_flags' require 'helper/get_docker_swarm_init_flags' require 'helper/get_docker_swarm_join_flags' require 'helper/get_values_init' require 'helper/pw_hash' require 'helper/windows_facts' require 'shared_examples/compose' require 'shared_examples/config' require 'shared_examples/exec' require 'shared_examples/image' require 'shared_examples/install' require 'shared_examples/machine' require 'shared_examples/params' require 'shared_examples/plugin' require 'shared_examples/registry' require 'shared_examples/repos' require 'shared_examples/run' require 'shared_examples/secrets' require 'shared_examples/service' require 'shared_examples/services' require 'shared_examples/stack' require 'shared_examples/swarm' require 'shared_examples/system_user' diff --git a/spec/shared_examples/compose.rb b/spec/shared_examples/compose.rb index 299cdd2..bd4c395 100644 --- a/spec/shared_examples/compose.rb +++ b/spec/shared_examples/compose.rb @@ -1,96 +1,98 @@ +# frozen_string_literal: true + shared_examples 'compose' do |_params, _facts| ensure_value = _params['ensure'] version = _params['version'] install_path = _params['install_path'] symlink_name = _params['symlink_name'] proxy = _params['proxy'] base_url = _params['base_url'] raw_url = _params['raw_url'] curl_ensure = _params['curl_ensure'] if _facts[:os]['family'] == 'windows' file_extension = '.exe' file_owner = 'Administrator' else file_extension = '' file_owner = 'root' end docker_compose_location = "#{install_path}/#{symlink_name}#{file_extension}" docker_compose_location_versioned = "#{install_path}/docker-compose-#{version}#{file_extension}" if ensure_value == 'present' docker_compose_url = if raw_url != :undef raw_url else "#{base_url}/#{version}/docker-compose-#{_facts[:kernel]}-x86_64#{file_extension}" end proxy_opt = if proxy != :undef "--proxy #{proxy}" else '' end if _facts[:os]['family'] == 'windows' docker_download_command = "if (Invoke-WebRequest #{docker_compose_url} #{proxy_opt} -UseBasicParsing -OutFile \"#{docker_compose_location_versioned}\") { exit 0 } else { exit 1 }" it { is_expected.to contain_exec("Install Docker Compose #{version}").with( # 'command' => template('docker/windows/download_docker_compose.ps1.erb'), 'provider' => 'powershell', 'creates' => docker_compose_location_versioned, ) is_expected.to contain_file(docker_compose_location).with( 'ensure' => 'link', 'target' => docker_compose_location_versioned, ).that_requires( "Exec[Install Docker Compose #{version}]", ) } else if curl_ensure it { is_expected.to contain_package('curl') } end it { is_expected.to contain_exec("Install Docker Compose #{version}").with( 'path' => '/usr/bin/', 'cwd' => '/tmp', 'command' => "curl -s -S -L #{proxy_opt} #{docker_compose_url} -o #{docker_compose_location_versioned}", 'creates' => docker_compose_location_versioned, ).that_requires( 'Package[curl]', ) is_expected.to contain_file(docker_compose_location_versioned).with( 'owner' => file_owner, 'mode' => '0755', ).that_requires( "Exec[Install Docker Compose #{version}]", ) is_expected.to contain_file(docker_compose_location).with( 'ensure' => 'link', 'target' => docker_compose_location_versioned, ).that_requires( "File[#{docker_compose_location_versioned}]", ) } end else it { is_expected.to contain_file(docker_compose_location_versioned).with( 'ensure' => 'absent', ) is_expected.to contain_file(docker_compose_location).with( 'ensure' => 'absent', ) } end end diff --git a/spec/shared_examples/config.rb b/spec/shared_examples/config.rb index 4ac62a5..7501b1e 100644 --- a/spec/shared_examples/config.rb +++ b/spec/shared_examples/config.rb @@ -1,23 +1,25 @@ +# frozen_string_literal: true + shared_examples 'config' do |_params, _facts| docker_users = _params['docker_users'] it { is_expected.to contain_class('docker::config') } unless docker_users.empty? docker_users.each do |user| - if _facts[:os]['family'] =~ %r{windows} + if %r{windows}.match?(_facts[:os]['family']) it { is_expected.to contain_docker__windows_account(user) } else it { is_expected.to contain_docker__system_user(user) } include_examples 'system_user', user, _params['docker_group'] end end end end diff --git a/spec/shared_examples/exec.rb b/spec/shared_examples/exec.rb index 7ada1df..2889d00 100644 --- a/spec/shared_examples/exec.rb +++ b/spec/shared_examples/exec.rb @@ -1,72 +1,74 @@ +# frozen_string_literal: true + shared_examples 'exec' do |_params, _facts, _defaults| command = _params['command'] container = _params['container'] detach = _params['detach'] docker_command = _defaults['docker_command'] env = _params['env'] interactive = _params['interactive'] onlyif = _params['onlyif'] refreshonly = _params['refreshonly'] sanitise_name = _params['sanitise_name'] tty = _params['tty'] unless_value = _params['unless'] if _facts[:os]['family'] == 'windows' exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/" exec_timeout = 3000 exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' else exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil end docker_exec_flags = get_docker_exec_flags( 'detach' => detach, 'interactive' => interactive, 'tty' => tty, 'env' => env, ) sanitised_container = if sanitise_name container.gsub('[^0-9A-Za-z.\-_]', '-') else container end exec = "#{docker_command} exec #{docker_exec_flags} #{sanitised_container} #{command}" unless_command = case unless_value when :undef nil when '' nil else "#{docker_command} exec #{docker_exec_flags} #{sanitised_container} #{unless_value}" end onlyif_command = case onlyif when :undef nil when '' nil when 'running' "#{docker_command} ps --no-trunc --format='table {{.Names}}' | grep '^#{sanitised_container}$'" else onlyif end it { is_expected.to contain_exec(exec).with( 'environment' => exec_environment, 'onlyif' => onlyif_command, 'path' => exec_path, 'refreshonly' => refreshonly, 'timeout' => exec_timeout, 'provider' => exec_provider, 'unless' => unless_command, ) } end diff --git a/spec/shared_examples/image.rb b/spec/shared_examples/image.rb index 059eb9a..95cc4cb 100644 --- a/spec/shared_examples/image.rb +++ b/spec/shared_examples/image.rb @@ -1,146 +1,146 @@ +# frozen_string_literal: true + shared_examples 'image' do |_params, _facts, _defaults| docker_command = _defaults['docker_command'] docker_dir = _params['docker_dir'] docker_file = _params['docker_file'] docker_tar = _params['docker_tar'] ensure_value = _params['ensure'] force = _params['force'] image = _params['image'] image_digest = _params['image_digest'] image_tag = _params['image_tag'] if _facts[:os]['family'] == 'windows' update_docker_image_template = 'docker/windows/update_docker_image.ps1.erb' update_docker_image_path = "#{_facts['docker_user_temp_path']}/update_docker_image.ps1" exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/" exec_timeout = 3000 update_docker_image_owner = nil exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' else update_docker_image_template = 'docker/update_docker_image.sh.erb' update_docker_image_path = '/usr/local/bin/update_docker_image.sh' update_docker_image_owner = 'root' exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil end it { is_expected.to contain_file(update_docker_image_path).with( 'ensure' => 'present', 'owner' => update_docker_image_owner, 'group' => update_docker_image_owner, 'mode' => '0555', # 'content' => template($update_docker_image_template), ) } image_force = if force '-f ' else '' end if image_tag != :undef image_arg = "#{image}:#{image_tag}" image_remove = "#{docker_command} rmi #{image_force}#{image}:#{image_tag}" image_find = "#{docker_command} images -q #{image}:#{image_tag}" elsif image_digest != :undef image_arg = "#{image}@#{image_digest}" image_remove = "#{docker_command} rmi #{image_force}#{image}:#{image_digest}" image_find = "#{docker_command} images -q #{image}@#{image_digest}" else image_arg = image image_remove = "#{docker_command} rmi #{image_force}#{image}" image_find = "#{docker_command} images -q #{image}" end _image_find = if _facts[:os]['family'] == 'windows' "If (-not (#{image_find}) ) { Exit 1 }" else "#{image_find} | grep ." end image_install = if docker_dir != :undef && docker_file != :undef "#{docker_command} build -t #{image_arg} -f #{docker_file} #{docker_dir}" elsif docker_dir != :undef "#{docker_command} build -t #{image_arg} #{docker_dir}" elsif docker_file != :undef if _facts[:os]['family'] == 'windows' "Get-Content #{docker_file} -Raw | #{docker_command} build -t #{image_arg} -" else "#{docker_command} build -t #{image_arg} - < #{docker_file}" end elsif docker_tar != :undef "#{docker_command} load -i #{docker_tar}" + elsif _facts[:os]['family'] == 'windows' + "& #{update_docker_image_path} -DockerImage #{image_arg}" else - if _facts[:os]['family'] == 'windows' - "& #{update_docker_image_path} -DockerImage #{image_arg}" - else - "#{update_docker_image_path} #{image_arg}" - end + "#{update_docker_image_path} #{image_arg}" end if ensure_value == 'absent' it { is_expected.to contain_exec(image_remove).with( 'path' => exec_path, 'environment' => exec_environment, 'onlyif' => _image_find, 'provider' => exec_provider, 'timeout' => exec_timeout, 'logoutput' => true, ) } elsif ensure_value == 'latest' || image_tag == 'latest' it { is_expected.to contain_notify("Check if image #{image_arg} is in-sync").with( 'noop' => false, ).that_notifies( "Exec[#{image_install}]", ) is_expected.to contain_exec(image_install).with( 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'returns' => ['0', '2'], 'provider' => exec_provider, 'logoutput' => true, ).that_requires( "File[#{update_docker_image_path}]", ).that_notifies( "Exec[echo 'Update of #{image_arg} complete']", ) is_expected.to contain_exec("echo 'Update of #{image_arg} complete'").with( 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'provider' => exec_provider, 'logoutput' => true, 'refreshonly' => true, ).that_requires( "File[#{update_docker_image_path}]", ) } elsif ensure_value == 'present' it { is_expected.to contain_exec(image_install).with( 'unless' => _image_find, 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'returns' => ['0', '2'], 'provider' => exec_provider, 'logoutput' => true, ).that_requires( "File[#{update_docker_image_path}]", ) } end end diff --git a/spec/shared_examples/install.rb b/spec/shared_examples/install.rb index 2ea4102..e7b87f7 100644 --- a/spec/shared_examples/install.rb +++ b/spec/shared_examples/install.rb @@ -1,156 +1,154 @@ +# frozen_string_literal: true + shared_examples 'install' do |_params, _facts| values = get_values_init(_params, _facts) ensure_value = if _params['version'] != :undef && _params['ensure'] != 'absent' _params['version'] else _params['ensure'] end if _params['manage_package'] docker_hash = if _params['repo_opt'] == :undef {} else { 'install_options' => _params['repo_opt'] } end if _params['package_source'] != :undef it { is_expected.to contain_class('docker::install') } provider_value = case _facts[:os]['family'] when 'Debian' 'dpkg' when 'RedHat' 'yum' else :undef end case _params['package_source'] when 'docker-engine' it { is_expected.to contain_package('docker').with( { 'ensure' => ensure_value, 'provider' => provider_value, 'source' => _params['package_source'], 'name' => _params['docker_engine_package_name'], }.merge(docker_hash), ) } when 'docker-ce' it { is_expected.to contain_package('docker').with( { 'ensure' => ensure_value, 'provider' => provider_value, 'source' => _params['package_source'], 'name' => _params['docker_ce_package_name'], }.merge(docker_hash), ) } end + elsif _facts[:os]['family'] != 'windows' + it { + is_expected.to contain_package('docker').with( + 'ensure' => ensure_value, + 'name' => values['docker_package_name'], + ) + } + + if ensure_value == 'absent' + _params['dependent_packages'].each do |dependent_package| + it { + is_expected.to contain_package(dependent_package).with( + 'ensure' => ensure_value, + ) + } + end + end + elsif ensure_value == 'absent' + it { + if _params['version'] != :undef + is_expected.to contain_exec('remove-docker-package').with( + 'command' => %r{-RequiredVersion #{_params['version']}}, + ) + end + + is_expected.to contain_exec('remove-docker-package').with( + 'command' => %r{\$package=Uninstall-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName -Force}, + 'provider' => 'powershell', + 'unless' => %r{\$package=Get-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName -ErrorAction Ignore}, + 'logoutput' => true, + ) + } else - if _facts[:os]['family'] != 'windows' + if _params['package_location'] it { - is_expected.to contain_package('docker').with( - 'ensure' => ensure_value, - 'name' => values['docker_package_name'], + is_expected.to contain_exec('install-docker-package').with( + 'command' => %r{Invoke-webrequest -UseBasicparsing -Outfile \$dockerLocation "#{_params['docker_download_url']}"}, + 'provider' => 'powershell', + 'unless' => %r{\$webRequest = \[System.Net.HttpWebRequest\]::Create("#{_params['docker_download_url']}");}, + 'logoutput' => true, + ).that_notifies( + 'Exec[service-restart-on-failure]', ) } - - if ensure_value == 'absent' - _params['dependent_packages'].each do |dependent_package| - it { - is_expected.to contain_package(dependent_package).with( - 'ensure' => ensure_value, - ) - } - end - end else - if ensure_value == 'absent' - it { - if _params['version'] != :undef - is_expected.to contain_exec('remove-docker-package').with( - 'command' => %r{-RequiredVersion #{_params['version']}}, - ) - end - - is_expected.to contain_exec('remove-docker-package').with( - 'command' => %r{\$package=Uninstall-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName -Force}, - 'provider' => 'powershell', - 'unless' => %r{\$package=Get-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName -ErrorAction Ignore}, - 'logoutput' => true, + it { + if _params['nuget_package_provider_version'] != :undef + is_expected. to contain_exec( + 'install-docker-package', + ).with_command( + %r{-RequiredVersion #{_params['nuget_package_provider_version']}}, + ).with_unless( + %r{\$module.Version.ToString\(\) -ne "#{_params['nuget_package_provider_version']}"}, ) - } - else - if _params['package_location'] - it { - is_expected.to contain_exec('install-docker-package').with( - 'command' => %r{Invoke-webrequest -UseBasicparsing -Outfile \$dockerLocation "#{_params['docker_download_url']}"}, - 'provider' => 'powershell', - 'unless' => %r{\$webRequest = \[System.Net.HttpWebRequest\]::Create("#{_params['docker_download_url']}");}, - 'logoutput' => true, - ).that_notifies( - 'Exec[service-restart-on-failure]', - ) - } - else - it { - if _params['nuget_package_provider_version'] != :undef - is_expected. to contain_exec( - 'install-docker-package', - ).with_command( - %r{-RequiredVersion #{_params['nuget_package_provider_version']}}, - ).with_unless( - %r{\$module.Version.ToString\(\) -ne "#{_params['nuget_package_provider_version']}"}, - ) - end - - if _params['docker_msft_provider_version'] != :undef - is_expected. to contain_exec( - 'install-docker-package', - ).with_command( - %r{-RequiredVersion #{_params['docker_msft_provider_version']}}, - ).with_unless( - %r{\$provider.Version.ToString\(\) -ne "#{_params['docker_msft_provider_version']}"}, - ) - end - - if _params['version'] != :undef - is_expected.to contain_exec( - 'install-docker-package', - ).with_command( - %r{-RequiredVersion #{_params['version']}}, - ).with_unless( - %r{\$package.Version.ToString\(\) -notmatch "#{_params['version']}"}, - ) - end + end - is_expected.to contain_exec('install-docker-package').with( - 'command' => %r{\$package=Install-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName -Force}, - 'provider' => 'powershell', - 'unless' => %r{\$package=Get-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName}, - 'logoutput' => true, - ).that_notifies( - 'Exec[service-restart-on-failure]', - ) - } + if _params['docker_msft_provider_version'] != :undef + is_expected. to contain_exec( + 'install-docker-package', + ).with_command( + %r{-RequiredVersion #{_params['docker_msft_provider_version']}}, + ).with_unless( + %r{\$provider.Version.ToString\(\) -ne "#{_params['docker_msft_provider_version']}"}, + ) end - it { - is_expected.to contain_exec('service-restart-on-failure').with( - 'command' => 'SC.exe failure Docker reset= 432000 actions= restart/30000/restart/60000/restart/60000', - 'refreshonly' => true, - 'logoutput' => true, - 'provider' => 'powershell', + if _params['version'] != :undef + is_expected.to contain_exec( + 'install-docker-package', + ).with_command( + %r{-RequiredVersion #{_params['version']}}, + ).with_unless( + %r{\$package.Version.ToString\(\) -notmatch "#{_params['version']}"}, ) - } - end + end + + is_expected.to contain_exec('install-docker-package').with( + 'command' => %r{\$package=Install-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName -Force}, + 'provider' => 'powershell', + 'unless' => %r{\$package=Get-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName}, + 'logoutput' => true, + ).that_notifies( + 'Exec[service-restart-on-failure]', + ) + } end + + it { + is_expected.to contain_exec('service-restart-on-failure').with( + 'command' => 'SC.exe failure Docker reset= 432000 actions= restart/30000/restart/60000/restart/60000', + 'refreshonly' => true, + 'logoutput' => true, + 'provider' => 'powershell', + ) + } end end end diff --git a/spec/shared_examples/machine.rb b/spec/shared_examples/machine.rb index 693c5b7..3541d5d 100644 --- a/spec/shared_examples/machine.rb +++ b/spec/shared_examples/machine.rb @@ -1,93 +1,95 @@ +# frozen_string_literal: true + shared_examples 'machine' do |_params, _facts, _defaults| ensure_value = _params['ensure'] version = _params['version'] install_path = _params['install_path'] proxy = _params['proxy'] url = _params['url'] curl_ensure = _params['curl_ensure'] if _facts[:os]['family'] == 'windows' file_extension = '.exe' file_owner = 'Administrator' else file_extension = '' file_owner = 'root' end docker_machine_location = "#{install_path}/docker-machine#{file_extension}" docker_machine_location_versioned = "#{install_path}/docker-machine-#{version}#{file_extension}" if ensure_value == 'present' docker_machine_url = case url when :undef "https://github.com/docker/machine/releases/download/v#{version}/docker-machine-#{_facts[:kernel]}-x86_64#{file_extension}" else url end proxy_opt = case proxy when :undef '' else "--proxy #{proxy}" end if _facts[:os]['family'] == 'windows' docker_download_command = "if (Invoke-WebRequest #{docker_machine_url} #{proxy_opt} -UseBasicParsing -OutFile \"#{docker_machine_location_versioned}\") { exit 0 } else { exit 1 }" it { is_expected.to contain_exec("Install Docker Machine #{version}").with( # 'command' => template('docker/windows/download_docker_machine.ps1.erb'), 'provider' => 'powershell', 'creates' => docker_machine_location_versioned, ) is_expected.to contain_file(docker_machine_location).with( 'ensure' => 'link', 'target' => docker_machine_location_versioned, ).that_requires( "Exec[Install Docker Machine #{version}]", ) } else if curl_ensure it { is_expected.to contain_package('curl') } end it { is_expected.to contain_exec("Install Docker Machine #{version}").with( 'path' => '/usr/bin/', 'cwd' => '/tmp', 'command' => "curl -s -S -L #{proxy_opt} #{docker_machine_url} -o #{docker_machine_location_versioned}", 'creates' => docker_machine_location_versioned, ).that_requires( 'Package[curl]', ) is_expected.to contain_file(docker_machine_location_versioned).with( 'owner' => file_owner, 'mode' => '0755', ).that_requires( "Exec[Install Docker Machine #{version}]", ) is_expected.to contain_file(docker_machine_location).with( 'ensure' => 'link', 'target' => docker_machine_location_versioned, ).that_requires( "File[#{docker_machine_location_versioned}]", ) } end else is_expected.to contain_file(docker_machine_location_versioned).with( 'ensure' => 'absent', ) is_expected.to contain_file(docker_machine_location).with( 'ensure' => 'absent', ) end end diff --git a/spec/shared_examples/params.rb b/spec/shared_examples/params.rb index 8156a66..8457124 100644 --- a/spec/shared_examples/params.rb +++ b/spec/shared_examples/params.rb @@ -1,21 +1,23 @@ +# frozen_string_literal: true + shared_examples 'params' do |_facts| case _facts[:os]['family'] when 'Debian' if _facts[:os]['release']['full'] != '14.04' it { is_expected.to contain_class('docker::params') is_expected.to contain_class('docker::systemd_reload') is_expected.to contain_exec('docker-systemd-reload').with( 'path' => [ '/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/', ], 'command' => 'systemctl daemon-reload', 'refreshonly' => 'true', ) } end end end diff --git a/spec/shared_examples/plugin.rb b/spec/shared_examples/plugin.rb index 2bda0a6..793cd3a 100644 --- a/spec/shared_examples/plugin.rb +++ b/spec/shared_examples/plugin.rb @@ -1,88 +1,90 @@ +# frozen_string_literal: true + shared_examples 'plugin' do |_params, _facts, _defaults| ensure_value = _params['ensure'] plugin_name = _params['plugin_name'] enabled = _params['enabled'] timeout = _params['timeout'] plugin_alias = _params['plugin_alias'] disable_on_install = _params['disable_on_install'] disable_content_trust = _params['disable_content_trust'] grant_all_permissions = _params['grant_all_permissions'] force_remove = _params['force_remove'] settings = _params['settings'] docker_command = "#{_defaults['docker_command']} plugin" if ensure_value == 'present' docker_plugin_install_flags = get_docker_plugin_install_flags( 'plugin_name' => plugin_name, 'plugin_alias' => plugin_alias, 'disable_on_install' => disable_on_install, 'disable_content_trust' => disable_content_trust, 'grant_all_permissions' => grant_all_permissions, 'settings' => settings, ) exec_install = "#{docker_command} install #{docker_plugin_install_flags}" unless_install = "#{docker_command} ls --format='{{.PluginReference}}' | grep -w #{plugin_name}" it { is_expected.to contain_exec("plugin install #{plugin_name}").with( 'command' => exec_install, 'environment' => 'HOME=/root', 'path' => ['/bin', '/usr/bin'], 'timeout' => 0, 'unless' => unless_install, ) } elsif ensure_value == 'absent' docker_plugin_remove_flags = get_docker_plugin_remove_flags( 'plugin_name' => plugin_name, 'force_remove' => force_remove, ) exec_rm = "#{docker_command} rm #{docker_plugin_remove_flags}" onlyif_rm = "#{docker_command} ls --format='{{.PluginReference}}' | grep -w #{plugin_name}" it { is_expected.to contain_exec("plugin remove #{plugin_name}").with( 'command' => exec_rm, 'environment' => 'HOME=/root', 'path' => ['/bin', '/usr/bin'], 'timeout' => 0, 'onlyif' => onlyif_rm, ) } end if enabled docker_plugin_enable_flags = get_docker_plugin_enable_flags( 'plugin_name' => plugin_name, 'plugin_alias' => plugin_alias, 'timeout' => timeout, ) exec_enable = "#{docker_command} enable #{docker_plugin_enable_flags}" onlyif_enable = "#{docker_command} ls -f enabled=false --format='{{.PluginReference}}' | grep -w #{plugin_name}" it { is_expected.to contain_exec("plugin enable #{plugin_name}").with( 'command' => exec_enable, 'environment' => 'HOME=/root', 'path' => ['/bin', '/usr/bin'], 'timeout' => 0, 'onlyif' => onlyif_enable, ) } else it { is_expected.to contain_exec("disable #{plugin_name}").with( 'command' => "#{docker_command} disable #{plugin_name}", 'environment' => 'HOME=/root', 'path' => ['/bin', '/usr/bin'], 'timeout' => 0, 'unless' => "#{docker_command} ls -f enabled=false --format='{{.PluginReference}}' | grep -w #{plugin_name}", ) } end end diff --git a/spec/shared_examples/registry.rb b/spec/shared_examples/registry.rb index 9975500..6efc170 100644 --- a/spec/shared_examples/registry.rb +++ b/spec/shared_examples/registry.rb @@ -1,121 +1,123 @@ -shared_examples 'registry' do |_title, _params, _facts, _defaults| - server = _params['server'] - ensure_value = _params['ensure'] - username = _params['username'] - password = _params['password'] - pass_hash = _params['pass_hash'] - email = _params['email'] - local_user = _params['local_user'] - version = _params['version'] - receipt = _params['receipt'] +# frozen_string_literal: true - docker_command = _defaults['docker_command'] +shared_examples 'registry' do |title, params, facts, defaults| + server = params['server'] + ensure_value = params['ensure'] + username = params['username'] + password = params['password'] + pass_hash = params['pass_hash'] + email = params['email'] + local_user = params['local_user'] + version = params['version'] + receipt = params['receipt'] - if _facts[:os]['family'] == 'windows' - exec_environment = ["PATH=#{_facts['docker_program_files_path']}/Docker/"] + docker_command = defaults['docker_command'] + + if facts[:os]['family'] == 'windows' + exec_environment = ["PATH=#{facts['docker_program_files_path']}/Docker/"] exec_timeout = 3000 - exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] + exec_path = ["#{facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' password_env = '$env:password' exec_user = nil else exec_environment = [] exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil password_env = "\${password}" exec_user = local_user - local_user_home = _facts[:docker_home_dirs][local_user] + local_user_home = facts[:docker_home_dirs][local_user] end if ensure_value == 'present' if username != :undef && password != :undef && email != :undef && version != :undef && version =~ %r{1[.][1-9]0?} auth_cmd = "#{docker_command} login -u '#{username}' -p \"#{password_env}\" -e '#{email}' #{server}" auth_environment = "password=#{password}" elsif username != :undef && password != :undef auth_cmd = "#{docker_command} login -u '#{username}' -p \"#{password_env}\" #{server}" auth_environment = "password=#{password}" else auth_cmd = "#{docker_command} login #{server}" auth_environment = '' end else auth_cmd = "#{docker_command} logout #{server}" auth_environment = '' end - docker_auth = "#{_title}#{auth_environment}#{auth_cmd}#{local_user}" + docker_auth = "#{title}#{auth_environment}#{auth_cmd}#{local_user}" exec_env = if auth_environment != '' exec_environment << auth_environment << "docker_auth=#{docker_auth}" else exec_environment << "docker_auth=#{docker_auth}" end if receipt - if _facts[:os]['family'] != 'windows' + if facts[:os]['family'] != 'windows' server_strip = server.tr('/', '_') local_user_strip = local_user.gsub('[-_]', '') _pass_hash = case pass_hash when :undef pw_hash(docker_auth, 'SHA-512', local_user_strip) else pass_hash end - _auth_command = "#{auth_cmd} || rm -f \"/#{local_user_home}/registry-auth-puppet_receipt_#{server_strip}_#{local_user}\"" + auth_command = "#{auth_cmd} || rm -f \"/#{local_user_home}/registry-auth-puppet_receipt_#{server_strip}_#{local_user}\"" it { is_expected.to contain_file('/${local_user_home}/registry-auth-puppet_receipt_${server_strip}_${local_user}').with( 'ensure' => ensure_value, 'content' => _pass_hash, 'owner' => local_user, 'group' => local_user, ).that_notifies( - "Exec[#{_title} auth]", + "Exec[#{title} auth]", ) } else server_strip = server.gsub('[/:]', '_') - passfile = "#{_facts['docker_user_temp_path']}/registry-auth-puppet_receipt_#{server_strip}_#{local_user}" - _auth_command = "if (-not (#{auth_cmd})) { Remove-Item -Path #{passfile} -Force -Recurse -EA SilentlyContinue; exit 0 } else { exit 0 }" + passfile = "#{facts['docker_user_temp_path']}/registry-auth-puppet_receipt_#{server_strip}_#{local_user}" + auth_command = "if (-not (#{auth_cmd})) { Remove-Item -Path #{passfile} -Force -Recurse -EA SilentlyContinue; exit 0 } else { exit 0 }" if ensure_value == 'absent' it { is_expected.to contain_file(passfile).with( 'ensure' => ensure_value, ).that_notifies( - "Exec[#{_title} auth]", + "Exec[#{title} auth]", ) } elsif ensure_value == 'present' it { is_expected.to contain_exec(compute - hash).with( # 'command' => template('docker/windows/compute_hash.ps1.erb'), 'environment' => exec_env, 'provider' => exec_provider, 'logoutput' => true, # 'unless' => template('docker/windows/check_hash.ps1.erb'), ).that_notifies( - "Exec[#{_title} auth]", + "Exec[#{title} auth]", ) } end end else - _auth_command = auth_cmd + auth_command = auth_cmd end it { - is_expected.to contain_exec("#{_title} auth").with( + is_expected.to contain_exec("#{title} auth").with( 'environment' => exec_env, - 'command' => _auth_command, + 'command' => auth_command, 'user' => exec_user, 'path' => exec_path, 'timeout' => exec_timeout, 'provider' => exec_provider, 'refreshonly' => receipt, ) } end diff --git a/spec/shared_examples/repos.rb b/spec/shared_examples/repos.rb index 099c107..9e3c0b4 100644 --- a/spec/shared_examples/repos.rb +++ b/spec/shared_examples/repos.rb @@ -1,109 +1,111 @@ -shared_examples 'repos' do |_params, _facts| +# frozen_string_literal: true + +shared_examples 'repos' do |params, facts| it { is_expected.to contain_class('docker::repos') } - values = get_values_init(_params, _facts) + values = get_values_init(params, facts) location = values['package_location'] key_source = values['package_key_source'] key_check_source = values['package_key_check_source'] - architecture = _facts[:os]['architecture'] + architecture = facts[:os]['architecture'] - unless _params['prerequired_packages'].empty? - _params['prerequired_packages'].each do |package| + unless params['prerequired_packages'].empty? + params['prerequired_packages'].each do |package| it { is_expected.to contain_package(package) } end end - case _facts[:os]['family'] + case facts[:os]['family'] when 'Debian' release = values['release'] package_key = values['package_key'] package_repos = values['package_repos'] - if _params['use_upstream_package_source'] + if params['use_upstream_package_source'] it { is_expected.to contain_apt__source('docker').with( 'location' => location, 'architecture' => architecture, 'release' => release, 'repos' => package_repos, 'key' => { 'id' => package_key, 'source' => key_source, }, 'include' => { 'src' => false, }, ) } url_split = location.split('/') repo_host = url_split[2] - pin_ensure = case _params['pin_upstream_package_source'] + pin_ensure = case params['pin_upstream_package_source'] when true 'present' else 'absent' end it { is_expected.to contain_apt__pin('docker').with( 'ensure' => pin_ensure, 'origin' => repo_host, - 'priority' => _params['apt_source_pin_level'], + 'priority' => params['apt_source_pin_level'], ) } - if _params['manage_package'] + if params['manage_package'] it { is_expected.to contain_class('apt') } - if _facts[:os]['name'] == 'Debian' && _facts[:os]['distro']['codename'] == 'wheezy' + if facts[:os]['name'] == 'Debian' && facts[:os]['distro']['codename'] == 'wheezy' it { is_expected.to contain_class('apt::backports') } end it { - _params['prerequired_packages'].each do |package| + params['prerequired_packages'].each do |package| is_expected.to contain_exec('apt_update').that_comes_before("package[#{package}]") end is_expected.to contain_apt__source('docker').that_comes_before('package[docker]') } end end when 'RedHat' - if _params['manage_package'] + if params['manage_package'] baseurl = case location when :undef nil else location end gpgkey = case key_source when :undef nil else key_source end gpgkey_check = key_check_source - if _params['use_upstream_package_source'] + if params['use_upstream_package_source'] it { is_expected.to contain_yumrepo('docker').with( 'descr' => 'Docker', 'baseurl' => baseurl, 'gpgkey' => gpgkey, 'gpgcheck' => gpgkey_check, ).that_comes_before('package[docker]') } end end end end diff --git a/spec/shared_examples/run.rb b/spec/shared_examples/run.rb index 5e42136..530f3c6 100644 --- a/spec/shared_examples/run.rb +++ b/spec/shared_examples/run.rb @@ -1,462 +1,449 @@ -shared_examples 'run' do |_title, _params, _facts, _defaults| - after = _params['after'] - after_create = _params['after_create'] - after_service = _params['after_service'] - after_start = _params['after_start'] - after_stop = _params['after_stop'] - before_start = _params['before_start'] - before_stop = _params['before_stop'] - command = _params['command'] - cpuset = _params['cpuset'] - custom_unless = _params['custom_unless'] - depend_services = _params['depend_services'] - depends = _params['depends'] - detach = _params['detach'] - disable_network = _params['disable_network'] - dns = _params['dns'] - dns_search = _params['dns_search'] - docker_service = _params['docker_service'] - ensure_value = _params['ensure'] - env = _params['env'] - env_file = _params['env_file'] - expose = _params['expose'] - extra_parameters = _params['extra_parameters'] - extra_systemd_parameters = _params['extra_systemd_parameters'] - health_check_cmd = _params['health_check_cmd'] - health_check_interval = _params['health_check_interval'] - hostentries = _params['hostentries'] - hostname = _params['hostname'] - image = _params['image'] - labels = _params['labels'] - links = _params['links'] - lxc_conf = _params['lxc_conf'] - manage_service = _params['manage_service'] - memory_limit = _params['memory_limit'] - net = _params['net'] - ports = _params['ports'] - privileged = _params['privileged'] - pull_on_start = _params['pull_on_start'] - read_only = _params['read_only'] - remain_after_exit = _params['remain_after_exit'] - remove_container_on_start = _params['remove_container_on_start'] - remove_container_on_stop = _params['remove_container_on_stop'] - remove_volume_on_start = _params['remove_volume_on_start'] - remove_volume_on_stop = _params['remove_volume_on_stop'] - restart = _params['restart'] - restart_on_unhealthy = _params['restart_on_unhealthy'] - restart_service = _params['restart_service'] - restart_service_on_docker_refresh = _params['restart_service_on_docker_refresh'] - running = _params['running'] - service_prefix = _params['service_prefix'] - service_provider = _params['service_provider'] - socket_connect = _params['socket_connect'] - stop_wait_time = _params['stop_wait_time'] - syslog_identifier = _params['syslog_identifier'] - systemd_restart = _params['systemd_restart'] - tty = _params['tty'] - use_name = _params['use_name'] - username = _params['username'] - volumes = _params['volumes'] - volumes_from = _params['volumes_from'] - docker_group = _defaults['docker_group'] +# frozen_string_literal: true + +shared_examples 'run' do |title, params, facts, defaults| + # after = params['after'] + # after_create = params['after_create'] + # after_service = params['after_service'] + # after_start = params['after_start'] + # after_stop = params['after_stop'] + # before_start = params['before_start'] + # before_stop = params['before_stop'] + command = params['command'] + cpuset = params['cpuset'] + # custom_unless = params['custom_unless'] + # depend_services = params['depend_services'] + # depends = params['depends'] + # detach = params['detach'] + disable_network = params['disable_network'] + dns = params['dns'] + dns_search = params['dns_search'] + docker_service = params['docker_service'] + ensure_value = params['ensure'] + env = params['env'] + env_file = params['env_file'] + expose = params['expose'] + extra_parameters = params['extra_parameters'] + # extra_systemd_parameters = params['extra_systemd_parameters'] + health_check_cmd = params['health_check_cmd'] + health_check_interval = params['health_check_interval'] + hostentries = params['hostentries'] + hostname = params['hostname'] + image = params['image'] + labels = params['labels'] + links = params['links'] + lxc_conf = params['lxc_conf'] + manage_service = params['manage_service'] + memory_limit = params['memory_limit'] + net = params['net'] + ports = params['ports'] + privileged = params['privileged'] + # pull_on_start = params['pull_on_start'] + read_only = params['read_only'] + # remain_after_exit = params['remain_after_exit'] + # remove_container_on_start = params['remove_container_on_start'] + # remove_container_on_stop = params['remove_container_on_stop'] + # remove_volume_on_start = params['remove_volume_on_start'] + # remove_volume_on_stop = params['remove_volume_on_stop'] + restart = params['restart'] + restart_on_unhealthy = params['restart_on_unhealthy'] + # restart_service = params['restart_service'] + restart_service_on_docker_refresh = params['restart_service_on_docker_refresh'] + running = params['running'] + service_prefix = params['service_prefix'] + service_provider = params['service_provider'] + socket_connect = params['socket_connect'] + stop_wait_time = params['stop_wait_time'] + syslog_identifier = params['syslog_identifier'] + # systemd_restart = params['systemd_restart'] + tty = params['tty'] + use_name = params['use_name'] + username = params['username'] + volumes = params['volumes'] + volumes_from = params['volumes_from'] + docker_group = defaults['docker_group'] if socket_connect != [] sockopts = [socket_connect].join(',') - docker_command = "#{_defaults['docker_command']} -H #{sockopts}" + docker_command = "#{defaults['docker_command']} -H #{sockopts}" else - docker_command = _defaults['docker_command'] + docker_command = defaults['docker_command'] end if use_name it { - is_expected.to contain_notify("docker use_name warning: #{_title}").with( + is_expected.to contain_notify("docker use_name warning: #{title}").with( 'message' => 'The use_name parameter is no-longer required and will be removed in a future release', 'withpath' => true, ) } end service_provider_real = case service_provider.to_s when 'undef' - _defaults['service_provider'] + defaults['service_provider'] else service_provider end - valid_detach = if detach == :undef - case service_provider_real - when 'systemd' - false - else - _defaults['detach_service_in_init'] - end - else - detach - end - docker_run_flags = get_docker_run_flags( 'cpuset' => [cpuset], 'disable_network' => disable_network, 'dns_search' => [dns_search], 'dns' => [dns], 'env_file' => [env_file], 'env' => [env], 'expose' => [expose], - 'extra_params' => [extra_parameters], + 'extra_params' => [extra_parameters], 'health_check_cmd' => health_check_cmd, 'health_check_interval' => health_check_interval, 'hostentries' => [hostentries], 'hostname' => hostname, 'labels' => [labels], 'links' => [links], 'lxc_conf' => [lxc_conf], 'memory_limit' => memory_limit, 'net' => net, - 'osfamily' => _facts[:os]['family'], + 'osfamily' => facts[:os]['family'], 'ports' => [ports], 'privileged' => privileged, 'read_only' => read_only, 'restart_on_unhealthy' => restart_on_unhealthy, 'socket_connect' => [socket_connect], 'tty' => tty, 'username' => username, 'volumes_from' => [volumes_from], 'volumes' => [volumes], ) - sanitised_title = _title.gsub('[^0-9A-Za-z.\-_]', '-') + sanitised_title = title.gsub('[^0-9A-Za-z.\-_]', '-') - if _facts[:os]['family'] == 'windows' - exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/;#{_facts['docker_systemroot']}/System32/" + if facts[:os]['family'] == 'windows' + exec_environment = "PATH=#{facts['docker_program_files_path']}/Docker/;#{facts['docker_systemroot']}/System32/" exec_timeout = 3000 - exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] + exec_path = ["#{facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' - cidfile = "#{_facts['docker_user_temp_path']}/#{service_prefix}#{sanitised_title}.cid" + cidfile = "#{facts['docker_user_temp_path']}/#{service_prefix}#{sanitised_title}.cid" restart_check = "#{docker_command} inspect #{sanitised_title} -f '{{ if eq \\\"unhealthy\\\" .State.Health.Status }} {{ .Name }}{{ end }}' | findstr #{sanitised_title}" container_running_check = "\$state = #{docker_command} inspect #{sanitised_title} -f \"{{ .State.Running }}\"; if (\$state -ieq \"true\") { Exit 0 } else { Exit 1 }" else exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil cidfile = "/var/run/#{service_prefix}#{sanitised_title}.cid" restart_check = "#{docker_command} inspect #{sanitised_title} -f '{{ if eq \"unhealthy\" .State.Health.Status }} {{ .Name }}{{ end }}' | grep #{sanitised_title}" container_running_check = "#{docker_command} inspect #{sanitised_title} -f \"{{ .State.Running }}\" | grep true" end if restart_on_unhealthy it { - is_expected.to contain_exec("Restart unhealthy container #{_title} with docker").with( + is_expected.to contain_exec("Restart unhealthy container #{title} with docker").with( 'command' => "#{docker_command} restart #{sanitised_title}", 'onlyif' => restart_check, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } end if restart.to_s != 'undef' if ensure_value == 'absent' it { - is_expected.to contain_exec("stop #{_title} with docker").with( + is_expected.to contain_exec("stop #{title} with docker").with( 'command' => "#{docker_command} stop --time=#{stop_wait_time} #{sanitised_title}", 'onlyif' => "#{docker_command} inspect #{sanitised_title}", 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) - is_expected.to contain_exec("remove #{_title} with docker").with( + is_expected.to contain_exec("remove #{title} with docker").with( 'command' => "#{docker_command} rm -v #{sanitised_title}", 'onlyif' => "#{docker_command} inspect #{sanitised_title}", 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) is_expected.to contain_file(cidfile).with( 'ensure' => 'absent', ) } else run_with_docker_command = [ "#{docker_command} run -d #{docker_run_flags}", "--name #{sanitised_title} --cidfile=#{cidfile}", "--restart=\"#{restart}\" #{image} #{command}", ] - inspect = [ - "#{docker_command} inspect #{sanitised_title}", - ] + # inspect = [ + # "#{docker_command} inspect #{sanitised_title}", + # ] - exec_unless = if custom_unless - custom_unless << inspect - else - inspect - end + # exec_unless = if custom_unless + # custom_unless << inspect + # else + # inspect + # end it { - is_expected.to contain_exec("run #{_title} with docker").with( + is_expected.to contain_exec("run #{title} with docker").with( 'command' => run_with_docker_command.join(' '), ## todo: ## fix the following strange behavior: ## expected that the catalogue would contain Exec[run command with docker] with unless set to [["docker inspect command"]] ## but it is set to [["docker inspect command"], "docker inspect command"] # 'unless' => exec_unless, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } if !running it { - is_expected.to contain_exec("stop #{_title} with docker").with( + is_expected.to contain_exec("stop #{title} with docker").with( 'command' => "#{docker_command} stop --time=#{stop_wait_time} #{sanitised_title}", 'onlyif' => container_running_check, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } else it { - is_expected.to contain_exec("start #{_title} with docker").with( + is_expected.to contain_exec("start #{title} with docker").with( 'command' => "#{docker_command} start #{sanitised_title}", 'unless' => container_running_check, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } end end else case service_provider_real when 'systemd' hasstatus = true - init_template = 'docker/etc/systemd/system/docker-run.erb' initscript = "/etc/systemd/system/#{service_prefix}#{sanitised_title}.service" mode = '0644' startscript = "/usr/local/bin/docker-run-#{sanitised_title}-start.sh" - startstop_template = 'docker/usr/local/bin/docker-run.sh.epp' stopscript = "/usr/local/bin/docker-run-#{sanitised_title}-stop.sh" when 'upstart' hasstatus = true - init_template = 'docker/etc/init.d/docker-run.erb' initscript = "/etc/init.d/#{service_prefix}#{sanitised_title}" mode = '0750' startscript = nil - startstop_template = nil stopscript = nil else - hasstatus = _defaults['service_hasstatus'] + hasstatus = defaults['service_hasstatus'] end _syslog_identifier = if syslog_identifier syslog_identifier else "#{service_prefix}#{sanitised_title}" end if ensure_value == 'absent' - if _facts[:os]['family'] == 'windows' + if facts[:os]['family'] == 'windows' it { is_expected.to contain_exec("stop container #{service_prefix}#{sanitised_title}").with( 'command' => "#{docker_command} stop --time=#{stop_wait_time} #{sanitised_title}", 'onlyif' => "#{docker_command} inspect #{sanitised_title}", 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ).that_notifies( "Exec[remove container #{service_prefix}#{sanitised_title}]", ) } else it { is_expected.to contain_service("#{service_prefix}#{sanitised_title}").with( 'ensure' => false, 'enable' => false, 'hasstatus' => hasstatus, 'provider' => service_provider_real, ) } end it { is_expected.to contain_exec("remove container #{service_prefix}#{sanitised_title}").with( 'command' => "#{docker_command} rm -v #{sanitised_title}", 'onlyif' => "#{docker_command} inspect #{sanitised_title}", 'environment' => exec_environment, 'path' => exec_path, 'refreshonly' => true, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } - if _facts[:os]['family'] != 'windows' + if facts[:os]['family'] != 'windows' it { is_expected.to contain_file("/etc/systemd/system/#{service_prefix}#{sanitised_title}.service").with( 'ensure' => 'absent', ) } if startscript it { is_expected.to contain_file(startscript).with( 'ensure' => 'absent', ) } end if stopscript it { is_expected.to contain_file(stopscript).with( 'ensure' => 'absent', ) } end else it { is_expected.to contain_file(cidfile).with( 'ensure' => 'absent', ) } end else if startscript it { is_expected.to contain_file(startscript).with( 'ensure' => 'file', 'owner' => 'root', 'group' => docker_group, 'mode' => '0770', ) } end if stopscript it { is_expected.to contain_file(stopscript).with( 'ensure' => 'file', 'owner' => 'root', 'group' => docker_group, 'mode' => '0770', ) } end it { is_expected.to contain_file(initscript).with( 'ensure' => 'file', 'owner' => 'root', 'group' => docker_group, 'mode' => mode, ) } if manage_service if !running it { is_expected.to contain_service("#{service_prefix}#{sanitised_title}").with( 'ensure' => running, 'enable' => false, 'hasstatus' => hasstatus, ).that_requires( "File[#{initscript}]", ) } else if initscript == "/etc/init.d/#{service_prefix}#{sanitised_title}" transition_onlyif = [ "/usr/bin/test -f /var/run/docker-#{sanitised_title}.cid &&", "/usr/bin/test -f /etc/init.d/#{service_prefix}#{sanitised_title}", ] it { is_expected.to contain_exec("/bin/sh /etc/init.d/#{service_prefix}#{sanitised_title} stop").with( 'onlyif' => transition_onlyif.join(' '), ).that_comes_before( "File[/var/run/#{service_prefix}#{sanitised_title}.cid]", ) is_expected.to contain_file("/var/run/#{service_prefix}#{sanitised_title}.cid").with( 'ensure' => 'absent', ).that_comes_before( "File[#{initscript}]", ) } end it { is_expected.to contain_service("#{service_prefix}#{sanitised_title}").with( 'ensure' => running, 'enable' => true, 'provider' => service_provider_real, 'hasstatus' => hasstatus, ).that_requires( "File[#{initscript}]", ) } if docker_service if docker_service.to_s == 'true' it { is_expected.to contain_service('docker').that_comes_before("Service[#{service_prefix}#{sanitised_title}]") } if restart_service_on_docker_refresh.to_s == 'true' it { is_expected.to contain_service('docker').that_notifies("Service[#{service_prefix}#{sanitised_title}]") } end else it { is_expected.to contain_service('docker').with('name' => docker_service).that_comes_before("Service[#{service_prefix}#{sanitised_title}]") } if restart_service_on_docker_refresh.to_s == 'true' it { is_expected.to contain_service('docker').with('name' => docker_service).that_notifies("Service[#{service_prefix}#{sanitised_title}]") } end end end end end if service_provider_real == 'systemd' it { is_expected.to contain_exec("docker-#{sanitised_title}-systemd-reload").with( 'path' => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'], 'command' => 'systemctl daemon-reload', 'refreshonly' => true, ).that_requires( [ "File[#{initscript}]", "File[#{startscript}]", "File[#{stopscript}]", ], ).that_subscribes_to( [ "File[#{initscript}]", "File[#{startscript}]", "File[#{stopscript}]", ], ).that_comes_before( "Service[#{service_prefix}#{sanitised_title}]", ) } end end end end diff --git a/spec/shared_examples/secrets.rb b/spec/shared_examples/secrets.rb index 09669d2..e3e5c00 100644 --- a/spec/shared_examples/secrets.rb +++ b/spec/shared_examples/secrets.rb @@ -1,38 +1,40 @@ -shared_examples 'secrets' do |_title, _params, _facts, _defaults| - ensure_value = _params['ensure'] - label = _params['label'] - secret_name = _params['secret_name'] - secret_path = _params['secret_path'] +# frozen_string_literal: true - docker_command = "#{_defaults['docker_command']} secret" +shared_examples 'secrets' do |title, params, _facts, defaults| + ensure_value = params['ensure'] + label = params['label'] + secret_name = params['secret_name'] + secret_path = params['secret_path'] + + docker_command = "#{defaults['docker_command']} secret" if ensure_value == 'present' docker_secrets_flags = get_docker_secrets_flags( 'ensure' => ensure_value, 'label' => label, 'secret_name' => secret_name, 'secret_path' => secret_path, ) exec_secret = "#{docker_command} #{docker_secrets_flags}" unless_secret = "#{docker_command} inspect #{secret_name}" it { - is_expected.to contain_exec("#{_title} docker secret create").with( + is_expected.to contain_exec("#{title} docker secret create").with( 'command' => exec_secret, 'unless' => unless_secret, 'path' => ['/bin', '/usr/bin'], ) } end if ensure_value == 'absent' it { - is_expected.to contain_exec("#{_title} docker secret rm").with( + is_expected.to contain_exec("#{title} docker secret rm").with( 'command' => "#{docker_command} rm #{secret_name}", 'onlyif' => "#{docker_command} inspect #{secret_name}", 'path' => ['/bin', '/usr/bin'], ) } end end diff --git a/spec/shared_examples/service.rb b/spec/shared_examples/service.rb index 741d5ea..f3d7ef8 100644 --- a/spec/shared_examples/service.rb +++ b/spec/shared_examples/service.rb @@ -1,166 +1,166 @@ -shared_examples 'service' do |_params, _facts| - dns_array = [_params['dns']] - dns_search_array = [_params['dns_search']] - extra_parameters_array = [_params['extra_parameters']] - labels_array = [_params['labels']] - shell_values_array = [_params['shell_values']] - tcp_bind_array = [_params['tcp_bind']] - - _service_config = if _params['service_config'] != :undef - _params['service_config'] - else - if _facts[:os]['family'] == 'Debian' - "/etc/default/#{_params['service_name']}" - else - nil - end - end - - _manage_service = case _params['manage_service'] - when true - 'Service[docker]' - else - [] - end - - if _facts[:os]['family'] == 'RedHat' +# frozen_string_literal: true + +shared_examples 'service' do |params, facts| + # dns_array = [params['dns']] + # dns_search_array = [params['dns_search']] + # extra_parameters_array = [params['extra_parameters']] + # labels_array = [params['labels']] + # shell_values_array = [params['shell_values']] + # tcp_bind_array = [params['tcp_bind']] + + service_config = if params['service_config'] != :undef + params['service_config'] + elsif facts[:os]['family'] == 'Debian' + "/etc/default/#{params['service_name']}" + else + nil + end + + manage_service = case params['manage_service'] + when true + 'Service[docker]' + else + [] + end + + if facts[:os]['family'] == 'RedHat' it { - is_expected.to contain_file(_params['storage_setup_file']).with( + is_expected.to contain_file(params['storage_setup_file']).with( 'ensure' => 'file', 'force' => true, - 'before' => _manage_service, - 'notify' => _manage_service, + 'before' => manage_service, + 'notify' => manage_service, ) } end - if _facts[:os]['family'] == 'windows' + if facts[:os]['family'] == 'windows' [ - "#{_facts['docker_program_data_path']}/docker/", - "#{_facts['docker_program_data_path']}/docker/config/", + "#{facts['docker_program_data_path']}/docker/", + "#{facts['docker_program_data_path']}/docker/config/", ].each do |dir| it { is_expected.to contain_file(dir).with_ensure('directory') } end end - case _params['service_provider'] + case params['service_provider'] when 'systemd' it { is_expected.to contain_file('/etc/systemd/system/docker.service.d').with_ensure('directory') } - if _params['service_overrides_template'] + if params['service_overrides_template'] it { is_expected.to contain_file('/etc/systemd/system/docker.service.d/service-overrides.conf').with( 'ensure' => 'file', # 'content' => template($service_overrides_template), - 'before' => _manage_service, + 'before' => manage_service, ).that_notifies( 'Exec[docker-systemd-reload-before-service]', ) } end - if _params['socket_override'] + if params['socket_override'] it { is_expected.to contain_file('/etc/systemd/system/docker.socket.d').with_ensure('directory') } it { is_expected.to contain_file('/etc/systemd/system/docker.socket.d/socket-overrides.conf').with( 'ensure' => 'file', # 'content' => template($socket_overrides_template), ).that_comes_before( - _manage_service, + manage_service, ).that_notifies( 'Exec[docker-systemd-reload-before-service]', ) } end it { is_expected.to contain_exec('docker-systemd-reload-before-service').with( 'path' => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'], 'command' => 'systemctl daemon-reload > /dev/null', 'refreshonly' => true, ).that_notifies( - _manage_service, + manage_service, ) } when 'upstart' it { is_expected.to contain_file('/etc/init.d/docker').with( 'ensure' => 'link', 'target' => '/lib/init/upstart-job', 'force' => true, ).that_notifies( - _manage_service, + manage_service, ) } end - if _params['storage_config'] != :undef + if params['storage_config'] != :undef it { - is_expected.to contain_file(_params['storage_config']).with( + is_expected.to contain_file(params['storage_config']).with( 'ensure' => 'file', 'force' => true, ).that_notifies( - _manage_service, + manage_service, ) } end - if _service_config + if service_config it { - is_expected.to contain_file(_service_config).with( + is_expected.to contain_file(service_config).with( 'ensure' => 'file', 'force' => true, ).that_notifies( - _manage_service, + manage_service, ) } end - if _params['manage_service'] - if _facts[:os]['family'] == 'windows' + if params['manage_service'] + if facts[:os]['family'] == 'windows' it { is_expected.to contain_reboot('pending_reboot').with( 'when' => 'pending', 'onlyif' => 'component_based_servicing', 'timeout' => 1, ) } end it { - _hasstatus = if _params['service_hasstatus'] == :undef + hasstatus = if params['service_hasstatus'] == :undef + nil + else + params['service_hasstatus'] + end + + hasrestart = if params['service_hasrestart'] == :undef nil else - _params['service_hasstatus'] + params['service_hasrestart'] end - _hasrestart = if _params['service_hasrestart'] == :undef - nil - else - _params['service_hasrestart'] - end - - _provider = if _params['service_provider'] == :undef - nil - else - _params['service_provider'] - end + provider = if params['service_provider'] == :undef + nil + else + params['service_provider'] + end is_expected.to contain_service('docker').with( - 'ensure' => _params['service_state'], - 'name' => _params['service_name'], - 'enable' => _params['service_enable'], - 'hasstatus' => _hasstatus, - 'hasrestart' => _hasrestart, - 'provider' => _provider, + 'ensure' => params['service_state'], + 'name' => params['service_name'], + 'enable' => params['service_enable'], + 'hasstatus' => hasstatus, + 'hasrestart' => hasrestart, + 'provider' => provider, ) } end end diff --git a/spec/shared_examples/services.rb b/spec/shared_examples/services.rb index 7b84c8a..3ccf20f 100644 --- a/spec/shared_examples/services.rb +++ b/spec/shared_examples/services.rb @@ -1,139 +1,135 @@ -shared_examples 'services' do |_title, _params, _facts, _defaults| - command = _params['command'] - create = _params['create'] - detach = _params['detach'] - ensure_value = _params['ensure'] - env = _params['env'] - extra_params = _params['extra_params'] - host_socket = _params['host_socket'] - image = _params['image'] - label = _params['label'] - mounts = _params['mounts'] - networks = _params['networks'] - publish = _params['publish'] - registry_mirror = _params['registry_mirror'] - replicas = _params['replicas'] - scale = _params['scale'] - service_name = _params['service_name'] - tty = _params['tty'] - update = _params['update'] - user = _params['user'] - workdir = _params['workdir'] +# frozen_string_literal: true - docker_command = "#{_defaults['docker_command']} service" +shared_examples 'services' do |title, params, facts, defaults| + command = params['command'] + create = params['create'] + detach = params['detach'] + ensure_value = params['ensure'] + env = params['env'] + extra_params = params['extra_params'] + host_socket = params['host_socket'] + image = params['image'] + label = params['label'] + mounts = params['mounts'] + networks = params['networks'] + publish = params['publish'] + registry_mirror = params['registry_mirror'] + replicas = params['replicas'] + scale = params['scale'] + service_name = params['service_name'] + tty = params['tty'] + update = params['update'] + user = params['user'] + workdir = params['workdir'] - if _facts[:os]['family'] == 'windows' - exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/;#{_facts['docker_systemroot']}/System32/" - exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] + docker_command = "#{defaults['docker_command']} service" + + if facts[:os]['family'] == 'windows' + exec_environment = "PATH=#{facts['docker_program_files_path']}/Docker/;#{facts['docker_systemroot']}/System32/" + exec_path = ["#{facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' exec_timeout = 3000 else exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_provider = nil exec_timeout = 0 end if create docker_service_create_flags = get_docker_service_flags( 'detach' => detach, 'env' => Array(env), 'service_name' => service_name, 'label' => Array(label), 'publish' => publish, 'replicas' => replicas, 'tty' => tty, 'user' => user, 'workdir' => workdir, 'extra_params' => Array(extra_params), 'image' => image, 'host_socket' => host_socket, 'registry_mirror' => registry_mirror, 'mounts' => mounts, 'networks' => networks, 'command' => command, ) - _service_name = if service_name == :undef - '' - else - service_name - end - exec_create = "#{docker_command} create --name #{docker_service_create_flags}" - unless_create = "docker service ps #{_service_name}" + unless_create = "docker service ps #{service_name == :undef ? '' : service_name}" it { - is_expected.to contain_exec("#{_title} docker service create").with( + is_expected.to contain_exec("#{title} docker service create").with( 'command' => exec_create, 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'provider' => exec_provider, 'unless' => unless_create, ) } end if update docker_service_flags = get_docker_service_flags( 'detach' => detach, 'env' => Array(env), 'service_name' => service_name, 'label' => Array(label), 'publish' => publish, 'replicas' => replicas, 'tty' => tty, 'user' => user, 'workdir' => workdir, 'extra_params' => Array(extra_params), 'image' => image, 'host_socket' => host_socket, 'registry_mirror' => registry_mirror, ) exec_update = "#{docker_command} update #{docker_service_flags}" it { - is_expected.to contain_exec("#{_title} docker service update").with( + is_expected.to contain_exec("#{title} docker service update").with( 'command' => exec_update, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } end if scale - docker_service_flags = get_docker_service_flags( - 'service_name' => service_name, - 'replicas' => replicas, - 'extra_params' => Array(extra_params), - ) + # docker_service_flags = get_docker_service_flags( + # 'service_name' => service_name, + # 'replicas' => replicas, + # 'extra_params' => Array(extra_params), + # ) exec_scale = "#{docker_command} scale #{service_name}=#{replicas}" it { - is_expected.to contain_exec("#{_title} docker service scale").with( + is_expected.to contain_exec("#{title} docker service scale").with( 'command' => exec_scale, 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'provider' => exec_provider, ) } end if ensure_value == 'absent' it { - is_expected.to contain_exec("#{_title} docker service remove").with( + is_expected.to contain_exec("#{title} docker service remove").with( 'command' => "docker service rm #{service_name}", 'onlyif' => "docker service ps #{service_name}", 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } end end diff --git a/spec/shared_examples/stack.rb b/spec/shared_examples/stack.rb index e7bd949..22a86b5 100644 --- a/spec/shared_examples/stack.rb +++ b/spec/shared_examples/stack.rb @@ -1,57 +1,59 @@ -shared_examples 'stack' do |_title, _params, _facts, _defaults| - ensure_value = _params['ensure'] - stack_name = _params['stack_name'] - bundle_file = _params['bundle_file'] - compose_files = _params['compose_files'] - prune = _params['prune'] - with_registry_auth = _params['with_registry_auth'] - resolve_image = _params['resolve_image'] +# frozen_string_literal: true + +shared_examples 'stack' do |_title, params, facts, defaults| + ensure_value = params['ensure'] + stack_name = params['stack_name'] + bundle_file = params['bundle_file'] + compose_files = params['compose_files'] + prune = params['prune'] + with_registry_auth = params['with_registry_auth'] + resolve_image = params['resolve_image'] # deprecation('docker::stack','The docker stack define type will be deprecated in a future release. Please migrate to the docker_stack type/provider.') - docker_command = "#{_defaults['docker_command']} stack" + docker_command = "#{defaults['docker_command']} stack" - if _facts[:os]['family'] == 'windows' + if facts[:os]['family'] == 'windows' exec_path = ['C:/Program Files/Docker/'] check_stack = '$info = docker stack ls | select-string -pattern web if ($info -eq $null) { Exit 1 } else { Exit 0 }' provider = 'powershell' else exec_path = ['/bin', '/usr/bin'] check_stack = "#{docker_command} ls | grep #{stack_name}" provider = nil end if ensure_value == 'present' docker_stack_flags = get_docker_stack_flags( 'stack_name' => stack_name, 'bundle_file' => bundle_file, 'compose_files' => compose_files, 'prune' => prune, 'with_registry_auth' => with_registry_auth, 'resolve_image' => resolve_image, ) exec_stack = "#{docker_command} deploy #{docker_stack_flags} #{stack_name}" it { is_expected.to contain_exec("docker stack create #{stack_name}").with( 'command' => exec_stack, 'unless' => check_stack, 'path' => exec_path, 'provider' => provider, ) } end if ensure_value == 'absent' it { is_expected.to contain_exec("docker stack destroy #{stack_name}").with( 'command' => "#{docker_command} rm #{stack_name}", 'onlyif' => check_stack, 'path' => exec_path, 'provider' => provider, ) } end end diff --git a/spec/shared_examples/swarm.rb b/spec/shared_examples/swarm.rb index 37a4cf5..5a7357d 100644 --- a/spec/shared_examples/swarm.rb +++ b/spec/shared_examples/swarm.rb @@ -1,104 +1,106 @@ -shared_examples 'swarm' do |_title, _params, _facts, _defaults| - ensure_value = _params['ensure'] - init = _params['init'] - join = _params['join'] - advertise_addr = _params['advertise_addr'] - autolock = _params['autolock'] - cert_expiry = _params['cert_expiry'] - default_addr_pool = _params['default_addr_pool'] - default_addr_pool_mask_length = _params['default_addr_pool_mask_length'] - dispatcher_heartbeat = _params['dispatcher_heartbeat'] - external_ca = _params['external_ca'] - force_new_cluster = _params['force_new_cluster'] - listen_addr = _params['listen_addr'] - max_snapshots = _params['max_snapshots'] - snapshot_interval = _params['snapshot_interval'] - token = _params['token'] - manager_ip = _params['manager_ip'] +# frozen_string_literal: true - if _facts[:os]['family'] == 'windows' - exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/" - exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] +shared_examples 'swarm' do |_title, params, facts, defaults| + ensure_value = params['ensure'] + init = params['init'] + join = params['join'] + advertise_addr = params['advertise_addr'] + autolock = params['autolock'] + cert_expiry = params['cert_expiry'] + default_addr_pool = params['default_addr_pool'] + default_addr_pool_mask_length = params['default_addr_pool_mask_length'] + dispatcher_heartbeat = params['dispatcher_heartbeat'] + external_ca = params['external_ca'] + force_new_cluster = params['force_new_cluster'] + listen_addr = params['listen_addr'] + max_snapshots = params['max_snapshots'] + snapshot_interval = params['snapshot_interval'] + token = params['token'] + manager_ip = params['manager_ip'] + + if facts[:os]['family'] == 'windows' + exec_environment = "PATH=#{facts['docker_program_files_path']}/Docker/" + exec_path = ["#{facts['docker_program_files_path']}/Docker/"] exec_timeout = 3000 exec_provider = 'powershell' unless_init = '$info = docker info | select-string -pattern "Swarm: active" if ($info -eq $null) { Exit 1 } else { Exit 0 }' unless_join = '$info = docker info | select-string -pattern "Swarm: active" if ($info -eq $null) { Exit 1 } else { Exit 0 }' onlyif_leave = '$info = docker info | select-string -pattern "Swarm: active" if ($info -eq $null) { Exit 1 } else { Exit 0 }' else exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil unless_init = 'docker info | grep -w "Swarm: active"' unless_join = 'docker info | grep -w "Swarm: active"' onlyif_leave = 'docker info | grep -w "Swarm: active"' end - docker_command = "#{_defaults['docker_command']} swarm" + docker_command = "#{defaults['docker_command']} swarm" if init docker_swarm_init_flags = get_docker_swarm_init_flags( 'init' => init, 'advertise_addr' => advertise_addr, 'autolock' => autolock, 'cert_expiry' => cert_expiry, 'dispatcher_heartbeat' => dispatcher_heartbeat, 'default_addr_pool' => default_addr_pool, 'default_addr_pool_mask_length' => default_addr_pool_mask_length, 'external_ca' => external_ca, 'force_new_cluster' => force_new_cluster, 'listen_addr' => listen_addr, 'max_snapshots' => max_snapshots, 'snapshot_interval' => snapshot_interval, ) exec_init = "#{docker_command} #{docker_swarm_init_flags}" it { is_expected.to contain_exec('Swarm init').with( 'command' => exec_init, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, 'unless' => unless_init, ) } end if join docker_swarm_join_flags = get_docker_swarm_join_flags( 'join' => join, 'advertise_addr' => advertise_addr, 'listen_addr' => listen_addr, 'token' => token, ) exec_join = "#{docker_command} #{docker_swarm_join_flags} #{manager_ip}" it { is_expected.to contain_exec('Swarm join').with( 'command' => exec_join, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, 'unless' => unless_join, ) } end if ensure_value == 'absent' it { is_expected.to contain_exec('Leave swarm').with( 'command' => 'docker swarm leave --force', 'onlyif' => onlyif_leave, 'path' => exec_path, 'provider' => exec_provider, ) } end end diff --git a/spec/shared_examples/system_user.rb b/spec/shared_examples/system_user.rb index ae8bec2..4f16b1f 100644 --- a/spec/shared_examples/system_user.rb +++ b/spec/shared_examples/system_user.rb @@ -1,20 +1,18 @@ -shared_examples 'system_user' do |user, group| - _create_user = true +# frozen_string_literal: true +shared_examples 'system_user' do |user, group| docker_group = group - if _create_user - it { - is_expected.to contain_user(user).with( - 'ensure' => 'present', - ).that_comes_before("Exec[docker-system-user-#{user}]") - } - end + it { + is_expected.to contain_user(user).with( + 'ensure' => 'present', + ).that_comes_before("Exec[docker-system-user-#{user}]") + } it { is_expected.to contain_exec("docker-system-user-#{user}").with( 'command' => "/usr/sbin/usermod -aG #{docker_group} #{user}", 'unless' => "/bin/cat /etc/group | grep '^#{docker_group}:' | grep -qw #{user}", ) } end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 373813b..65d59b8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,93 +1,95 @@ +# frozen_string_literal: true + require 'puppetlabs_spec_helper/module_spec_helper' require 'rspec-puppet-facts' require 'shared_examples' require 'rspec-puppet' require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) include RspecPuppetFacts default_facts = { puppetversion: Puppet.version, facterversion: Facter.version, } default_fact_files = [ File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')), File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')), ] default_fact_files.each do |f| next unless File.exist?(f) && File.readable?(f) && File.size?(f) begin default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) rescue => e RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end end RSpec.configure do |c| c.mock_with :rspec c.default_facts = default_facts c.before :each do # set to strictest setting for testing # by default Puppet runs at warning level Puppet.settings[:strict] = :warning end c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] c.after(:suite) do end end # Ensures that a module is defined # @param module_name Name of the module def ensure_module_defined(module_name) module_name.split('::').reduce(Object) do |last_module, next_module| last_module.const_set(next_module, Module.new) unless last_module.const_defined?(next_module, false) last_module.const_get(next_module, false) end end RSpec::Matchers.define :require_string_for do |property| match do |type_class| config = { name: 'name' } config[property] = 2 expect { type_class.new(config) }.to raise_error(Puppet::Error, %r{#{property} should be a String}) end failure_message do |type_class| "#{type_class} should require #{property} to be a String" end end RSpec::Matchers.define :require_hash_for do |property| match do |type_class| config = { name: 'name' } config[property] = 2 expect { type_class.new(config) }.to raise_error(Puppet::Error, %r{#{property} should be a Hash}) end failure_message do |type_class| "#{type_class} should require #{property} to be a Hash" end end RSpec::Matchers.define :require_array_for do |property| match do |type_class| config = { name: 'name' } config[property] = 2 expect { type_class.new(config) }.to raise_error(Puppet::Error, %r{#{property} should be an Array}) end failure_message do |type_class| "#{type_class} should require #{property} to be an Array" end end at_exit { RSpec::Puppet::Coverage.report! } # 'spec_overrides' from sync.yml will appear below this line diff --git a/spec/spec_helper_acceptance_local.rb b/spec/spec_helper_acceptance_local.rb index 0a8ea62..b492e65 100644 --- a/spec/spec_helper_acceptance_local.rb +++ b/spec/spec_helper_acceptance_local.rb @@ -1,193 +1,195 @@ +# frozen_string_literal: true + require 'puppet_litmus' require 'rspec/retry' require 'tempfile' include PuppetLitmus # This method allows a block to be passed in and if an exception is raised # that matches the 'error_matcher' matcher, the block will wait a set number # of seconds before retrying. # Params: # - max_retry_count - Max number of retries # - retry_wait_interval_secs - Number of seconds to wait before retry # - error_matcher - Matcher which the exception raised must match to allow retry # Example Usage: # retry_on_error_matching(3, 5, /OpenGPG Error/) do # apply_manifest(pp, :catch_failures => true) # end def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, error_matcher = nil) try = 0 begin try += 1 yield rescue StandardError => e raise unless try < max_retry_count && (error_matcher.nil? || e.message =~ error_matcher) sleep retry_wait_interval_secs retry end end def create_remote_file(name, full_name, file_content) Tempfile.open name do |tempfile| File.open(tempfile.path, 'w') { |file| file.puts file_content } bolt_upload_file(tempfile.path, full_name) end end RSpec.configure do |c| # Add exclusive filter for Windows untill all the windows functionality is implemented c.filter_run_excluding win_broken: true # Readable test descriptions c.formatter = :documentation # show retry status in spec process c.verbose_retry = true # show exception that triggers a retry if verbose_retry is set to true c.display_try_failure_messages = true # Configure all nodes in nodeset c.before :suite do # Install module and dependencies # Due to RE-6764, running yum update renders the machine unable to install # other software. Thus this workaround. if os[:family] == 'redhat' run_shell('mv /etc/yum.repos.d/redhat.repo /etc/yum.repos.d/internal-mirror.repo', expect_failures: true) run_shell('rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm', expect_failures: true) run_shell('yum update -y -q') # run_shell('yum upgrade -y') end if os[:family] == 'debian' || os[:family] == 'ubuntu' run_shell('apt-get update -y') # run_shell('apt-get upgrade -y') run_shell('apt-get install -y lsb-release') run_shell('apt-get install -y net-tools') end run_shell('puppet module install puppetlabs-stdlib --version 4.24.0', expect_failures: true) run_shell('puppet module install puppetlabs-apt --version 4.4.1', expect_failures: true) run_shell('puppet module install puppetlabs-translate --version 1.0.0', expect_failures: true) run_shell('puppet module install puppetlabs-powershell --version 2.1.5', expect_failures: true) run_shell('puppet module install puppetlabs-reboot --version 2.0.0', expect_failures: true) # net-tools required for netstat utility being used by some tests if os[:family] == 'redhat' && os[:release].to_i == 7 run_shell('yum -y install lvm2 device-mapper device-mapper-persistent-data device-mapper-event device-mapper-libs device-mapper-event-libs') run_shell('yum install -y yum-utils net-tools') run_shell('yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo') run_shell('yum-config-manager --enable docker\*') end docker_compose_content_v3 = <<-EOS version: "3.4" x-images: &default-image alpine:3.8 services: compose_test: image: *default-image command: /bin/sh -c "while true; do echo hello world; sleep 1; done" EOS docker_compose_override_v3 = <<-EOS version: "3.4" x-images: &default-image debian:stable-slim services: compose_test: image: *default-image command: /bin/sh -c "while true; do echo hello world; sleep 1; done" EOS docker_stack_override_v3 = <<-EOS version: "3.4" x-images: &default-image debian:stable-slim services: compose_test: image: *default-image command: /bin/sh -c "while true; do echo hello world; sleep 1; done" EOS docker_compose_content_v3_windows = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: external: name: nat EOS docker_compose_override_v3_windows = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: external: name: nat EOS docker_compose_override_v3_windows2016 = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver-sac2016 command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: external: name: nat EOS docker_stack_content_windows = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle command: cmd.exe /C "ping 8.8.8.8 -t" EOS docker_stack_override_windows = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver EOS docker_stack_override_windows2016 = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver-sac2016 EOS if os[:family] == 'windows' create_remote_file(host, '/tmp/docker-compose-v3.yml', docker_compose_content_v3_windows) create_remote_file(host, '/tmp/docker-stack.yml', docker_stack_content_windows) - if os[:release] =~ %r{2019} + if %r{2019}.match?(os[:release]) create_remote_file(host, '/tmp/docker-compose-override-v3.yml', docker_compose_override_v3_windows) create_remote_file(host, '/tmp/docker-stack-override.yml', docker_stack_override_windows) else create_remote_file(host, '/tmp/docker-compose-override-v3.yml', docker_compose_override_v3_windows2016) create_remote_file(host, '/tmp/docker-stack-override.yml', docker_stack_override_windows2016) end else create_remote_file(host, '/tmp/docker-compose-v3.yml', docker_compose_content_v3) create_remote_file(host, '/tmp/docker-stack.yml', docker_compose_content_v3) create_remote_file(host, '/tmp/docker-compose-override-v3.yml', docker_compose_override_v3) create_remote_file(host, '/tmp/docker-stack-override.yml', docker_stack_override_v3) end next unless os[:family] == 'windows' result = run_shell("ipconfig | findstr /i 'ipv4'") raise 'Could not retrieve ip address for Windows box' if result.exit_code != 0 ip = result.stdout.split("\n")[0].split(':')[1].strip retry_on_error_matching(60, 5, %r{connection failure running}) do @windows_ip = ip end apply_manifest("class { 'docker': docker_ee => true, extra_parameters => '\"insecure-registries\": [ \"#{@windows_ip}:5000\" ]' }", catch_failures: true) docker_path = 'C:\\Program Files\\Docker' run_shell("set PATH \"%PATH%;C:\\Users\\Administrator\\AppData\\Local\\Temp;#{docker_path}\"") puts 'Waiting for box to come online' sleep 300 end end diff --git a/spec/unit/lib/facter/docker_spec.rb b/spec/unit/lib/facter/docker_spec.rb index 8088903..715aa5e 100644 --- a/spec/unit/lib/facter/docker_spec.rb +++ b/spec/unit/lib/facter/docker_spec.rb @@ -1,123 +1,125 @@ +# frozen_string_literal: true + require 'spec_helper' require 'json' describe 'Facter::Util::Fact' do before :each do Facter.clear if Facter.value(:kernel) == 'windows' docker_command = 'powershell -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -c docker' Facter::Util::Resolution.stubs(:which).with('docker').returns('C:\Program Files\Docker\docker.exe') else docker_command = 'docker' Facter::Util::Resolution.stubs(:which).with('docker').returns('/usr/bin/docker') end docker_info = File.read(fixtures('facts', 'docker_info')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} info --format '{{json .}}'").returns(docker_info) processors = File.read(fixtures('facts', 'processors')) Facter.fact(:processors).stubs(:value).returns(JSON.parse(processors)) docker_version = File.read(fixtures('facts', 'docker_version')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} version --format '{{json .}}'").returns(docker_version) docker_network_list = File.read(fixtures('facts', 'docker_network_list')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} network ls | tail -n +2").returns(docker_network_list) docker_network_names = [] docker_network_list.each_line { |line| docker_network_names.push line.split[1] } docker_network_names.each do |network| inspect = File.read(fixtures('facts', "docker_network_inspect_#{network}")) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} network inspect #{network}").returns(inspect) end docker_worker_token = File.read(fixtures('facts', 'docker_swarm_worker_token')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} swarm join-token worker -q").returns(docker_worker_token.chomp) docker_manager_token = File.read(fixtures('facts', 'docker_swarm_manager_token')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} swarm join-token manager -q").returns(docker_manager_token.chomp) end after(:each) { Facter.clear } describe 'docker fact with composer network' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-c5810f1e3113,docker0,eth0,lo') end it do fact = File.read(fixtures('facts', 'facts_with_compose')) fact = JSON.parse(fact.to_json, quirks_mode: true) facts = eval(fact) # rubocop:disable Security/Eval expect(Facter.fact(:docker).value).to include( 'network' => facts['network'], ) end end describe 'docker fact without composer network' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do fact = File.read(fixtures('facts', 'facts_without_compose')).chomp fact_json = fact.to_json facts = JSON.parse(fact_json, quirks_mode: true) facts = eval(facts) # rubocop:disable Security/Eval expect(Facter.fact(:docker).value).to include( 'network' => facts['network'], ) end end describe 'docker client version' do before(:each) do docker_version = File.read(fixtures('facts', 'docker_version')) Facter.fact(:docker_version).stubs(:value).returns(JSON.parse(docker_version)) Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do expect(Facter.fact(:docker_client_version).value).to eq( '17.03.1-ce-client', ) end end describe 'docker server version' do before(:each) do docker_version = File.read(fixtures('facts', 'docker_version')) Facter.fact(:docker_version).stubs(:value).returns(JSON.parse(docker_version)) Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do expect(Facter.fact(:docker_server_version).value).to eq( '17.03.1-ce-server', ) end end describe 'docker info' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it 'has valid entries' do expect(Facter.fact(:docker).value).to include( 'Architecture' => 'x86_64', ) end end describe 'docker swarm worker join-token' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do expect(Facter.fact(:docker_worker_join_token).value).to eq( 'SWMTKN-1-2m7ekt7511j5kgrc6seyrewpdxv47ksz1sdg7iybzhuug6nmws-0jh0syqeoj3tlr81p165ydfkm', ) end end describe 'docker swarm manager join-token' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do expect(Facter.fact(:docker_manager_join_token).value).to eq( 'SWMTKN-1-2m7ekt7511j5kgrc6seyrewpdxv47ksz1sdg7iybzhuug6nmws-8gh1ns1lcavgau8k9p6ou7xj3', ) end end end diff --git a/spec/unit/lib/puppet/provider/docker_network_spec.rb b/spec/unit/lib/puppet/provider/docker_network_spec.rb index 804bb27..6800b74 100644 --- a/spec/unit/lib/puppet/provider/docker_network_spec.rb +++ b/spec/unit/lib/puppet/provider/docker_network_spec.rb @@ -1,28 +1,30 @@ +# frozen_string_literal: true + require 'spec_helper' describe Puppet::Type.type(:docker_network).provider(:ruby) do let(:provider) { resource.provider } let(:instance) { provider.class.instances.first } let(:resource) do Puppet::Type.type(:docker_network).new( ensure: :present, name: 'test-network', driver: 'host', subnet: ['192.168.3.0/24', '10.0.0.0/24'], ) end before :each do # need to reach deep into puppet to unhook the confinement call, so the provider gets properly loaded ['docker', '/usr/local/bin/docker'].each do |docker_path| allow(Puppet::Confine::Exists).to receive(:which).with(docker_path).and_return('/usr/local/bin/docker') end end describe 'create' do it 'creates a docker network' do provider.class.expects(:docker).with(['network', 'create', "--driver=#{resource[:driver]}", "--subnet=#{resource[:subnet][0]}", "--subnet=#{resource[:subnet][1]}", resource[:name]]) expect(provider.create).to be_nil end end end diff --git a/spec/unit/lib/puppet/type/docker_compose_spec.rb b/spec/unit/lib/puppet/type/docker_compose_spec.rb index b3ce01f..9b310ff 100644 --- a/spec/unit/lib/puppet/type/docker_compose_spec.rb +++ b/spec/unit/lib/puppet/type/docker_compose_spec.rb @@ -1,45 +1,47 @@ +# frozen_string_literal: true + require 'spec_helper' compose = Puppet::Type.type(:docker_compose) describe compose do let :params do [ :name, :provider, :scale, :options, :up_args, ] end let :properties do [ :ensure, ] end it 'has expected properties' do properties.each do |property| expect(compose.properties.map(&:name)).to be_include(property) end end it 'has expected parameters' do params.each do |param| expect(compose.parameters).to be_include(param) end end it 'requires options to be an array' do expect(compose).to require_array_for('options') end it 'requires up_args to be a string' do expect(compose).to require_string_for('up_args') end it 'requires scale to be a hash' do expect(compose).to require_hash_for('scale') end end diff --git a/spec/unit/lib/puppet/type/docker_network_spec.rb b/spec/unit/lib/puppet/type/docker_network_spec.rb index ed99582..bfe8815 100644 --- a/spec/unit/lib/puppet/type/docker_network_spec.rb +++ b/spec/unit/lib/puppet/type/docker_network_spec.rb @@ -1,39 +1,41 @@ +# frozen_string_literal: true + require 'spec_helper' network = Puppet::Type.type(:docker_network) describe network do let :params do [ :name, :provider, :subnet, :gateway, :ip_range, :aux_address, :options, :additional_flags, ] end let :properties do [ :ensure, :driver, :ipam_driver, :id, ] end it 'has expected properties' do properties.each do |property| expect(network.properties.map(&:name)).to be_include(property) end end it 'has expected parameters' do params.each do |param| expect(network.parameters).to be_include(param) end end end diff --git a/spec/unit/lib/puppet/type/docker_stack_spec.rb b/spec/unit/lib/puppet/type/docker_stack_spec.rb index 4cfb8ec..8cd1dc5 100644 --- a/spec/unit/lib/puppet/type/docker_stack_spec.rb +++ b/spec/unit/lib/puppet/type/docker_stack_spec.rb @@ -1,35 +1,37 @@ +# frozen_string_literal: true + require 'spec_helper' stack = Puppet::Type.type(:docker_stack) describe stack do let :params do [ :name, :provider, :up_args, ] end let :properties do [ :ensure, ] end it 'has expected properties' do properties.each do |property| expect(stack.properties.map(&:name)).to be_include(property) end end it 'has expected parameters' do params.each do |param| expect(stack.parameters).to be_include(param) end end it 'requires up_args to be a string' do expect(stack).to require_string_for('up_args') end end diff --git a/spec/unit/lib/puppet/type/docker_volume_spec.rb b/spec/unit/lib/puppet/type/docker_volume_spec.rb index c2de5ac..2ff8776 100644 --- a/spec/unit/lib/puppet/type/docker_volume_spec.rb +++ b/spec/unit/lib/puppet/type/docker_volume_spec.rb @@ -1,32 +1,34 @@ +# frozen_string_literal: true + require 'spec_helper' volume = Puppet::Type.type(:docker_volume) describe volume do let :params do [ :name, :provider, :options, ] end let :properties do [ :driver, :mountpoint, ] end it 'has expected properties' do properties.each do |property| expect(volume.properties.map(&:name)).to be_include(property) end end it 'has expected parameters' do params.each do |param| expect(volume.parameters).to be_include(param) end end end