diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..12ed4ff --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,6 @@ +FROM puppet/pdk:latest + +# [Optional] Uncomment this section to install additional packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends + diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000..a719361 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,38 @@ +# devcontainer + + +For format details, see https://aka.ms/devcontainer.json. + +For config options, see the README at: +https://github.com/microsoft/vscode-dev-containers/tree/v0.140.1/containers/puppet + +``` json +{ + "name": "Puppet Development Kit (Community)", + "dockerFile": "Dockerfile", + + // Set *default* container specific settings.json values on container create. + "settings": { + "terminal.integrated.profiles.linux": { + "bash": { + "path": "bash", + } + } + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "puppet.puppet-vscode", + "rebornix.Ruby" + ], + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "pdk --version", +} +``` + + + diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..cdd65d2 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,17 @@ +{ + "name": "Puppet Development Kit (Community)", + "dockerFile": "Dockerfile", + + "settings": { + "terminal.integrated.profiles.linux": { + "bash": { + "path": "bash" + } + } + }, + + "extensions": [ + "puppet.puppet-vscode", + "rebornix.Ruby" + ] +} diff --git a/.fixtures-puppetv3.yml b/.fixtures-puppetv3.yml deleted file mode 100644 index 46e0628..0000000 --- a/.fixtures-puppetv3.yml +++ /dev/null @@ -1,10 +0,0 @@ -fixtures: - repositories: - common: - repo: 'https://github.com/ghoneycutt/puppet-module-common.git' - ref: 'v1.7.0' - stdlib: - repo: 'https://github.com/puppetlabs/puppetlabs-stdlib.git' - ref: '4.6.0' - symlinks: - types: "#{source_dir}" diff --git a/.fixtures.yml b/.fixtures.yml index da1811f..9391fb8 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -5,15 +5,15 @@ fixtures: ref: 'v1.7.0' stdlib: repo: 'https://github.com/puppetlabs/puppetlabs-stdlib.git' - ref: '4.6.0' + ref: '5.0.0' cron: - repo: 'git://github.com/puppetlabs/puppetlabs-cron_core.git' + repo: 'https://github.com/puppetlabs/puppetlabs-cron_core.git' ref: '1.0.0' mount: - repo: 'git://github.com/puppetlabs/puppetlabs-mount_core.git' + repo: 'https://github.com/puppetlabs/puppetlabs-mount_core.git' ref: '1.0.2' selinux: - repo: 'git://github.com/puppetlabs/puppetlabs-selinux_core.git' + repo: 'https://github.com/puppetlabs/puppetlabs-selinux_core.git' ref: '1.0.1' symlinks: types: "#{source_dir}" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9032a01 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +*.rb eol=lf +*.erb eol=lf +*.pp eol=lf +*.sh eol=lf +*.epp eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5c39551 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,92 @@ +--- +name: CI + +on: pull_request + +concurrency: + group: ${{ github.head_ref }} + cancel-in-progress: true + +jobs: + setup_matrix: + name: Setup Test Matrix + runs-on: ubuntu-20.04 + timeout-minutes: 40 + outputs: + puppet_unit_test_matrix: ${{ steps.get-outputs.outputs.puppet_unit_test_matrix }} + github_action_test_matrix: ${{ steps.get-outputs.outputs.github_action_test_matrix }} + steps: + - uses: actions/checkout@v3 + + - name: Setup ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '2.7.3' + bundler-cache: true + + - name: Run static validations + run: bundle exec rake validate lint + + - name: Run rake rubocop + run: bundle exec rake rubocop + + - name: Setup Test Matrix + id: get-outputs + run: bundle exec metadata2gha --use-fqdn --pidfile-workaround false + + unit: + needs: setup_matrix + runs-on: ubuntu-20.04 + timeout-minutes: 40 + strategy: + fail-fast: false + matrix: + include: ${{fromJson(needs.setup_matrix.outputs.puppet_unit_test_matrix)}} + name: Spec Puppet ${{ matrix.puppet }} (Ruby ${{ matrix.ruby }}) + steps: + - uses: actions/checkout@v3 + + - name: Setup ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + + - name: Run tests + run: bundle exec rake parallel_spec + +# TODO: active when acceptance tests have been added +# acceptance: +# name: Litmus Acceptance +# runs-on: ubuntu-20.04 +# env: +# BOLT_GEM: true +# CI: true +# steps: +# - uses: actions/checkout@v3 +# - name: Setup ruby +# uses: ruby/setup-ruby@v1 +# with: +# ruby-version: '2.7.3' +# bundler-cache: true +# +# - name: Provision Testing Environments +# run: | +# bundle exec rake 'litmus:provision_list[default]' +# bundle exec rake 'litmus:install_agent' +# bundle exec rake 'litmus:install_module' +# - name: Run Tests +# run: bundle exec rake 'litmus:acceptance:parallel' +# +# - name: Tear Down +# run: bundle exec rake 'litmus:tear_down' + + tests: + needs: + - unit +# TODO: active when acceptance tests have been added +# - acceptance + runs-on: ubuntu-20.04 + name: Test suite + steps: + - run: echo Test suite completed diff --git a/.gitignore b/.gitignore index 222e35e..988dcbb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,34 +1,28 @@ -# Default .gitignore for Ruby -*.gem -*.rbc -.bundle -.config -coverage -InstalledFiles -lib/bundler/man -pkg -rdoc -spec/reports -test/tmp -test/version_tmp -tmp - -# YARD artifacts +.git/ +.*.sw[op] +.metadata .yardoc -_yardoc -doc/ - -# Vim -*.swp - -# Eclipse -.project - -# OS X +.yardwarns +*.iml +/.bundle/ +/.idea/ +/.vagrant/ +/coverage/ +/bin/ +/doc/ +/Gemfile.local +/Gemfile.lock +/junit/ +/log/ +/pkg/ +/spec/fixtures/manifests/ +/spec/fixtures/modules/ +/tmp/ +/vendor/ +/convert_report.txt +/update_report.txt .DS_Store - -# Puppet -coverage/ -spec/fixtures/manifests/* -spec/fixtures/modules/* -Gemfile.lock +.project +.envrc +/inventory.yaml +/spec/fixtures/litmus_inventory.yaml diff --git a/.pdkignore b/.pdkignore new file mode 100644 index 0000000..a956c8f --- /dev/null +++ b/.pdkignore @@ -0,0 +1,46 @@ +.git/ +.*.sw[op] +.metadata +.yardoc +.yardwarns +*.iml +/.bundle/ +/.idea/ +/.vagrant/ +/coverage/ +/bin/ +/doc/ +/Gemfile.local +/Gemfile.lock +/junit/ +/log/ +/pkg/ +/spec/fixtures/manifests/ +/spec/fixtures/modules/ +/tmp/ +/vendor/ +/convert_report.txt +/update_report.txt +.DS_Store +.project +.envrc +/inventory.yaml +/spec/fixtures/litmus_inventory.yaml +/appveyor.yml +/.editorconfig +/.fixtures.yml +/Gemfile +/.gitattributes +/.gitignore +/.gitlab-ci.yml +/.pdkignore +/.puppet-lint.rc +/Rakefile +/rakelib/ +/.rspec +/.rubocop.yml +/.yardopts +/spec/ +/.vscode/ +/.sync.yml +/.devcontainer/ diff --git a/.puppet-lint.rc b/.puppet-lint.rc new file mode 100644 index 0000000..4fa16f9 --- /dev/null +++ b/.puppet-lint.rc @@ -0,0 +1,3 @@ +--relative +--no-80chars-check +--no-140chars-check diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..16f9cdb --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--format documentation diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..31e8248 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,519 @@ +--- +require: +- rubocop-performance +- rubocop-rspec +AllCops: + DisplayCopNames: true + TargetRubyVersion: '2.5' + Include: + - "**/*.rb" + Exclude: + - bin/* + - ".vendor/**/*" + - "**/Gemfile" + - "**/Rakefile" + - pkg/**/* + - spec/fixtures/**/* + - vendor/**/* + - "**/Puppetfile" + - "**/Vagrantfile" + - "**/Guardfile" +Layout/LineLength: + Description: People have wide screens, use them. + Max: 200 +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 +RSpec/DescribeSymbol: + Exclude: + - spec/unit/facter/**/*.rb +Style/BlockDelimiters: + Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to + be consistent then. + EnforcedStyle: braces_for_chaining +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/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 +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/CaseWhenSplat: + Enabled: true +Performance/ConstantRegexp: + Enabled: true +Performance/MethodObjectAsBlock: + Enabled: true +Performance/RedundantSortBlock: + Enabled: true +Performance/RedundantStringChars: + Enabled: true +Performance/ReverseFirst: + Enabled: true +Performance/SortReverse: + Enabled: true +Performance/Squeeze: + Enabled: true +Performance/StringInclude: + Enabled: true +Performance/Sum: + Enabled: true +Style/CollectionMethods: + Enabled: true +Style/MethodCalledOnDoEndBlock: + Enabled: true +Style/StringMethods: + Enabled: true +Bundler/InsecureProtocolSource: + Enabled: false +Gemspec/DuplicatedAssignment: + Enabled: false +Gemspec/OrderedDependencies: + Enabled: false +Gemspec/RequiredRubyVersion: + Enabled: false +Gemspec/RubyVersionGlobalsUsage: + Enabled: false +Layout/ArgumentAlignment: + Enabled: false +Layout/BeginEndAlignment: + Enabled: false +Layout/ClosingHeredocIndentation: + Enabled: false +Layout/EmptyComment: + Enabled: false +Layout/EmptyLineAfterGuardClause: + Enabled: false +Layout/EmptyLinesAroundArguments: + Enabled: false +Layout/EmptyLinesAroundAttributeAccessor: + Enabled: false +Layout/EndOfLine: + Enabled: false +Layout/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/DuplicateElsifCondition: + Enabled: false +Lint/DuplicateRequire: + Enabled: false +Lint/DuplicateRescueException: + 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/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/ToJSON: + Enabled: false +Lint/TopLevelReturnWithArgument: + Enabled: false +Lint/TrailingCommaInAttributeDeclaration: + 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 +Naming/VariableNumber: + Enabled: false +Performance/BindCall: + Enabled: false +Performance/DeletePrefix: + Enabled: false +Performance/DeleteSuffix: + Enabled: false +Performance/InefficientHashSearch: + Enabled: false +Performance/UnfreezeString: + Enabled: false +Performance/UriDefaultParser: + 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/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/AsciiComments: + Enabled: false +Style/BisectedAttrAccessor: + Enabled: false +Style/CaseLikeIf: + Enabled: false +Style/ClassEqualityComparison: + Enabled: false +Style/ColonMethodDefinition: + Enabled: false +Style/CombinableLoops: + Enabled: false +Style/CommentedKeyword: + Enabled: false +Style/Dir: + 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/FrozenStringLiteralComment: + 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/NegatedUnless: + Enabled: false +Style/NumericPredicate: + Enabled: false +Style/OptionalBooleanParameter: + Enabled: false +Style/OrAssignment: + Enabled: false +Style/RandomWithOffset: + 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/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 +Lint/DuplicateBranch: + Enabled: false +Lint/DuplicateRegexpCharacterClassElement: + Enabled: false +Lint/EmptyBlock: + Enabled: false +Lint/EmptyClass: + Enabled: false +Lint/NoReturnInBeginEndBlocks: + Enabled: false +Lint/ToEnumArguments: + Enabled: false +Lint/UnexpectedBlockArity: + Enabled: false +Lint/UnmodifiedReduceAccumulator: + Enabled: false +Performance/CollectionLiteralInLoop: + Enabled: false +Style/ArgumentsForwarding: + Enabled: false +Style/CollectionCompact: + Enabled: false +Style/DocumentDynamicEvalDefinition: + Enabled: false +Style/NegatedIfElseCondition: + Enabled: false +Style/NilLambda: + Enabled: false +Style/RedundantArgument: + Enabled: false +Style/SwapValues: + Enabled: false diff --git a/.sync.yml b/.sync.yml new file mode 100644 index 0000000..90f2df6 --- /dev/null +++ b/.sync.yml @@ -0,0 +1,39 @@ +# This file can be used to customize the files managed by PDK. +# +# See https://github.com/puppetlabs/pdk-templates/blob/main/README.md +# for more information. +# +# See https://github.com/puppetlabs/pdk-templates/blob/main/config_defaults.yml +# for the default values. +--- +appveyor.yml: + delete: true + +.gitlab-ci.yml: + delete: true + +.travis.yml: + delete: true + +Gemfile: + unmanaged: false + optional: + ':development': + - gem: 'github_changelog_generator' + version: '~> 1.15' + condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')" + ':test': + # provides metadata2gha, needed for unit tests + - gem: 'puppet_metadata' + version: '~> 1.9.0' + +spec/spec_helper.rb: + coverage_report: true + minimum_code_coverage_percentage: 100 + hiera_config: 'hiera' + mock_with: ':rspec' + +Rakefile: + default_disabled_lint_checks: + - '80chars' + - '140chars' diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7385f2a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,57 +0,0 @@ ---- -language: ruby - -cache: bundler - -before_install: - - bundle -v - - rm Gemfile.lock || true - - gem update --system - - gem update bundler - - gem --version - - bundle -v - -sudo: false - -script: 'SPEC_OPTS="--format documentation" bundle exec rake validate lint spec' - -matrix: - fast_finish: true - include: - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 4.5.0" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 4.6.0" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 4.7.0" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 4.8.0" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 4.9.0" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 4.10.0" - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 4" - - rvm: 2.4.1 - env: PUPPET_GEM_VERSION="~> 5" - - rvm: 2.5.1 - env: PUPPET_GEM_VERSION="~> 6" - -notifications: - email: false diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..2f1e4f7 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "puppet.puppet-vscode", + "rebornix.Ruby" + ] +} diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000..29c933b --- /dev/null +++ b/.yardopts @@ -0,0 +1 @@ +--markup markdown diff --git a/Gemfile b/Gemfile index f8bdb02..9584486 100644 --- a/Gemfile +++ b/Gemfile @@ -1,38 +1,76 @@ source ENV['GEM_SOURCE'] || 'https://rubygems.org' -if puppetversion = ENV['PUPPET_GEM_VERSION'] - gem 'puppet', puppetversion, :require => false -else - gem 'puppet', :require => false +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 + +group :development do + 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', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.5.1', require: false if Gem::Requirement.create(['>= 3.0.0', '< 3.0.5']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.6.1', require: false if Gem::Requirement.create(['>= 3.1.0', '< 3.1.3']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.6.3', require: false if Gem::Requirement.create(['>= 3.2.0', '< 4.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "voxpupuli-puppet-lint-plugins", '~> 4.0', require: false + gem "facterdb", '~> 1.18', require: false + gem "metadata-json-lint", '>= 2.0.2', '< 4.0.0', require: false + gem "puppetlabs_spec_helper", '~> 5.0', require: false + gem "rspec-puppet-facts", '~> 2.0', require: false + gem "codecov", '~> 0.2', require: false + gem "dependency_checker", '~> 0.2', require: false + gem "parallel_tests", '= 3.12.1', require: false + gem "pry", '~> 0.10', require: false + gem "simplecov-console", '~> 0.5', require: false + gem "puppet-debugger", '~> 1.0', require: false + gem "rubocop", '= 1.6.1', require: false + gem "rubocop-performance", '= 1.9.1', require: false + gem "rubocop-rspec", '= 2.0.1', require: false + gem "rb-readline", '= 0.5.5', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "github_changelog_generator", '~> 1.15', require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0') +end +group :system_tests do + gem "puppet_litmus", '< 1.0.0', require: false, platforms: [:ruby, :x64_mingw] + gem "serverspec", '~> 2.41', require: false end +group :test do + gem "puppet_metadata", '~> 1.9.0', 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 + +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'), +] -gem 'facter', '>= 1.7.0', :require => false -gem 'rspec-puppet', '>= 2.4.0', :require => false -gem 'puppet-lint', '~> 2.0', :require => false -gem 'puppet-lint-absolute_classname-check', :require => false -gem 'puppet-lint-alias-check', :require => false -gem 'puppet-lint-empty_string-check', :require => false -gem 'puppet-lint-file_ensure-check', :require => false -gem 'puppet-lint-file_source_rights-check', :require => false -gem 'puppet-lint-leading_zero-check', :require => false -gem 'puppet-lint-spaceship_operator_without_tag-check', :require => false -gem 'puppet-lint-trailing_comma-check', :require => false -gem 'puppet-lint-undef_in_function-check', :require => false -gem 'puppet-lint-unquoted_string-check', :require => false -gem 'puppet-lint-variable_contains_upcase', :require => false - -gem 'rspec', '~> 2.0', :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9' -gem 'rake', '~> 10.0', :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9' -gem 'json', '<= 1.8', :require => false if RUBY_VERSION < '2.0.0' -gem 'json_pure', '<= 2.0.1', :require => false if RUBY_VERSION < '2.0.0' -gem 'metadata-json-lint', '0.0.11' if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9' -gem 'metadata-json-lint', '1.0.0' if RUBY_VERSION >= '1.9' && RUBY_VERSION < '2.0' -gem 'metadata-json-lint' if RUBY_VERSION >= '2.0' - -gem 'puppetlabs_spec_helper', '2.0.2', :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9' -gem 'puppetlabs_spec_helper', '>= 2.0.0', :require => false if RUBY_VERSION >= '1.9' -gem 'parallel_tests', '<= 2.9.0', :require => false if RUBY_VERSION < '2.0.0' - -if puppetversion && puppetversion < '5.0' - gem 'semantic_puppet', :require => false +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/README.md b/README.md index f0d19f0..26680fb 100644 --- a/README.md +++ b/README.md @@ -40,108 +40,48 @@ Hash of resource type `cron`. - *Default*: undef -crons_hiera_merge ------------------ -Boolean to control merges of all found instances of types::crons in Hiera. This is useful for specifying cron resources at different levels of the hierarchy and having them all included in the catalog. - -This will default to 'true' in future versions. - -- *Default*: false - execs ----- Hash of resource type `exec`. - *Default*: undef -execs_hiera_merge ------------------ -Boolean to control merges of all found instances of types::execs in Hiera. This is useful for specifying exec resources at different levels of the hierarchy and having them all included in the catalog. - -This will default to 'true' in future versions. - -- *Default*: false - file_lines ---------- Hash of resource type `file_line`. - *Default*: undef -file_lines_hiera_merge ----------------------- -Boolean to control merges of all found instances of types::file_lines in Hiera. -This is useful for specifying file_line resources at different levels of the -hierarchy and having them all included in the catalog. - -This will default to 'true' in future versions. - -- *Default*: true - files ----- Hash of resource type `file`. - *Default*: undef -files_hiera_merge ------------------ -Boolean to control merges of all found instances of types::files in Hiera. This is useful for specifying file resources at different levels of the hierarchy and having them all included in the catalog. - -This will default to 'true' in future versions. - -- *Default*: false - mounts ------ Hash of resource type `mount`. - *Default*: undef -mounts_hiera_merge ------------------- -Boolean to control merges of all found instances of types::mounts in Hiera. This is useful for specifying mount resources at different levels of the hierarchy and having them all included in the catalog. - -This will default to 'true' in future versions. - -- *Default*: false - packages -------- Hash of resource type `package`. - *Default*: undef -packages_hiera_merge --------------------- -Boolean to control merges of all found instances of types::packages in Hiera. This is useful for specifying package resources at different levels of the hierarchy and having them all included in the catalog. - -- *Default*: true - selbooleans ----------- Hash of resource type `selboolean`. - *Default*: undef -selbooleans_hiera_merge ------------------------ -Boolean to control merges of all found instances of types::selboolean in Hiera. This is useful for specifying selboolean resources at different levels of the hierarchy and having them all included in the catalog. - -- *Default*: true - services -------- Hash of resource type `service`. - *Default*: undef -services_hiera_merge --------------------- -Boolean to control merges of all found instances of types::services in Hiera. This is useful for specifying file resources at different levels of the hierarchy and having them all included in the catalog. - -- *Default*: true - === # Defines diff --git a/Rakefile b/Rakefile index 5fe42a7..d68f852 100644 --- a/Rakefile +++ b/Rakefile @@ -1,16 +1,91 @@ +# frozen_string_literal: true + +require 'bundler' +require 'puppet_litmus/rake_tasks' if Bundler.rubygems.find_name('puppet_litmus').any? require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-lint/tasks/puppet-lint' +require 'puppet-syntax/tasks/puppet-syntax' +require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any? +require 'github_changelog_generator/task' if Bundler.rubygems.find_name('github_changelog_generator').any? +require 'puppet-strings/tasks' if Bundler.rubygems.find_name('puppet-strings').any? + +def changelog_user + return unless Rake.application.top_level_tasks.include? "changelog" + returnVal = nil || JSON.load(File.read('metadata.json'))['author'] + raise "unable to find the changelog_user in .sync.yml, or the author in metadata.json" if returnVal.nil? + puts "GitHubChangelogGenerator user:#{returnVal}" + returnVal +end + +def changelog_project + return unless Rake.application.top_level_tasks.include? "changelog" + + returnVal = nil + returnVal ||= begin + metadata_source = JSON.load(File.read('metadata.json'))['source'] + metadata_source_match = metadata_source && metadata_source.match(%r{.*\/([^\/]*?)(?:\.git)?\Z}) + + metadata_source_match && metadata_source_match[1] + end + + raise "unable to find the changelog_project in .sync.yml or calculate it from the source in metadata.json" if returnVal.nil? + + puts "GitHubChangelogGenerator project:#{returnVal}" + returnVal +end + +def changelog_future_release + return unless Rake.application.top_level_tasks.include? "changelog" + returnVal = "v%s" % JSON.load(File.read('metadata.json'))['version'] + raise "unable to find the future_release (version) in metadata.json" if returnVal.nil? + puts "GitHubChangelogGenerator future_release:#{returnVal}" + returnVal +end + +PuppetLint.configuration.send('disable_relative') PuppetLint.configuration.send('disable_80chars') PuppetLint.configuration.send('disable_140chars') -PuppetLint.configuration.relative = true -PuppetLint.configuration.ignore_paths = ['spec/**/*.pp', 'pkg/**/*.pp', 'vendor/**/*.pp'] -desc 'Validate manifests, templates, ruby files and shell scripts' -task :validate do - Dir['spec/**/*.rb', 'lib/**/*.rb'].each do |ruby_file| - sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ + +if Bundler.rubygems.find_name('github_changelog_generator').any? + GitHubChangelogGenerator::RakeTask.new :changelog do |config| + raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil? + config.user = "#{changelog_user}" + config.project = "#{changelog_project}" + config.future_release = "#{changelog_future_release}" + config.exclude_labels = ['maintenance'] + config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)." + config.add_pr_wo_labels = true + config.issues = false + config.merge_prefix = "### UNCATEGORIZED PRS; LABEL THEM ON GITHUB" + config.configure_sections = { + "Changed" => { + "prefix" => "### Changed", + "labels" => ["backwards-incompatible"], + }, + "Added" => { + "prefix" => "### Added", + "labels" => ["enhancement", "feature"], + }, + "Fixed" => { + "prefix" => "### Fixed", + "labels" => ["bug", "documentation", "bugfix"], + }, + } end - Dir['files/**/*.sh'].each do |shell_script| - sh "bash -n #{shell_script}" +else + desc 'Generate a Changelog from GitHub' + task :changelog do + raise < 1.15' + condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')" +EOM end end + diff --git a/data/common.yaml b/data/common.yaml new file mode 100644 index 0000000..2fbf0ff --- /dev/null +++ b/data/common.yaml @@ -0,0 +1 @@ +--- {} diff --git a/hiera.yaml b/hiera.yaml new file mode 100644 index 0000000..545fff3 --- /dev/null +++ b/hiera.yaml @@ -0,0 +1,21 @@ +--- +version: 5 + +defaults: # Used for any hierarchy level that omits these keys. + datadir: data # This path is relative to hiera.yaml's directory. + data_hash: yaml_data # Use the built-in YAML backend. + +hierarchy: + - name: "osfamily/major release" + paths: + # Used to distinguish between Debian and Ubuntu + - "os/%{facts.os.name}/%{facts.os.release.major}.yaml" + - "os/%{facts.os.family}/%{facts.os.release.major}.yaml" + # Used for Solaris + - "os/%{facts.os.family}/%{facts.kernelrelease}.yaml" + - name: "osfamily" + paths: + - "os/%{facts.os.name}.yaml" + - "os/%{facts.os.family}.yaml" + - name: 'common' + path: 'common.yaml' diff --git a/manifests/cron.pp b/manifests/cron.pp index 67f1990..4bf7f91 100644 --- a/manifests/cron.pp +++ b/manifests/cron.pp @@ -1,24 +1,68 @@ -# == Define: types::cron +# @summary Define for cron types +# For a full description of the cron type check: https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md +# +# @param command +# Value passed to command attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#command for more information. +# +# @param ensure +# Value passed to ensure attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#ensure for more information. +# +# @param environment +# Value passed to environment attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#environment for more information. +# +# @param hour +# Value passed to hour attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#hour for more information. +# +# @param minute +# Value passed to minute attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#minute for more information. +# +# @param month +# Value passed to month attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#month for more information. +# +# @param monthday +# Value passed to monthday attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#monthday for more information. +# +# @param provider +# Value passed to provider attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#provider for more information. +# +# @param special +# Value passed to special attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#special for more information. +# +# @param target +# Value passed to target attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#target for more information. +# +# @param user +# Value passed to user attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#user for more information. +# +# @param weekday +# Value passed to weekday attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-cron_core/blob/main/REFERENCE.md#weekday for more information. # define types::cron ( - $command, - $ensure = 'present', - $environment = undef, - $hour = undef, - $minute = undef, - $month = undef, - $monthday = undef, - $provider = undef, - $special = undef, - $target = undef, - $user = undef, - $weekday = undef, + String[1] $command, + Enum['present', 'absent'] $ensure = 'present', + Optional[String[1]] $environment = undef, + Optional[String[1]] $hour = undef, + Optional[String[1]] $minute = undef, + Optional[String[1]] $month = undef, + Optional[String[1]] $monthday = undef, + Optional[String[1]] $provider = undef, + Optional[String[1]] $special = undef, + Optional[String[1]] $target = undef, + Optional[String[1]] $user = undef, + Optional[String[1]] $weekday = undef, ) { - - # validate params - validate_re($ensure, '^(present)|(absent)$', - "types::cron::${name}::ensure is invalid and does not match the regex.") - cron { $name: ensure => $ensure, command => $command, diff --git a/manifests/exec.pp b/manifests/exec.pp index 4bb98e1..534408b 100644 --- a/manifests/exec.pp +++ b/manifests/exec.pp @@ -1,37 +1,93 @@ -# == Define: types::exec +# @summary Define for exec types +# For a full description of the exec type check: https://www.puppet.com/docs/puppet/7/types/exec.html +# +# @param command +# Value passed to command attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-command for more information. +# +# @param creates +# Value passed to creates attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-creates for more information. +# +# @param cwd +# Value passed to cwd attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-cwd for more information. +# +# @param environment +# Value passed to environment attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-environment for more information. +# +# @param group +# Value passed to group attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-group for more information. +# +# @param logoutput +# Value passed to logoutput attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-logoutput for more information. +# +# @param onlyif +# Value passed to onlyif attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-onlyif for more information. +# +# @param path +# Value passed to path attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-path for more information. +# +# @param provider +# Value passed to provider attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-provider for more information. +# +# @param refresh +# Value passed to refresh attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-refresh for more information. +# +# @param refreshonly +# Value passed to refreshonly attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-refreshonly for more information. +# +# @param returns +# Value passed to returns attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-returns for more information. +# +# @param timeout +# Value passed to timeout attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-timeout for more information. +# +# @param tries +# Value passed to tries attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-tries for more information. +# +# @param try_sleep +# Value passed to try_sleep attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-try_sleep for more information. +# +# @param unless +# Value passed to unless attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-unless for more information. +# +# @param user +# Value passed to user attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/exec.html#exec-attribute-user for more information. # define types::exec ( - $command, - $creates = undef, - $cwd = undef, - $environment = undef, - $group = undef, - $logoutput = undef, - $onlyif = undef, - $path = undef, - $provider = undef, - $refresh = undef, - $refreshonly = undef, - $returns = undef, - $timeout = undef, - $tries = undef, - $try_sleep = undef, - $unless = undef, - $user = undef, + String[1] $command, + Optional[Stdlib::Absolutepath] $creates = undef, + Optional[Stdlib::Absolutepath] $cwd = undef, + Optional[String[1]] $environment = undef, + Optional[String[1]] $group = undef, + Optional[Variant[Boolean, Enum['on_failure']]] $logoutput = undef, + Optional[String[1]] $onlyif = undef, + Optional[String[1]] $path = undef, + Optional[Enum['posix', 'shell', 'windows']] $provider = undef, + Optional[String[1]] $refresh = undef, + Optional[Boolean] $refreshonly = undef, + Optional[Integer] $returns = undef, + Optional[Integer] $timeout = undef, + Optional[Integer] $tries = undef, + Optional[Integer] $try_sleep = undef, + Optional[String[1]] $unless = undef, + Optional[String[1]] $user = undef, ) { - - # validate params - if $creates != undef { - validate_absolute_path($creates) - } - if $cwd != undef { - validate_absolute_path($cwd) - } - if $provider != undef { - validate_re($provider, '^(posix|shell|windows)$', - "types::exec::${name}::provider is invalid and does not match the regex.") - } - exec { $name: command => $command, creates => $creates, diff --git a/manifests/file.pp b/manifests/file.pp index 990f46b..246225f 100644 --- a/manifests/file.pp +++ b/manifests/file.pp @@ -1,37 +1,129 @@ -# == Define: types::file +# @summary Define for file types +# For a full description of the exec type check: https://www.puppet.com/docs/puppet/7/types/file.html +# +# @param ensure +# Value passed to ensure attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-ensure for more information. +# +# @param owner +# Value passed to owner attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-owner for more information. +# +# @param group +# Value passed to group attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-group for more information. +# +# @param mode +# Value passed to mode attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-mode for more information. +# +# @param backup +# Value passed to backup attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-backup for more information. +# +# @param checksum +# Value passed to checksum attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-checksum for more information. +# +# @param content +# Value passed to content attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-content for more information. +# +# @param force +# Value passed to force attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-force for more information. +# +# @param ignore +# Value passed to ignore attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-ignore for more information. +# +# @param links +# Value passed to links attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-links for more information. +# +# @param provider +# Value passed to provider attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-provider for more information. +# +# @param purge +# Value passed to purge attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-purge for more information. +# +# @param recurse +# Value passed to recurse attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-recurse for more information. +# +# @param recurselimit +# Value passed to recurselimit attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-recurselimit for more information. +# +# @param replace +# Value passed to replace attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-replace for more information. +# +# @param selinux_ignore_defaults +# Value passed to selinux_ignore_defaults attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-selinux_ignore_defaults for more information. +# +# @param selrange +# Value passed to selrange attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-selrange for more information. +# +# @param selrole +# Value passed to selrole attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-selrole for more information. +# +# @param seltype +# Value passed to seltype attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-seltype for more information. +# +# @param seluser +# Value passed to seluser attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-seluser for more information. +# +# @param show_diff +# Value passed to show_diff attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-show_diff for more information. +# +# @param source +# Value passed to source attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-source for more information. +# +# @param sourceselect +# Value passed to sourceselect attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-sourceselect for more information. +# +# @param target +# Value passed to target attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/file.html#file-attribute-target for more information. # define types::file ( - $ensure = present, - $owner = root, - $group = root, - $mode = '0644', - $backup = undef, - $checksum = undef, - $content = undef, - $force = undef, - $ignore = undef, - $links = undef, - $provider = undef, - $purge = undef, - $recurse = undef, - $recurselimit = undef, - $replace = undef, - $selinux_ignore_defaults = undef, - $selrange = undef, - $selrole = undef, - $seltype = undef, - $seluser = undef, - $show_diff = undef, - $source = undef, - $sourceselect = undef, - $target = undef, + Enum['present', 'absent', 'file', 'directory', 'link'] $ensure = 'present', + String[1] $owner = 'root', + String[1] $group = 'root', + Stdlib::Filemode $mode = '0644', + Optional[String[1]] $backup = undef, + Optional[String[1]] $checksum = undef, + Optional[String[1]] $content = undef, + Optional[String[1]] $force = undef, + Optional[Variant[String[1], Array[String[1]]]] $ignore = undef, + Optional[String[1]] $links = undef, + Optional[String[1]] $provider = undef, + Optional[Variant[Boolean, Enum['yes', 'no']]] $purge = undef, + Optional[Variant[Boolean, Enum['remote']]] $recurse = undef, + Optional[Integer] $recurselimit = undef, + Optional[Variant[Boolean, Enum['yes', 'no']]] $replace = undef, + Optional[Boolean] $selinux_ignore_defaults = undef, + Optional[String[1]] $selrange = undef, + Optional[String[1]] $selrole = undef, + Optional[String[1]] $seltype = undef, + Optional[String[1]] $seluser = undef, + Optional[Variant[Boolean, Enum['yes', 'no']]] $show_diff = undef, + Optional[String[1]] $source = undef, + Optional[String[1]] $sourceselect = undef, + Optional[String[1]] $target = undef, ) { - - # validate params - validate_re($ensure, '^(present)|(absent)|(file)|(directory)|(link)$', - "types::file::${name}::ensure is invalid and does not match the regex.") - validate_absolute_path($name) - validate_re($mode, '^\d{4}$', "types::file::${name}::mode must be exactly 4 digits.") + assert_type(Stdlib::Absolutepath, $name) file { $name: ensure => $ensure, diff --git a/manifests/file_line.pp b/manifests/file_line.pp index c92b8e8..ea8941b 100644 --- a/manifests/file_line.pp +++ b/manifests/file_line.pp @@ -1,21 +1,28 @@ -# == Define: types::file_line +# @summary Define for file_line types +# For a full description of the exec type check: https://github.com/puppetlabs/puppetlabs-stdlib/blob/main/REFERENCE.md#file_line +# +# @param path +# Value passed to path attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-stdlib/blob/main/REFERENCE.md#-file_line--path for more information. +# +# @param line +# Value passed to line attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-stdlib/blob/main/REFERENCE.md#line for more information. +# +# @param match +# Value passed to match attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-stdlib/blob/main/REFERENCE.md#-file_line--match for more information. +# +# @param ensure +# Value passed to ensure attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-stdlib/blob/main/REFERENCE.md#ensure for more information. # define types::file_line ( - $path, - $line, - $match = undef, - $ensure = 'present', + Stdlib::Absolutepath $path, + String[1] $line, + Optional[String[1]] $match = undef, + Enum['present', 'absent'] $ensure = 'present', ) { - - validate_re($ensure, '^(present)|(absent)$', - "types::file_line::${name}::ensure is invalid and does not match the regex.") - validate_absolute_path($path) - validate_string($line) - - if $match { - validate_string($match) - } - file_line { $name: ensure => $ensure, path => $path, diff --git a/manifests/init.pp b/manifests/init.pp index 02de97f..e6ebfb0 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,154 +1,54 @@ -# == Class: types +# @summary Module to manage types +# Puppet module to manage default types through hashes in Hiera with the +# create_resources() function. This module adds validation and helper functions, +# such as ensuring directories. Without specifying any hashes, this module will +# take no action. # -# Module to manage types +# @param crons +# Hash of resource type `cron`. +# +# @param execs +# Hash of resource type `exec`. +# +# @param file_lines +# Hash of resource type `file_line`. +# +# @param files +# Hash of resource type `file`. +# +# @param mounts +# Hash of resource type `mount`. +# +# @param packages +# Hash of resource type `package`. +# +# @param selbooleans +# Hash of resource type `selboolean`. +# +# @param services +# Hash of resource type `service`. +# +# @param ensure_packages +# Array of packages to install with `ensure_packages`. # class types ( - $crons = undef, - $execs = undef, - $file_lines = undef, - $files = undef, - $mounts = undef, - $packages = undef, - $selbooleans = undef, - $services = undef, - $crons_hiera_merge = false, - $execs_hiera_merge = false, - $file_lines_hiera_merge = true, - $files_hiera_merge = false, - $mounts_hiera_merge = false, - $packages_hiera_merge = true, - $selbooleans_hiera_merge = true, - $services_hiera_merge = true, + Hash $crons = {}, + Hash $execs = {}, + Hash $file_lines = {}, + Hash $files = {}, + Hash $mounts = {}, + Hash $packages = {}, + Hash $selbooleans = {}, + Hash $services = {}, + Array $ensure_packages = [], ) { - - if is_string($crons_hiera_merge) { - $crons_hiera_merge_real = str2bool($crons_hiera_merge) - } else { - $crons_hiera_merge_real = $crons_hiera_merge - } - validate_bool($crons_hiera_merge_real) - - $execs_hiera_merge_bool = str2bool($execs_hiera_merge) - - if is_string($file_lines_hiera_merge) { - $file_lines_hiera_merge_real = str2bool($file_lines_hiera_merge) - } else { - $file_lines_hiera_merge_real = $file_lines_hiera_merge - } - validate_bool($file_lines_hiera_merge_real) - - if is_string($files_hiera_merge) { - $files_hiera_merge_real = str2bool($files_hiera_merge) - } else { - $files_hiera_merge_real = $files_hiera_merge - } - validate_bool($files_hiera_merge_real) - - if is_string($mounts_hiera_merge) { - $mounts_hiera_merge_real = str2bool($mounts_hiera_merge) - } else { - $mounts_hiera_merge_real = $mounts_hiera_merge - } - validate_bool($mounts_hiera_merge_real) - - if is_string($packages_hiera_merge) { - $packages_hiera_merge_real = str2bool($packages_hiera_merge) - } else { - $packages_hiera_merge_real = $packages_hiera_merge - } - validate_bool($packages_hiera_merge_real) - - if is_string($selbooleans_hiera_merge) { - $selbooleans_hiera_merge_real = str2bool($selbooleans_hiera_merge) - } else { - $selbooleans_hiera_merge_real = $selbooleans_hiera_merge - } - validate_bool($selbooleans_hiera_merge_real) - - if is_string($services_hiera_merge) { - $services_hiera_merge_real = str2bool($services_hiera_merge) - } else { - $services_hiera_merge_real = $services_hiera_merge - } - validate_bool($services_hiera_merge_real) - - if $crons != undef { - if $crons_hiera_merge_real == true { - $crons_real = hiera_hash('types::crons') - } else { - $crons_real = $crons - } - validate_hash($crons_real) - create_resources('types::cron',$crons_real) - } - - if $execs != undef { - if $execs_hiera_merge_bool == true { - $execs_real = hiera_hash('types::execs') - } else { - $execs_real = $execs - } - validate_hash($execs_real) - create_resources('types::exec',$execs_real) - } - - if $file_lines != undef { - if $file_lines_hiera_merge_real == true { - $file_lines_real = hiera_hash('types::file_lines') - } else { - $file_lines_real = $file_lines - } - validate_hash($file_lines_real) - create_resources('types::file_line',$file_lines_real) - } - - if $files != undef { - if $files_hiera_merge_real == true { - $files_real = hiera_hash('types::files') - } else { - $files_real = $files - } - validate_hash($files_real) - create_resources('types::file',$files_real) - } - - if $mounts != undef { - if $mounts_hiera_merge_real == true { - $mounts_real = hiera_hash('types::mounts') - } else { - $mounts_real = $mounts - } - validate_hash($mounts_real) - create_resources('types::mount',$mounts_real) - } - - if $packages != undef { - if $packages_hiera_merge_real == true { - $packages_real = hiera_hash('types::packages') - } else { - $packages_real = $packages - } - validate_hash($packages_real) - create_resources('types::package',$packages_real) - } - - if $selbooleans != undef { - if $selbooleans_hiera_merge_real == true { - $selbooleans_real = hiera_hash('types::selboolean') - } else { - $selbooleans_real = $selbooleans - } - validate_hash($selbooleans_real) - create_resources('types::selboolean',$selbooleans_real) - } - - if $services != undef { - if $services_hiera_merge_real == true { - $services_real = hiera_hash('types::services') - } else { - $services_real = $services - } - validate_hash($services_real) - create_resources('types::service',$services_real) - } + create_resources('types::cron',$crons) + create_resources('types::exec',$execs) + create_resources('types::file_line',$file_lines) + create_resources('types::file',$files) + create_resources('types::mount',$mounts) + create_resources('types::package',$packages) + create_resources('types::selboolean',$selbooleans) + create_resources('types::service',$services) + ensure_packages($ensure_packages) } diff --git a/manifests/mount.pp b/manifests/mount.pp index 90376b7..ba4d7ef 100644 --- a/manifests/mount.pp +++ b/manifests/mount.pp @@ -1,34 +1,73 @@ -# == Define: types::mount +# @summary Define for mount types +# For a full description of the mount type check: https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md +# +# @param device +# Value passed to device attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#device for more information. +# +# @param fstype +# Value passed to fstype attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#fstype for more information. +# +# @param ensure +# Value passed to ensure attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#ensure for more information. +# +# @param atboot +# Value passed to atboot attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#atboot for more information. +# +# @param blockdevice +# Value passed to blockdevice attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#blockdevice for more information. +# +# @param dump +# Value passed to dump attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#dump for more information. +# +# @param options +# Value passed to options attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#options for more information. +# +# @param pass +# Value passed to pass attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#pass for more information. +# +# @param provider +# Value passed to provider attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#provider for more information. +# +# @param remounts +# Value passed to remounts attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#remounts for more information. +# +# @param target +# Value passed to target attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-mount_core/blob/main/REFERENCE.md#target for more information. # define types::mount ( - $device, - $fstype, - $ensure = mounted, - $atboot = true, - $blockdevice = undef, - $dump = undef, - $options = undef, - $pass = undef, - $provider = undef, - $remounts = undef, - $target = undef, + String[1] $device, + String[1] $fstype, + Enum['defined', 'present', 'unmounted', 'absent', 'mounted'] $ensure = 'mounted', + Boolean $atboot = true, + Optional[String[1]] $blockdevice = undef, + Optional[String[1]] $dump = undef, + Optional[String[1]] $options = undef, + Optional[String[1]] $pass = undef, + Optional[String[1]] $provider = undef, + Optional[Boolean] $remounts = undef, + Optional[String[1]] $target = undef, ) { - - # validate params - validate_re($ensure, '^(present)|(unmounted)|(absent)|(mounted)$', - "types::mount::${name}::ensure is invalid and does not match the regex.") - validate_absolute_path($name) - if $ensure != 'absent' { # ensure target exists - include ::common + include common common::mkdir_p { $name: } } # Solaris cannot handle 'defaults' as a mount option. A common use case would # be to have NFS exports specified in Hiera for multiple systems and if the # system is Solaris, it would throw an error. - if $options == 'defaults' and $::osfamily == 'Solaris' { + if $options == 'defaults' and $facts['os']['family'] == 'Solaris' { $options_real = '-' } else { $options_real = $options diff --git a/manifests/package.pp b/manifests/package.pp index 52bfe52..6b13238 100644 --- a/manifests/package.pp +++ b/manifests/package.pp @@ -1,32 +1,53 @@ -# == Define: types::package +# @summary Define for package types +# For a full description of the exec type check: https://www.puppet.com/docs/puppet/7/types/package.html +# +# @param ensure +# Value passed to ensure attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/package.html#package-attribute-ensure for more information. +# +# @param adminfile +# Value passed to adminfile attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/package.html#package-attribute-adminfile for more information. +# +# @param allowcdrom +# Value passed to allowcdrom attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/package.html#package-attribute-allowcdrom for more information. +# +# @param configfiles +# Value passed to configfiles attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/package.html#package-attribute-configfiles for more information. +# +# @param install_options +# Value passed to install_options attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/package.html#package-attribute-install_options for more information. +# +# @param provider +# Value passed to provider attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/package.html#package-attribute-provider for more information. +# +# @param responsefile +# Value passed to responsefile attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/package.html#package-attribute-responsefile for more information. +# +# @param source +# Value passed to source attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/package.html#package-attribute-source for more information. +# +# @param uninstall_options +# Value passed to uninstall_options attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/package.html#package-attribute-uninstall_options for more information. # define types::package ( - $ensure = 'present', - $adminfile = undef, - $allowcdrom = undef, - $configfiles = undef, - $install_options = undef, - $provider = undef, - $responsefile = undef, - $source = undef, - $uninstall_options = undef, + Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'] $ensure = 'present', + Optional[Stdlib::Absolutepath] $adminfile = undef, + Optional[String[1]] $allowcdrom = undef, + Optional[Enum['keep', 'replace']] $configfiles = undef, + Optional[String[1]] $install_options = undef, + Optional[String[1]] $provider = undef, + Optional[Stdlib::Absolutepath] $responsefile = undef, + Optional[String[1]] $source = undef, + Optional[String[1]] $uninstall_options = undef, ) { - - validate_string($ensure) - - if $adminfile != undef { - validate_absolute_path($adminfile) - } - - if $configfiles != undef { - validate_re($configfiles, '^(keep)|(replace)$', - "types::package::${name}::configfiles is invalid and does not match the regex.") - } - - if $responsefile != undef { - validate_absolute_path($responsefile) - } - package { $name: ensure => $ensure, adminfile => $adminfile, diff --git a/manifests/selboolean.pp b/manifests/selboolean.pp index f422328..ff98493 100644 --- a/manifests/selboolean.pp +++ b/manifests/selboolean.pp @@ -1,18 +1,23 @@ -# == Define: types::selboolean +# @summary Define for selboolean types +# For a full description of the cron type check: https://github.com/puppetlabs/puppetlabs-selinux_core/blob/main/REFERENCE.md +# +# @param value +# Value passed to value attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-selinux_core/blob/main/REFERENCE.md#value for more information. +# +# @param persistent +# Value passed to persistent attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-selinux_core/blob/main/REFERENCE.md#persistent for more information. +# +# @param provider +# Value passed to provider attribute. Unused if empty. +# Check https://github.com/puppetlabs/puppetlabs-selinux_core/blob/main/REFERENCE.md#provider for more information. # define types::selboolean ( - $value, - $persistent = false, - $provider = undef, + Enum['on', 'off'] $value, + Boolean $persistent = false, + Optional[String[1]] $provider = undef, ) { - - validate_re($value, '^(on)|(off)$', - "types::selboolean::${name}::value is invalid should be 'on' or 'off'.") - validate_bool($persistent) - if $provider != undef { - validate_string($provider) - } - selboolean { $name: value => $value, persistent => $persistent, diff --git a/manifests/service.pp b/manifests/service.pp index ce07a51..379f4de 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -1,37 +1,78 @@ -# == Define: types::service +# @summary Define for service types +# For a full description of the exec type check: https://www.puppet.com/docs/puppet/7/types/service.html +# +# @param ensure +# Value passed to ensure attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-ensure for more information. +# +# @param binary +# Value passed to binary attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-binary for more information. +# +# @param control +# Value passed to control attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-control for more information. +# +# @param enable +# Value passed to enable attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-enable for more information. +# +# @param hasrestart +# Value passed to hasrestart attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-hasrestart for more information. +# +# @param hasstatus +# Value passed to hasstatus attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-hasstatus for more information. +# +# @param manifest +# Value passed to manifest attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-manifest for more information. +# +# @param path +# Value passed to path attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-path for more information. +# +# @param pattern +# Value passed to pattern attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-pattern for more information. +# +# @param provider +# Value passed to provider attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-provider for more information. +# +# @param restart +# Value passed to restart attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-restart for more information. +# +# @param start +# Value passed to start attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-start for more information. +# +# @param status +# Value passed to status attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-status for more information. +# +# @param stop +# Value passed to stop attribute. Unused if empty. +# Check https://www.puppet.com/docs/puppet/7/types/service.html#service-attribute-stop for more information. # define types::service ( - $ensure = 'running', - $binary = undef, - $control = undef, - $enable = true, - $hasrestart = undef, - $hasstatus = undef, - $manifest = undef, - $path = undef, - $pattern = undef, - $provider = undef, - $restart = undef, - $start = undef, - $status = undef, - $stop = undef, + Variant[Boolean, Enum['stopped', 'running', 'false', 'true']] $ensure = 'running', + Optional[String[1]] $binary = undef, + Optional[String[1]] $control = undef, + Variant[Boolean, Enum['true', 'false', 'manual']] $enable = true, + Optional[Variant[Boolean, Enum['true', 'false']]] $hasrestart = undef, + Optional[Variant[Boolean, Enum['true', 'false']]] $hasstatus = undef, + Optional[String[1]] $manifest = undef, + Optional[String[1]] $path = undef, + Optional[String[1]] $pattern = undef, + Optional[String[1]] $provider = undef, + Optional[String[1]] $restart = undef, + Optional[String[1]] $start = undef, + Optional[String[1]] $status = undef, + Optional[String[1]] $stop = undef, ) { - - # validate params - if $ensure != undef { - validate_re($ensure, '^(stopped|false|running|true)$', - "types::service::${name}::ensure can only be , , or and is set to <${ensure}>") - } - - if $enable != undef { - if is_string($enable) { - validate_re($enable, '^(true|false|manual)$', - "types::service::${name}::enable can only be , or and is set to <${enable}>") - } else { - validate_bool($enable) - } - } - service { $name: ensure => $ensure, binary => $binary, diff --git a/metadata.json b/metadata.json index 1b09baa..0d4902e 100644 --- a/metadata.json +++ b/metadata.json @@ -3,20 +3,31 @@ "version": "1.13.0", "author": "ghoneycutt", "summary": "Puppet module to manage default types through hashes in Hiera", - "description": "Puppet module to manage default types through hashes in Hiera with the\ncreate_resources() function. This module adds validation and helper functions,\nsuch as ensuring directories. Without specifying any hashes, this module will take no action.", "license": "Apache-2.0", - "source": "git://github.com/ghoneycutt/puppet-module-types.git", + "source": "git://github.com:ghoneycutt/puppet-module-types.git", "project_page": "https://github.com/ghoneycutt/puppet-module-types", "issues_url": "https://github.com/ghoneycutt/puppet-module-types/issues", - "requirements": [ - {"name":"puppet","version_requirement":">= 3.2.0 < 7.0.0"} - ], "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">= 4.6.0 < 7.0.0"}, - {"name":"ghoneycutt/common","version_requirement":">= 1.7.0 < 2.0.0"}, - {"name":"puppetlabs/cron_core","version_requirement":">= 1.0.0 <2.0.0"}, - {"name":"puppetlabs/mount_core","version_requirement":">= 1.0.2 <2.0.0"}, - {"name":"puppetlabs/selinux_core","version_requirement":">= 1.0.1 <2.0.0"} + { + "name": "puppetlabs/stdlib", + "version_requirement": ">= 5.0.0 < 9.0.0" + }, + { + "name": "ghoneycutt/common", + "version_requirement": ">= 1.7.0 < 2.0.0" + }, + { + "name": "puppetlabs/cron_core", + "version_requirement": ">= 1.0.0 < 2.0.0" + }, + { + "name": "puppetlabs/mount_core", + "version_requirement": ">= 1.0.2 < 2.0.0" + }, + { + "name": "puppetlabs/selinux_core", + "version_requirement": ">= 1.0.1 < 2.0.0" + } ], "operatingsystem_support": [ { @@ -49,5 +60,15 @@ { "operatingsystem": "Ubuntu" } - ] + ], + "requirements": [ + { + "name": "puppet", + "version_requirement": ">= 6.0.0 < 8.0.0" + } + ], + "description": "Puppet module to manage default types through hashes in Hiera with the\ncreate_resources() function. This module adds validation and helper functions,\nsuch as ensuring directories. Without specifying any hashes, this module will take no action.", + "pdk-version": "2.7.1", + "template-url": "pdk-default#2.7.4", + "template-ref": "tags/2.7.4-0-g58edf57" } diff --git a/pdk.yaml b/pdk.yaml new file mode 100644 index 0000000..4bef4bd --- /dev/null +++ b/pdk.yaml @@ -0,0 +1,2 @@ +--- +ignore: [] diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 504bba8..048bd40 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1,73 +1,88 @@ require 'spec_helper' describe 'types' do - - it { should compile.with_all_deps } + it { is_expected.to compile.with_all_deps } context 'with default options' do - it { should contain_class('types') } + it { is_expected.to contain_class('types') } end context 'with mounts specified as a hash' do - let(:facts) { { :osfamily => 'RedHat' } } - let(:params) { { :mounts => { - '/mnt' => { - 'device' => '/dev/dvd', - 'fstype' => 'iso9660', - 'atboot' => 'no', - 'remounts' => 'true', - }, - '/srv/nfs/home' => { - 'device' => 'nfsserver:/export/home', - 'fstype' => 'nfs', - 'options' => 'rw,rsize=8192,wsize=8192', - 'remounts' => 'true', - 'blockdevice' => '-', + let(:facts) { { osfamily: 'RedHat' } } + let(:params) do + { + mounts: { + '/mnt' => { + 'device' => '/dev/dvd', + 'fstype' => 'iso9660', + 'atboot' => false, + 'remounts' => true, + }, + '/srv/nfs/home' => { + 'device' => 'nfsserver:/export/home', + 'fstype' => 'nfs', + 'options' => 'rw,rsize=8192,wsize=8192', + 'remounts' => true, + 'blockdevice' => '-', + } + } } - } } } - - it { should contain_class('types') } - - it { - should contain_mount('/mnt').with({ - 'ensure' => 'mounted', - 'device' => '/dev/dvd', - 'fstype' => 'iso9660', - 'atboot' => 'no', - 'remounts' => 'true', - }) - } - - it { - should contain_exec('mkdir_p-/mnt').with({ - 'command' => 'mkdir -p /mnt', - 'unless' => 'test -d /mnt', - }) - } - - it { - should contain_mount('/srv/nfs/home').with({ - 'device' => 'nfsserver:/export/home', - 'fstype' => 'nfs', - 'options' => 'rw,rsize=8192,wsize=8192', - 'remounts' => 'true', - 'blockdevice' => '-', - }) - } - - it { - should contain_exec('mkdir_p-/srv/nfs/home').with({ - 'command' => 'mkdir -p /srv/nfs/home', - 'unless' => 'test -d /srv/nfs/home', - }) - } + end + + it { is_expected.to contain_class('types') } + + it do + is_expected.to contain_mount('/mnt').with( + { + 'ensure' => 'mounted', + 'device' => '/dev/dvd', + 'fstype' => 'iso9660', + 'atboot' => false, + 'remounts' => true, + }, + ) + end + + it do + is_expected.to contain_exec('mkdir_p-/mnt').with( + { + 'command' => 'mkdir -p /mnt', + 'unless' => 'test -d /mnt', + }, + ) + end + + it do + is_expected.to contain_mount('/srv/nfs/home').with( + { + 'device' => 'nfsserver:/export/home', + 'fstype' => 'nfs', + 'options' => 'rw,rsize=8192,wsize=8192', + 'remounts' => true, + 'blockdevice' => '-', + }, + ) + end + + it do + is_expected.to contain_exec('mkdir_p-/srv/nfs/home').with( + { + 'command' => 'mkdir -p /srv/nfs/home', + 'unless' => 'test -d /srv/nfs/home', + }, + ) + end + + it { is_expected.to contain_types__mount('/mnt') } # only needed for 100% resource coverage + it { is_expected.to contain_types__mount('/srv/nfs/home') } # only needed for 100% resource coverage + it { is_expected.to contain_common__mkdir_p('/mnt') } # only needed for 100% resource coverage + it { is_expected.to contain_common__mkdir_p('/srv/nfs/home') } # only needed for 100% resource coverage end context 'with file_lines specified as a hash' do - let(:facts) { { :osfamily => 'RedHat' } } - let :params do + let(:facts) { { osfamily: 'RedHat' } } + let(:params) do { - :file_lines_hiera_merge => 'false', - :file_lines => { + file_lines: { 'some_file' => { 'path' => '/tmp/foo', 'line' => 'option=asdf', @@ -86,145 +101,173 @@ } end - it { should contain_class('types') } - - it { - should contain_file_line('some_file').with({ - 'path' => '/tmp/foo', - 'line' => 'option=asdf', - 'match' => nil, - }) - } - - it { - should contain_file_line('some_other_file').with({ - 'path' => '/tmp/bar', - 'line' => 'option=asdf', - 'match' => '^option', - }) - } - - it { - should contain_file_line('another_line').with({ - 'ensure' => 'absent', - 'path' => '/tmp/bar', - 'line' => 'param=x', - }) - } + it { is_expected.to contain_class('types') } + + it do + is_expected.to contain_file_line('some_file').with( + { + 'path' => '/tmp/foo', + 'line' => 'option=asdf', + 'match' => nil, + }, + ) + end + + it do + is_expected.to contain_file_line('some_other_file').with( + { + 'path' => '/tmp/bar', + 'line' => 'option=asdf', + 'match' => '^option', + }, + ) + end + + it do + is_expected.to contain_file_line('another_line').with( + { + 'ensure' => 'absent', + 'path' => '/tmp/bar', + 'line' => 'param=x', + }, + ) + end + + it { is_expected.to contain_types__file_line('some_file') } # only needed for 100% resource coverage + it { is_expected.to contain_types__file_line('some_other_file') } # only needed for 100% resource coverage + it { is_expected.to contain_types__file_line('another_line') } # only needed for 100% resource coverage end context 'with files specified as a hash' do - let(:facts) { { :osfamily => 'RedHat' } } - let(:params) { { :files => { - '/localdisk' => { - 'ensure' => 'directory', - 'mode' => '0755', - 'owner' => 'root', - 'group' => 'root', - }, - '/tmp/file1' => { - 'ensure' => 'present', - 'mode' => '0777', - 'owner' => 'root', - 'group' => 'root', - 'content' => 'This is the content', - 'backup' => 'foobucket', - 'checksum' => 'none', - 'force' => 'purge', - 'ignore' => ['.svn', '.foo'], - 'links' => 'follow', - 'provider' => 'posix', - 'purge' => true, - 'recurse' => true, - 'recurselimit' => 2, - 'replace' => false, - 'selinux_ignore_defaults' => false, - 'selrange' => 's0', - 'selrole' => 'object_r', - 'seltype' => 'var_t', - 'seluser' => 'system_u', - 'show_diff' => false, - 'source' => 'puppet://modules/types/mydir', - 'sourceselect' => 'first', - }, - '/tmp/file2' => { - }, - '/softlink' => { - 'ensure' => 'link', - 'target' => '/etc/motd', - }, - '/tmp/dir' => { - 'ensure' => 'directory', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0777', - }, - } } } - - it { should contain_class('types') } - - it { - should contain_file('/localdisk').with({ - 'ensure' => 'directory', - 'mode' => '0755', - 'owner' => 'root', - 'group' => 'root', - }) - } - - it { - should contain_file('/tmp/file1').with({ - 'ensure' => 'present', - 'mode' => '0777', - 'owner' => 'root', - 'group' => 'root', - 'content' => 'This is the content', - 'backup' => 'foobucket', - 'checksum' => 'none', - 'force' => 'purge', - 'ignore' => ['.svn', '.foo'], - 'links' => 'follow', - 'provider' => 'posix', - 'purge' => true, - 'recurse' => true, - 'recurselimit' => 2, - 'replace' => false, - 'selinux_ignore_defaults' => false, - 'selrange' => 's0', - 'selrole' => 'object_r', - 'seltype' => 'var_t', - 'seluser' => 'system_u', - 'show_diff' => false, - 'source' => 'puppet://modules/types/mydir', - 'sourceselect' => 'first', - }) - } - - it { - should contain_file('/tmp/file2').with({ - 'ensure' => 'present', - 'mode' => '0644', - 'owner' => 'root', - 'group' => 'root', - }) - } - - it { - should contain_file('/tmp/dir').with({ - 'ensure' => 'directory', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0777', - }) - } + let(:facts) { { osfamily: 'RedHat' } } + let(:params) do + { + files: { + '/localdisk' => { + 'ensure' => 'directory', + 'mode' => '0755', + 'owner' => 'root', + 'group' => 'root', + }, + '/tmp/file1' => { + 'ensure' => 'present', + 'mode' => '0777', + 'owner' => 'root', + 'group' => 'root', + 'content' => 'This is the content', + 'backup' => 'foobucket', + 'checksum' => 'none', + 'force' => 'purge', + 'ignore' => ['.svn', '.foo'], + 'links' => 'follow', + 'provider' => 'posix', + 'purge' => true, + 'recurse' => true, + 'recurselimit' => 2, + 'replace' => false, + 'selinux_ignore_defaults' => false, + 'selrange' => 's0', + 'selrole' => 'object_r', + 'seltype' => 'var_t', + 'seluser' => 'system_u', + 'show_diff' => false, + 'source' => 'puppet://modules/types/mydir', + 'sourceselect' => 'first', + }, + '/tmp/file2' => { + }, + '/softlink' => { + 'ensure' => 'link', + 'target' => '/etc/motd', + }, + '/tmp/dir' => { + 'ensure' => 'directory', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0777', + }, + } + } + end + + it { is_expected.to contain_class('types') } + + it do + is_expected.to contain_file('/localdisk').with( + { + 'ensure' => 'directory', + 'mode' => '0755', + 'owner' => 'root', + 'group' => 'root', + }, + ) + end + + it do + is_expected.to contain_file('/tmp/file1').with( + { + 'ensure' => 'present', + 'mode' => '0777', + 'owner' => 'root', + 'group' => 'root', + 'content' => 'This is the content', + 'backup' => 'foobucket', + 'checksum' => 'none', + 'force' => 'purge', + 'ignore' => ['.svn', '.foo'], + 'links' => 'follow', + 'provider' => 'posix', + 'purge' => true, + 'recurse' => true, + 'recurselimit' => 2, + 'replace' => false, + 'selinux_ignore_defaults' => false, + 'selrange' => 's0', + 'selrole' => 'object_r', + 'seltype' => 'var_t', + 'seluser' => 'system_u', + 'show_diff' => false, + 'source' => 'puppet://modules/types/mydir', + 'sourceselect' => 'first', + }, + ) + end + + it do + is_expected.to contain_file('/tmp/file2').with( + { + 'ensure' => 'present', + 'mode' => '0644', + 'owner' => 'root', + 'group' => 'root', + }, + ) + end + + it do + is_expected.to contain_file('/tmp/dir').with( + { + 'ensure' => 'directory', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0777', + }, + ) + end + + it { is_expected.to contain_file('/softlink') } # only needed for 100% resource coverage + it { is_expected.to contain_types__file('/localdisk') } # only needed for 100% resource coverage + it { is_expected.to contain_types__file('/softlink') } # only needed for 100% resource coverage + it { is_expected.to contain_types__file('/tmp/dir') } # only needed for 100% resource coverage + it { is_expected.to contain_types__file('/tmp/file1') } # only needed for 100% resource coverage + it { is_expected.to contain_types__file('/tmp/file2') } # only needed for 100% resource coverage end context 'with packages specified as a hash' do - let(:facts) { { :osfamily => 'RedHat' } } - let :params do + let(:facts) { { osfamily: 'RedHat' } } + let(:params) do { - :packages_hiera_merge => 'false', - :packages => { + packages: { 'pkg1' => { 'ensure' => 'present', }, @@ -238,34 +281,42 @@ } end - it { should contain_class('types') } + it { is_expected.to contain_class('types') } - it { - should contain_package('pkg1').with({ - 'ensure' => 'present', - }) - } + it do + is_expected.to contain_package('pkg1').with( + { + 'ensure' => 'present', + }, + ) + end - it { - should contain_package('pkg2').with({ - 'ensure' => 'absent', - }) - } + it do + is_expected.to contain_package('pkg2').with( + { + 'ensure' => 'absent', + }, + ) + end - it { - should contain_package('pkg3').with({ - 'ensure' => 'latest', - }) - } + it do + is_expected.to contain_package('pkg3').with( + { + 'ensure' => 'latest', + }, + ) + end + it { is_expected.to contain_types__package('pkg1') } + it { is_expected.to contain_types__package('pkg2') } # only needed for 100% resource coverage + it { is_expected.to contain_types__package('pkg3') } # only needed for 100% resource coverage end context 'with selboolean specified as a hash' do - let(:facts) { { :osfamily => 'RedHat' } } - let :params do + let(:facts) { { osfamily: 'RedHat' } } + let(:params) do { - :selbooleans_hiera_merge => 'false', - :selbooleans => { + selbooleans: { 'nfs_export_all_ro' => { 'value' => 'on', }, @@ -277,125 +328,145 @@ } end - it { should contain_class('types') } - it { - should contain_selboolean('nfs_export_all_ro').with({ - 'value' => 'on', - }) - } - it { - should contain_selboolean('nfs_export_all_rw').with({ - 'persistent' => true, - 'value' => 'on', - }) - } + it { is_expected.to contain_class('types') } + it do + is_expected.to contain_selboolean('nfs_export_all_ro').with( + { + 'value' => 'on', + }, + ) + end + + it do + is_expected.to contain_selboolean('nfs_export_all_rw').with( + { + 'persistent' => true, + 'value' => 'on', + }, + ) + end + + it { is_expected.to contain_types__selboolean('nfs_export_all_ro') } # only needed for 100% resource coverage + it { is_expected.to contain_types__selboolean('nfs_export_all_rw') } # only needed for 100% resource coverage end context 'with selboolean specified as an invalid type' do - let(:facts) { { :osfamily => 'RedHat' } } - let(:params) { { :selbooleans => ['not','a','hash'] } } + let(:facts) { { osfamily: 'RedHat' } } + let(:params) { { selbooleans: ['not', 'a', 'hash'] } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') + is_expected.to contain_class('types') }.to raise_error(Puppet::Error) end end context 'with mounts specified as an invalid type' do - let(:params) { { :mounts => ['not','a','hash'] } } + let(:params) { { mounts: ['not', 'a', 'hash'] } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/\["not", "a", "hash"\] is not a Hash\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a Hash value}) end end context 'with packages specified as an invalid type' do - let(:params) { { :packages => ['not','a','hash'] } } + let(:params) { { packages: ['not', 'a', 'hash'] } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') + is_expected.to contain_class('types') }.to raise_error(Puppet::Error) end end context 'with file_lines specified as an invalid type' do - let(:params) { { :file_lines => ['not','a','hash'] } } + let(:params) { { file_lines: ['not', 'a', 'hash'] } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') + is_expected.to contain_class('types') }.to raise_error(Puppet::Error) end end context 'with files specified as an invalid type' do - let(:params) { { :files => ['not','a','hash'] } } + let(:params) { { files: ['not', 'a', 'hash'] } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/\["not", "a", "hash"\] is not a Hash\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a Hash value}) end end context 'with cron specified as a hash' do - let(:facts) { { :osfamily => 'RedHat' } } - let(:params) { { :crons => { - 'cronjob-1' => { - 'command' => '/usr/local/bin/some-script.sh', - 'hour' => '0', - 'minute' => '10', - 'weekday' => '0', - }, - 'cronjob-2' => { - 'command' => '/usr/local/bin/script.sh', - 'hour' => '23', - 'minute' => '0', - 'user' => 'www-user', + let(:facts) { { osfamily: 'RedHat' } } + let(:params) do + { + crons: { + 'cronjob-1' => { + 'command' => '/usr/local/bin/some-script.sh', + 'hour' => '0', + 'minute' => '10', + 'weekday' => '0', + }, + 'cronjob-2' => { + 'command' => '/usr/local/bin/script.sh', + 'hour' => '23', + 'minute' => '0', + 'user' => 'www-user', + } + } } - } } } - - it { should contain_class('types') } - - it { - should contain_cron('cronjob-1').with({ - 'ensure' => 'present', - 'command' => '/usr/local/bin/some-script.sh', - 'hour' => '0', - 'minute' => '10', - 'weekday' => '0', - }) - } - it { - should contain_cron('cronjob-2').with({ - 'ensure' => 'present', - 'command' => '/usr/local/bin/script.sh', - 'hour' => '23', - 'minute' => '0', - 'user' => 'www-user', - }) - } + end + + it { is_expected.to contain_class('types') } + + it do + is_expected.to contain_cron('cronjob-1').with( + { + 'ensure' => 'present', + 'command' => '/usr/local/bin/some-script.sh', + 'hour' => '0', + 'minute' => '10', + 'weekday' => '0', + }, + ) + end + + it do + is_expected.to contain_cron('cronjob-2').with( + { + 'ensure' => 'present', + 'command' => '/usr/local/bin/script.sh', + 'hour' => '23', + 'minute' => '0', + 'user' => 'www-user', + }, + ) + end + + it { is_expected.to contain_types__cron('cronjob-1') } # only needed for 100% resource coverage + it { is_expected.to contain_types__cron('cronjob-2') } # only needed for 100% resource coverage end context 'with cron specified as an invalid type' do - let(:params) { { :crons => ['not','a','hash'] } } + let(:params) { { crons: ['not', 'a', 'hash'] } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/\["not", "a", "hash"\] is not a Hash\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a Hash value}) end end context 'with exec specified as a hash' do - let(:facts) { { :osfamily => 'RedHat' } } + let(:facts) { { osfamily: 'RedHat' } } let(:params) do { - :execs => { + execs: { 'exec-1' => { 'command' => '/usr/local/bin/some-script.sh', 'creates' => '/tmp/touch', @@ -422,41 +493,48 @@ } end - it { should contain_class('types') } + it { is_expected.to contain_class('types') } it do - should contain_types__exec('exec-1').with({ - 'command' => '/usr/local/bin/some-script.sh', - 'creates' => '/tmp/touch', - 'cwd' => '/tmp', - 'environment' => 'var=value', - 'group' => 'group-1', - 'logoutput' => true, - 'onlyif' => '/onlyif.sh', - 'path' => '/tmp', - 'provider' => 'shell', - }) - end - it { - should contain_types__exec('exec-2').with({ - 'command' => '/usr/local/bin/script.sh', - 'refresh' => '/refresh.sh', - 'refreshonly' => true, - 'returns' => 242, - 'timeout' => 3, - 'tries' => 3, - 'try_sleep' => 3, - 'unless' => '/unless.sh', - 'user' => 'tester', - }) - } + is_expected.to contain_types__exec('exec-1').with( + { + 'command' => '/usr/local/bin/some-script.sh', + 'creates' => '/tmp/touch', + 'cwd' => '/tmp', + 'environment' => 'var=value', + 'group' => 'group-1', + 'logoutput' => true, + 'onlyif' => '/onlyif.sh', + 'path' => '/tmp', + 'provider' => 'shell', + }, + ) + end + + it do + is_expected.to contain_types__exec('exec-2').with( + { + 'command' => '/usr/local/bin/script.sh', + 'refresh' => '/refresh.sh', + 'refreshonly' => true, + 'returns' => 242, + 'timeout' => 3, + 'tries' => 3, + 'try_sleep' => 3, + 'unless' => '/unless.sh', + 'user' => 'tester', + }, + ) + end + + it { is_expected.to contain_exec('exec-1') } # only needed for 100% resource coverage + it { is_expected.to contain_exec('exec-2') } # only needed for 100% resource coverage end context 'with services specified as a hash' do - let :params do + let(:params) do { - :services_hiera_merge => 'false', - :services => { + services: { 'service-stopped' => { 'ensure' => 'stopped', 'enable' => 'false', @@ -469,29 +547,66 @@ } end - it { should contain_class('types') } - - it { - should contain_service('service-stopped').with({ - 'ensure' => 'stopped', - 'enable' => 'false', - }) - } - it { - should contain_service('service-running').with({ - 'ensure' => 'running', - 'enable' => 'true', - }) - } + it { is_expected.to contain_class('types') } + + it do + is_expected.to contain_service('service-stopped').with( + { + 'ensure' => 'stopped', + 'enable' => 'false', + }, + ) + end + + it do + is_expected.to contain_service('service-running').with( + { + 'ensure' => 'running', + 'enable' => 'true', + }, + ) + end + + it { is_expected.to contain_types__service('service-stopped') } # only needed for 100% resource coverage + it { is_expected.to contain_types__service('service-running') } # only needed for 100% resource coverage end context 'with service specified as an invalid type' do - let(:params) { { :services => ['not','a','hash'] } } + let(:params) { { services: ['not', 'a', 'hash'] } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') + is_expected.to contain_class('types') }.to raise_error(Puppet::Error) end end + + context 'with ensure_packages specified as an array [pkg1, pkg2]' do + let(:params) do + { + ensure_packages: ['pkg1', 'pkg2'], + } + end + + it { is_expected.to contain_package('pkg1') } + it { is_expected.to contain_package('pkg2') } + end + + context 'with ensure_packages specified as an array with duplicate package names [dupllicate, dupllicate, unique]' do + let(:params) { { ensure_packages: ['dupllicate', 'dupllicate', 'unique'] } } + + it { is_expected.to contain_package('dupllicate') } + it { is_expected.to contain_package('unique') } + end + + context 'with ensure_packages specifying an already declared package name' do + let(:params) { { ensure_packages: ['dupllicate', 'unique'] } } + let(:pre_condition) do + "package { 'dupllicate': + }" + end + + it { is_expected.to contain_package('dupllicate') } + it { is_expected.to contain_package('unique') } + end end diff --git a/spec/default_facts.yml b/spec/default_facts.yml new file mode 100644 index 0000000..f777abf --- /dev/null +++ b/spec/default_facts.yml @@ -0,0 +1,8 @@ +# Use default_module_facts.yml for module specific facts. +# +# Facts specified here will override the values provided by rspec-puppet-facts. +--- +ipaddress: "172.16.254.254" +ipaddress6: "FE80:0000:0000:0000:AAAA:AAAA:AAAA" +is_pe: false +macaddress: "AA:AA:AA:AA:AA:AA" diff --git a/spec/defines/cron_spec.rb b/spec/defines/cron_spec.rb index 970e0f6..82f9fd6 100644 --- a/spec/defines/cron_spec.rb +++ b/spec/defines/cron_spec.rb @@ -1,72 +1,75 @@ require 'spec_helper' describe 'types::cron' do - context 'cron with bare minimum specified' do let(:title) { 'cronjob-1' } - let(:params) do - { :command => '/usr/local/bin/script.sh' } - end - let(:facts) { { :osfamily => 'RedHat' } } + let(:params) { { command: '/usr/local/bin/script.sh' } } + let(:facts) { { osfamily: 'RedHat' } } - it { - should contain_cron('cronjob-1').with({ - 'ensure' => 'present', - 'command' => '/usr/local/bin/script.sh', - }) - } + it do + is_expected.to contain_cron('cronjob-1').with( + { + 'ensure' => 'present', + 'command' => '/usr/local/bin/script.sh', + }, + ) + end end context 'cron with all options specified' do let(:title) { 'cronjob-1' } let(:params) do - { :command => '/usr/local/bin/script.sh', - :ensure => 'absent', - :environment => '/bin:/usr/bin', - :hour => '1', - :minute => '10', - :month => 'Jan', - :monthday => '1', - :provider => 'crontab', - :special => 'absent', - :target => 'root', - :user => 'root', - :weekday => '6', + { + command: '/usr/local/bin/script.sh', + ensure: 'absent', + environment: '/bin:/usr/bin', + hour: '1', + minute: '10', + month: 'Jan', + monthday: '1', + provider: 'crontab', + special: 'absent', + target: 'root', + user: 'root', + weekday: '6', } end - let(:facts) { { :osfamily => 'RedHat' } } + let(:facts) { { osfamily: 'RedHat' } } - it { - should contain_cron('cronjob-1').with({ - 'ensure' => 'absent', - 'command' => '/usr/local/bin/script.sh', - 'environment' => '/bin:/usr/bin', - 'hour' => '1', - 'minute' => '10', - 'month' => 'Jan', - 'monthday' => '1', - 'provider' => 'crontab', - 'special' => 'absent', - 'target' => 'root', - 'user' => 'root', - 'weekday' => '6', - }) - } + it do + is_expected.to contain_cron('cronjob-1').only_with( + { + 'ensure' => 'absent', + 'command' => '/usr/local/bin/script.sh', + 'environment' => '/bin:/usr/bin', + 'hour' => '1', + 'minute' => '10', + 'month' => 'Jan', + 'monthday' => '1', + 'provider' => 'crontab', + 'special' => 'absent', + 'target' => 'root', + 'user' => 'root', + 'weekday' => '6', + }, + ) + end end context 'cron with invalid ensure' do let(:title) { 'invalid' } let(:params) do - { :command => '/usr/local/bin/script', - :hour => '2', - :minute => '0', - :ensure => '!invalid', + { + command: '/usr/local/bin/script', + hour: '2', + minute: '0', + ensure: '!invalid', } end - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/types::cron::invalid::ensure is invalid and does not match the regex\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a match for Enum}) end end end diff --git a/spec/defines/exec_spec.rb b/spec/defines/exec_spec.rb index 4644f2d..59d2363 100644 --- a/spec/defines/exec_spec.rb +++ b/spec/defines/exec_spec.rb @@ -1,87 +1,91 @@ require 'spec_helper' describe 'types::exec' do let(:title) { 'testing' } - let(:facts) { { :osfamily => 'RedHat' } } + let(:facts) { { osfamily: 'RedHat' } } context 'exec with no parameter specified' do - it 'should fail' do - expect { should contain_class(subject) }.to raise_error(Puppet::Error, /(expects a value for parameter \'command\'|Must pass command to)/) + it 'fails' do + expect { is_expected.to contain_class(:subject) }.to raise_error(Puppet::Error, %r{(expects a value for parameter \'command\'|Must pass command to)}) end end context 'exec with bare minimum specified' do - let(:params) { { :command => '/spec/testing.sh' } } - it { should contain_exec('testing').only_with_command('/spec/testing.sh') } + let(:params) { { command: '/spec/testing.sh' } } + + it { is_expected.to contain_exec('testing').only_with_command('/spec/testing.sh') } end context 'exec with all options specified' do let(:title) { 'testing' } let(:params) do { - :command => '/spec/testing.sh', - :creates => '/creates', - :cwd => '/spec', - :environment => 'test=true', - :group => 'group', - :logoutput => true, - :onlyif => '/onlyif.sh', - :path => '/path', - :provider => 'shell', - :refresh => '/refresh.sh', - :refreshonly => true, - :returns => 242, - :timeout => 3, - :tries => 3, - :try_sleep => 3, - :unless => '/unless.sh', - :user => 'tester', + command: '/spec/testing.sh', + creates: '/creates', + cwd: '/spec', + environment: 'test=true', + group: 'group', + logoutput: true, + onlyif: '/onlyif.sh', + path: '/path', + provider: 'shell', + refresh: '/refresh.sh', + refreshonly: true, + returns: 242, + timeout: 3, + tries: 3, + try_sleep: 3, + unless: '/unless.sh', + user: 'tester', } end - it { - should contain_exec('testing').with({ - 'command' => '/spec/testing.sh', - 'creates' => '/creates', - 'cwd' => '/spec', - 'environment' => 'test=true', - 'group' => 'group', - 'logoutput' => true, - 'onlyif' => '/onlyif.sh', - 'path' => '/path', - 'provider' => 'shell', - 'refresh' => '/refresh.sh', - 'refreshonly' => true, - 'returns' => 242, - 'timeout' => 3, - 'tries' => 3, - 'try_sleep' => 3, - 'unless' => '/unless.sh', - 'user' => 'tester', - }) - } + it do + is_expected.to contain_exec('testing').only_with( + { + 'command' => '/spec/testing.sh', + 'creates' => '/creates', + 'cwd' => '/spec', + 'environment' => 'test=true', + 'group' => 'group', + 'logoutput' => true, + 'onlyif' => '/onlyif.sh', + 'path' => '/path', + 'provider' => 'shell', + 'refresh' => '/refresh.sh', + 'refreshonly' => true, + 'returns' => 242, + 'timeout' => 3, + 'tries' => 3, + 'try_sleep' => 3, + 'unless' => '/unless.sh', + 'user' => 'tester', + }, + ) + end end context 'exec with invalid provider' do - let(:params) { { :provider=> 'invalid', :command => '/spec/testing.sh' } } - it 'should fail' do - expect { should contain_class(subject) }.to raise_error(Puppet::Error, /types::exec::testing::provider is invalid and does not match the regex/) + let(:params) { { provider: 'invalid', command: '/spec/testing.sh' } } + + it 'fails' do + expect { is_expected.to contain_class(:subject) }.to raise_error(Puppet::Error, %r{expects an undef value or a match for Enum}) end end describe 'variable type and content validations' do - mandatory_params = { :command => '/spec/testing.sh' } + mandatory_params = { command: '/spec/testing.sh' } validations = { 'validate_absolute_path' => { - :name => %w[creates cwd], - :valid => ['/absolute/filepath', '/absolute/directory/'], - :invalid => ['./relative/path', %w[array], { 'ha' => 'sh' }, 3, 2.42, true, nil], - :message => 'is not an absolute path', + name: ['creates', 'cwd'], + valid: ['/absolute/filepath', '/absolute/directory/'], + invalid: ['./relative/path', ['array'], { 'ha' => 'sh' }, 3, 2.42, true, nil], + message: 'expects a Stdlib::Absolutepath', }, 'validate_re' => { - :name => %w[provider], - :valid => %w[posix shell windows], - :invalid => ['string', %w[array], { 'ha' => 'sh' }, 3, 2.42, true, nil], - :message => 'types::exec::testing::provider is invalid and does not match the regex', + name: ['provider'], + valid: ['posix', 'shell', 'windows'], + invalid: ['string', ['array'], { 'ha' => 'sh' }, 3, 2.42, true, nil], + message: 'expects an undef value or a match for Enum', }, } @@ -90,16 +94,18 @@ var[:params] = {} if var[:params].nil? var[:valid].each do |valid| context "when #{var_name} (#{type}) is set to valid #{valid} (as #{valid.class})" do - let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => valid, }].reduce(:merge) } - it { should compile } + let(:params) { [mandatory_params, var[:params], { "#{var_name}": valid, }].reduce(:merge) } + + it { is_expected.to compile } end end var[:invalid].each do |invalid| context "when #{var_name} (#{type}) is set to invalid #{invalid} (as #{invalid.class})" do - let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => invalid, }].reduce(:merge) } - it 'should fail' do - expect { should contain_class(subject) }.to raise_error(Puppet::Error, /#{var[:message]}/) + let(:params) { [mandatory_params, var[:params], { "#{var_name}": invalid, }].reduce(:merge) } + + it 'fails' do + expect { is_expected.to contain_class(:subject) }.to raise_error(Puppet::Error, %r{#{var[:message]}}) end end end diff --git a/spec/defines/file_line_spec.rb b/spec/defines/file_line_spec.rb index 1febdae..10719d0 100644 --- a/spec/defines/file_line_spec.rb +++ b/spec/defines/file_line_spec.rb @@ -5,68 +5,74 @@ context 'file_line with minimal parameters specified (path and line)' do let(:params) do { - :path => '/tmp/foo', - :line => 'option=asdf', + path: '/tmp/foo', + line: 'option=asdf', } end - it { should contain_file_line('some_file').with({ - 'path' => '/tmp/foo', - 'line' => 'option=asdf', - 'match' => nil, - }) - } + it do + is_expected.to contain_file_line('some_file').with( + { + 'path' => '/tmp/foo', + 'line' => 'option=asdf', + 'match' => nil, + }, + ) + end end context 'file_line with all parameters specified' do let(:params) do { - :ensure => 'present', - :path => '/tmp/foo', - :line => 'option=asdf', - :match => '^option', + ensure: 'present', + path: '/tmp/foo', + line: 'option=asdf', + match: '^option', } end - it { should contain_file_line('some_file').with({ - 'ensure' => 'present', - 'path' => '/tmp/foo', - 'line' => 'option=asdf', - 'match' => '^option', - }) - } + it do + is_expected.to contain_file_line('some_file').only_with( + { + 'ensure' => 'present', + 'path' => '/tmp/foo', + 'line' => 'option=asdf', + 'match' => '^option', + }, + ) + end end describe 'with an invalid path for the path parameter' do let(:params) do { - :path => 'invalid/path', - :line => 'option=asdf', - :match => '^option', + path: 'invalid/path', + line: 'option=asdf', + match: '^option', } end - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/"invalid\/path" is not an absolute path/) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a Stdlib::Absolutepath}) end end describe 'with an invalid ensure parameter' do let(:params) do { - :ensure => '!invalid', - :path => '/tmp/foo', - :line => 'option=asdf', - :match => '^option', + ensure: '!invalid', + path: '/tmp/foo', + line: 'option=asdf', + match: '^option', } end - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/types::file_line::some_file::ensure is invalid and does not match the regex\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a match for Enum}) end end @@ -74,48 +80,48 @@ context 'for the path parameter' do let(:params) do { - :path => true, - :line => 'option=asdf', - :match => '^option', + path: true, + line: 'option=asdf', + match: '^option', } end - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/true is not an absolute path/) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a Stdlib::Absolutepath}) end end context 'for the line parameter' do let(:params) do { - :path => '/tmp/foo', - :line => ['invalid','type'], - :match => '^option', + path: '/tmp/foo', + line: ['invalid', 'type'], + match: '^option', } end - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/\["invalid", "type"\] is not a string/) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a String value}) end end context 'for the match parameter' do let(:params) do { - :path => '/tmp/foo', - :line => 'option=asdf', - :match => ['invalid','type'], + path: '/tmp/foo', + line: 'option=asdf', + match: ['invalid', 'type'], } end - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/\["invalid", "type"\] is not a string/) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a value of type Undef or String}) end end end diff --git a/spec/defines/file_spec.rb b/spec/defines/file_spec.rb index 3a8414b..1342776 100644 --- a/spec/defines/file_spec.rb +++ b/spec/defines/file_spec.rb @@ -3,119 +3,128 @@ let(:title) { '/tmp/foo' } context 'file with no options specified' do - it { should contain_file('/tmp/foo').with({ - 'ensure' => 'present', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }) - } + it do + is_expected.to contain_file('/tmp/foo').with( + { + 'ensure' => 'present', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }, + ) + end end context 'file with all options specified' do let(:params) do - { :ensure => 'present', - :mode => '0777', - :owner => 'root', - :group => 'root', - :content => 'This is the content', - :backup => 'foobucket', - :checksum => 'none', - :force => 'purge', - :ignore => ['.svn', '.foo'], - :links => 'follow', - :provider => 'posix', - :purge => true, - :recurse => true, - :recurselimit => 2, - :replace => false, - :selinux_ignore_defaults => false, - :selrange => 's0', - :selrole => 'object_r', - :seltype => 'var_t', - :seluser => 'system_u', - :show_diff => false, - :source => 'puppet://modules/types/mydir', - :sourceselect => 'first', + { + ensure: 'present', + mode: '0777', + owner: 'root', + group: 'root', + content: 'This is the content', + backup: 'foobucket', + checksum: 'none', + force: 'purge', + ignore: ['.svn', '.foo'], + links: 'follow', + provider: 'posix', + purge: true, + recurse: true, + recurselimit: 2, + replace: false, + selinux_ignore_defaults: false, + selrange: 's0', + selrole: 'object_r', + seltype: 'var_t', + seluser: 'system_u', + show_diff: false, + source: 'puppet://modules/types/mydir', + sourceselect: 'first', } end - it { - should contain_file('/tmp/foo').with({ - 'ensure' => 'present', - 'mode' => '0777', - 'owner' => 'root', - 'group' => 'root', - 'content' => 'This is the content', - 'backup' => 'foobucket', - 'checksum' => 'none', - 'force' => 'purge', - 'ignore' => ['.svn', '.foo'], - 'links' => 'follow', - 'provider' => 'posix', - 'purge' => true, - 'recurse' => true, - 'recurselimit' => 2, - 'replace' => false, - 'selinux_ignore_defaults' => false, - 'selrange' => 's0', - 'selrole' => 'object_r', - 'seltype' => 'var_t', - 'seluser' => 'system_u', - 'show_diff' => false, - 'source' => 'puppet://modules/types/mydir', - 'sourceselect' => 'first', - }) - } + it do + is_expected.to contain_file('/tmp/foo').only_with( + { + 'ensure' => 'present', + 'mode' => '0777', + 'owner' => 'root', + 'group' => 'root', + 'content' => 'This is the content', + 'backup' => 'foobucket', + 'checksum' => 'none', + 'force' => 'purge', + 'ignore' => ['.svn', '.foo'], + 'links' => 'follow', + 'provider' => 'posix', + 'purge' => true, + 'recurse' => true, + 'recurselimit' => 2, + 'replace' => false, + 'selinux_ignore_defaults' => false, + 'selrange' => 's0', + 'selrole' => 'object_r', + 'seltype' => 'var_t', + 'seluser' => 'system_u', + 'show_diff' => false, + 'source' => 'puppet://modules/types/mydir', + 'sourceselect' => 'first', + }, + ) + end end describe 'with ensure' do - ['present','absent','file','directory','link'].each do |value| + ['present', 'absent', 'file', 'directory', 'link'].each do |value| context "set to #{value}" do - let(:params) { { :ensure => value } } + let(:params) { { ensure: value } } - it { should contain_file('/tmp/foo').with({ - 'ensure' => value, - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }) + it { + is_expected.to contain_file('/tmp/foo').with( + { + 'ensure' => value, + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }, + ) } end end end context 'file with invalid ensure' do - let(:params) { { :ensure => 'invalid' } } + let(:params) { { ensure: 'invalid' } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/types::file::\/tmp\/foo::ensure is invalid and does not match the regex\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a match for Enum}) end end describe 'file with mode set to invalid' do - ['666',665,'10666','foo',true].each do |value| + ['666', 665, '10666', 'foo', true].each do |value| context "value of #{value}" do - let(:params) { { :mode => 'invalid' } } + let(:params) { { mode: 'invalid' } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/types::file::\/tmp\/foo::mode must be exactly 4 digits\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a match for Stdlib::Filemode}) end end end end context 'file with name that is not an absolute path' do - let(:params) { { :ensure => 'invalid/path' } } + let(:title) { 'invalid/path' } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/types::file::\/tmp\/foo::ensure is invalid and does not match the regex\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a Stdlib::Absolutepath}) end end end diff --git a/spec/defines/mount_spec.rb b/spec/defines/mount_spec.rb index 6acdc71..bf253fb 100644 --- a/spec/defines/mount_spec.rb +++ b/spec/defines/mount_spec.rb @@ -1,75 +1,87 @@ require 'spec_helper' describe 'types::mount' do - context 'mount with bare minimum specified' do let(:title) { '/mnt' } let(:params) do - { :device => '/dev/dvd', - :fstype => 'iso9660', + { + device: '/dev/dvd', + fstype: 'iso9660', + } + end + let(:facts) do + { + os: { family: 'Redhat' }, + osfamily: 'RedHat', # needed for common module :( } end - let(:facts) { { :osfamily => 'RedHat' } } - it { - should contain_mount('/mnt').with({ - 'ensure' => 'mounted', - 'name' => '/mnt', - 'atboot' => true, - 'device' => '/dev/dvd', - 'fstype' => 'iso9660', - }) - } + it do + is_expected.to contain_mount('/mnt').with( + { + 'ensure' => 'mounted', + 'name' => '/mnt', + 'atboot' => true, + 'device' => '/dev/dvd', + 'fstype' => 'iso9660', + }, + ) + end + + it { is_expected.to contain_common__mkdir_p('/mnt') } end context 'mount with all options specified' do let(:title) { '/mnt' } let(:params) do - { :device => '/dev/fiction', - :fstype => 'iso9660', - :ensure => 'absent', - :atboot => false, - :blockdevice => '/dev/blockdevice', - :dump => '1', - :options => 'ro', - :pass => '1', - :provider => 'customprovider', - :remounts => true, + { + device: '/dev/fiction', + fstype: 'iso9660', + ensure: 'absent', + atboot: false, + blockdevice: '/dev/blockdevice', + dump: '1', + options: 'ro', + pass: '1', + provider: 'customprovider', + remounts: true, } end - let(:facts) { { :osfamily => 'RedHat' } } - it { - should contain_mount('/mnt').with({ - 'ensure' => 'absent', - 'atboot' => false, - 'device' => '/dev/fiction', - 'fstype' => 'iso9660', - 'name' => '/mnt', - 'blockdevice' => '/dev/blockdevice', - 'dump' => '1', - 'options' => 'ro', - 'pass' => '1', - 'provider' => 'customprovider', - 'remounts' => true, - }) - } + it do + is_expected.to contain_mount('/mnt').only_with( + { + 'ensure' => 'absent', + 'atboot' => false, + 'device' => '/dev/fiction', + 'fstype' => 'iso9660', + 'name' => '/mnt', + 'blockdevice' => '/dev/blockdevice', + 'dump' => '1', + 'options' => 'ro', + 'pass' => '1', + 'provider' => 'customprovider', + 'remounts' => true, + }, + ) + end end context 'mount with invalid ensure' do let(:title) { 'invalid' } let(:params) do - { :device => '/dev/fiction', - :fstype => 'iso9660', - :target => '/mnt', - :ensure => '!invalid', + { + device: '/dev/fiction', + fstype: 'iso9660', + target: '/mnt', + ensure: '!invalid', } end - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/types::mount::invalid::ensure is invalid and does not match the regex\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a match for Enum}) end end @@ -77,16 +89,25 @@ context 'on osfamily RedHat' do let(:title) { '/mnt/test' } let(:params) do - { :ensure => 'absent', - :device => '/dev/fiction', - :fstype => 'iso9660', + { + ensure: 'absent', + device: '/dev/fiction', + fstype: 'iso9660', } end - let(:facts) { { :osfamily => 'RedHat' } } + let(:facts) { { osfamily: 'RedHat' } } - it { - should_not contain_exec('mkdir_p-/mnt/test') - } + it do + is_expected.to contain_mount('/mnt/test').with( + { + 'ensure' => 'absent', + 'device' => '/dev/fiction', + 'fstype' => 'iso9660', + }, + ) + end + + it { is_expected.not_to contain_exec('mkdir_p-/mnt/test') } end end @@ -94,41 +115,59 @@ context 'on osfamily Solaris' do let(:title) { '/mnt' } let(:params) do - { :device => '/dev/fiction', - :fstype => 'iso9660', - :options => 'defaults', + { + device: '/dev/fiction', + fstype: 'iso9660', + options: 'defaults', + } + end + let(:facts) do + { + os: { family: 'Solaris' }, + osfamily: 'Solaris', # needed for common module :( } end - let(:facts) { { :osfamily => 'Solaris' } } - it { - should contain_mount('/mnt').with({ - 'ensure' => 'mounted', - 'device' => '/dev/fiction', - 'fstype' => 'iso9660', - 'options' => '-', - }) - } + it do + is_expected.to contain_mount('/mnt').with( + { + 'ensure' => 'mounted', + 'device' => '/dev/fiction', + 'fstype' => 'iso9660', + 'options' => '-', + }, + ) + end + + it { is_expected.to contain_common__mkdir_p('/mnt') } end context 'on osfamily that is not Solaris' do let(:title) { '/mnt' } let(:params) do - { :device => '/dev/fiction', - :fstype => 'iso9660', - :options => 'defaults', + { + device: '/dev/fiction', + fstype: 'iso9660', + options: 'defaults', + } + end + let(:facts) do + { + os: { family: 'Debian' }, + osfamily: 'Debian', # needed for common module :( } end - let(:facts) { { :osfamily => 'Debian' } } - it { - should contain_mount('/mnt').with({ - 'ensure' => 'mounted', - 'device' => '/dev/fiction', - 'fstype' => 'iso9660', - 'options' => 'defaults', - }) - } + it do + is_expected.to contain_mount('/mnt').with( + { + 'ensure' => 'mounted', + 'device' => '/dev/fiction', + 'fstype' => 'iso9660', + 'options' => 'defaults', + }, + ) + end end end end diff --git a/spec/defines/package_spec.rb b/spec/defines/package_spec.rb index 46026d3..863e231 100644 --- a/spec/defines/package_spec.rb +++ b/spec/defines/package_spec.rb @@ -1,87 +1,73 @@ require 'spec_helper' describe 'types::package' do - context 'package with bare minimum specified' do let(:title) { 'pkg1' } - it { - should contain_package('pkg1').with({ - 'ensure' => 'present', - }) - } + let(:facts) { { osfamily: 'RedHat' } } + + it { is_expected.to contain_package('pkg1').with_ensure('present') } end context 'package with all options specified' do let(:title) { 'pkg1' } let(:params) do { - :ensure => 'installed', - :adminfile => '/path/to/adminfile', - :configfiles => 'keep', - :install_options => '--installoption', - :provider => 'yum', - :responsefile => '/path/to/responsefile', - :source => 'http://source/URL/', - :uninstall_options => '--uninstall_option', + ensure: 'installed', + adminfile: '/path/to/adminfile', + configfiles: 'keep', + install_options: '--installoption', + provider: 'yum', + responsefile: '/path/to/responsefile', + source: 'http://source/URL/', + uninstall_options: '--uninstall_option', } end - let(:facts) { { :osfamily => 'RedHat' } } - it { - should contain_package('pkg1').with({ - 'ensure' => 'installed', - 'adminfile' => '/path/to/adminfile', - 'configfiles' => 'keep', - 'install_options' => '--installoption', - 'provider' => 'yum', - 'responsefile' => '/path/to/responsefile', - 'source' => 'http://source/URL/', - 'uninstall_options' => '--uninstall_option', - }) - } + it do + is_expected.to contain_package('pkg1').only_with( + { + 'ensure' => 'installed', + 'adminfile' => '/path/to/adminfile', + 'configfiles' => 'keep', + 'install_options' => '--installoption', + 'provider' => 'yum', + 'responsefile' => '/path/to/responsefile', + 'source' => 'http://source/URL/', + 'uninstall_options' => '--uninstall_option', + }, + ) + end end context 'package with invalid configfiles' do let(:title) { 'pkg1' } - let(:params) do - { - :configfiles => 'invalid', - } - end - let(:facts) { { :osfamily => 'RedHat' } } + let(:params) { { configfiles: 'invalid' } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/types::package::pkg1::configfiles is invalid and does not match the regex\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects an undef value or a match for Enum}) end end context 'package with invalid type for ensure' do let(:title) { 'invalidtype' } - let(:params) do - { - :ensure => ['invalid','type'], - } - end + let(:params) { { ensure: ['invalid', 'type'] } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/\["invalid", "type"\] is not a string\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a match for Enum}) end end context 'package with invalid responsefile' do let(:title) { 'pkg1' } - let(:params) do - { :responsefile => 'invalid/path' } - end - let(:facts) { { :osfamily => 'RedHat' } } + let(:params) { { responsefile: 'invalid/path' } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/"invalid\/path" is not an absolute path\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a Stdlib::Absolutepath}) end end end diff --git a/spec/defines/selboolean_spec.rb b/spec/defines/selboolean_spec.rb index 3963b56..ad43ae8 100644 --- a/spec/defines/selboolean_spec.rb +++ b/spec/defines/selboolean_spec.rb @@ -4,79 +4,78 @@ context 'selboolean with all options specified' do let(:params) do - { :persistent => true, - :value => 'on', - :provider => 'getsebool', + { + persistent: true, + value: 'on', + provider: 'getsebool', } end - it { - should contain_selboolean('nfs_export_all_ro').with({ - 'persistent' => true, - 'value' => 'on', - }) - } + it do + is_expected.to contain_selboolean('nfs_export_all_ro').only_with( + { + 'persistent' => true, + 'value' => 'on', + 'provider' => 'getsebool', + }, + ) + end end describe 'with value' do - ['on','off'].each do |value| + ['on', 'off'].each do |value| context "set to #{value}" do - let(:params) { { :value => value } } + let(:params) { { value: value } } - it { - should contain_selboolean('nfs_export_all_ro').with({ - 'persistent' => false, - 'value' => value, - }) - } + it do + is_expected.to contain_selboolean('nfs_export_all_ro').with( + { + 'persistent' => false, + 'value' => value, + }, + ) + end end end end context 'selboolean with invalid value for provider' do - let(:params) do - { :provider => false, } - end - it 'should fail' do + let(:params) { { provider: false } } + + it 'fails' do expect { - should contain_class('types') + is_expected.to contain_class('types') }.to raise_error(Puppet::Error) end end context 'selboolean with invalid value for persistent' do - let(:params) do - { :persistent => 'invalid setting', } - end - it 'should fail' do + let(:params) { { persistent: 'invalid setting' } } + + it 'fails' do expect { - should contain_class('types') + is_expected.to contain_class('types') }.to raise_error(Puppet::Error) end end context 'selboolean with invalid value for value' do - let(:params) do - { :value => 'invalid setting', } - end + let(:params) { { value: 'invalid setting' } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') + is_expected.to contain_class('types') }.to raise_error(Puppet::Error) end end context 'selboolean with no value - value is mandatory' do - let(:params) do - { :persistent => false } - end + let(:params) { { persistent: false } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') + is_expected.to contain_class('types') }.to raise_error(Puppet::Error) end end - end diff --git a/spec/defines/service_spec.rb b/spec/defines/service_spec.rb index 8ba7d7f..6c0077a 100644 --- a/spec/defines/service_spec.rb +++ b/spec/defines/service_spec.rb @@ -1,105 +1,107 @@ require 'spec_helper' describe 'types::service' do - context 'service with bare minimum specified' do let(:title) { 'service_minimum' } - it { - should contain_service('service_minimum').with({ - 'ensure' => 'running', - 'enable' => true, - }) - } + + it do + is_expected.to contain_service('service_minimum').with( + { + 'ensure' => 'running', + 'enable' => true, + }, + ) + end end context 'service with all options specified' do let(:title) { 'service_maximum' } let(:params) do { - :ensure => 'stopped', - :binary => '/bin/true', - :control => 'SERVICE_MAXIMUM_START', - :enable => 'manual', - :hasrestart => 'true', - :hasstatus => 'false', - :manifest => '/bin/manifest', - :path => '/etc/init.d', - :pattern => 'service_maximum', - :provider => 'init', - :restart => '/bin/restart', - :start => '/bin/start', - :status => '/bin/status', - :stop => '/bin/stop', + ensure: 'stopped', + binary: '/bin/true', + control: 'SERVICE_MAXIMUM_START', + enable: 'manual', + hasrestart: 'true', + hasstatus: 'false', + manifest: '/bin/manifest', + path: '/etc/init.d', + pattern: 'service_maximum', + provider: 'init', + restart: '/bin/restart', + start: '/bin/start', + status: '/bin/status', + stop: '/bin/stop', } end - it { - should contain_service('service_maximum').with({ - 'ensure' => 'stopped', - 'binary' => '/bin/true', - 'control' => 'SERVICE_MAXIMUM_START', - 'enable' => 'manual', - 'hasrestart' => 'true', - 'hasstatus' => 'false', - 'manifest' => '/bin/manifest', - 'path' => '/etc/init.d', - 'pattern' => 'service_maximum', - 'provider' => 'init', - 'restart' => '/bin/restart', - 'start' => '/bin/start', - 'status' => '/bin/status', - 'stop' => '/bin/stop', - }) - } + it do + is_expected.to contain_service('service_maximum').only_with( + { + 'ensure' => 'stopped', + 'binary' => '/bin/true', + 'control' => 'SERVICE_MAXIMUM_START', + 'enable' => 'manual', + 'hasrestart' => 'true', + 'hasstatus' => 'false', + 'manifest' => '/bin/manifest', + 'path' => '/etc/init.d', + 'pattern' => 'service_maximum', + 'provider' => 'init', + 'restart' => '/bin/restart', + 'start' => '/bin/start', + 'status' => '/bin/status', + 'stop' => '/bin/stop', + }, + ) + end end context 'service with invalid ensure' do let(:title) { 'invalid' } - let(:params) do - { - :ensure => 'invalid', - } - end + let(:params) { { ensure: 'invalid' } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/types::service::invalid::ensure can only be , , or and is set to /) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a value of type Boolean or Enum}) end end describe 'with parameter enable' do - ['true',true,'false',false,'manual'].each do |value| + ['true', true, 'false', false, 'manual'].each do |value| context "set to #{value}" do let(:title) { 'my_service' } - let(:params) { { :enable => value } } + let(:params) { { enable: value } } - it { - should contain_service('my_service').with({ - 'enable' => value, - }) - } + it do + is_expected.to contain_service('my_service').with( + { + 'enable' => value, + }, + ) + end end end context 'set to an invalid string' do let(:title) { 'invalid' } - let(:params) { { :enable => 'invalid' } } + let(:params) { { enable: 'invalid' } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/types::service::invalid::enable can only be , or and is set to /) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a value of type Boolean or Enum}) end end context 'set to an invalid type (non-string and non-boolean)' do let(:title) { 'invalid_type' } - let(:params) { { :enable => ['invalid','type'] } } + let(:params) { { enable: ['invalid', 'type'] } } - it 'should fail' do + it 'fails' do expect { - should contain_class('types') - }.to raise_error(Puppet::Error,/\["invalid", "type"\] is not a boolean\./) + is_expected.to contain_class('types') + }.to raise_error(Puppet::Error, %r{expects a value of type Boolean or Enum}) end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 74f727d..415ba7d 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,16 +1,75 @@ +# frozen_string_literal: true + +RSpec.configure do |c| + c.mock_with :rspec +end + require 'puppetlabs_spec_helper/module_spec_helper' +require 'rspec-puppet-facts' + +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, +} -RSpec.configure do |config| - config.hiera_config = 'spec/fixtures/hiera/hiera.yaml' - config.before :each do - # Ensure that we don't accidentally cache facts and environment between - # test cases. This requires each example group to explicitly load the - # facts being exercised with something like - # Facter.collection.loader.load(:ipaddress) - Facter.clear - Facter.clear_messages +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 - config.default_facts = { - :environment => 'rp_env', - } end + +# read default_facts and merge them over what is provided by facterdb +default_facts.each do |fact, value| + add_custom_fact fact, value +end + +RSpec.configure do |c| + c.default_facts = default_facts + c.hiera_config = 'hiera' + c.before :each do + # set to strictest setting for testing + # by default Puppet runs at warning level + Puppet.settings[:strict] = :warning + Puppet.settings[:strict_variables] = true + end + c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] + c.after(:suite) do + RSpec::Puppet::Coverage.report!(100) + end + + # Filter backtrace noise + backtrace_exclusion_patterns = [ + %r{spec_helper}, + %r{gems}, + ] + + if c.respond_to?(:backtrace_exclusion_patterns) + c.backtrace_exclusion_patterns = backtrace_exclusion_patterns + elsif c.respond_to?(:backtrace_clean_patterns) + c.backtrace_clean_patterns = backtrace_exclusion_patterns + 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 + +# 'spec_overrides' from sync.yml will appear below this line