diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000..12ed4ff109 --- /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 0000000000..a719361689 --- /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 0000000000..cdd65d220a --- /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.yml b/.fixtures.yml index 44121bb74e..fbee13667e 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -1,10 +1,14 @@ +--- fixtures: repositories: - apt: - repo: "https://github.com/puppetlabs/puppetlabs-apt.git" - branch: "1.8.x" - stdlib: "https://github.com/puppetlabs/puppetlabs-stdlib.git" - firewall: "https://github.com/puppetlabs/puppetlabs-firewall.git" + apt: "https://github.com/puppetlabs/puppetlabs-apt.git" + augeas_core: "https://github.com/puppetlabs/puppetlabs-augeas_core.git" concat: "https://github.com/puppetlabs/puppetlabs-concat.git" - symlinks: - postgresql: "#{source_dir}" + cron_core: "https://github.com/puppetlabs/puppetlabs-cron_core.git" + facts: 'https://github.com/puppetlabs/puppetlabs-facts.git' + firewall: "https://github.com/puppetlabs/puppetlabs-firewall.git" + provision: "https://github.com/puppetlabs/provision.git" + puppet_agent: 'https://github.com/puppetlabs/puppetlabs-puppet_agent.git' + stdlib: "https://github.com/puppetlabs/puppetlabs-stdlib.git" + yumrepo_core: "https://github.com/puppetlabs/puppetlabs-yumrepo_core.git" + systemd: "https://github.com/voxpupuli/puppet-systemd.git" diff --git a/.gitattributes b/.gitattributes index e1fb344e08..9032a014a0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,5 @@ -*.sh eol=lf -*.rb eol=lf +*.rb eol=lf +*.erb eol=lf +*.pp eol=lf +*.sh eol=lf +*.epp eol=lf diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..e3a97007e3 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,15 @@ +## Summary +Provide a detailed description of all the changes present in this pull request. + +## Additional Context +Add any additional context about the problem here. +- [ ] Root cause and the steps to reproduce. (If applicable) +- [ ] Thought process behind the implementation. + +## Related Issues (if any) +Mention any related issues or pull requests. + +## Checklist +- [ ] 🟢 Spec tests. +- [ ] 🟢 Acceptance tests. +- [ ] Manually verified. (For example `puppet apply`) \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..93cd3406b7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,21 @@ +name: "ci" + +on: + pull_request: + branches: + - "main" + workflow_dispatch: + +jobs: + Spec: + uses: "puppetlabs/cat-github-actions/.github/workflows/module_ci.yml@main" + with: + runs_on: "ubuntu-24.04" + secrets: "inherit" + + Acceptance: + needs: Spec + uses: "puppetlabs/cat-github-actions/.github/workflows/module_acceptance.yml@main" + with: + runs_on: "ubuntu-24.04" + secrets: "inherit" diff --git a/.github/workflows/mend.yml b/.github/workflows/mend.yml new file mode 100644 index 0000000000..b4100a5af0 --- /dev/null +++ b/.github/workflows/mend.yml @@ -0,0 +1,15 @@ +name: "mend" + +on: + pull_request: + branches: + - "main" + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + + mend: + uses: "puppetlabs/cat-github-actions/.github/workflows/mend_ruby.yml@main" + secrets: "inherit" diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 0000000000..c6539f7e37 --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,20 @@ +name: "nightly" + +on: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + Spec: + uses: "puppetlabs/cat-github-actions/.github/workflows/module_ci.yml@main" + with: + runs_on: "ubuntu-24.04" + secrets: "inherit" + + Acceptance: + needs: Spec + uses: "puppetlabs/cat-github-actions/.github/workflows/module_acceptance.yml@main" + with: + runs_on: "ubuntu-24.04" + secrets: "inherit" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..4b3b80fc80 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,9 @@ +name: "Publish module" + +on: + workflow_dispatch: + +jobs: + release: + uses: "puppetlabs/cat-github-actions/.github/workflows/module_release.yml@main" + secrets: "inherit" diff --git a/.github/workflows/release_prep.yml b/.github/workflows/release_prep.yml new file mode 100644 index 0000000000..bb0b7acce1 --- /dev/null +++ b/.github/workflows/release_prep.yml @@ -0,0 +1,15 @@ +name: "Release Prep" + +on: + workflow_dispatch: + inputs: + version: + description: "Module version to be released. Must be a valid semver string. (1.2.3)" + required: true + +jobs: + release_prep: + uses: "puppetlabs/cat-github-actions/.github/workflows/module_release_prep.yml@main" + with: + version: "${{ github.event.inputs.version }}" + secrets: "inherit" diff --git a/.gitignore b/.gitignore index b5db85e051..2803e566b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,35 @@ -pkg/ -Gemfile.lock -vendor/ -spec/fixtures/ -.vagrant/ -.bundle/ -coverage/ -.idea/ +.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/ +/.vendor/ +/convert_report.txt +/update_report.txt +.DS_Store +.project +.envrc +/inventory.yaml +/spec/fixtures/litmus_inventory.yaml +.resource_types +.modules +.task_cache.json +.plan_cache.json +.rerun.json +bolt-debug.log diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile new file mode 100644 index 0000000000..0814c5e61f --- /dev/null +++ b/.gitpod.Dockerfile @@ -0,0 +1,18 @@ +FROM gitpod/workspace-full +RUN sudo wget https://apt.puppet.com/puppet-tools-release-bionic.deb && \ + wget https://apt.puppetlabs.com/puppet6-release-bionic.deb && \ + sudo dpkg -i puppet6-release-bionic.deb && \ + sudo dpkg -i puppet-tools-release-bionic.deb && \ + sudo apt-get update && \ + sudo apt-get install -y pdk zsh puppet-agent && \ + sudo apt-get clean && \ + sudo rm -rf /var/lib/apt/lists/* +RUN sudo usermod -s $(which zsh) gitpod && \ + sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" && \ + echo "plugins=(git gitignore github gem pip bundler python ruby docker docker-compose)" >> /home/gitpod/.zshrc && \ + echo 'PATH="$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/puppetlabs/bin:/opt/puppetlabs/puppet/bin"' >> /home/gitpod/.zshrc && \ + sudo /opt/puppetlabs/puppet/bin/gem install puppet-debugger hub -N && \ + mkdir -p /home/gitpod/.config/puppet && \ + /opt/puppetlabs/puppet/bin/ruby -r yaml -e "puts ({'disabled' => true}).to_yaml" > /home/gitpod/.config/puppet/analytics.yml +RUN rm -f puppet6-release-bionic.deb puppet-tools-release-bionic.deb +ENTRYPOINT /usr/bin/zsh diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000000..9d89d9faa2 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,9 @@ +image: + file: .gitpod.Dockerfile + +tasks: + - init: pdk bundle install + +vscode: + extensions: + - puppet.puppet-vscode@1.2.0:f5iEPbmOj6FoFTOV6q8LTg== diff --git a/.pdkignore b/.pdkignore new file mode 100644 index 0000000000..84684be63f --- /dev/null +++ b/.pdkignore @@ -0,0 +1,51 @@ +.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/ +/.vendor/ +/convert_report.txt +/update_report.txt +.DS_Store +.project +.envrc +/inventory.yaml +/spec/fixtures/litmus_inventory.yaml +.resource_types +.modules +.task_cache.json +.plan_cache.json +.rerun.json +bolt-debug.log +/.fixtures.yml +/Gemfile +/.gitattributes +/.github/ +/.gitignore +/.pdkignore +/.puppet-lint.rc +/Rakefile +/rakelib/ +/.rspec +/..yml +/.yardopts +/spec/ +/.vscode/ +/.sync.yml +/.devcontainer/ diff --git a/.project b/.project deleted file mode 100644 index a680a0bce7..0000000000 --- a/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - postgresql - - - - - - org.cloudsmith.geppetto.pp.dsl.ui.modulefileBuilder - - - - - org.eclipse.xtext.ui.shared.xtextBuilder - - - - - - org.cloudsmith.geppetto.pp.dsl.ui.puppetNature - org.eclipse.xtext.ui.shared.xtextNature - - diff --git a/.puppet-lint.rc b/.puppet-lint.rc new file mode 100644 index 0000000000..f01626d456 --- /dev/null +++ b/.puppet-lint.rc @@ -0,0 +1,3 @@ +--relative +--no-anchor_resource-check +--no-params_empty_string_assignment-check diff --git a/.rspec b/.rspec new file mode 100644 index 0000000000..16f9cdb013 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--format documentation diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000000..439ea84ee8 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,731 @@ +--- +require: +- rubocop-performance +- rubocop-rspec +AllCops: + NewCops: enable + DisplayCopNames: true + TargetRubyVersion: '2.6' + Include: + - "**/*.rb" + Exclude: + - bin/* + - ".vendor/**/*" + - "**/Gemfile" + - "**/Rakefile" + - pkg/**/* + - spec/fixtures/**/* + - vendor/**/* + - "**/Puppetfile" + - "**/Vagrantfile" + - "**/Guardfile" +inherit_from: ".rubocop_todo.yml" +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/GemFilename: + Enabled: false +Bundler/InsecureProtocolSource: + Enabled: false +Capybara/CurrentPathExpectation: + Enabled: false +Capybara/VisibilityMatcher: + 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/FeatureMethods: + Enabled: false +RSpec/ContainExactly: + 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/MatchArray: + 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/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 +Capybara/MatchStyle: + Enabled: false +Capybara/NegationMatcher: + Enabled: false +Capybara/SpecificActions: + Enabled: false +Capybara/SpecificFinders: + Enabled: false +Capybara/SpecificMatcher: + Enabled: false +Gemspec/DeprecatedAttributeAssignment: + Enabled: false +Gemspec/DevelopmentDependencies: + Enabled: false +Gemspec/RequireMFA: + Enabled: false +Layout/LineContinuationLeadingSpace: + Enabled: false +Layout/LineContinuationSpacing: + Enabled: false +Layout/LineEndStringConcatenationIndentation: + Enabled: false +Layout/SpaceBeforeBrackets: + Enabled: false +Lint/AmbiguousAssignment: + Enabled: false +Lint/AmbiguousOperatorPrecedence: + Enabled: false +Lint/AmbiguousRange: + Enabled: false +Lint/ConstantOverwrittenInRescue: + Enabled: false +Lint/DeprecatedConstants: + Enabled: false +Lint/DuplicateBranch: + Enabled: false +Lint/DuplicateMagicComment: + Enabled: false +Lint/DuplicateMatchPattern: + Enabled: false +Lint/DuplicateRegexpCharacterClassElement: + Enabled: false +Lint/EmptyBlock: + Enabled: false +Lint/EmptyClass: + Enabled: false +Lint/EmptyInPattern: + Enabled: false +Lint/IncompatibleIoSelectWithFiberScheduler: + Enabled: false +Lint/LambdaWithoutLiteralBlock: + Enabled: false +Lint/NoReturnInBeginEndBlocks: + Enabled: false +Lint/NonAtomicFileOperation: + Enabled: false +Lint/NumberedParameterAssignment: + Enabled: false +Lint/OrAssignmentToConstant: + Enabled: false +Lint/RedundantDirGlobSort: + Enabled: false +Lint/RefinementImportMethods: + Enabled: false +Lint/RequireRangeParentheses: + Enabled: false +Lint/RequireRelativeSelfPath: + Enabled: false +Lint/SymbolConversion: + Enabled: false +Lint/ToEnumArguments: + Enabled: false +Lint/TripleQuotes: + Enabled: false +Lint/UnexpectedBlockArity: + Enabled: false +Lint/UnmodifiedReduceAccumulator: + Enabled: false +Lint/UselessRescue: + Enabled: false +Lint/UselessRuby2Keywords: + Enabled: false +Metrics/CollectionLiteralLength: + Enabled: false +Naming/BlockForwarding: + Enabled: false +Performance/CollectionLiteralInLoop: + Enabled: false +Performance/ConcurrentMonotonicTime: + Enabled: false +Performance/MapCompact: + Enabled: false +Performance/RedundantEqualityComparisonBlock: + Enabled: false +Performance/RedundantSplitRegexpArgument: + Enabled: false +Performance/StringIdentifierArgument: + Enabled: false +RSpec/BeEq: + Enabled: false +RSpec/BeNil: + Enabled: false +RSpec/ChangeByZero: + Enabled: false +RSpec/ClassCheck: + Enabled: false +RSpec/DuplicatedMetadata: + Enabled: false +RSpec/ExcessiveDocstringSpacing: + Enabled: false +RSpec/FactoryBot/ConsistentParenthesesStyle: + Enabled: false +RSpec/FactoryBot/FactoryNameStyle: + Enabled: false +RSpec/FactoryBot/SyntaxMethods: + Enabled: false +RSpec/IdenticalEqualityAssertion: + Enabled: false +RSpec/NoExpectationExample: + Enabled: false +RSpec/PendingWithoutReason: + Enabled: false +RSpec/Rails/AvoidSetupHook: + Enabled: false +RSpec/Rails/HaveHttpStatus: + Enabled: false +RSpec/Rails/InferredSpecType: + Enabled: false +RSpec/Rails/MinitestAssertions: + Enabled: false +RSpec/Rails/TravelAround: + Enabled: false +RSpec/RedundantAround: + Enabled: false +RSpec/SkipBlockInsideExample: + Enabled: false +RSpec/SortMetadata: + Enabled: false +RSpec/SubjectDeclaration: + Enabled: false +RSpec/VerifiedDoubleReference: + Enabled: false +Security/CompoundHash: + Enabled: false +Security/IoMethods: + Enabled: false +Style/ArgumentsForwarding: + Enabled: false +Style/ArrayIntersect: + Enabled: false +Style/CollectionCompact: + Enabled: false +Style/ComparableClamp: + Enabled: false +Style/ConcatArrayLiterals: + Enabled: false +Style/DataInheritance: + Enabled: false +Style/DirEmpty: + Enabled: false +Style/DocumentDynamicEvalDefinition: + Enabled: false +Style/EmptyHeredoc: + Enabled: false +Style/EndlessMethod: + Enabled: false +Style/EnvHome: + Enabled: false +Style/FetchEnvVar: + Enabled: false +Style/FileEmpty: + Enabled: false +Style/FileRead: + Enabled: false +Style/FileWrite: + Enabled: false +Style/HashConversion: + Enabled: false +Style/HashExcept: + Enabled: false +Style/IfWithBooleanLiteralBranches: + Enabled: false +Style/InPatternThen: + Enabled: false +Style/MagicCommentFormat: + Enabled: false +Style/MapCompactWithConditionalBlock: + Enabled: false +Style/MapToHash: + Enabled: false +Style/MapToSet: + Enabled: false +Style/MinMaxComparison: + Enabled: false +Style/MultilineInPatternThen: + Enabled: false +Style/NegatedIfElseCondition: + Enabled: false +Style/NestedFileDirname: + Enabled: false +Style/NilLambda: + Enabled: false +Style/NumberedParameters: + Enabled: false +Style/NumberedParametersLimit: + Enabled: false +Style/ObjectThen: + Enabled: false +Style/OpenStructUse: + Enabled: false +Style/OperatorMethodCall: + Enabled: false +Style/QuotedSymbols: + Enabled: false +Style/RedundantArgument: + Enabled: false +Style/RedundantConstantBase: + Enabled: false +Style/RedundantDoubleSplatHashBraces: + Enabled: false +Style/RedundantEach: + Enabled: false +Style/RedundantHeredocDelimiterQuotes: + Enabled: false +Style/RedundantInitialize: + Enabled: false +Style/RedundantLineContinuation: + Enabled: false +Style/RedundantSelfAssignmentBranch: + Enabled: false +Style/RedundantStringEscape: + Enabled: false +Style/SelectByRegexp: + Enabled: false +Style/StringChars: + Enabled: false +Style/SwapValues: + Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000000..732977e113 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,34 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2023-11-29 05:29:46 UTC using RuboCop version 1.48.1. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 7 +# Configuration parameters: Include, CustomTransform, IgnoreMethods, SpecSuffixOnly. +# Include: **/*_spec*rb*, **/spec/**/* +RSpec/FilePath: + Exclude: + - 'spec/defines/server/instance/config.rb' + - 'spec/defines/server/instance/initdb.rb' + - 'spec/defines/server/instance/late_initdb.rb' + - 'spec/defines/server/instance/passwd.rb' + - 'spec/defines/server/instance/reload.rb' + - 'spec/defines/server/instance/service.rb' + - 'spec/unit/puppet/type/postgresql_conn_validator.rb' + +# Offense count: 214 +# Configuration parameters: EnforcedStyle, IgnoreSharedExamples. +# SupportedStyles: always, named_only +RSpec/NamedSubject: + Enabled: false + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: nested, compact +Style/ClassAndModuleChildren: + Exclude: + - 'lib/puppet/util/postgresql_validator.rb' diff --git a/.sync.yml b/.sync.yml index ac83790739..2721daf03f 100644 --- a/.sync.yml +++ b/.sync.yml @@ -1,9 +1,51 @@ --- -.travis.yml: - extras: - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" +".gitlab-ci.yml": + delete: true +.puppet-lint.rc: + extra_disabled_lint_checks: + - 140chars-check +appveyor.yml: + delete: true +.rubocop.yml: + include_todos: true +Gemfile: + optional: + ":development": + - gem: github_changelog_generator + version: '= 1.15.2' +Rakefile: + changelog_user: puppetlabs + changelog_max_issues: 500 + extra_disabled_lint_checks: + - anchor_resource + - params_empty_string_assignment spec/spec_helper.rb: + mock_with: ":rspec" + coverage_report: true + exclude_platforms: + - Scientific-6 + - Scientific-7 + - Debian-9 + - Debian-10 + - Debian-11 + - SLES-12 + - SLES-15 + - Ubuntu-14.04 + - Ubuntu-16.04 + - Ubuntu-18.04 + - Ubuntu-20.04 + - Ubuntu-22.04 +.gitpod.Dockerfile: + unmanaged: false +.gitpod.yml: + unmanaged: false +.github/workflows/auto_release.yml: + unmanaged: false +.github/workflows/ci.yml: + unmanaged: true +.github/workflows/nightly.yml: unmanaged: true +.github/workflows/release.yml: + unmanaged: false +.travis.yml: + delete: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c418ab5f2a..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -sudo: false -language: ruby -bundler_args: --without system_tests -script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--format documentation'" -matrix: - fast_finish: true - include: - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3.0" - - rvm: 2.1.5 - env: PUPPET_GEM_VERSION="~> 3.0" - - rvm: 2.1.5 - env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes" - - rvm: 2.1.6 - env: PUPPET_GEM_VERSION="~> 4.0" STRICT_VARIABLES="yes" -notifications: - email: false diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..6da8d472f8 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "puppet.puppet-vscode", + "Shopify.ruby-lsp" + ] +} diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000000..29c933bcf1 --- /dev/null +++ b/.yardopts @@ -0,0 +1 @@ +--markup markdown diff --git a/CHANGELOG.md b/CHANGELOG.md index 49ad2cc6b7..487ea482a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,790 +1,1056 @@ -## 2015-09-01 - Supported Release 4.6.0 -### Summary -This release adds a proxy feature for yum, Postgis improvements, and decoupling pg_hba_rule from postgresql::server. - -#### Features -- Support setting a proxy for yum operations -- Allow for undefined PostGIS version -- Decouple pg_hba_rule from postgresql::server - -#### Bugfixes -- Fix postgis default package name on RedHat - -## 2015-07-27 - Supported Release 4.5.0 -### Summary -This release adds sequence grants, some postgresql 9.4 fixes, and `onlyif` to -the psql resource. - -### Features -- Add `onlyif` parameter to `postgresql_psql` -- Add unsupported compatibility with Ubuntu 15.04 -- Add unsupported compatibility with SLES 11/12 and OpenSuSE 13.2 -- Add `postgresql::server::grant::onlyif_exists` attribute -- Add `postgresql::server::table_grant::onlyif_exists` attribute -- Add granting permissions on sequences - -### Bugfixes -- Added docs for `postgresql::server::grant` -- Fix `pg_hba_conf_defaults => false` to not disable ipv4/ipv6 acls -- Fix 9.4 for `postgresql::server::pg_hba_rule` - -## 2015-07-07 - Supported Release 4.4.2 -### Summary -This release fixes a bug introduced in 4.4.0. - -#### Bugfixes -- Fixes `withenv` execution under Puppet 2.7. (MODULES-2185) - -## 2015-07-01 - Supported Release 4.4.1 -### Summary -This release fixes RHEL 7 & Fedora with manage_package_repo switched on. - -#### Bugfixes -- Ensure manage_package_repo variable is in scope for systemd-override file for RHEL7 - -## 2015-06-30 - Supported Release 4.4.0 -### Summary -This release has several new features, bugfixes, and test improvements. - -#### Features -- Adds a resource to manage recovery.conf. -- Adds a parameter that allows the specification of a validate connection script in `postgresql::client`. -- Adds support for plpython package management. -- Adds support for postgresql-docs management. -- Adds ability to make `postgresql::server::schema` titles unique. (MODULES-2049) -- Updates puppetlabs-apt module dependency to support version 2.1.0. - -#### Bugfixes -- Fix `postgresql_psql` parameter ordering to work on OpenBSD with Future Parser -- Fix setting postgres role password (MODULES-1869) -- Fix execution command with puppet <3.4 (MODULES-1923) -- Fix Puppet.newtype deprecation warning (MODULES-2007) -- Fix systemd override for manage_repo package versions -- Fix Copy snakeoil certificate and key instead of symlinking - -#### Test Improvements -- Allows setting BEAKER and BEAKER_RSPEC versions via environment variables. -- Enables Unit testing on Travis CI with Puppet 4. -- Cleans up spec_helper_acceptance.rb to use new puppet_install_helper gem. - -## 2015-03-24 - Supported Release 4.3.0 -### Summary -This release fixes compatibility with Puppet 4 and removes opportunities for local users to view the postgresql password. It also adds a new custom resource to aid in managing replication. - -#### Features -- Add `postgresql::server::logdir` parameter to manage the logdir -- Add `environment` parameter to `postgresql_psql` -- Add `postgresql_replication_slot` custom resource - -#### Bugfixes -- Fix for Puppet 4 -- Don't print postgresql\_psql password in command -- Allow `postgresql::validate_db_connection` for more than one host+port+database combo -- Fix service command on Debian 8 and up -- Fix `postgresql::server::extension` to work with custom user/group/port -- Fix `postgresql::server::initdb` to work with custom user/group/port -- Fix changing template1 encoding -- Fix default `postgresql::server::grant::object_name` value -- Fix idempotency of granting all tables in schema with `puppet::server::grant` -- Fix lint warnings -- Fix apt key to use 40 character key and bump puppetlabs-apt to >= 1.8.0 < 2.0.0 - - -##2015-03-10 - Supported Release 4.2.0 -###Summary - -This release has several new features including support for server extensions, improved grant support, and a number of bugfixes. - -####Features -- Changes to support OpenBSD -- Add `service_reload` parameter to `postgresql::server` -- Add `comment` parameter to `postgresql::server::database` (MODULES-1153) -- Add `postgresql::server::extension` defined type -- Add postgresql versions for utopic and jessie -- Update `postgresql::server::grant` to support 'GRANT SCHEMA' and 'ALL TABLES IN SCHEMA' - -####Bugfixes -- Lint cleanup -- Remove outdated upgrade info from README -- Use correct TCP port when checking password -- Create role before database -- Fix template1 encoding on Debian -- Require server package before user permissions -- Fix `service_status` default for FreeBSD to allow PostgreSQL to start the first run -- Fix invalid US-ASCII byte sequence in `postgresql::server::grant` comments -- Reverted to default behavior for Debian systems as `pg_config` should not be overwritten (MODULES-1485) - -##2014-11-04 - Supported Release 4.1.0 -###Summary - -This release adds the ability to change the PGDATA directory, and also includes documentation and test updates, future parser support, and a few other new features. - -####Features -- Future parser support -- Documentation updates -- Test updates -- Add a link from `/etc/sysconfig/pgsql/postgresql-${version}` to `/etc/sysconfig/pgsql/postgresql` to support init scripts from the postgresql.org repo -- Add support for changing the PGDATA directory -- Set default versions for Fedora 21 and FreeBSD - -##2014-09-03 - Supported Release 4.0.0 -###Summary - -This release removes the uninstall ability from the module, removes the firewall -management, overhauls all of the acceptance testing, as well as adds better -support for SuSE and Fedora. - -###Backwards Incompatible changes. - -- Uninstall code removal. -- Firewall management for Postgres. -- Set manage_pg_ident_conf to true. - -####Uninstallation removal - -We rely heavily on the ability to uninstall and reinstall postgres throughout -our testing code, testing features like "can I move from the distribution -packages to the upstream packages through the module" and over time we've -learnt that the uninstall code simply doesn't work a lot of the time. It -leaves traces of postgres behind or fails to remove certain packages on Ubuntu, -and generally causes bits to be left on your system that you didn't expect. - -When we then reinstall things fail because it's not a true clean slate, and -this causes us enormous problems during test. We've spent weeks and months -working on these tests and they simply don't hold up well across the full range -of PE platforms. - -Due to all these problems we've decided to take a stance on uninstalling in -general. We feel that in 2014 it's completely reasonable and normal to have a -good provisioning pipeline combined with your configuration management and the -"correct" way to uninstall a fully installed service like postgresql is to -simply reprovision the server without it in the first place. As a general rule -this is how I personally like to work and I think is a good practice. - -####I'm not OK with this! - -We understand that there are environments and situations in which it's not easy -to do that. What if you accidently deployed Postgres on 100,000 nodes? In the -future we're going to take a look at building some example 'profiles' to be -found under examples/ within this module that can uninstall postgres on popular -platforms. These can be modified and used in your specific case to uninstall -postgresql. They will be much more brute force and reliant on deleting entire -directories and require you to do more work up front in specifying where things -are installed but we think it'll prove to be a much cleaner mechanism for this -kind of thing rather than trying to weave it into the main module logic itself. - -####Features -- Removal of uninstall. -- Removal of firewall management. -- Tests ported to rspec3. -- Acceptance tests rewritten. -- Add a defined type for creating database schemas. -- Add a pg_ident_rule defined type. -- Set manage_pg_ident_conf to true. -- Manage pg_ident.conf by default. -- Improve selinux support for tablespace. -- Remove deprecation warnings. -- Support changing PGDATA on RedHat. -- Add SLES 11 support. - -####Bugfixes -- Link pg_config binary into /usr/bin. -- Fix fedora support by using systemd. -- Initdb should create xlogdir if set. - -##2014-08-27 - Supported Release 3.4.3 -###Summary - -This release fixes Ubuntu 10.04 with Facter 2.2. - -####Features -####Bugfixes -- Use a regular expression to match the major OS version on Ubuntu. - -##2014-07-31 - Supported Release 3.4.2 -###Summary - -This release fixes recent Fedora versions. - -####Features -####Bugfixes -- Fix Fedora. - -##2014-07-15 - Supported Release 3.4.1 -###Summary - -This release merely updates metadata.json so the module can be uninstalled and -upgraded via the puppet module command. - -##2014-04-14 - Supported Release 3.4.0 -###Summary - -This feature rolls up several important features, the biggest being PostGIS -handling and allowing `port` to be set on postgresql::server in order to -change the port that Postgres listens on. We've added support for RHEL7 -and Ubuntu 14.04, as well as allowing you to manage the service via -`service_ensure` finally. + +# Changelog -####Features -- Added `perl_package_name` for installing bindings. -- Added `service_ensure` for allowing control of services. -- Added `postgis_version` and postgis class for installing postgis. -- Added `port` for selecting the port Postgres runs on. -- Add support for RHEL7 and Ubuntu 14.04. -- Add `default_db` to postgresql::server::database. -- Widen the selection of unquoted parameters in postgresql_conf{} -- Require the service within postgresql::server::reload for RHEL7. -- Add `inherit` to postgresql::server::role. +All notable changes to this project will be documented in this file. -####Bugfixes +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). -##2014-03-04 - Supported Release 3.3.3 -###Summary - -This is a supported release. This release removes a testing symlink that can -cause trouble on systems where /var is on a seperate filesystem from the -modulepath. +## [v10.6.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.6.0) - 2025-10-13 -####Features -####Bugfixes -####Known Bugs -* SLES is not supported. +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v10.5.0...v10.6.0) -##2014-03-04 - Supported Release 3.3.2 -###Summary -This is a supported release. It fixes a problem with updating passwords on postgresql.org distributed versions of PostgreSQL. +### Added -####Bugfixes -- Correct psql path when setting password on custom versions. -- Documentation updates -- Test updates +- Allow puppetlabs/apt 11.x & puppet/systemd 9.x [#1645](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1645) ([kenyon](https://github.com/kenyon)) +- Add support for Debian 13 (trixie) [#1638](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1638) ([trefzer](https://github.com/trefzer)) +- Role: Add support for valid_until [#1624](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1624) ([mooreandrew](https://github.com/mooreandrew)) -####Known Bugs -* SLES is not supported. +### Fixed +- Debian 11: Use correct package name for python bindings [#1647](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1647) ([bastelfreak](https://github.com/bastelfreak)) +- Unbreak Debian support with custom encoding [#1564](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1564) ([smortex](https://github.com/smortex)) -##2014-02-12 - Version 3.3.1 -####Bugfix: -- Allow dynamic rubygems host +### Other +- (CAT-2296) Update github runner image to ubuntu-24.04 [#1636](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1636) ([shubhamshinde360](https://github.com/shubhamshinde360)) -##2014-01-28 - Version 3.3.0 +## [v10.5.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.5.0) - 2025-01-07 -###Summary +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v10.4.0...v10.5.0) -This release rolls up a bunch of bugfixes our users have found and fixed for -us over the last few months. This improves things for 9.1 users, and makes -this module usable on FreeBSD. +### Added -This release is dedicated to 'bma', who's suffering with Puppet 3.4.1 issues -thanks to Puppet::Util::SUIDManager.run_and_capture. +- puppet/systemd: allow 8.x [#1627](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1627) ([evgeni](https://github.com/evgeni)) +- puppetlabs/apt: allow 10.x [#1626](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1626) ([evgeni](https://github.com/evgeni)) -####Features - - Add lc_ config entry settings - - Can pass template at database creation. - - Add FreeBSD support. - - Add support for customer `xlogdir` parameter. - - Switch tests from rspec-system to beaker. (This isn't really a feature) +## [v10.4.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.4.0) - 2024-12-16 -####Bugfixes - - Properly fix the deprecated Puppet::Util::SUIDManager.run_and_capture errors. - - Fix NOREPLICATION option for Postgres 9.1 - - Wrong parameter name: manage_pg_conf -> manage_pg_hba_conf - - Add $postgresql::server::client_package_name, referred to by install.pp - - Add missing service_provider/service_name descriptions in ::globals. - - Fix several smaller typos/issues throughout. - - Exec['postgresql_initdb'] needs to be done after $datadir exists - - Prevent defined resources from floating in the catalog. - - Fix granting all privileges on a table. - - Add some missing privileges. - - Remove deprecated and unused concat::fragment parameters. +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v10.3.0...v10.4.0) +### Added -##2013-11-05 - Version 3.2.0 +- added default version for fedora 40 and 41 [#1621](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1621) ([lweller](https://github.com/lweller)) +- (CAT-2124) Add support for Ubuntu 24 [#1619](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1619) ([skyamgarp](https://github.com/skyamgarp)) +- Add EL9 support [#1591](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1591) ([bastelfreak](https://github.com/bastelfreak)) -###Summary +### Fixed -Add's support for Ubuntu 13.10 (and 14.04) as well as x, y, z. +- Avoid opening the file in postgresql_conf [#1599](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1599) ([ekohl](https://github.com/ekohl)) -####Features -- Add versions for Ubuntu 13.10 and 14.04. -- Use default_database in validate_db_connection instead of a hardcoded -'postgres' -- Add globals/params layering for default_database. -- Allow specification of default database name. +### Other -####Bugs -- Fixes to the README. +- Document how to select a version as its own chapter [#1610](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1610) ([ekohl](https://github.com/ekohl)) +- Fix typo in README: instaces -> instances [#1607](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1607) ([ekohl](https://github.com/ekohl)) +## [v10.3.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.3.0) - 2024-05-08 -##2013-10-25 - Version 3.1.0 +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v10.2.0...v10.3.0) -###Summary +### Added -This is a minor feature and bug fix release. +- allow puppet-systemd version 7 [#1595](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1595) ([TheMeier](https://github.com/TheMeier)) -Firstly, the postgresql_psql type now includes a new parameter `search_path` which is equivalent to using `set search_path` which allows you to change the default schema search path. +### Fixed -The default version of Fedora 17 has now been added, so that Fedora 17 users can enjoy the module. +- Fix instance reload [#1588](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1588) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) -And finally we've extended the capabilities of the defined type postgresql::validate_db_connection so that now it can handle retrying and sleeping between retries. This feature has been monopolized to fix a bug we were seeing with startup race conditions, but it can also be used by remote systems to 'wait' for PostgreSQL to start before their Puppet run continues. +## [v10.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.2.0) - 2024-04-11 -####Features -- Defined $default_version for Fedora 17 (Bret Comnes) -- add search_path attribute to postgresql_psql resource (Jeremy Kitchen) -- (GH-198) Add wait and retry capability to validate_db_connection (Ken Barber) +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v10.1.0...v10.2.0) -####Bugs -- enabling defined postgres user password without resetting on every puppet run (jonoterc) -- periods are valid in configuration variables also (Jeremy Kitchen) -- Add zero length string to join() function (Jarl Stefansson) -- add require of install to reload class (cdenneen) -- (GH-198) Fix race condition on postgresql startup (Ken Barber) -- Remove concat::setup for include in preparation for the next concat release (Ken Barber) +### Added +- Use modern APT keyrings on Debian family; require puppetlabs/apt 9.2 [#1563](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1563) ([kenyon](https://github.com/kenyon)) +- List Debian 12 as supported system [#1488](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1488) ([deric](https://github.com/deric)) -##2013-10-14 - Version 3.0.0 +### Fixed -Final release of 3.0, enjoy! +- acceptance tests: ensure code is idempotent [#1589](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1589) ([bastelfreak](https://github.com/bastelfreak)) +## [v10.1.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.1.0) - 2024-03-26 -##2013-10-14 - Version 3.0.0-rc3 +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v10.0.3...v10.1.0) -###Summary +### Added -Add a parameter to unmanage pg_hba.conf to fix a regression from 2.5, as well -as allowing owner to be passed into x. +- Add a global password_encryption parameter [#1584](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1584) ([ekohl](https://github.com/ekohl)) +- Use RequiresMountsFor on datadir [#1582](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1582) ([ekohl](https://github.com/ekohl)) +- Support Ubuntu 24.04 and postgis for postgresql 16 [#1581](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1581) ([bmiklautz](https://github.com/bmiklautz)) +- Add Fedora 39 support [#1580](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1580) ([lweller](https://github.com/lweller)) -####Features -- `manage_pg_hba_conf` parameter added to control pg_hba.conf management. -- `owner` parameter added to server::db. +### Other +- Fix typo in postgresql_conf provider docs [#1579](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1579) ([bastelfreak](https://github.com/bastelfreak)) -##2013-10-09 - Version 3.0.0-rc2 +## [v10.0.3](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.0.3) - 2024-01-09 -###Summary +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v10.0.2...v10.0.3) -A few bugfixes have been found since -rc1. +### Fixed -####Fixes -- Special case for $datadir on Amazon -- Fix documentation about username/password for the postgresql_hash function +- support for a custom apt source release [#1561](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1561) ([h0tw1r3](https://github.com/h0tw1r3)) +- (#1556) Fix Python package name for Ubuntu >= 22.04 [#1557](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1557) ([antaflos](https://github.com/antaflos)) +- Unconfine postgresql_conf [#1551](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1551) ([smortex](https://github.com/smortex)) +## [v10.0.2](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.0.2) - 2023-11-08 -##2013-10-01 - Version 3.0.0-rc1 +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v10.0.1...v10.0.2) -###Summary +### Fixed -Version 3 was a major rewrite to fix some internal dependency issues, and to -make the new Public API more clear. As a consequence a lot of things have -changed for version 3 and older revisions that we will try to outline here. +- postgresql_conf: Fix regex for value param and add tests [#1544](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1544) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) -(NOTE: The format of this CHANGELOG differs to normal in an attempt to -explain the scope of changes) +## [v10.0.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.0.1) - 2023-10-12 -* Server specific objects now moved under `postgresql::server::` namespace: +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v10.0.0...v10.0.1) -To restructure server specific elements under the `postgresql::server::` -namespaces the following objects were renamed as such: +### Fixed -`postgresql::database` -> `postgresql::server::database` -`postgresql::database_grant` -> `postgresql::server::database_grant` -`postgresql::db` -> `postgresql::server::db` -`postgresql::grant` -> `postgresql::server::grant` -`postgresql::pg_hba_rule` -> `postgresql::server::pg_hba_rule` -`postgresql::plperl` -> `postgresql::server::plperl` -`postgresql::contrib` -> `postgresql::server::contrib` -`postgresql::role` -> `postgresql::server::role` -`postgresql::table_grant` -> `postgresql::server::table_grant` -`postgresql::tablespace` -> `postgresql::server::tablespace` +- Fix `postgresql::default()` return value for unknown parameters [#1530](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1530) ([smortex](https://github.com/smortex)) +- Fix the `postgresql::postgresql_password()` function [#1529](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1529) ([smortex](https://github.com/smortex)) -* New `postgresql::server::config_entry` resource for managing configuration: +## [v10.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v10.0.0) - 2023-10-11 -Previously we used the `file_line` resource to modify `postgresql.conf`. This -new revision now adds a new resource named `postgresql::server::config_entry` -for managing this file. For example: +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v9.2.0...v10.0.0) -```puppet - postgresql::server::config_entry { 'check_function_bodies': - value => 'off', - } -``` +### Changed -If you were using `file_line` for this purpose, you should change to this new -methodology. +- postgis: Drop EL5 leftovers and fix package name for Fedora [#1521](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1521) ([bastelfreak](https://github.com/bastelfreak)) +- Drop EoL SLES 11.4 code [#1520](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1520) ([bastelfreak](https://github.com/bastelfreak)) +- Drop code for Debian without systemd [#1514](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1514) ([bastelfreak](https://github.com/bastelfreak)) +- puppet/systemd: Allow 6.x [#1505](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1505) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- set datatype for directories to Stdlib::Absolutepath [#1499](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1499) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- Drop postgresql 8.4/RHEL6 specific code [#1489](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1489) ([bastelfreak](https://github.com/bastelfreak)) +- Drop postgresql 8.1/RHEL5 specific code [#1486](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1486) ([bastelfreak](https://github.com/bastelfreak)) +- Delete deprecated validate_db_connection() defined resource [#1484](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1484) ([bastelfreak](https://github.com/bastelfreak)) +- postgresql::server: Remove deprecated createdb_path parameter [#1483](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1483) ([bastelfreak](https://github.com/bastelfreak)) +- postgresql::server: Remove deprecated version parameter [#1482](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1482) ([bastelfreak](https://github.com/bastelfreak)) +- puppetlabs/stdlib: Require 9.x [#1481](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1481) ([bastelfreak](https://github.com/bastelfreak)) +- port: Enforce Stdlib::Port datatype [#1473](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1473) ([bastelfreak](https://github.com/bastelfreak)) +- Add Server Instance Feature [#1450](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1450) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) -* `postgresql_puppet_extras.conf` has been removed: +### Added -Now that we have a methodology for managing `postgresql.conf`, and due to -concerns over the file management methodology using an `exec { 'touch ...': }` -as a way to create an empty file the existing postgresql\_puppet\_extras.conf -file is no longer managed by this module. +- Drop EoL FreeBSD 9.4/9.5 specific code [#1519](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1519) ([bastelfreak](https://github.com/bastelfreak)) +- Drop code compatibility for non-systemd Red Hat [#1518](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1518) ([ekohl](https://github.com/ekohl)) +- add $manage_selinux as a parameter, keep default, simpler condition [#1516](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1516) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- add port and psql_path parameter to initdb define [#1510](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1510) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- PDK update 2.7.0->3.0.0 [#1508](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1508) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- variables to parameters for tablespace/schema/reassign_owned_by [#1507](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1507) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- server::schema: Drop unused $version variable [#1506](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1506) ([bastelfreak](https://github.com/bastelfreak)) +- Prefer $connect_settings over explicit parameters [#1498](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1498) ([bastelfreak](https://github.com/bastelfreak)) +- server::extension: make user/group/psql_path configureable [#1497](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1497) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- server::db: Make port/user/group configureable [#1494](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1494) ([bastelfreak](https://github.com/bastelfreak)) +- server::database_grant: Always set default user/group and expose port as parameter [#1493](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1493) ([bastelfreak](https://github.com/bastelfreak)) +- server::database: make user/group/psql_path/default_db configureable [#1492](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1492) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- Provide a default for config_entry's path and enforce absolute path [#1490](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1490) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) -If you wish to recreate this methodology yourself, use this pattern: +### Fixed -```puppet - class { 'postgresql::server': } +- Fix password_encryption for DBVERSION in server::role [#1515](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1515) ([cruelsmith](https://github.com/cruelsmith)) +- Flexible password encryption in pg hba conf [#1512](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1512) ([cruelsmith](https://github.com/cruelsmith)) +- service name should be unique to allow instances [#1504](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1504) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- server::grant: make port optional/restore connect_settings feature [#1496](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1496) ([bastelfreak](https://github.com/bastelfreak)) - $extras = "/tmp/include.conf" +## [v9.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v9.2.0) - 2023-08-30 - file { $extras: - content => 'max_connections = 123', - notify => Class['postgresql::server::service'], - }-> - postgresql::server::config_entry { 'include': - value => $extras, - } -``` +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v9.1.0...v9.2.0) -* All uses of the parameter `charset` changed to `encoding`: +### Added -Since PostgreSQL uses the terminology `encoding` not `charset` the parameter -has been made consisent across all classes and resources. +- port parameter: Cleanup datatype [#1471](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1471) ([bastelfreak](https://github.com/bastelfreak)) +- puppet/systemd: Allow 5.x & puppetlabs/concat: Allow 9.x [#1448](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1448) ([bastelfreak](https://github.com/bastelfreak)) +- Add default version for Fedora 37, 38 [#1421](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1421) ([lweller](https://github.com/lweller)) +- Defaulting password encryption for version above 14 [#1406](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1406) ([cruelsmith](https://github.com/cruelsmith)) -* The `postgresql` base class is no longer how you set globals: +### Fixed -The old global override pattern was less then optimal so it has been fixed, -however we decided to demark this properly by specifying these overrides in -the class `postgresql::global`. Consult the documentation for this class now -to see what options are available. +- port parameter: log warning when its a string [#1474](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1474) ([bastelfreak](https://github.com/bastelfreak)) +- pg_hba.conf: Introduce a newline after each rule [#1472](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1472) ([bastelfreak](https://github.com/bastelfreak)) +- (CAT-1262)-updated legacy repo for SUSE [#1462](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1462) ([praj1001](https://github.com/praj1001)) +- Fix log directory config entry name [#1457](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1457) ([chillinger](https://github.com/chillinger)) +- Make anchors in defined resources unique [#1455](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1455) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- implement key parameter for config_entry defined resource [#1454](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1454) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- add missing parameters to initdb [#1451](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1451) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- Fix default value for $service_status on ArchLinux [#1410](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1410) ([smortex](https://github.com/smortex)) +- Fix wrong Sensitive handling for updating role passwords [#1404](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1404) ([cruelsmith](https://github.com/cruelsmith)) -Also, some parameter elements have been moved between this and the -`postgresql::server` class where it made sense. +## [v9.1.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v9.1.0) - 2023-06-12 -* `config_hash` parameter collapsed for the `postgresql::server` class: +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v9.0.3...v9.1.0) -Because the `config_hash` was really passing data through to what was in -effect an internal class (`postgresql::config`). And since we don't want this -kind of internal exposure the parameters were collapsed up into the -`postgresql::server` class directly. +### Added -* Lots of changes to 'private' or 'undocumented' classes: +- pdksync - (MAINT) - Allow Stdlib 9.x [#1440](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1440) ([LukasAud](https://github.com/LukasAud)) -If you were using these before, these have changed names. You should only use -what is documented in this README.md, and if you don't have what you need you -should raise a patch to add that feature to a public API. All internal classes -now have a comment at the top indicating them as private to make sure the -message is clear that they are not supported as Public API. +## [v9.0.3](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v9.0.3) - 2023-05-09 -* `pg_hba_conf_defaults` parameter included to turn off default pg\_hba rules: +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v9.0.2...v9.0.3) -The defaults should be good enough for most cases (if not raise a bug) but if -you simply need an escape hatch, this setting will turn off the defaults. If -you want to do this, it may affect the rest of the module so make sure you -replace the rules with something that continues operation. +### Fixed -* `postgresql::database_user` has now been removed: +- (GH-1426) - Update value to accept array [#1434](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1434) ([jordanbreen28](https://github.com/jordanbreen28)) +- (#1432) - Fix `Unable to mark 'unless' as sensitive` [#1433](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1433) ([kBite](https://github.com/kBite)) -Use `postgresql::server::role` instead. +## [v9.0.2](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v9.0.2) - 2023-05-02 -* `postgresql::psql` resource has now been removed: +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v9.0.1...v9.0.2) -Use `postgresql_psql` instead. In the future we may recreate this as a wrapper -to add extra capability, but it will not match the old behaviour. +### Fixed -* `postgresql_default_version` fact has now been removed: +- (CONT-950) - Fix mismatched data types [#1430](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1430) ([jordanbreen28](https://github.com/jordanbreen28)) +- (CONT-904) - Removal of tech debt [#1429](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1429) ([jordanbreen28](https://github.com/jordanbreen28)) +- (CONT-949) - Bump stdlib dependency [#1428](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1428) ([jordanbreen28](https://github.com/jordanbreen28)) -It didn't make sense to have this logic in a fact any more, the logic has been -moved into `postgresql::params`. +## [v9.0.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v9.0.1) - 2023-04-24 -* `ripienaar/concat` is no longer used, instead we use `puppetlabs/concat`: +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v9.0.0...v9.0.1) -The older concat module is now deprecated and moved into the -`puppetlabs/concat` namespace. Functionality is more or less identical, but -you may need to intervene during the installing of this package - as both use -the same `concat` namespace. +### Fixed ---- -##2013-09-09 Release 2.5.0 +- Fix wrong data type for `data_checksums` parameter [#1420](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1420) ([smortex](https://github.com/smortex)) -###Summary +## [v9.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v9.0.0) - 2023-04-21 -The focus of this release is primarily to capture the fixes done to the -types and providers to make sure refreshonly works properly and to set -the stage for the large scale refactoring work of 3.0.0. +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v8.3.0...v9.0.0) -####Features +### Changed +- (CONT-792) - Add Puppet 8/Drop Puppet 6 [#1414](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1414) ([jordanbreen28](https://github.com/jordanbreen28)) -####Bugfixes -- Use boolean for refreshonly. -- Fix postgresql::plperl documentation. -- Add two missing parameters to config::beforeservice -- Style fixes +## [v8.3.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v8.3.0) - 2023-04-21 +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v8.2.1...v8.3.0) -##2013-08-01 Release 2.4.1 +### Added -###Summary +- convert ERB templates to EPP [#1399](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1399) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- (CONT-361) Syntax update [#1397](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1397) ([LukasAud](https://github.com/LukasAud)) +- Add multi instance support, refactoring reload.pp (6/x) [#1392](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1392) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- Add multi instance support, refactoring password.pp (5/x) [#1391](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1391) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- Add multi instance support, refactoring late_initdb.pp (3/x) [#1384](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1384) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- Add multi instance support, refactoring initdb.pp (2/x) [#1383](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1383) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- Add multi instance support, refactoring config.pp (1/x) [#1382](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1382) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- pg_hba_rule: Validate userinput in postgresql::server [#1376](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1376) ([bastelfreak](https://github.com/bastelfreak)) +- pg_hba_rule: Move `type` datatype to own type [#1375](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1375) ([bastelfreak](https://github.com/bastelfreak)) +- pg_hba_rule does not properly verify address parameter [#1372](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1372) ([tuxmea](https://github.com/tuxmea)) -This minor bugfix release solves an idempotency issue when using plain text -passwords for the password_hash parameter for the postgresql::role defined -type. Without this, users would continually see resource changes everytime -your run Puppet. +### Fixed -####Bugfixes -- Alter role call not idempotent with cleartext passwords (Ken Barber) +- Ubuntu 14/16/17: Drop code leftovers [#1388](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1388) ([bastelfreak](https://github.com/bastelfreak)) +- remove debian 8 and 9 corpses [#1387](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1387) ([SimonHoenscheid](https://github.com/SimonHoenscheid)) +- Archlinux client and server package names were swapped around [#1381](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1381) ([tobixen](https://github.com/tobixen)) +- apt::source: configure repo only for current architecture [#1380](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1380) ([bastelfreak](https://github.com/bastelfreak)) +- pdksync - (CONT-189) Remove support for RedHat6 / OracleLinux6 / Scientific6 [#1371](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1371) ([david22swan](https://github.com/david22swan)) +- pdksync - (CONT-130) - Dropping Support for Debian 9 [#1368](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1368) ([jordanbreen28](https://github.com/jordanbreen28)) +- (maint) Codebase Hardening [#1366](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1366) ([david22swan](https://github.com/david22swan)) +- Fix table grant with schema [#1315](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1315) ([vaol](https://github.com/vaol)) +## [v8.2.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v8.2.1) - 2022-08-24 -##2013-07-19 Release 2.4.0 +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v8.2.0...v8.2.1) -###Summary +### Fixed -This updates adds the ability to change permissions on tables, create template -databases from normal databases, manage PL-Perl's postgres package, and -disable the management of `pg_hba.conf`. +- Fix puppet-strings documentation [#1363](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1363) ([ekohl](https://github.com/ekohl)) +- (GH-1360) Reverting REFERENCE.md changes [#1361](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1361) ([pmcmaw](https://github.com/pmcmaw)) +- Only require password when used [#1356](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1356) ([arjenz](https://github.com/arjenz)) -####Features -- Add `postgresql::table_grant` defined resource -- Add `postgresql::plperl` class -- Add `manage_pg_hba_conf` parameter to the `postgresql::config` class -- Add `istemplate` parameter to the `postgresql::database` define +## [v8.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v8.2.0) - 2022-08-23 -####Bugfixes -- Update `postgresql::role` class to be able to update roles when modified -instead of only on creation. -- Update tests -- Fix documentation of `postgresql::database_grant` +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v8.1.0...v8.2.0) +### Added -##2.3.0 +- pdksync - (GH-cat-11) Certify Support for Ubuntu 22.04 [#1355](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1355) ([david22swan](https://github.com/david22swan)) +- (MODULES-11251) Add support for backup provider "pg_dump" [#1319](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1319) ([fraenki](https://github.com/fraenki)) -This feature release includes the following changes: +### Fixed -* Add a new parameter `owner` to the `database` type. This can be used to - grant ownership of a new database to a specific user. (Bruno Harbulot) -* Add support for operating systems other than Debian/RedHat, as long as the - user supplies custom values for all of the required paths, package names, etc. - (Chris Price) -* Improved integration testing (Ken Barber) +- Ensure multiple postgresql::server::recovery resources can be defined [#1348](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1348) ([Deroin](https://github.com/Deroin)) +## [v8.1.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v8.1.0) - 2022-07-21 -##2.2.1 +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v8.0.0...v8.1.0) -This release fixes a bug whereby one of our shell commands (psql) were not ran from a globally accessible directory. This was causing permission denied errors when the command attempted to change user without changing directory. +### Added -Users of previous versions might have seen this error: +- Fix service status detection on Debian-based OSes [#1349](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1349) ([arjenz](https://github.com/arjenz)) +- (FM-8971) allow deferred function for role pwd [#1347](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1347) ([tvpartytonight](https://github.com/tvpartytonight)) +- Set version for Fedora 36 [#1345](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1345) ([lweller](https://github.com/lweller)) +- Add Red Hat Enterprise Linux 9 support [#1303](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1303) ([ekohl](https://github.com/ekohl)) - Error: Error executing SQL; psql returned 256: 'could not change directory to "/root" +### Fixed -This patch should correct that. +- (GH-1352) - Updating postgresql service version on SLES [#1353](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1353) ([pmcmaw](https://github.com/pmcmaw)) +- Respect $service_status on Red Hat-based distros [#1351](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1351) ([ekohl](https://github.com/ekohl)) +- Add version for Ubuntu 22.04 [#1350](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1350) ([arjenz](https://github.com/arjenz)) +- README.md: correct postgresql_conn_validator example [#1332](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1332) ([bastelfreak](https://github.com/bastelfreak)) +- pdksync - (GH-iac-334) Remove Support for Ubuntu 14.04/16.04 [#1331](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1331) ([david22swan](https://github.com/david22swan)) +- Remove unused variable in reload.pp [#1327](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1327) ([ekohl](https://github.com/ekohl)) +- Use systemctl reload on EL 7 and higher [#1326](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1326) ([ekohl](https://github.com/ekohl)) -#### Detail Changes +## [v8.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v8.0.0) - 2022-03-03 -* Set /tmp as default CWD for postgresql_psql +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.5.0...v8.0.0) +### Changed -##2.2.0 +- Support setting default_privileges on all schemas [#1298](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1298) ([fish-face](https://github.com/fish-face)) -This feature release introduces a number of new features and bug fixes. +### Added -First of all it includes a new class named `postgresql::python` which provides you with a convenient way of install the python Postgresql client libraries. +- add default version for Fedora 35 [#1317](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1317) ([jflorian](https://github.com/jflorian)) +- add scram-sha-256 support [#1313](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1313) ([fe80](https://github.com/fe80)) +- add support for Ubuntu Hirsute and Impish [#1312](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1312) ([nicholascioli](https://github.com/nicholascioli)) +- Allow systemd to mask postgresql service file [#1310](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1310) ([kimsondrup](https://github.com/kimsondrup)) +- Make ::contrib a noop on OSes without a contrib package [#1309](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1309) ([cduelo](https://github.com/cduelo)) +- pdksync - (IAC-1753) - Add Support for AlmaLinux 8 [#1308](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1308) ([david22swan](https://github.com/david22swan)) +- MODULES-11201: add service_name for Ubuntu 18.04 and later [#1306](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1306) ([moritz-makandra](https://github.com/moritz-makandra)) +- pdksync - (IAC-1751) - Add Support for Rocky 8 [#1305](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1305) ([david22swan](https://github.com/david22swan)) +- Default privileges support schemas [#1300](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1300) ([fish-face](https://github.com/fish-face)) +- Support target_role in default_privileges [#1297](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1297) ([fish-face](https://github.com/fish-face)) - class { 'postgresql::python': - } +### Fixed -You are now able to use `postgresql::database_user` without having to specify a password_hash, useful for different authentication mechanisms that do not need passwords (ie. cert, local etc.). +- pdksync - (IAC-1787) Remove Support for CentOS 6 [#1324](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1324) ([david22swan](https://github.com/david22swan)) +- Fix python package name in RHEL/CentOS 8 [#1316](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1316) ([kajinamit](https://github.com/kajinamit)) +- Drop further code for Debian 6 and Ubuntu 10 [#1307](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1307) ([ekohl](https://github.com/ekohl)) -We've also provided a lot more advanced custom parameters now for greater control of your Postgresql installation. Consult the class documentation for PuppetDB in the README. +## [v7.5.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.5.0) - 2021-09-28 -This release in particular has largely been contributed by the community members below, a big thanks to one and all. +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.4.1...v7.5.0) -#### Detailed Changes +### Added -* Add support for psycopg installation (Flaper Fesp and Dan Prince) -* Added default PostgreSQL version for Ubuntu 13.04 (Kamil Szymanski) -* Add ability to create users without a password (Bruno Harbulot) -* Three Puppet 2.6 fixes (Dominic Cleal) -* Add explicit call to concat::setup when creating concat file (Dominic Cleal) -* Fix readme typo (Jordi Boggiano) -* Update postgres_default_version for Ubuntu (Kamil Szymanski) -* Allow to set connection for noew role (Kamil Szymanski) -* Fix pg_hba_rule for postgres local access (Kamil Szymanski) -* Fix versions for travis-ci (Ken Barber) -* Add replication support (Jordi Boggiano) -* Cleaned up and added unit tests (Ken Barber) -* Generalization to provide more flexability in postgresql configuration (Karel Brezina) -* Create dependent directory for sudoers so tests work on Centos 5 (Ken Barber) -* Allow SQL commands to be run against a specific DB (Carlos Villela) -* Drop trailing comma to support Puppet 2.6 (Michael Arnold) +- Use Puppet-Datatype Sensitive for Passwords [#1279](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1279) ([cocker-cc](https://github.com/cocker-cc)) +### Fixed -##2.1.1 +- (IAC-1598) - Remove Support for Debian 8 [#1302](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1302) ([david22swan](https://github.com/david22swan)) +- Inline file contents in the catalog [#1299](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1299) ([ekohl](https://github.com/ekohl)) +- Fix changing default encoding [#1296](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1296) ([smortex](https://github.com/smortex)) +## [v7.4.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.4.1) - 2021-08-25 -This release provides a bug fix for RHEL 5 and Centos 5 systems, or specifically systems using PostgreSQL 8.1 or older. On those systems one would have received the error: +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.4.0...v7.4.1) - Error: Could not start Service[postgresqld]: Execution of ‘/sbin/service postgresql start’ returned 1: +### Fixed -And the postgresql log entry: +- (maint) Allow stdlib 8.0.0 [#1293](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1293) ([smortex](https://github.com/smortex)) - FATAL: unrecognized configuration parameter "include" +## [v7.4.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.4.0) - 2021-08-24 -This bug is due to a new feature we had added in 2.1.0, whereby the `include` directive in `postgresql.conf` was not compatible. As a work-around we have added checks in our code to make sure systems running PostgreSQL 8.1 or older do not have this directive added. +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.3.0...v7.4.0) -#### Detailed Changes +### Added -2013-01-21 - Ken Barber -* Only install `include` directive and included file on PostgreSQL >= 8.2 -* Add system tests for Centos 5 +- pdksync - (IAC-1709) - Add Support for Debian 11 [#1288](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1288) ([david22swan](https://github.com/david22swan)) +### Fixed -##2.1.0 +- drop code for Debian 6/7 and Ubuntu 10.04/12.04 [#1290](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1290) ([evgeni](https://github.com/evgeni)) -This release is primarily a feature release, introducing some new helpful constructs to the module. +## [v7.3.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.3.0) - 2021-08-03 -For starters, we've added the line `include 'postgresql_conf_extras.conf'` by default so extra parameters not managed by the module can be added by other tooling or by Puppet itself. This provides a useful escape-hatch for managing settings that are not currently managed by the module today. +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.2.0...v7.3.0) -We've added a new defined resource for managing your tablespace, so you can now create new tablespaces using the syntax: +### Added - postgresql::tablespace { 'dbspace': - location => '/srv/dbspace', - } +- MODULES-11049 - Implement default privileges changes [#1267](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1267) ([mtancoigne](https://github.com/mtancoigne)) -We've added a locale parameter to the `postgresql` class, to provide a default. Also the parameter has been added to the `postgresql::database` and `postgresql::db` defined resources for changing the locale per database: +### Fixed - postgresql::db { 'mydatabase': - user => 'myuser', - password => 'mypassword', - encoding => 'UTF8', - locale => 'en_NG', - } +- Do not add version component to repo definition [#1282](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1282) ([psapezhka](https://github.com/psapezhka)) +- (MODULES-8700) Autorequire the service in postgresql_psql [#1276](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1276) ([ekohl](https://github.com/ekohl)) -There is a new class for installing the necessary packages to provide the PostgreSQL JDBC client jars: +## [v7.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.2.0) - 2021-05-24 - class { 'postgresql::java': } +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.1.0...v7.2.0) -And we have a brand new defined resource for managing fine-grained rule sets within your pg_hba.conf access lists: +### Added - postgresql::pg_hba { 'Open up postgresql for access from 200.1.2.0/24': - type => 'host', - database => 'app', - user => 'app', - address => '200.1.2.0/24', - auth_method => 'md5', - } +- (MODULES-11069) add default version for fedora 34 [#1272](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1272) ([lweller](https://github.com/lweller)) +- MODULES-11047 - Allow managing rights for PUBLIC role [#1266](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1266) ([mtancoigne](https://github.com/mtancoigne)) -Finally, we've also added Travis-CI support and unit tests to help us iterate faster with tests to reduce regression. The current URL for these tests is here: https://travis-ci.org/puppetlabs/puppet-postgresql. Instructions on how to run the unit tests available are provided in the README for the module. +## [v7.1.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.1.0) - 2021-04-12 -A big thanks to all those listed below who made this feature release possible :-). +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.0.3...v7.1.0) -#### Detailed Changes +### Added -2013-01-18 - Simão Fontes & Flaper Fesp -* Remove trailing commas from params.pp property definition for Puppet 2.6.0 compatibility +- Add new common repo which contains add-ons [#1190](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1190) ([jorhett](https://github.com/jorhett)) -2013-01-18 - Lauren Rother -* Updated README.md to conform with best practices template +## [v7.0.3](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.0.3) - 2021-04-12 -2013-01-09 - Adrien Thebo -* Update postgresql_default_version to 9.1 for Debian 7.0 +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.0.2...v7.0.3) -2013-01-28 - Karel Brezina -* Add support for tablespaces +## [v7.0.2](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.0.2) - 2021-03-15 -2013-01-16 - Chris Price & Karel Brezina -* Provide support for an 'include' config file 'postgresql_conf_extras.conf' that users can modify manually or outside of the module. +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.0.1...v7.0.2) -2013-01-31 - jv -* Fix typo in README.pp for postgresql::db example +### Fixed -2013-02-03 - Ken Barber -* Add unit tests and travis-ci support +- (MODULES-10957) Override the set_sensitive_parameters method [#1258](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1258) ([sheenaajay](https://github.com/sheenaajay)) -2013-02-02 - Ken Barber -* Add locale parameter support to the 'postgresql' class +## [v7.0.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.0.1) - 2021-03-08 -2013-01-21 - Michael Arnold -* Add a class for install the packages containing the PostgreSQL JDBC jar +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v7.0.0...v7.0.1) -2013-02-06 - fhrbek -* Coding style fixes to reduce warnings in puppet-lint and Geppetto +### Fixed -2013-02-10 - Ken Barber -* Provide new defined resource for managing pg_hba.conf +- Ensure port is a string in psql command [#1253](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1253) ([ekohl](https://github.com/ekohl)) -2013-02-11 - Ken Barber -* Fix bug with reload of Postgresql on Redhat/Centos +## [v7.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v7.0.0) - 2021-03-04 -2013-02-15 - Erik Dalén -* Fix more style issues to reduce warnings in puppet-lint and Geppetto +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.10.2...v7.0.0) -2013-02-15 - Erik Dalén -* Fix case whereby we were modifying a hash after creation +### Changed +- pdksync - (MAINT) Remove SLES 11 support [#1247](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1247) ([sanfrancrisko](https://github.com/sanfrancrisko)) +- pdksync - (MAINT) Remove RHEL 5 family support [#1246](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1246) ([sanfrancrisko](https://github.com/sanfrancrisko)) +- pdksync - Remove Puppet 5 from testing and bump minimal version to 6.0.0 [#1238](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1238) ([carabasdaniel](https://github.com/carabasdaniel)) -##2.0.1 +### Added -Minor bugfix release. +- Add DNF module management [#1239](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1239) ([ekohl](https://github.com/ekohl)) -2013-01-16 - Chris Price - * Fix revoke command in database.pp to support postgres 8.1 (43ded42) +## [v6.10.2](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.10.2) - 2021-02-22 -2013-01-15 - Jordi Boggiano - * Add support for ubuntu 12.10 status (3504405) +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.10.1...v6.10.2) -##2.0.0 +### Fixed -Many thanks to the following people who contributed patches to this -release: +- Fix command shell escaping [#1240](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1240) ([DavidS](https://github.com/DavidS)) -* Adrien Thebo -* Albert Koch -* Andreas Ntaflos -* Brett Porter -* Chris Price -* dharwood -* Etienne Pelletier -* Florin Broasca -* Henrik -* Hunter Haugen -* Jari Bakken -* Jordi Boggiano -* Ken Barber -* nzakaria -* Richard Arends -* Spenser Gilliland -* stormcrow -* William Van Hevelingen +## [v6.10.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.10.1) - 2021-02-09 -Notable features: +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.10.0...v6.10.1) - * Add support for versions of postgres other than the system default version - (which varies depending on OS distro). This includes optional support for - automatically managing the package repo for the "official" postgres yum/apt - repos. (Major thanks to Etienne Pelletier and - Ken Barber for their tireless efforts and patience on this - feature set!) For example usage see `tests/official-postgresql-repos.pp`. +## [v6.10.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.10.0) - 2021-02-08 - * Add some support for Debian Wheezy and Ubuntu Quantal +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.9.0...v6.10.0) - * Add new `postgres_psql` type with a Ruby provider, to replace the old - exec-based `psql` type. This gives us much more flexibility around - executing SQL statements and controlling their logging / reports output. +### Added - * Major refactor of the "spec" tests--which are actually more like - acceptance tests. We now support testing against multiple OS distros - via vagrant, and the framework is in place to allow us to very easily add - more distros. Currently testing against Cent6 and Ubuntu 10.04. +- Set default PostgreSQL version for FreeBSD [#1227](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1227) ([olevole](https://github.com/olevole)) +- Clean up globals logic to support CentOS 8 stream [#1225](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1225) ([ekohl](https://github.com/ekohl)) - * Fixed a bug that was preventing multiple databases from being owned by the - same user - (9adcd182f820101f5e4891b9f2ff6278dfad495c - Etienne Pelletier ) +### Fixed - * Add support for ACLs for finer-grained control of user/interface access - (b8389d19ad78b4fb66024897097b4ed7db241930 - dharwood ) +- Also perform systemd daemon-reload on Puppet 6.1+ [#1233](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1233) ([ekohl](https://github.com/ekohl)) +- (bug) fix systemd daemon-reload order when updating service files [#1230](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1230) ([sheenaajay](https://github.com/sheenaajay)) +- Fix postgresql::sql task when password is not set [#1226](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1226) ([smortex](https://github.com/smortex)) - * Many other bug fixes and improvements! +## [v6.9.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.9.0) - 2021-01-18 ---- -##1.0.0 +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.8.0...v6.9.0) -2012-09-17 - Version 0.3.0 released +### Added -2012-09-14 - Chris Price - * Add a type for validating a postgres connection (ce4a049) +- pdksync - (feat) - Add support for puppet 7 [#1215](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1215) ([daianamezdrea](https://github.com/daianamezdrea)) +- Manage postgresql_conf_path file permissions [#1199](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1199) ([ekohl](https://github.com/ekohl)) -2012-08-25 - Jari Bakken - * Remove trailing commas. (e6af5e5) +### Fixed -2012-08-16 - Version 0.2.0 released +- (maint) updated defaults for rhel7 policycoreutils [#1212](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1212) ([sheenaajay](https://github.com/sheenaajay)) +- (IAC-1189) - Fix for SLES 15 SP 1 and later [#1209](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1209) ([david22swan](https://github.com/david22swan)) +- Change - Use systemd drop-in directory for unit overrides [#1201](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1201) ([blackknight36](https://github.com/blackknight36)) + +## [v6.8.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.8.0) - 2020-09-29 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.7.0...v6.8.0) + +### Added + +- add hostgssenc type to pg_hba rules [#1195](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1195) ([osijan](https://github.com/osijan)) +- Allow removal of config_entries via main class [#1187](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1187) ([ekohl](https://github.com/ekohl)) + +### Fixed + +- Fix contrib package name under debian 10 [#1188](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1188) ([neomilium](https://github.com/neomilium)) + +## [v6.7.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.7.0) - 2020-08-28 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.6.0...v6.7.0) + +### Added + +- pdksync - (IAC-973) - Update travis/appveyor to run on new default branch `main` [#1182](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1182) ([david22swan](https://github.com/david22swan)) + +## [v6.6.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.6.0) - 2020-06-22 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.5.0...v6.6.0) + +### Added + +- (IAC-746) - Add ubuntu 20.04 support [#1172](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1172) ([david22swan](https://github.com/david22swan)) + +### Fixed + +- Invert psql/package dependency logic [#1179](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1179) ([raphink](https://github.com/raphink)) +- Fix custom port in extension [#1165](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1165) ([Vampouille](https://github.com/Vampouille)) + +## [v6.5.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.5.0) - 2020-05-13 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.4.0...v6.5.0) + +### Added + +- service_ensure => true is now an allowed value (aliased to running) [#1167](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1167) ([binford2k](https://github.com/binford2k)) +- Finish conversion of `postgresql_acls_to_resources_hash` function [#1163](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1163) ([alexjfisher](https://github.com/alexjfisher)) +- Finish conversion of `postgresql_escape` function [#1162](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1162) ([alexjfisher](https://github.com/alexjfisher)) +- Finish conversion of `postgresql_password` function [#1161](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1161) ([alexjfisher](https://github.com/alexjfisher)) +- Allow usage of grant and role when not managing postgresql::server [#1159](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1159) ([tuxmea](https://github.com/tuxmea)) +- Add version configs for SLES 12 SP 3 to 5 [#1158](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1158) ([XnS](https://github.com/XnS)) +- Add extra parameter "extra_systemd_config" [#1156](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1156) ([veninga](https://github.com/veninga)) + +### Fixed + +- (MODULES-10610) Use correct lower bound for concat version [#1160](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1160) ([ghoneycutt](https://github.com/ghoneycutt)) + +## [v6.4.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.4.0) - 2020-03-17 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.3.0...v6.4.0) + +### Added + +- Add Fedora 31 compatibility [#1141](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1141) ([blackknight36](https://github.com/blackknight36)) +- feat: enable different database resource name in extension [#1136](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1136) ([jfroche](https://github.com/jfroche)) +- pdksync - (FM-8581) - Debian 10 added to travis and provision file refactored [#1130](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1130) ([david22swan](https://github.com/david22swan)) +- Puppet 4 functions [#1129](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1129) ([binford2k](https://github.com/binford2k)) + +### Fixed + +- Fix incorrectly quoted GRANT cmd on functions [#1150](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1150) ([olifre](https://github.com/olifre)) +- Correct versioncmp logic in config.pp [#1137](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1137) ([boydtom](https://github.com/boydtom)) +- Treat $version as an integer for comparison, defaults to string [#1135](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1135) ([boydtom](https://github.com/boydtom)) +- Allow usage of PUBLIC role [#1134](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1134) ([Vampouille](https://github.com/Vampouille)) +- fix missing systemd override config for EL8 (CentOS and RHEL) [#1131](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1131) ([david-barbion](https://github.com/david-barbion)) + +## [v6.3.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.3.0) - 2019-12-18 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.2.0...v6.3.0) + +### Added + +- Add support for granting privileges on functions [#1118](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1118) ([crispygoth](https://github.com/crispygoth)) +- (FM-8679) - Support added for CentOS 8 [#1117](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1117) ([david22swan](https://github.com/david22swan)) +- MODULES-10041 - allow define password_encryption for version above 10 [#1111](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1111) ([k2patel](https://github.com/k2patel)) + +### Fixed + +- Remove duplicate REFERENCE.md file with strange unicode character at end of filename [#1108](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1108) ([nudgegoonies](https://github.com/nudgegoonies)) + +## [v6.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.2.0) - 2019-09-13 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.1.0...v6.2.0) + +### Added + +- FM-8408 - add support on Debian10 [#1103](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1103) ([lionce](https://github.com/lionce)) +- Fix/directory defined twice [#1089](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1089) ([arcenik](https://github.com/arcenik)) +- Adding SLES 15 [#1087](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1087) ([msurato](https://github.com/msurato)) +- (FM-7500) conversion to use litmus [#1081](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1081) ([tphoney](https://github.com/tphoney)) + +### Fixed + +- (MODULES-9658) - custom ports are not labeled correctly [#1099](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1099) ([blackknight36](https://github.com/blackknight36)) +- Fix: When assigning a tablespace to a database, no equal sign is needed in the query [#1098](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1098) ([biertie](https://github.com/biertie)) +- Grant all tables in schema fixup [#1096](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1096) ([georgehansper](https://github.com/georgehansper)) +- (MODULES-9219) - puppetlabs-postgresql : catalog compilation fails when the service command is not installed [#1093](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1093) ([blackknight36](https://github.com/blackknight36)) + +## [v6.1.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.1.0) - 2019-06-04 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/v6.0.0...v6.1.0) + +### Added + +- (FM-8031) Add RedHat 8 support [#1083](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1083) ([eimlav](https://github.com/eimlav)) + +## [v6.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/v6.0.0) - 2019-05-14 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.12.1...v6.0.0) + +### Changed + +- pdksync - (MODULES-8444) - Raise lower Puppet bound [#1070](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1070) ([david22swan](https://github.com/david22swan)) +- (maint) remove inconsistent extra variable [#1044](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1044) ([binford2k](https://github.com/binford2k)) + +### Added + +- Add Fedora 30 compatibility [#1067](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1067) ([blackknight36](https://github.com/blackknight36)) +- Include EL8 version for config checks [#1060](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1060) ([ehelms](https://github.com/ehelms)) + +### Fixed + +- Support current version of puppetlabs/apt. [#1073](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1073) ([pillarsdotnet](https://github.com/pillarsdotnet)) +- change username/group/datadir defaults for FreeBSD [#1063](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1063) ([olevole](https://github.com/olevole)) + +## [5.12.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.12.1) - 2019-02-14 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.12.0...5.12.1) + +### Fixed + +- (FM-7811) - Use postgresql 9.4 for SLES 11 sp4 [#1057](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1057) ([david22swan](https://github.com/david22swan)) +- (MODULES-8553) Further cleanup for package tag issues [#1055](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1055) ([HelenCampbell](https://github.com/HelenCampbell)) + +## [5.12.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.12.0) - 2019-02-01 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.11.0...5.12.0) + +### Added + +- (MODULES-3804) Fix sort order of pg_hba_rule entries [#1040](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1040) ([olavmrk](https://github.com/olavmrk)) + +### Fixed + +- (MODULES-8553) Fix dependency on apt by explicitly using 'puppetlabs-postgresql' as tag [#1052](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1052) ([HelenCampbell](https://github.com/HelenCampbell)) +- (MODULES-8352) Don't use empty encoding string on initdb [#1043](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1043) ([binford2k](https://github.com/binford2k)) +- pdksync - (FM-7655) Fix rubygems-update for ruby < 2.3 [#1042](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1042) ([tphoney](https://github.com/tphoney)) + +## [5.11.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.11.0) - 2018-11-21 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.10.0...5.11.0) + +### Added + +- Add postgis support for postgres 10 [#1032](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1032) ([smussie](https://github.com/smussie)) + +### Fixed + +- Strip quotes from role names [#1034](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1034) ([jstuart](https://github.com/jstuart)) +- Ignore .psqlrc so output is clean and doesn't break Puppet [#1021](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1021) ([flaviogurgel](https://github.com/flaviogurgel)) +- Change initdb option '--xlogdir' to '-X' for PG10 compatibility [#976](https://github.com/puppetlabs/puppetlabs-postgresql/pull/976) ([fcanovai](https://github.com/fcanovai)) + +## [5.10.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.10.0) - 2018-09-27 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.9.0...5.10.0) + +### Added + +- pdksync - (MODULES-6805) metadata.json shows support for puppet 6 [#1026](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1026) ([tphoney](https://github.com/tphoney)) + +## [5.9.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.9.0) - 2018-09-07 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.8.0...5.9.0) + +### Added + +- pdksync - (MODULES-7705) - Bumping stdlib dependency from < 5.0.0 to < 6.0.0 [#1018](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1018) ([pmcmaw](https://github.com/pmcmaw)) + +## [5.8.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.8.0) - 2018-08-07 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.7.0...5.8.0) + +### Added + +- metadata.json: bump allowed version of puppetlabs-apt to 6.0.0 [#1012](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1012) ([mateusz-gozdek-sociomantic](https://github.com/mateusz-gozdek-sociomantic)) + +## [5.7.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.7.0) - 2018-07-20 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.6.0...5.7.0) + +### Added + +- (MODULES-7479) Update postgresql to support Ubuntu 18.04 [#1005](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1005) ([david22swan](https://github.com/david22swan)) +- (MODULES-6542) - Adding SLES 11 & 12 to metadata [#1001](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1001) ([pmcmaw](https://github.com/pmcmaw)) + +### Fixed + +- (MODULES-7479) Ensure net-tools is installed when testing on Ubuntu 18.04 [#1006](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1006) ([david22swan](https://github.com/david22swan)) +- (MODULES-7460) - Updating grant table to include INSERT privileges [#1004](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1004) ([pmcmaw](https://github.com/pmcmaw)) +- Fix packages choice for ubuntu 17.10 [#1000](https://github.com/puppetlabs/puppetlabs-postgresql/pull/1000) ([fflorens](https://github.com/fflorens)) + +## [5.6.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.6.0) - 2018-06-21 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.5.0...5.6.0) + +## [5.5.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.5.0) - 2018-06-19 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.4.0...5.5.0) + +### Changed + +- Fix creation of recovery.conf file when recovery configuration is not specified [#995](https://github.com/puppetlabs/puppetlabs-postgresql/pull/995) ([cdloh](https://github.com/cdloh)) + +### Added + +- Add compatibility for Fedora 28 [#994](https://github.com/puppetlabs/puppetlabs-postgresql/pull/994) ([jflorian](https://github.com/jflorian)) +- (MODULES-5994) Add debian 9 [#992](https://github.com/puppetlabs/puppetlabs-postgresql/pull/992) ([hunner](https://github.com/hunner)) +- Adding default Postgresql version for Ubuntu 18.04 [#981](https://github.com/puppetlabs/puppetlabs-postgresql/pull/981) ([lutaylor](https://github.com/lutaylor)) + +### Fixed + +- Fix quoting on schema owners [#979](https://github.com/puppetlabs/puppetlabs-postgresql/pull/979) ([hasegeli](https://github.com/hasegeli)) + +## [5.4.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.4.0) - 2018-03-27 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.3.0...5.4.0) + +### Added + +- (MODULES-6330) PDK convert 1.4.1 [#961](https://github.com/puppetlabs/puppetlabs-postgresql/pull/961) ([pmcmaw](https://github.com/pmcmaw)) +- Parameter `ensure` on `postgresql::server::grant` and `postgresql::server::database_grant` [#891](https://github.com/puppetlabs/puppetlabs-postgresql/pull/891) ([georgehansper](https://github.com/georgehansper)) + +### Fixed + +- Documentation error, `reassign_owned_by` uses `*_role` not `*_owner`. [#958](https://github.com/puppetlabs/puppetlabs-postgresql/pull/958) ([computermouth](https://github.com/computermouth)) + +## [5.3.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.3.0) - 2018-02-26 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.2.1...5.3.0) + +### Added + +- Support extension schemas [#948](https://github.com/puppetlabs/puppetlabs-postgresql/pull/948) ([hasegeli](https://github.com/hasegeli)) +- Inherit 9.6 settings for later PgSQL version on FreeBSD [#945](https://github.com/puppetlabs/puppetlabs-postgresql/pull/945) ([olevole](https://github.com/olevole)) +- MODULES-6194 - Add scram-sha-256 as a valid pg_hba_rule auth method [#941](https://github.com/puppetlabs/puppetlabs-postgresql/pull/941) ([f3nry](https://github.com/f3nry)) +- FM-6445 add a task [#930](https://github.com/puppetlabs/puppetlabs-postgresql/pull/930) ([tphoney](https://github.com/tphoney)) +- add ensure=>absent to postgresql::server::role [#897](https://github.com/puppetlabs/puppetlabs-postgresql/pull/897) ([georgehansper](https://github.com/georgehansper)) + +### Fixed + +- (maint) - Skip run_puppet_access_login on LTS [#956](https://github.com/puppetlabs/puppetlabs-postgresql/pull/956) ([pmcmaw](https://github.com/pmcmaw)) +- (MODULES-6608) - Adding puppet requirement for tasks versioncmp in beaker-task_helper [#952](https://github.com/puppetlabs/puppetlabs-postgresql/pull/952) ([pmcmaw](https://github.com/pmcmaw)) +- defaulted psql_path to postgresql::server::psql_path [#947](https://github.com/puppetlabs/puppetlabs-postgresql/pull/947) ([crayfishx](https://github.com/crayfishx)) +- According to the puppet doc, Pattern should be a list of regex. [#942](https://github.com/puppetlabs/puppetlabs-postgresql/pull/942) ([PierreR](https://github.com/PierreR)) +- This pull request fixes an augeas warning [#935](https://github.com/puppetlabs/puppetlabs-postgresql/pull/935) ([iakovgan](https://github.com/iakovgan)) + +## [5.2.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.2.1) - 2017-11-14 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.2.0...5.2.1) + +### Fixed + +- (MODULES-5956) fixes for postgresql release [#934](https://github.com/puppetlabs/puppetlabs-postgresql/pull/934) ([jbondpdx](https://github.com/jbondpdx)) +- add parameter "version" to postgresql::server::extension - fix dependency on database [#932](https://github.com/puppetlabs/puppetlabs-postgresql/pull/932) ([georgehansper](https://github.com/georgehansper)) + +## [5.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.2.0) - 2017-10-09 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.1.0...5.2.0) + +### Added + +- add parameter "version" to postgresql::server::extension to update the extension version [#896](https://github.com/puppetlabs/puppetlabs-postgresql/pull/896) ([georgehansper](https://github.com/georgehansper)) + +### Fixed + +- (PUP-8008) monkey patch spec_helper_acceptance [#925](https://github.com/puppetlabs/puppetlabs-postgresql/pull/925) ([eputnam](https://github.com/eputnam)) +- (PUP-8008) monkey patch spec_helper_acceptance [#924](https://github.com/puppetlabs/puppetlabs-postgresql/pull/924) ([eputnam](https://github.com/eputnam)) +- enhance --data-checksums on initdb [#915](https://github.com/puppetlabs/puppetlabs-postgresql/pull/915) ([mmoll](https://github.com/mmoll)) +- MODULES-5378 fix the change in error message [#909](https://github.com/puppetlabs/puppetlabs-postgresql/pull/909) ([tphoney](https://github.com/tphoney)) +- MODULES-5378 fix error message checking in test [#908](https://github.com/puppetlabs/puppetlabs-postgresql/pull/908) ([tphoney](https://github.com/tphoney)) +- Default contcat order [#900](https://github.com/puppetlabs/puppetlabs-postgresql/pull/900) ([matonb](https://github.com/matonb)) + +## [5.1.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.1.0) - 2017-07-17 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/5.0.0...5.1.0) + +### Added + +- add defined type postgresql::server::reassign_owned_by [#894](https://github.com/puppetlabs/puppetlabs-postgresql/pull/894) ([georgehansper](https://github.com/georgehansper)) +- add data_checksums option to initdb [#878](https://github.com/puppetlabs/puppetlabs-postgresql/pull/878) ([tjikkun](https://github.com/tjikkun)) + +## [5.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/5.0.0) - 2017-06-21 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.9.0...5.0.0) + +### Changed + +- Unset default log_line_prefix [#870](https://github.com/puppetlabs/puppetlabs-postgresql/pull/870) ([hasegeli](https://github.com/hasegeli)) +- Let listen_addresses be defined independently [#865](https://github.com/puppetlabs/puppetlabs-postgresql/pull/865) ([hasegeli](https://github.com/hasegeli)) + +### Added + +- (MODULES-1394) replace validate_db_connection type with custom type [#879](https://github.com/puppetlabs/puppetlabs-postgresql/pull/879) ([eputnam](https://github.com/eputnam)) +- [msync] 786266 Implement puppet-module-gems, a45803 Remove metadata.json from locales config [#860](https://github.com/puppetlabs/puppetlabs-postgresql/pull/860) ([wilson208](https://github.com/wilson208)) +- (FM-6116) - Adding POT file for metadata.json [#857](https://github.com/puppetlabs/puppetlabs-postgresql/pull/857) ([pmcmaw](https://github.com/pmcmaw)) +- Allowo to disable managing passwords for users [#846](https://github.com/puppetlabs/puppetlabs-postgresql/pull/846) ([bjoernhaeuser](https://github.com/bjoernhaeuser)) + +### Fixed + +- (maint) fix for connection validator [#882](https://github.com/puppetlabs/puppetlabs-postgresql/pull/882) ([eputnam](https://github.com/eputnam)) +- (MODULES-5050) Fix for grant_schema_spec [#881](https://github.com/puppetlabs/puppetlabs-postgresql/pull/881) ([eputnam](https://github.com/eputnam)) +- [MODULES-4598] Revert "Revert "fix default params for SUSE family OSes"" [#863](https://github.com/puppetlabs/puppetlabs-postgresql/pull/863) ([mmoll](https://github.com/mmoll)) +- [MODULES-4598] Revert "fix default params for SUSE family OSes" [#858](https://github.com/puppetlabs/puppetlabs-postgresql/pull/858) ([wilson208](https://github.com/wilson208)) + +## [4.9.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.9.0) - 2017-03-09 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.8.0...4.9.0) + +### Added + +- (MODULES-1508) add support for unix_socket_directories [#845](https://github.com/puppetlabs/puppetlabs-postgresql/pull/845) ([eputnam](https://github.com/eputnam)) +- (MODULES-1127) allow LANGUAGE as valid object_type [#838](https://github.com/puppetlabs/puppetlabs-postgresql/pull/838) ([eputnam](https://github.com/eputnam)) +- Support granting SELECT and UPDATE permission on sequences (MODULES-4158) [#823](https://github.com/puppetlabs/puppetlabs-postgresql/pull/823) ([chris-reeves](https://github.com/chris-reeves)) + +### Fixed + +- (MODULES-1707) add logic to params.pp for jdbc driver package on Debian [#847](https://github.com/puppetlabs/puppetlabs-postgresql/pull/847) ([eputnam](https://github.com/eputnam)) +- (maint) Schemas for a db should come after db [#840](https://github.com/puppetlabs/puppetlabs-postgresql/pull/840) ([hunner](https://github.com/hunner)) +- Fix typo: hostnosssl [#837](https://github.com/puppetlabs/puppetlabs-postgresql/pull/837) ([df7cb](https://github.com/df7cb)) +- Fix SQL style on role.pp [#794](https://github.com/puppetlabs/puppetlabs-postgresql/pull/794) ([hasegeli](https://github.com/hasegeli)) +- (#3858) Fix unless check in grant_role to work with roles as well as users [#788](https://github.com/puppetlabs/puppetlabs-postgresql/pull/788) ([thunderkeys](https://github.com/thunderkeys)) + +## [4.8.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.8.0) - 2016-07-26 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.7.1...4.8.0) + +## [4.7.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.7.1) - 2016-02-18 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.7.0...4.7.1) + +### Fixed + +- Add missing onlyif_function to sequence grant code [#738](https://github.com/puppetlabs/puppetlabs-postgresql/pull/738) ([cfrantsen](https://github.com/cfrantsen)) +- Correctly set $service_provider [#735](https://github.com/puppetlabs/puppetlabs-postgresql/pull/735) ([antaflos](https://github.com/antaflos)) + +## [4.7.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.7.0) - 2016-02-02 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.6.1...4.7.0) + +### Added + +- (MODULES-2960) Allow float postgresql_conf values [#721](https://github.com/puppetlabs/puppetlabs-postgresql/pull/721) ([hunner](https://github.com/hunner)) + +## [4.6.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.6.1) - 2015-12-04 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.6.0...4.6.1) + +## [4.6.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.6.0) - 2015-09-01 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.5.0...4.6.0) + +### Fixed + +- Fix postgis default package name on RedHat [#674](https://github.com/puppetlabs/puppetlabs-postgresql/pull/674) ([ckaenzig](https://github.com/ckaenzig)) + +## [4.5.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.5.0) - 2015-07-28 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.4.2...4.5.0) + +## [4.4.2](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.4.2) - 2015-07-08 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.4.1...4.4.2) + +### Added + +- (#2056) Added 9.4, corrected past versions based on docs [#625](https://github.com/puppetlabs/puppetlabs-postgresql/pull/625) ([cjestel](https://github.com/cjestel)) + +### Fixed + +- (MODULES-2185) Fix `withenv` execution under Puppet 2.7 [#664](https://github.com/puppetlabs/puppetlabs-postgresql/pull/664) ([domcleal](https://github.com/domcleal)) + +## [4.4.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.4.1) - 2015-07-01 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.4.0...4.4.1) + +### Fixed + +- (MODULES-2181) Fix variable scope for systemd-override [#659](https://github.com/puppetlabs/puppetlabs-postgresql/pull/659) ([kbarber](https://github.com/kbarber)) + +## [4.4.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.4.0) - 2015-06-30 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.3.0...4.4.0) + +### Added + +- (MODULES-1761) Provide defined resource for managing recovery.conf [#603](https://github.com/puppetlabs/puppetlabs-postgresql/pull/603) ([dacrome](https://github.com/dacrome)) + +### Fixed + +- (FM-2931) fixes logic problem with onlyif type param validation. [#654](https://github.com/puppetlabs/puppetlabs-postgresql/pull/654) ([bmjen](https://github.com/bmjen)) +- Fixed systemd override for manage_repo package versions [#639](https://github.com/puppetlabs/puppetlabs-postgresql/pull/639) ([cdenneen](https://github.com/cdenneen)) +- Apt fix [#618](https://github.com/puppetlabs/puppetlabs-postgresql/pull/618) ([tphoney](https://github.com/tphoney)) +- Fix URLs in metadata.json [#599](https://github.com/puppetlabs/puppetlabs-postgresql/pull/599) ([raphink](https://github.com/raphink)) + +## [4.3.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.3.0) - 2015-03-25 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.2.0...4.3.0) + +## [4.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.2.0) - 2015-03-10 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.1.0...4.2.0) + +### Fixed + +- Fix comment detection [#559](https://github.com/puppetlabs/puppetlabs-postgresql/pull/559) ([hunner](https://github.com/hunner)) +- Fix comment detection [#558](https://github.com/puppetlabs/puppetlabs-postgresql/pull/558) ([hunner](https://github.com/hunner)) + +## [4.1.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.1.0) - 2014-11-04 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/4.0.0...4.1.0) + +### Fixed + +- fix future parser error [#504](https://github.com/puppetlabs/puppetlabs-postgresql/pull/504) ([steeef](https://github.com/steeef)) + +## [4.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/4.0.0) - 2014-09-10 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.4.2...4.0.0) + +### Fixed + +- Fixes the accidental erasing of pg_ident.conf [#464](https://github.com/puppetlabs/puppetlabs-postgresql/pull/464) ([txaj](https://github.com/txaj)) + +## [3.4.2](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.4.2) - 2014-08-06 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.4.1...3.4.2) + +## [3.4.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.4.1) - 2014-07-21 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.4.0...3.4.1) + +## [3.4.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.4.0) - 2014-07-09 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.3.3...3.4.0) + +### Added + +- postgis support [#280](https://github.com/puppetlabs/puppetlabs-postgresql/pull/280) ([kitchen](https://github.com/kitchen)) + +### Fixed + +- This corrects the location of the pg_hba config file on debian oses in tests [#440](https://github.com/puppetlabs/puppetlabs-postgresql/pull/440) ([justinstoller](https://github.com/justinstoller)) +- Fix trailing }. [#436](https://github.com/puppetlabs/puppetlabs-postgresql/pull/436) ([apenney](https://github.com/apenney)) +- Fix postgresql_conf quote logic [#297](https://github.com/puppetlabs/puppetlabs-postgresql/pull/297) ([reidmv](https://github.com/reidmv)) + +## [3.3.3](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.3.3) - 2014-03-06 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.3.2...3.3.3) + +## [3.3.2](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.3.2) - 2014-03-03 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.3.1...3.3.2) + +## [3.3.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.3.1) - 2014-02-12 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.3.0...3.3.1) + +## [3.3.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.3.0) - 2014-01-28 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.2.0...3.3.0) + +### Added + +- Add support to custom xlogdir parameter [#256](https://github.com/puppetlabs/puppetlabs-postgresql/pull/256) ([mnencia](https://github.com/mnencia)) + +### Fixed + +- Fix typo, clearly from a copy/paste mistake [#347](https://github.com/puppetlabs/puppetlabs-postgresql/pull/347) ([mhagander](https://github.com/mhagander)) +- fix for concat error [#343](https://github.com/puppetlabs/puppetlabs-postgresql/pull/343) ([flypenguin](https://github.com/flypenguin)) +- Fix NOREPLICATION option for Postgres 9.1 [#333](https://github.com/puppetlabs/puppetlabs-postgresql/pull/333) ([brandonwamboldt](https://github.com/brandonwamboldt)) +- Wrong parameter name: manage_pg_conf -> manage_pg_hba_conf [#324](https://github.com/puppetlabs/puppetlabs-postgresql/pull/324) ([aadamovich](https://github.com/aadamovich)) +- Fix table_grant_spec to show a bug [#310](https://github.com/puppetlabs/puppetlabs-postgresql/pull/310) ([mcanevet](https://github.com/mcanevet)) + +## [3.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.2.0) - 2013-11-05 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.1.0...3.2.0) + +## [3.1.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.1.0) - 2013-10-25 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.0.0...3.1.0) + +### Fixed + +- (GH-198) Fix race condition on startup [#292](https://github.com/puppetlabs/puppetlabs-postgresql/pull/292) ([kbarber](https://github.com/kbarber)) + +## [3.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.0.0) - 2013-10-16 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.0.0-rc3...3.0.0) + +## [3.0.0-rc3](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.0.0-rc3) - 2013-10-16 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.0.0-rc2...3.0.0-rc3) + +## [3.0.0-rc2](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.0.0-rc2) - 2013-10-09 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/3.0.0-rc1...3.0.0-rc2) + +## [3.0.0-rc1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/3.0.0-rc1) - 2013-10-02 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.5.0...3.0.0-rc1) + +### Fixed + +- Fixing small typos [#248](https://github.com/puppetlabs/puppetlabs-postgresql/pull/248) ([ggeldenhuis](https://github.com/ggeldenhuis)) + +## [2.5.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.5.0) - 2013-09-09 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.4.1...2.5.0) + +## [2.4.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.4.1) - 2013-08-01 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.4.0...2.4.1) + +### Fixed + +- (GH-216) Alter role call not idempotent with cleartext passwords [#225](https://github.com/puppetlabs/puppetlabs-postgresql/pull/225) ([kbarber](https://github.com/kbarber)) + +## [2.4.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.4.0) - 2013-08-01 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.3.0...2.4.0) + +## [2.3.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.3.0) - 2013-06-06 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.2.1...2.3.0) + +## [2.2.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.2.1) - 2013-04-29 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.2.0...2.2.1) + +## [2.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.2.0) - 2013-04-26 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.1.1...2.2.0) + +## [2.1.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.1.1) - 2013-02-22 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.1.0...2.1.1) + +## [2.1.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.1.0) - 2013-02-20 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.0.1...2.1.0) + +## [2.0.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.0.1) - 2013-01-30 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/2.0.0...2.0.1) + +## [2.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/2.0.0) - 2013-01-15 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/1.0.0...2.0.0) + +### Added + +- Defining ACLs in pg_hba.conf [#20](https://github.com/puppetlabs/puppetlabs-postgresql/pull/20) ([dharwood](https://github.com/dharwood)) + +### Fixed + +- Syntax Error [#55](https://github.com/puppetlabs/puppetlabs-postgresql/pull/55) ([Spenser309](https://github.com/Spenser309)) + +## [1.0.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/1.0.0) - 2012-10-24 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/release-0.3.0...1.0.0) + +## [release-0.3.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/release-0.3.0) - 2012-09-17 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/release-0.2.0...release-0.3.0) + +## [release-0.2.0](https://github.com/puppetlabs/puppetlabs-postgresql/tree/release-0.2.0) - 2012-08-16 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/release-0.0.1...release-0.2.0) + +## [release-0.0.1](https://github.com/puppetlabs/puppetlabs-postgresql/tree/release-0.0.1) - 2012-05-02 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-postgresql/compare/01c9cbeb7c3bd5c7bd067c5d7438df7d34027fbc...release-0.0.1) diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000000..071e159c4e --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,2 @@ +# Setting ownership to the modules team +* @puppetlabs/modules @alexjfisher @bastelfreak @deric @ekohl @SimonHoenscheid @smortex diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f1cbde4bbf..e7a3a7c3fe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,220 +1,3 @@ -Checklist (and a short version for the impatient) -================================================= - - * Commits: - - - Make commits of logical units. - - - Check for unnecessary whitespace with "git diff --check" before - committing. - - - Commit using Unix line endings (check the settings around "crlf" in - git-config(1)). - - - Do not check in commented out code or unneeded files. - - - The first line of the commit message should be a short - description (50 characters is the soft limit, excluding ticket - number(s)), and should skip the full stop. - - - Associate the issue in the message. The first line should include - the issue number in the form "(#XXXX) Rest of message". - - - The body should provide a meaningful commit message, which: - - - uses the imperative, present tense: "change", not "changed" or - "changes". - - - includes motivation for the change, and contrasts its - implementation with the previous behavior. - - - Make sure that you have tests for the bug you are fixing, or - feature you are adding. - - - Make sure the test suites passes after your commit: - `bundle exec rspec spec/acceptance` More information on [testing](#Testing) below - - - When introducing a new feature, make sure it is properly - documented in the README.md - - * Submission: - - * Pre-requisites: - - - Make sure you have a [GitHub account](https://github.com/join) - - - [Create a ticket](https://tickets.puppetlabs.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppetlabs.com/browse/) you are patching for. - - * Preferred method: - - - Fork the repository on GitHub. - - - Push your changes to a topic branch in your fork of the - repository. (the format ticket/1234-short_description_of_change is - usually preferred for this project). - - - Submit a pull request to the repository in the puppetlabs - organization. - -The long version -================ - - 1. Make separate commits for logically separate changes. - - Please break your commits down into logically consistent units - which include new or changed tests relevant to the rest of the - change. The goal of doing this is to make the diff easier to - read for whoever is reviewing your code. In general, the easier - your diff is to read, the more likely someone will be happy to - review it and get it into the code base. - - If you are going to refactor a piece of code, please do so as a - separate commit from your feature or bug fix changes. - - We also really appreciate changes that include tests to make - sure the bug is not re-introduced, and that the feature is not - accidentally broken. - - Describe the technical detail of the change(s). If your - description starts to get too long, that is a good sign that you - probably need to split up your commit into more finely grained - pieces. - - Commits which plainly describe the things which help - reviewers check the patch and future developers understand the - code are much more likely to be merged in with a minimum of - bike-shedding or requested changes. Ideally, the commit message - would include information, and be in a form suitable for - inclusion in the release notes for the version of Puppet that - includes them. - - Please also check that you are not introducing any trailing - whitespace or other "whitespace errors". You can do this by - running "git diff --check" on your changes before you commit. - - 2. Sending your patches - - To submit your changes via a GitHub pull request, we _highly_ - recommend that you have them on a topic branch, instead of - directly on "master". - It makes things much easier to keep track of, especially if - you decide to work on another thing before your first change - is merged in. - - GitHub has some pretty good - [general documentation](http://help.github.com/) on using - their site. They also have documentation on - [creating pull requests](http://help.github.com/send-pull-requests/). - - In general, after pushing your topic branch up to your - repository on GitHub, you can switch to the branch in the - GitHub UI and click "Pull Request" towards the top of the page - in order to open a pull request. - - - 3. Update the related GitHub issue. - - If there is a GitHub issue associated with the change you - submitted, then you should update the ticket to include the - location of your branch, along with any other commentary you - may wish to make. - -Testing -======= - -Getting Started ---------------- - -Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby -package manager such as [bundler](http://bundler.io/) what Ruby packages, -or Gems, are required to build, develop, and test this software. - -Please make sure you have [bundler installed](http://bundler.io/#getting-started) -on your system, then use it to install all dependencies needed for this project, -by running - -```shell -% bundle install -Fetching gem metadata from https://rubygems.org/........ -Fetching gem metadata from https://rubygems.org/.. -Using rake (10.1.0) -Using builder (3.2.2) --- 8><-- many more --><8 -- -Using rspec-system-puppet (2.2.0) -Using serverspec (0.6.3) -Using rspec-system-serverspec (1.0.0) -Using bundler (1.3.5) -Your bundle is complete! -Use `bundle show [gemname]` to see where a bundled gem is installed. -``` - -NOTE some systems may require you to run this command with sudo. - -If you already have those gems installed, make sure they are up-to-date: - -```shell -% bundle update -``` - -With all dependencies in place and up-to-date we can now run the tests: - -```shell -% rake spec -``` - -This will execute all the [rspec tests](http://rspec-puppet.com/) tests -under [spec/defines](./spec/defines), [spec/classes](./spec/classes), -and so on. rspec tests may have the same kind of dependencies as the -module they are testing. While the module defines in its [Modulefile](./Modulefile), -rspec tests define them in [.fixtures.yml](./fixtures.yml). - -Some puppet modules also come with [beaker](https://github.com/puppetlabs/beaker) -tests. These tests spin up a virtual machine under -[VirtualBox](https://www.virtualbox.org/)) with, controlling it with -[Vagrant](http://www.vagrantup.com/) to actually simulate scripted test -scenarios. In order to run these, you will need both of those tools -installed on your system. - -You can run them by issuing the following command - -```shell -% rake spec_clean -% rspec spec/acceptance -``` - -This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml), -install puppet, copy this module and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb) -and then run all the tests under [spec/acceptance](./spec/acceptance). - -Writing Tests -------------- - -XXX getting started writing tests. - -If you have commit access to the repository -=========================================== - -Even if you have commit access to the repository, you will still need to -go through the process above, and have someone else review and merge -in your changes. The rule is that all changes must be reviewed by a -developer on the project (that did not write the code) to ensure that -all changes go through a code review process. - -Having someone other than the author of the topic branch recorded as -performing the merge is the record that they performed the code -review. - - -Additional Resources -==================== - -* [Getting additional help](http://puppetlabs.com/community/get-help) - -* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests) - -* [Patchwork](https://patchwork.puppetlabs.com) - -* [General GitHub documentation](http://help.github.com/) - -* [GitHub pull request documentation](http://help.github.com/send-pull-requests/) +# Contributing to Puppet modules +Check out our [Contributing to Supported Modules Blog Post](https://puppetlabs.github.io/iac/docs/contributing_to_a_module.html) to find all the information that you will need. diff --git a/Gemfile b/Gemfile index bfe64b186a..7a1566ddb4 100644 --- a/Gemfile +++ b/Gemfile @@ -1,48 +1,78 @@ -source ENV['GEM_SOURCE'] || "https://rubygems.org" +source ENV['GEM_SOURCE'] || 'https://rubygems.org' -def location_for(place, fake_version = nil) - if place =~ /^(git:[^#]*)#(.*)/ - [fake_version, { :git => $1, :branch => $2, :require => false }].compact - elsif place =~ /^file:\/\/(.*)/ - ['>= 0', { :path => File.expand_path($1), :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, { :require => false }] + [place_or_version, { require: false }] end end -group :development, :unit_tests do - gem 'rspec-core', '3.1.7', :require => false - gem 'puppetlabs_spec_helper', :require => false - gem 'simplecov', :require => false - gem 'puppet_facts', :require => false - gem 'json', :require => false +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 "racc", '~> 1.4.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "deep_merge", '~> 1.2.2', require: false + gem "voxpupuli-puppet-lint-plugins", '~> 5.0', require: false + gem "facterdb", '~> 1.18', require: false + gem "metadata-json-lint", '~> 4.0', require: false + gem "rspec-puppet-facts", '~> 2.0', require: false + gem "dependency_checker", '~> 1.0.0', require: false + gem "parallel_tests", '= 3.12.1', require: false + gem "pry", '~> 0.10', require: false + gem "simplecov-console", '~> 0.9', require: false + gem "puppet-debugger", '~> 1.0', require: false + gem "rubocop", '~> 1.50.0', require: false + gem "rubocop-performance", '= 1.16.0', require: false + gem "rubocop-rspec", '= 2.19.0', require: false + gem "rb-readline", '= 0.5.5', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "github_changelog_generator", '= 1.15.2', require: false +end +group :development, :release_prep do + gem "puppet-strings", '~> 4.0', require: false + gem "puppetlabs_spec_helper", '~> 7.0', require: false end - group :system_tests do - if beaker_version = ENV['BEAKER_VERSION'] - gem 'beaker', *location_for(beaker_version) - end - if beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION'] - gem 'beaker-rspec', *location_for(beaker_rspec_version) - else - gem 'beaker-rspec', :require => false - end - gem 'serverspec', :require => false - gem 'beaker-puppet_install_helper', :require => false + gem "puppet_litmus", '~> 1.0', require: false, platforms: [:ruby, :x64_mingw] + gem "CFPropertyList", '< 3.0.7', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "serverspec", '~> 2.41', require: false end +puppet_version = ENV['PUPPET_GEM_VERSION'] +facter_version = ENV['FACTER_GEM_VERSION'] +hiera_version = ENV['HIERA_GEM_VERSION'] +gems = {} -if facterversion = ENV['FACTER_GEM_VERSION'] - gem 'facter', facterversion, :require => false -else - gem 'facter', :require => false -end +gems['puppet'] = location_for(puppet_version) + +# If facter or hiera versions have been specified via the environment +# variables + +gems['facter'] = location_for(facter_version) if facter_version +gems['hiera'] = location_for(hiera_version) if hiera_version -if puppetversion = ENV['PUPPET_GEM_VERSION'] - gem 'puppet', puppetversion, :require => false -else - gem 'puppet', :require => false +gems.each do |gem_name, gem_params| + gem gem_name, *gem_params end -# vim:ft=ruby +# Evaluate Gemfile.local and ~/.gemfile if they exist +extra_gemfiles = [ + "#{__FILE__}.local", + File.join(Dir.home, '.gemfile'), +] + +extra_gemfiles.each do |gemfile| + if File.file?(gemfile) && File.readable?(gemfile) + eval(File.read(gemfile), binding) + end +end +# vim: syntax=ruby diff --git a/HISTORY.md b/HISTORY.md new file mode 100644 index 0000000000..cd32fe9a24 --- /dev/null +++ b/HISTORY.md @@ -0,0 +1,976 @@ +## 5.3.0 +### Summary +Implements rubocop changes within the module, alongside other smaller changes. + +#### Added +- ensure=>absent added to postgresql::server:role. +- Support added for Fedora 27. +- scram-sha-256 added as a valid ph_hba_rule auth method. +- 9.6 settings inherited for later PgSQL versions on FreeBSD. +- A require has been added for puppet. + +#### Changed +- Changes made to avoid the useless loading of files by augeas. +- Modulesync changes. +- psql_path defaulted to postgresql::server::psql_path. +- Rubocop changes have been made. + +#### Removed +- Debian 9 support deprecated. + +## Supported Release 5.2.1 +### Summary +Bug fix for issue introduced in 5.2.0 + +#### Fixed +- issue where the module was attempting to install extensions before a database was available. ([SERVER-2003](https://tickets.puppetlabs.com/browse/SERVER-2003)) + +## Supported Release 5.2.0 +### Summary +Adds several new features including some work around OS support. Also includes a couple of fixes to tests and the removal of unsupported Ubuntu versions. + +#### Added +- Added default postgresql version of Ubuntu 17.4 version to the globals.pp file. +- Fedora 26 provides postgresql-server version 9.6 by default - Added support to manifests/globals.pp to avoid puppet failures on Fedora 26 nodes. +- Use postgresql 9.6 for the newest SLES and openSUSE releases. +- Enhanced --data-checksums on initdb. +- Added support for Debian version 9. +- Added a `version` parameter. + +#### Changed +- Replaced validate_re calls with puppet datatype `Pattern` and is_array calls with puppet datatype `Array`. +- Installation method for apt in the spec_helper_acceptance, this is a temporary workaround due to issues with module installation. + +#### Fixed +- Updated spec tests to remove deprecation warnings. +- Docs formatting. +- Pass default_connect_settings to validate service ([MODULES-4682](https://tickets.puppetlabs.com/browse/MODULES-4682)) +- Rocket Alignment for Lint. +- Fixed changes in error messages in tests ([MODULES-5378](https://tickets.puppetlabs.com/browse/MODULES-5378)) + +#### Removed +- Removed unsupported Ubuntu versions 10.04 and 12.04 ([MODULES-5501](https://tickets.puppetlabs.com/browse/MODULES-5501)) +- Removed unsupported Debian version 6. +- Removed numeric order override. + +## Supported Release 5.1.0 +### Summary +This release includes Japanese translations for internationalization, Puppet 5 support, implementation of defined type postgresql::server::reassign_owned_by. + +#### Features +- Updating translations for readmes/README_ja_JP.md +- add defined type postgresql::server::reassign_owned_by +- Allow order parameter to be string value +- prep for puppet 5 ([MODULES-5144](https://tickets.puppetlabs.com/browse/MODULES-5144)) +- add data_checksums option to initdb +- parameter ensure of custom resource postgresql_replication_slot is not documented ([MODULES-2989](https://tickets.puppetlabs.com/browse/MODULES-2989)) + +#### Bug Fixes +- Adding a space for header formatting +- use https for apt.postgresql.org repo +- msync puppet 5 and ruby 2.4 ([MODULES-5197](https://tickets.puppetlabs.com/browse/MODULES-5187)) +- Only run test on postgresql >= 9.0 ([FM-6240](https://tickets.puppetlabs.com/browse/FM-6240)) +- Fix Ruby 2.4 deprecation in postgresql_acls_to_resources_hash + +## Supported Release 5.0.0 +### Summary +This **major** release dropped support for Puppet 3 and PostgreSQL 8.x, added Puppet 4 data types, and deprecated the validate_db_connection type. + +#### Added +- `locales/` directory, .pot file, and i18n `config.yaml`. ([FM-6116](https://tickets.puppet.com/browse/FM-6116)) +- `update_password` parameter to toggle password management per role. +- **Puppet 4** type validation. +- new `postgresql_conn_validator` custom type and deprecated `validate_db_connection`. ([MODULES-1394](https://tickets.puppet.com/browse/MODULES-1394)) + +#### Changed +- default postgis versions in postgresql::globals to use newer versions. +- puppetlabs-concat and puppetlabs-apt dependencies to use latest versions. ([MODULES-4906](https://tickets.puppet.com/browse/MODULES-4906), [MODULES-4947](https://tickets.puppet.com/browse/MODULES-4947)) +- default value for `log_line_prefix` to `undef`. +- `listen_addresses` default value to 'localhost'. Allows for it to be set independently of a class declaration. +- use of stdlib validate_* functions. They have been removed in favor of Puppet 4 type validation. +- lower Puppet dependency in metadata to 4.7.0. ([MODULES-4826](https://tickets.puppet.com/browse/MODULES-4826)) + +#### Fixed +- deprecated apt::source parameters(`key`,`key_source`, & `include_src`). +- default SUSE parameters. ([MODULES-4598](https://tickets.puppet.com/browse/MODULES-4598)) +- use of force parameter on concat resources. + +## Supported Release 4.9.0 +### Summary +This release adds several types and, among other bugs, fixes an issue with the yum URL. + +#### Features +- Modifying ownership of databases and schemas now available (MODULES-3247) +- Use `module_workdir` to specify a custom directory in which to execute psql commands +- `grant_role` and `grant` types added! +- Support for parallel unit testing (parallel_tests) +- Override download/installation repo URL with `repo_baseurl` +- Set your timezone with `timezone` +- Grant privileges on LANGUAGEs +- Added support for Debian Stretch and Ubuntu Yakkety Yak + +#### Bugfixes +- Usernames and passwords are now converted to strings before password hash is created +- Specify default database name if it is not the username +- Update to yum repo +- Schema name conflicts fix + +## Supported Release 4.8.0 +### Summary +This release primarily fixes an issue with `postgresql_conf` values of ipaddresses being considered floats and not getting quoted. + +#### Features +- Add `default_connect_settings` parameter to `postgresql::server` +- Running under strict variables is now supported +- Add timestamps into logs by default + +#### Bugfixes +- Obscure password in postgresql\_psql type +- Fix ip address quoting in postgresql\_conf type +- Fix handling of systemd service on Ubuntu +- Mark log_min_duration_statement setting as requiring a service restart +- Add fixes for Fedora 23, Fedora 24, FreeBSD, OpenBSD +- Fix environment handling to avoid "Overriding environment setting" message +- Work around PUP-6385, using empty arrays instead of undef when specifying resource relationships +- README editorial pass +- Reduce whitespace in templates +- Update build/test infrastructure + +## Supported Release 4.7.1 +### Summary +This release contains some bugfixes and documentation updates. + +#### Bugfixes +- (MODULES-3024) Quote database objects when creating databases. +- Properly escape case where password ends with '$'. +- Fixes password change when postgres is configure to non-standard port. +- Unpins concat dependency to be able to use concat 2.x. +- Workaround to fix installing on Amazon Linux. +- Fixes proper defaulting of `$service_provider` parameter. +- Fixes postgres server init script naming on Amazon Linux. +- Fixes service reload parameter on Arch Linux. +- Adds missing onlyif_function to sequence grant code. +- Fixes to the markdown of the README. + +## Supported Release 4.7.0 +### Summary +A release with a considerable amount of new features, including remote db support and several platform support updates. Various bugfixes including several to address warnings and a sizable README update. + +#### Features +- Remote DB support - Connection-settings allows a hash of options that can be used when connecting to a remote DB. +- Debian 8 support. +- Updated systemd-override to support fedora and CentOS paths. +- Adds the ability to define the extension name separately from the title of the resource, which allows you to add the extension to more than one database. +- Added parameter to disable automatic service restarts on config changes. +- Ubuntu 15.10 compatibility. +- OpenBSD version is now 9.4. +- Added .gitattributes to maintain line endings for .sh and .rb files. +- Adds default postgis version for 9.5. +- Allows float postgresql_conf values. +- Schedule apt update after install of repo. + +#### Bugfixes +- Fixed systemd-override for RedHat systems with unmanaged Yum repos. +- Removed inherits postgresql::params. +- Multi-node tests are now not ran by default. +- Change apt::pin to apt_postgresql_org to prevent error message. +- Removed syntax error near UTF8. +- Removal of extra blanks and backslashes in README. +- Double quotes now used around database name to prevent syntax error. +- Removes ruby 1.8.7 and puppet 2.7 from travis-ci jobs. +- Fixed paths to work on Amazon Linux. +- Fixed quotes around locale options. +- Huge README update. +- Update to use current msync configs. +- Fixes postgresql::server acceptance test descriptions. + +## Supported Release 4.6.1 +###Summary + +Small release for support of newer PE versions. This increments the version of PE in the metadata.json file. + +## 2015-09-01 - Supported Release 4.6.0 +### Summary +This release adds a proxy feature for yum, Postgis improvements, and decoupling pg_hba_rule from postgresql::server. + +#### Features +- Support setting a proxy for yum operations +- Allow for undefined PostGIS version +- Decouple pg_hba_rule from postgresql::server + +#### Bugfixes +- Fix postgis default package name on RedHat + +## 2015-07-27 - Supported Release 4.5.0 +### Summary +This release adds sequence grants, some postgresql 9.4 fixes, and `onlyif` to +the psql resource. + +### Features +- Add `onlyif` parameter to `postgresql_psql` +- Add unsupported compatibility with Ubuntu 15.04 +- Add unsupported compatibility with SLES 11/12 and OpenSuSE 13.2 +- Add `postgresql::server::grant::onlyif_exists` attribute +- Add `postgresql::server::table_grant::onlyif_exists` attribute +- Add granting permissions on sequences + +### Bugfixes +- Added docs for `postgresql::server::grant` +- Fix `pg_hba_conf_defaults => false` to not disable ipv4/ipv6 acls +- Fix 9.4 for `postgresql::server::pg_hba_rule` + +## 2015-07-07 - Supported Release 4.4.2 +### Summary +This release fixes a bug introduced in 4.4.0. + +#### Bugfixes +- Fixes `withenv` execution under Puppet 2.7. (MODULES-2185) + +## 2015-07-01 - Supported Release 4.4.1 +### Summary +This release fixes RHEL 7 & Fedora with manage_package_repo switched on. + +#### Bugfixes +- Ensure manage_package_repo variable is in scope for systemd-override file for RHEL7 + +## 2015-06-30 - Supported Release 4.4.0 +### Summary +This release has several new features, bugfixes, and test improvements. + +#### Features +- Adds a resource to manage recovery.conf. +- Adds a parameter that allows the specification of a validate connection script in `postgresql::client`. +- Adds support for plpython package management. +- Adds support for postgresql-docs management. +- Adds ability to make `postgresql::server::schema` titles unique. (MODULES-2049) +- Updates puppetlabs-apt module dependency to support version 2.1.0. + +#### Bugfixes +- Fix `postgresql_psql` parameter ordering to work on OpenBSD with Future Parser +- Fix setting postgres role password (MODULES-1869) +- Fix execution command with puppet <3.4 (MODULES-1923) +- Fix Puppet.newtype deprecation warning (MODULES-2007) +- Fix systemd override for manage_repo package versions +- Fix Copy snakeoil certificate and key instead of symlinking + +#### Test Improvements +- Allows setting BEAKER and BEAKER_RSPEC versions via environment variables. +- Enables Unit testing on Travis CI with Puppet 4. +- Cleans up spec_helper_acceptance.rb to use new puppet_install_helper gem. + +## 2015-03-24 - Supported Release 4.3.0 +### Summary +This release fixes compatibility with Puppet 4 and removes opportunities for local users to view the postgresql password. It also adds a new custom resource to aid in managing replication. + +#### Features +- Add `postgresql::server::logdir` parameter to manage the logdir +- Add `environment` parameter to `postgresql_psql` +- Add `postgresql_replication_slot` custom resource + +#### Bugfixes +- Fix for Puppet 4 +- Don't print postgresql\_psql password in command +- Allow `postgresql::validate_db_connection` for more than one host+port+database combo +- Fix service command on Debian 8 and up +- Fix `postgresql::server::extension` to work with custom user/group/port +- Fix `postgresql::server::initdb` to work with custom user/group/port +- Fix changing template1 encoding +- Fix default `postgresql::server::grant::object_name` value +- Fix idempotency of granting all tables in schema with `puppet::server::grant` +- Fix lint warnings +- Fix apt key to use 40 character key and bump puppetlabs-apt to >= 1.8.0 < 2.0.0 + + +##2015-03-10 - Supported Release 4.2.0 +###Summary + +This release has several new features including support for server extensions, improved grant support, and a number of bugfixes. + +####Features +- Changes to support OpenBSD +- Add `service_reload` parameter to `postgresql::server` +- Add `comment` parameter to `postgresql::server::database` (MODULES-1153) +- Add `postgresql::server::extension` defined type +- Add postgresql versions for utopic and jessie +- Update `postgresql::server::grant` to support 'GRANT SCHEMA' and 'ALL TABLES IN SCHEMA' + +####Bugfixes +- Lint cleanup +- Remove outdated upgrade info from README +- Use correct TCP port when checking password +- Create role before database +- Fix template1 encoding on Debian +- Require server package before user permissions +- Fix `service_status` default for FreeBSD to allow PostgreSQL to start the first run +- Fix invalid US-ASCII byte sequence in `postgresql::server::grant` comments +- Reverted to default behavior for Debian systems as `pg_config` should not be overwritten (MODULES-1485) + +##2014-11-04 - Supported Release 4.1.0 +###Summary + +This release adds the ability to change the PGDATA directory, and also includes documentation and test updates, future parser support, and a few other new features. + +####Features +- Future parser support +- Documentation updates +- Test updates +- Add a link from `/etc/sysconfig/pgsql/postgresql-${version}` to `/etc/sysconfig/pgsql/postgresql` to support init scripts from the postgresql.org repo +- Add support for changing the PGDATA directory +- Set default versions for Fedora 21 and FreeBSD + +##2014-09-03 - Supported Release 4.0.0 +###Summary + +This release removes the uninstall ability from the module, removes the firewall +management, overhauls all of the acceptance testing, as well as adds better +support for SuSE and Fedora. + +###Backwards Incompatible changes. + +- Uninstall code removal. +- Firewall management for Postgres. +- Set manage_pg_ident_conf to true. + +####Uninstallation removal + +We rely heavily on the ability to uninstall and reinstall postgres throughout +our testing code, testing features like "can I move from the distribution +packages to the upstream packages through the module" and over time we've +learnt that the uninstall code simply doesn't work a lot of the time. It +leaves traces of postgres behind or fails to remove certain packages on Ubuntu, +and generally causes bits to be left on your system that you didn't expect. + +When we then reinstall things fail because it's not a true clean slate, and +this causes us enormous problems during test. We've spent weeks and months +working on these tests and they simply don't hold up well across the full range +of PE platforms. + +Due to all these problems we've decided to take a stance on uninstalling in +general. We feel that in 2014 it's completely reasonable and normal to have a +good provisioning pipeline combined with your configuration management and the +"correct" way to uninstall a fully installed service like postgresql is to +simply reprovision the server without it in the first place. As a general rule +this is how I personally like to work and I think is a good practice. + +####I'm not OK with this! + +We understand that there are environments and situations in which it's not easy +to do that. What if you accidently deployed Postgres on 100,000 nodes? In the +future we're going to take a look at building some example 'profiles' to be +found under examples/ within this module that can uninstall postgres on popular +platforms. These can be modified and used in your specific case to uninstall +postgresql. They will be much more brute force and reliant on deleting entire +directories and require you to do more work up front in specifying where things +are installed but we think it'll prove to be a much cleaner mechanism for this +kind of thing rather than trying to weave it into the main module logic itself. + +####Features +- Removal of uninstall. +- Removal of firewall management. +- Tests ported to rspec3. +- Acceptance tests rewritten. +- Add a defined type for creating database schemas. +- Add a pg_ident_rule defined type. +- Set manage_pg_ident_conf to true. +- Manage pg_ident.conf by default. +- Improve selinux support for tablespace. +- Remove deprecation warnings. +- Support changing PGDATA on RedHat. +- Add SLES 11 support. + +####Bugfixes +- Link pg_config binary into /usr/bin. +- Fix fedora support by using systemd. +- Initdb should create xlogdir if set. +- Use a regular expression to match the major OS version on Ubuntu. + +##2014-07-31 - Supported Release 3.4.2 +###Summary + +This release fixes recent Fedora versions. + +####Features +####Bugfixes +- Fix Fedora. + +##2014-07-15 - Supported Release 3.4.1 +###Summary + +This release merely updates metadata.json so the module can be uninstalled and +upgraded via the puppet module command. + +##2014-04-14 - Supported Release 3.4.0 +###Summary + +This feature rolls up several important features, the biggest being PostGIS +handling and allowing `port` to be set on postgresql::server in order to +change the port that Postgres listens on. We've added support for RHEL7 +and Ubuntu 14.04, as well as allowing you to manage the service via +`service_ensure` finally. + +####Features +- Added `perl_package_name` for installing bindings. +- Added `service_ensure` for allowing control of services. +- Added `postgis_version` and postgis class for installing postgis. +- Added `port` for selecting the port Postgres runs on. +- Add support for RHEL7 and Ubuntu 14.04. +- Add `default_db` to postgresql::server::database. +- Widen the selection of unquoted parameters in postgresql_conf{} +- Require the service within postgresql::server::reload for RHEL7. +- Add `inherit` to postgresql::server::role. + +####Bugfixes + +##2014-03-04 - Supported Release 3.3.3 +###Summary + +This is a supported release. This release removes a testing symlink that can +cause trouble on systems where /var is on a seperate filesystem from the +modulepath. + +####Features +####Bugfixes +####Known Bugs +* SLES is not supported. + +##2014-03-04 - Supported Release 3.3.2 +###Summary +This is a supported release. It fixes a problem with updating passwords on postgresql.org distributed versions of PostgreSQL. + +####Bugfixes +- Correct psql path when setting password on custom versions. +- Documentation updates +- Test updates + +####Known Bugs +* SLES is not supported. + + +##2014-02-12 - Version 3.3.1 +####Bugfix: +- Allow dynamic rubygems host + + +##2014-01-28 - Version 3.3.0 + +###Summary + +This release rolls up a bunch of bugfixes our users have found and fixed for +us over the last few months. This improves things for 9.1 users, and makes +this module usable on FreeBSD. + +This release is dedicated to 'bma', who's suffering with Puppet 3.4.1 issues +thanks to Puppet::Util::SUIDManager.run_and_capture. + +####Features + - Add lc_ config entry settings + - Can pass template at database creation. + - Add FreeBSD support. + - Add support for customer `xlogdir` parameter. + - Switch tests from rspec-system to beaker. (This isn't really a feature) + +####Bugfixes + - Properly fix the deprecated Puppet::Util::SUIDManager.run_and_capture errors. + - Fix NOREPLICATION option for Postgres 9.1 + - Wrong parameter name: manage_pg_conf -> manage_pg_hba_conf + - Add $postgresql::server::client_package_name, referred to by install.pp + - Add missing service_provider/service_name descriptions in ::globals. + - Fix several smaller typos/issues throughout. + - Exec['postgresql_initdb'] needs to be done after $datadir exists + - Prevent defined resources from floating in the catalog. + - Fix granting all privileges on a table. + - Add some missing privileges. + - Remove deprecated and unused concat::fragment parameters. + + +##2013-11-05 - Version 3.2.0 + +###Summary + +Add's support for Ubuntu 13.10 (and 14.04) as well as x, y, z. + +####Features +- Add versions for Ubuntu 13.10 and 14.04. +- Use default_database in validate_db_connection instead of a hardcoded +'postgres' +- Add globals/params layering for default_database. +- Allow specification of default database name. + +####Bugs +- Fixes to the README. + + +##2013-10-25 - Version 3.1.0 + +###Summary + +This is a minor feature and bug fix release. + +Firstly, the postgresql_psql type now includes a new parameter `search_path` which is equivalent to using `set search_path` which allows you to change the default schema search path. + +The default version of Fedora 17 has now been added, so that Fedora 17 users can enjoy the module. + +And finally we've extended the capabilities of the defined type postgresql::validate_db_connection so that now it can handle retrying and sleeping between retries. This feature has been monopolized to fix a bug we were seeing with startup race conditions, but it can also be used by remote systems to 'wait' for PostgreSQL to start before their Puppet run continues. + +####Features +- Defined $default_version for Fedora 17 (Bret Comnes) +- add search_path attribute to postgresql_psql resource (Jeremy Kitchen) +- (GH-198) Add wait and retry capability to validate_db_connection (Ken Barber) + +####Bugs +- enabling defined postgres user password without resetting on every puppet run (jonoterc) +- periods are valid in configuration variables also (Jeremy Kitchen) +- Add zero length string to join() function (Jarl Stefansson) +- add require of install to reload class (cdenneen) +- (GH-198) Fix race condition on postgresql startup (Ken Barber) +- Remove concat::setup for include in preparation for the next concat release (Ken Barber) + + +##2013-10-14 - Version 3.0.0 + +Final release of 3.0, enjoy! + + +##2013-10-14 - Version 3.0.0-rc3 + +###Summary + +Add a parameter to unmanage pg_hba.conf to fix a regression from 2.5, as well +as allowing owner to be passed into x. + +####Features +- `manage_pg_hba_conf` parameter added to control pg_hba.conf management. +- `owner` parameter added to server::db. + + +##2013-10-09 - Version 3.0.0-rc2 + +###Summary + +A few bugfixes have been found since -rc1. + +####Fixes +- Special case for $datadir on Amazon +- Fix documentation about username/password for the postgresql_hash function + + +##2013-10-01 - Version 3.0.0-rc1 + +###Summary + +Version 3 was a major rewrite to fix some internal dependency issues, and to +make the new Public API more clear. As a consequence a lot of things have +changed for version 3 and older revisions that we will try to outline here. + +(NOTE: The format of this CHANGELOG differs to normal in an attempt to +explain the scope of changes) + +* Server specific objects now moved under `postgresql::server::` namespace: + +To restructure server specific elements under the `postgresql::server::` +namespaces the following objects were renamed as such: + +`postgresql::database` -> `postgresql::server::database` +`postgresql::database_grant` -> `postgresql::server::database_grant` +`postgresql::db` -> `postgresql::server::db` +`postgresql::grant` -> `postgresql::server::grant` +`postgresql::pg_hba_rule` -> `postgresql::server::pg_hba_rule` +`postgresql::plperl` -> `postgresql::server::plperl` +`postgresql::contrib` -> `postgresql::server::contrib` +`postgresql::role` -> `postgresql::server::role` +`postgresql::table_grant` -> `postgresql::server::table_grant` +`postgresql::tablespace` -> `postgresql::server::tablespace` + +* New `postgresql::server::config_entry` resource for managing configuration: + +Previously we used the `file_line` resource to modify `postgresql.conf`. This +new revision now adds a new resource named `postgresql::server::config_entry` +for managing this file. For example: + +```puppet + postgresql::server::config_entry { 'check_function_bodies': + value => 'off', + } +``` + +If you were using `file_line` for this purpose, you should change to this new +methodology. + +* `postgresql_puppet_extras.conf` has been removed: + +Now that we have a methodology for managing `postgresql.conf`, and due to +concerns over the file management methodology using an `exec { 'touch ...': }` +as a way to create an empty file the existing postgresql\_puppet\_extras.conf +file is no longer managed by this module. + +If you wish to recreate this methodology yourself, use this pattern: + +```puppet + class { 'postgresql::server': } + + $extras = "/tmp/include.conf" + + file { $extras: + content => 'max_connections = 123', + notify => Class['postgresql::server::service'], + }-> + postgresql::server::config_entry { 'include': + value => $extras, + } +``` + +* All uses of the parameter `charset` changed to `encoding`: + +Since PostgreSQL uses the terminology `encoding` not `charset` the parameter +has been made consisent across all classes and resources. + +* The `postgresql` base class is no longer how you set globals: + +The old global override pattern was less then optimal so it has been fixed, +however we decided to demark this properly by specifying these overrides in +the class `postgresql::global`. Consult the documentation for this class now +to see what options are available. + +Also, some parameter elements have been moved between this and the +`postgresql::server` class where it made sense. + +* `config_hash` parameter collapsed for the `postgresql::server` class: + +Because the `config_hash` was really passing data through to what was in +effect an internal class (`postgresql::config`). And since we don't want this +kind of internal exposure the parameters were collapsed up into the +`postgresql::server` class directly. + +* Lots of changes to 'private' or 'undocumented' classes: + +If you were using these before, these have changed names. You should only use +what is documented in this README.md, and if you don't have what you need you +should raise a patch to add that feature to a public API. All internal classes +now have a comment at the top indicating them as private to make sure the +message is clear that they are not supported as Public API. + +* `pg_hba_conf_defaults` parameter included to turn off default pg\_hba rules: + +The defaults should be good enough for most cases (if not raise a bug) but if +you simply need an escape hatch, this setting will turn off the defaults. If +you want to do this, it may affect the rest of the module so make sure you +replace the rules with something that continues operation. + +* `postgresql::database_user` has now been removed: + +Use `postgresql::server::role` instead. + +* `postgresql::psql` resource has now been removed: + +Use `postgresql_psql` instead. In the future we may recreate this as a wrapper +to add extra capability, but it will not match the old behaviour. + +* `postgresql_default_version` fact has now been removed: + +It didn't make sense to have this logic in a fact any more, the logic has been +moved into `postgresql::params`. + +* `ripienaar/concat` is no longer used, instead we use `puppetlabs/concat`: + +The older concat module is now deprecated and moved into the +`puppetlabs/concat` namespace. Functionality is more or less identical, but +you may need to intervene during the installing of this package - as both use +the same `concat` namespace. + +--- +##2013-09-09 Release 2.5.0 + +###Summary + +The focus of this release is primarily to capture the fixes done to the +types and providers to make sure refreshonly works properly and to set +the stage for the large scale refactoring work of 3.0.0. + +####Features + + +####Bugfixes +- Use boolean for refreshonly. +- Fix postgresql::plperl documentation. +- Add two missing parameters to config::beforeservice +- Style fixes + + +##2013-08-01 Release 2.4.1 + +###Summary + +This minor bugfix release solves an idempotency issue when using plain text +passwords for the password_hash parameter for the postgresql::role defined +type. Without this, users would continually see resource changes everytime +your run Puppet. + +####Bugfixes +- Alter role call not idempotent with cleartext passwords (Ken Barber) + + +##2013-07-19 Release 2.4.0 + +###Summary + +This updates adds the ability to change permissions on tables, create template +databases from normal databases, manage PL-Perl's postgres package, and +disable the management of `pg_hba.conf`. + +####Features +- Add `postgresql::table_grant` defined resource +- Add `postgresql::plperl` class +- Add `manage_pg_hba_conf` parameter to the `postgresql::config` class +- Add `istemplate` parameter to the `postgresql::database` define + +####Bugfixes +- Update `postgresql::role` class to be able to update roles when modified +instead of only on creation. +- Update tests +- Fix documentation of `postgresql::database_grant` + + +##2.3.0 + +This feature release includes the following changes: + +* Add a new parameter `owner` to the `database` type. This can be used to + grant ownership of a new database to a specific user. (Bruno Harbulot) +* Add support for operating systems other than Debian/RedHat, as long as the + user supplies custom values for all of the required paths, package names, etc. + (Chris Price) +* Improved integration testing (Ken Barber) + + +##2.2.1 + +This release fixes a bug whereby one of our shell commands (psql) were not ran from a globally accessible directory. This was causing permission denied errors when the command attempted to change user without changing directory. + +Users of previous versions might have seen this error: + + Error: Error executing SQL; psql returned 256: 'could not change directory to "/root" + +This patch should correct that. + +#### Detail Changes + +* Set /tmp as default CWD for postgresql_psql + + +##2.2.0 + +This feature release introduces a number of new features and bug fixes. + +First of all it includes a new class named `postgresql::python` which provides you with a convenient way of install the python Postgresql client libraries. + + class { 'postgresql::python': + } + +You are now able to use `postgresql::database_user` without having to specify a password_hash, useful for different authentication mechanisms that do not need passwords (ie. cert, local etc.). + +We've also provided a lot more advanced custom parameters now for greater control of your Postgresql installation. Consult the class documentation for PuppetDB in the README. + +This release in particular has largely been contributed by the community members below, a big thanks to one and all. + +#### Detailed Changes + +* Add support for psycopg installation (Flaper Fesp and Dan Prince) +* Added default PostgreSQL version for Ubuntu 13.04 (Kamil Szymanski) +* Add ability to create users without a password (Bruno Harbulot) +* Three Puppet 2.6 fixes (Dominic Cleal) +* Add explicit call to concat::setup when creating concat file (Dominic Cleal) +* Fix readme typo (Jordi Boggiano) +* Update postgres_default_version for Ubuntu (Kamil Szymanski) +* Allow to set connection for noew role (Kamil Szymanski) +* Fix pg_hba_rule for postgres local access (Kamil Szymanski) +* Fix versions for travis-ci (Ken Barber) +* Add replication support (Jordi Boggiano) +* Cleaned up and added unit tests (Ken Barber) +* Generalization to provide more flexability in postgresql configuration (Karel Brezina) +* Create dependent directory for sudoers so tests work on Centos 5 (Ken Barber) +* Allow SQL commands to be run against a specific DB (Carlos Villela) +* Drop trailing comma to support Puppet 2.6 (Michael Arnold) + + +##2.1.1 + + +This release provides a bug fix for RHEL 5 and Centos 5 systems, or specifically systems using PostgreSQL 8.1 or older. On those systems one would have received the error: + + Error: Could not start Service[postgresqld]: Execution of ‘/sbin/service postgresql start’ returned 1: + +And the postgresql log entry: + + FATAL: unrecognized configuration parameter "include" + +This bug is due to a new feature we had added in 2.1.0, whereby the `include` directive in `postgresql.conf` was not compatible. As a work-around we have added checks in our code to make sure systems running PostgreSQL 8.1 or older do not have this directive added. + +#### Detailed Changes + +2013-01-21 - Ken Barber +* Only install `include` directive and included file on PostgreSQL >= 8.2 +* Add system tests for Centos 5 + + +##2.1.0 + +This release is primarily a feature release, introducing some new helpful constructs to the module. + +For starters, we've added the line `include 'postgresql_conf_extras.conf'` by default so extra parameters not managed by the module can be added by other tooling or by Puppet itself. This provides a useful escape-hatch for managing settings that are not currently managed by the module today. + +We've added a new defined resource for managing your tablespace, so you can now create new tablespaces using the syntax: + + postgresql::tablespace { 'dbspace': + location => '/srv/dbspace', + } + +We've added a locale parameter to the `postgresql` class, to provide a default. Also the parameter has been added to the `postgresql::database` and `postgresql::db` defined resources for changing the locale per database: + + postgresql::db { 'mydatabase': + user => 'myuser', + password => 'mypassword', + encoding => 'UTF8', + locale => 'en_NG', + } + +There is a new class for installing the necessary packages to provide the PostgreSQL JDBC client jars: + + class { 'postgresql::java': } + +And we have a brand new defined resource for managing fine-grained rule sets within your pg_hba.conf access lists: + + postgresql::pg_hba { 'Open up postgresql for access from 200.1.2.0/24': + type => 'host', + database => 'app', + user => 'app', + address => '200.1.2.0/24', + auth_method => 'md5', + } + +Finally, we've also added Travis-CI support and unit tests to help us iterate faster with tests to reduce regression. The current URL for these tests is here: https://travis-ci.org/puppetlabs/puppet-postgresql. Instructions on how to run the unit tests available are provided in the README for the module. + +A big thanks to all those listed below who made this feature release possible :-). + +#### Detailed Changes + +2013-01-18 - Simão Fontes & Flaper Fesp +* Remove trailing commas from params.pp property definition for Puppet 2.6.0 compatibility + +2013-01-18 - Lauren Rother +* Updated README.md to conform with best practices template + +2013-01-09 - Adrien Thebo +* Update postgresql_default_version to 9.1 for Debian 7.0 + +2013-01-28 - Karel Brezina +* Add support for tablespaces + +2013-01-16 - Chris Price & Karel Brezina +* Provide support for an 'include' config file 'postgresql_conf_extras.conf' that users can modify manually or outside of the module. + +2013-01-31 - jv +* Fix typo in README.pp for postgresql::db example + +2013-02-03 - Ken Barber +* Add unit tests and travis-ci support + +2013-02-02 - Ken Barber +* Add locale parameter support to the 'postgresql' class + +2013-01-21 - Michael Arnold +* Add a class for install the packages containing the PostgreSQL JDBC jar + +2013-02-06 - fhrbek +* Coding style fixes to reduce warnings in puppet-lint and Geppetto + +2013-02-10 - Ken Barber +* Provide new defined resource for managing pg_hba.conf + +2013-02-11 - Ken Barber +* Fix bug with reload of Postgresql on Redhat/Centos + +2013-02-15 - Erik Dalén +* Fix more style issues to reduce warnings in puppet-lint and Geppetto + +2013-02-15 - Erik Dalén +* Fix case whereby we were modifying a hash after creation + + +##2.0.1 + +Minor bugfix release. + +2013-01-16 - Chris Price + * Fix revoke command in database.pp to support postgres 8.1 (43ded42) + +2013-01-15 - Jordi Boggiano + * Add support for ubuntu 12.10 status (3504405) + +##2.0.0 + +Many thanks to the following people who contributed patches to this +release: + +* Adrien Thebo +* Albert Koch +* Andreas Ntaflos +* Brett Porter +* Chris Price +* dharwood +* Etienne Pelletier +* Florin Broasca +* Henrik +* Hunter Haugen +* Jari Bakken +* Jordi Boggiano +* Ken Barber +* nzakaria +* Richard Arends +* Spenser Gilliland +* stormcrow +* William Van Hevelingen + +Notable features: + + * Add support for versions of postgres other than the system default version + (which varies depending on OS distro). This includes optional support for + automatically managing the package repo for the "official" postgres yum/apt + repos. (Major thanks to Etienne Pelletier and + Ken Barber for their tireless efforts and patience on this + feature set!) For example usage see `tests/official-postgresql-repos.pp`. + + * Add some support for Debian Wheezy and Ubuntu Quantal + + * Add new `postgres_psql` type with a Ruby provider, to replace the old + exec-based `psql` type. This gives us much more flexibility around + executing SQL statements and controlling their logging / reports output. + + * Major refactor of the "spec" tests--which are actually more like + acceptance tests. We now support testing against multiple OS distros + via vagrant, and the framework is in place to allow us to very easily add + more distros. Currently testing against Cent6 and Ubuntu 10.04. + + * Fixed a bug that was preventing multiple databases from being owned by the + same user + (9adcd182f820101f5e4891b9f2ff6278dfad495c - Etienne Pelletier ) + + * Add support for ACLs for finer-grained control of user/interface access + (b8389d19ad78b4fb66024897097b4ed7db241930 - dharwood ) + + * Many other bug fixes and improvements! + +--- +##1.0.0 + +2012-09-17 - Version 0.3.0 released + +2012-09-14 - Chris Price + * Add a type for validating a postgres connection (ce4a049) + +2012-08-25 - Jari Bakken + * Remove trailing commas. (e6af5e5) + +2012-08-16 - Version 0.2.0 released + +[5.4.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/5.3.0...5.4.0 +[5.3.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/5.2.1...5.3.0 diff --git a/LICENSE b/LICENSE index 7a29c73c87..d645695673 100644 --- a/LICENSE +++ b/LICENSE @@ -187,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2013 Puppet Labs + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/NOTICE b/NOTICE index c01b4637bc..295ce296de 100644 --- a/NOTICE +++ b/NOTICE @@ -1,8 +1,8 @@ -Puppetlabs postgresql module +postgresql puppet module -Copyright 2012 Inkling Systems Inc -Copyright 2012-2013 Puppet Labs Inc -Copyright 2012-2013 Camptocamp SA. +Copyright (C) 2012-2016 Puppet Labs, Inc. +Copyright (C) 2012 Inkling Systems Inc +Copyright (C) 2012-2013 Camptocamp SA. This product includes software developed by: The Puppet Labs Inc (http://www.puppetlabs.com/). @@ -12,3 +12,18 @@ This product includes also software developed by: This product includes also software developed by: Inkling Systems Inc (https://www.inkling.com/) + +Puppet Labs can be contacted at: info@puppetlabs.com + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md index 4d0a49e3c5..8f7141dbb3 100644 --- a/README.md +++ b/README.md @@ -1,1192 +1,600 @@ -postgresql -========== - -Table of Contents ------------------ - -1. [Overview - What is the PostgreSQL module?](#overview) -2. [Module Description - What does the module do?](#module-description) -3. [Setup - The basics of getting started with PostgreSQL module](#setup) - * [PE 3.2 supported module](#pe-32-supported-module) - * [Configuring the server](#configuring-the-server) -4. [Usage - How to use the module for various tasks](#usage) -5. [Reference - The classes, defines,functions and facts available in this module](#reference) -6. [Limitations - OS compatibility, etc.](#limitations) +# postgresql + +#### Table of Contents + +1. [Module Description - What does the module do?](#module-description) +2. [Setup - The basics of getting started with postgresql module](#setup) + * [What postgresql affects](#what-postgresql-affects) + * [Getting started with postgresql](#getting-started-with-postgresql) +3. [Usage - Configuration options and additional functionality](#usage) + * [Configure a server](#configure-a-server) + * [Configure an instance](#configure-an-instance) + * [Create a database](#create-a-database) + * [Manage users, roles, and permissions](#manage-users-roles-and-permissions) + * [Manage ownership of DB objects](#manage-ownership-of-db-objects) + * [Override defaults](#override-defaults) + * [Create an access rule for pg_hba.conf](#create-an-access-rule-for-pg_hbaconf) + * [Create user name maps for pg_ident.conf](#create-user-name-maps-for-pg_identconf) + * [Validate connectivity](#validate-connectivity) + * [Backups](#backups) +4. [Reference - An under-the-hood peek at what the module is doing and how](#reference) +5. [Limitations - OS compatibility, etc.](#limitations) +6. [License](#license) 7. [Development - Guide for contributing to the module](#development) -8. [Transfer Notice - Notice of authorship change](#transfer-notice) + * [Contributors - List of module contributors](#contributors) +8. [Tests](#tests) 9. [Contributors - List of module contributors](#contributors) -Overview --------- +## Module description -The PostgreSQL module allows you to easily manage postgres databases with Puppet. +The postgresql module allows you to manage PostgreSQL databases with Puppet. -Module Description -------------------- +PostgreSQL is a high-performance, free, open-source relational database server. The postgresql module allows you to manage packages, services, databases, users, and common security settings in PostgreSQL. -PostgreSQL is a high-performance, free, open-source relational database server. The postgresql module allows you to manage PostgreSQL packages and services on several operating systems, while also supporting basic management of PostgreSQL databases and users. The module offers support for basic management of common security settings. +## Setup -Setup ------ +### What postgresql affects -**What puppetlabs-PostgreSQL affects:** - -* package/service/configuration files for PostgreSQL -* listened-to ports +* Package, service, and configuration files for PostgreSQL +* Listened-to ports * IP and mask (optional) -**Introductory Questions** - -The postgresql module offers many security configuration settings. Before getting started, you will want to consider: - -* Do you want/need to allow remote connections? - * If yes, what about TCP connections? -* How restrictive do you want the database superuser's permissions to be? - -Your answers to these questions will determine which of the module's parameters you'll want to specify values for. - -###PE 3.2 supported module - -PE 3.2 introduces Puppet Labs supported modules. The version of the postgresql module that ships within PE 3.2 is supported via normal [Puppet Enterprise support](http://puppetlabs.com/services/customer-support) channels. If you would like to access the [supported module](http://forge.puppetlabs.com/supported) version, you will need to uninstall the shipped module and install the supported version from the Puppet Forge. You can do this by first running - - # puppet module uninstall puppetlabs-postgresql -and then running - - # puppet module install puppetlabs/postgresql - -###Configuring the server - -The main configuration you'll need to do will be around the `postgresql::server` class. The default parameters are reasonable, but fairly restrictive regarding permissions for who can connect and from where. To manage a PostgreSQL server with sane defaults: - - class { 'postgresql::server': } - -For a more customized configuration: - - class { 'postgresql::server': - ip_mask_deny_postgres_user => '0.0.0.0/32', - ip_mask_allow_all_users => '0.0.0.0/0', - listen_addresses => '*', - ipv4acls => ['hostssl all johndoe 192.168.0.0/24 cert'], - postgres_password => 'TPSrep0rt!', - } - -Once you've completed your configuration of `postgresql::server`, you can test out your settings from the command line: - - $ psql -h localhost -U postgres - $ psql -h my.postgres.server -U - -If you get an error message from these commands, it means that your permissions are set in a way that restricts access from where you're trying to connect. That might be a good thing or a bad thing, depending on your goals. - -For more details about server configuration parameters consult the [PostgreSQL Runtime Configuration docs](http://www.postgresql.org/docs/current/static/runtime-config.html). - -Usage ------ - -###Creating a database - -There are many ways to set up a postgres database using the `postgresql::server::db` class. For instance, to set up a database for PuppetDB: - - class { 'postgresql::server': } - - postgresql::server::db { 'mydatabasename': - user => 'mydatabaseuser', - password => postgresql_password('mydatabaseuser', 'mypassword'), - } - -###Managing users, roles and permissions - -To manage users, roles and permissions: - - class { 'postgresql::server': } - - postgresql::server::role { 'marmot': - password_hash => postgresql_password('marmot', 'mypasswd'), - } - - postgresql::server::database_grant { 'test1': - privilege => 'ALL', - db => 'test1', - role => 'marmot', - } - - postgresql::server::table_grant { 'my_table of test2': - privilege => 'ALL', - table => 'my_table', - db => 'test2', - role => 'marmot', - } - -In this example, you would grant ALL privileges on the test1 database and on the `my_table` table of the test2 database to the user or group specified by dan. - -At this point, you would just need to plunk these database name/username/password values into your PuppetDB config files, and you are good to go. - -###Managing remote users, roles and permissions - -Remote SQL objects are managed using the same Puppet resources as local SQL objects with the additional of a connect_settings hash. This provides control over how Puppet should connect to the remote Postgres instances and the version that should be used when generating SQL commands. - -When provided the connect_settings hash can contain environment variables to control Postgres client connections, such as: PGHOST, PGPORT, PGPASSWORD PGSSLKEY (see http://www.postgresql.org/docs/9.4/static/libpq-envars.html) Additionally the special value of DBVERSION can be provided to specify the target database's version. If the connect_settings hash is omitted or empty then Puppet will connect to the local Postgres instance. - -A connect_settings hash can be provided with each of the Puppet resources or a default connect_settings hash can be set in postgresql::globals. Per resource configuration of connect_settings allows for SQL object to be creating on multiple database by multiple users. - - $connection_settings_super2 = { - 'PGUSER' => "super2", - 'PGPASSWORD' => "foobar2", - 'PGHOST' => "127.0.0.1", - 'PGPORT' => "5432", - 'PGDATABASE' => "postgres", - } - - include postgresql::server - - # Connect with no special settings, i.e domain sockets, user postges - postgresql::server::role{'super2': - password_hash => "foobar2", - superuser => true, - - connect_settings => {}, - require => [ - Class['postgresql::globals'], - Class['postgresql::server::service'], - ], - } - - # Now using this new user connect via TCP - postgresql::server::database { 'db1': - connect_settings => $connection_settings_super2, - - require => Postgresql::Server::Role['super2'], - } - -Reference ---------- - -The postgresql module comes with many options for configuring the server. While you are unlikely to use all of the below settings, they allow you a decent amount of control over your security settings. - -Classes: - -* [postgresql::client](#class-postgresqlclient) -* [postgresql::globals](#class-postgresqlglobals) -* [postgresql::lib::devel](#class-postgresqllibdevel) -* [postgresql::lib::java](#class-postgresqllibjava) -* [postgresql::lib::docs](#class-postgresqllibdocs) -* [postgresql::lib::perl](#class-postgresqllibperl) -* [postgresql::lib::python](#class-postgresqllibpython) -* [postgresql::server](#class-postgresqlserver) -* [postgresql::server::plperl](#class-postgresqlserverplperl) -* [postgresql::server::plpython](#class-postgresqlserverplpython) -* [postgresql::server::contrib](#class-postgresqlservercontrib) -* [postgresql::server::postgis](#class-postgresqlserverpostgis) - -Resources: - -* [postgresql::server::config_entry](#resource-postgresqlserverconfig_entry) -* [postgresql::server::db](#resource-postgresqlserverdb) -* [postgresql::server::database](#resource-postgresqlserverdatabase) -* [postgresql::server::database_grant](#resource-postgresqlserverdatabase_grant) -* [postgresql::server::extension](#resource-postgresqlserverextension) -* [postgresql::server::pg_hba_rule](#resource-postgresqlserverpg_hba_rule) -* [postgresql::server::pg_ident_rule](#resource-postgresqlserverpg_ident_rule) -* [postgresql::server::recovery](#resource-postgresqlserverrecovery) -* [postgresql::server::role](#resource-postgresqlserverrole) -* [postgresql::server::schema](#resource-postgresqlserverschema) -* [postgresql::server::table_grant](#resource-postgresqlservertable_grant) -* [postgresql::server::tablespace](#resource-postgresqlservertablespace) -* [postgresql::validate_db_connection](#resource-postgresqlvalidate_db_connection) - -Custom Resources: - -* [postgresql_psql](#custom-resource-postgresql_psql) -* [postgresql_replication_slot](#custom-resource-postgresql_replication_slot) -* [postgresql_conf](#custom-resource-postgresql_conf) - -Functions: - -* [postgresql_password](#function-postgresql_password) -* [postgresql_acls_to_resources_hash](#function-postgresql_acls_to_resources_hashacl_array-id-order_offset) - - -###Class: postgresql::globals -*Note:* most server specific defaults should be overriden in the `postgresql::server` class. This class should only be used if you are using a non-standard OS or if you are changing elements such as `version` or `manage_package_repo` that can only be changed here. - -This class allows you to configure the main settings for this module in a global way, to be used by the other classes and defined resources. On its own it does nothing. - -For example, if you wanted to overwrite the default `locale` and `encoding` for all classes you could use the following combination: - - class { 'postgresql::globals': - encoding => 'UTF-8', - locale => 'en_US.UTF-8', - }-> - class { 'postgresql::server': - } - -That would make the `encoding` and `locale` the default for all classes and defined resources in this module. - -If you want to use the upstream PostgreSQL packaging, and be specific about the version you wish to download, you could use something like this: - - class { 'postgresql::globals': - manage_package_repo => true, - version => '9.2', - }-> - class { 'postgresql::server': } - -####`client_package_name` -This setting can be used to override the default postgresql client package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`server_package_name` -This setting can be used to override the default postgresql server package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`contrib_package_name` -This setting can be used to override the default postgresql contrib package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`devel_package_name` -This setting can be used to override the default postgresql devel package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`java_package_name` -This setting can be used to override the default postgresql java package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`docs_package_name` -This setting can be used to override the default postgresql docs package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`perl_package_name` -This setting can be used to override the default postgresql Perl package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`plperl_package_name` -This setting can be used to override the default postgresql PL/perl package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`plpython_package_name` -This setting can be used to override the default postgresql PL/python package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`python_package_name` -This setting can be used to override the default postgresql Python package name. If not specified, the module will use whatever package name is the default for your OS distro. - -####`service_ensure` -This setting can be used to override the default postgresql service ensure status. If not specified, the module will use `ensure` instead. - -####`service_name` -This setting can be used to override the default postgresql service name. If not specified, the module will use whatever service name is the default for your OS distro. - -####`service_provider` -This setting can be used to override the default postgresql service provider. If not specified, the module will use whatever service provider is the default for your OS distro. - -####`service_status` -This setting can be used to override the default status check command for your PostgreSQL service. If not specified, the module will use whatever service status is the default for your OS distro. - -####`default_database` -This setting is used to specify the name of the default database to connect with. On most systems this will be "postgres". - -####`initdb_path` -Path to the `initdb` command. - -####`createdb_path` -**Deprecated** -Path to the `createdb` command. - -####`psql_path` -Path to the `psql` command. - -####`pg_hba_conf_path` -Path to your `pg_hba.conf` file. - -####`pg_ident_conf_path` -Path to your `pg_ident.conf` file. - -####`postgresql_conf_path` -Path to your `postgresql.conf` file. - -####`recovery_conf_path` -Path to your `recovery.conf` file. - -####`pg_hba_conf_defaults` -If false, disables the defaults supplied with the module for `pg_hba.conf`. This is useful if you disagree with the defaults and wish to override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform basic `psql` operations for example. - -####`datadir` -This setting can be used to override the default postgresql data directory for the target platform. If not specified, the module will use whatever directory is the default for your OS distro. Please note that changing the datadir after installation will cause the server to come to a full stop before being able to make the change. For RedHat systems, the data directory must be labeled appropriately for SELinux. On Ubuntu, you need to explicitly set needs_initdb to true in order to allow Puppet to initialize the database in the new datadir (needs_initdb defaults to true on other systems). - -Warning: If datadir is changed from the default, puppet will not manage purging of the original data directory, which will cause it to fail if the data directory is changed back to the original. - -####`confdir` -This setting can be used to override the default postgresql configuration directory for the target platform. If not specified, the module will use whatever directory is the default for your OS distro. - -####`bindir` -This setting can be used to override the default postgresql binaries directory for the target platform. If not specified, the module will use whatever directory is the default for your OS distro. - -####`xlogdir` -This setting can be used to override the default postgresql xlog directory. If not specified the module will use initdb's default path. - -####`logdir` -This setting can be used to override the default postgresql log directory. If not specified the module will use initdb's default path. - -####`user` -This setting can be used to override the default postgresql super user and owner of postgresql related files in the file system. If not specified, the module will use the user name 'postgres'. - -####`group` -This setting can be used to override the default postgresql user group to be used for related files in the file system. If not specified, the module will use the group name 'postgres'. - -####`version` -The version of PostgreSQL to install/manage. This is a simple way of providing a specific version such as '9.2' or '8.4' for example. - -Defaults to your operating system default. - -####`postgis_version` -The version of PostGIS to install if you install PostGIS. Defaults to the lowest available with the version of PostgreSQL to be installed. - -####`needs_initdb` -This setting can be used to explicitly call the initdb operation after server package is installed and before the postgresql service is started. If not specified, the module will decide whether to call initdb or not depending on your OS distro. - -####`encoding` -This will set the default encoding encoding for all databases created with this module. On certain operating systems this will be used during the `template1` initialization as well so it becomes a default outside of the module as well. Defaults to the operating system default. - -####`locale` -This will set the default database locale for all databases created with this module. On certain operating systems this will be used during the `template1` initialization as well so it becomes a default outside of the module as well. Defaults to `undef` which is effectively `C`. - -####`repo_proxy` -This will set the proxy option for the official PostgreSQL yum-repositories only, Debian is currently not supported. This is useful if your server is behind a corporate firewall and needs to use proxyservers for outside connectivity. - - -#####Debian - -On Debian you'll need to ensure that the 'locales-all' package is installed for full functionality of Postgres. - -####`manage_package_repo` -If `true` this will setup the official PostgreSQL repositories on your host. Defaults to `false`. - -###Class: postgresql::server -The following list are options that you can set in the `config_hash` parameter of `postgresql::server`. - -####`postgres_password` -This value defaults to `undef`, meaning the super user account in the postgres database is a user called `postgres` and this account does not have a password. If you provide this setting, the module will set the password for the `postgres` user to your specified value. - -####`package_name` -The name of the package to use for installing the server software. Defaults to the default for your OS distro. - -####`package_ensure` -Value to pass through to the `package` resource when creating the server instance. Defaults to `undef`. - -####`plperl_package_name` -This sets the default package name for the PL/Perl extension. Defaults to utilising the operating system default. - -####`plpython_package_name` -This sets the default package name for the PL/Python extension. Defaults to utilising the operating system default. - -####`service_manage` -This setting selects whether Puppet should manage the service. Defaults to `true`. - -####`service_name` -This setting can be used to override the default postgresql service name. If not specified, the module will use whatever service name is the default for your OS distro. - -####`service_provider` -This setting can be used to override the default postgresql service provider. If not specified, the module will use whatever service name is the default for your OS distro. - -####`service_reload` -This setting can be used to override the default reload command for your PostgreSQL service. If not specified, the module will the default reload command for your OS distro. - -####`service_restart_on_change` -This setting can be used to override the default behaviour to restart your Postgresql service when a config entry has been changed that requires a service restart to become active. Defaults to `true`. - -####`service_status` -This setting can be used to override the default status check command for your PostgreSQL service. If not specified, the module will use whatever service name is the default for your OS distro. - -####`default_database` -This setting is used to specify the name of the default database to connect with. On most systems this will be "postgres". - -####`listen_addresses` -This value defaults to `localhost`, meaning the postgres server will only accept connections from localhost. If you'd like to be able to connect to postgres from remote machines, you can override this setting. A value of `*` will tell postgres to accept connections from any remote machine. Alternately, you can specify a comma-separated list of hostnames or IP addresses. (For more info, have a look at the `postgresql.conf` file from your system's postgres package). - -####`port` -This value defaults to `5432`, meaning the postgres server will listen on TCP port 5432. Note that the same port number is used for all IP addresses the server listens on. Also note that for RedHat systems and early Debian systems, changing the port will cause the server to come to a full stop before being able to make the change. - -####`ip_mask_deny_postgres_user` -This value defaults to `0.0.0.0/0`. Sometimes it can be useful to block the superuser account from remote connections if you are allowing other database users to connect remotely. Set this to an IP and mask for which you want to deny connections by the postgres superuser account. So, e.g., the default value of `0.0.0.0/0` will match any remote IP and deny access, so the postgres user won't be able to connect remotely at all. Conversely, a value of `0.0.0.0/32` would not match any remote IP, and thus the deny rule will not be applied and the postgres user will be allowed to connect. - -####`ip_mask_allow_all_users` -This value defaults to `127.0.0.1/32`. By default, Postgres does not allow any database user accounts to connect via TCP from remote machines. If you'd like to allow them to, you can override this setting. You might set it to `0.0.0.0/0` to allow database users to connect from any remote machine, or `192.168.0.0/16` to allow connections from any machine on your local 192.168 subnet. - -####`ipv4acls` -List of strings for access control for connection method, users, databases, IPv4 addresses; see [postgresql documentation](http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html) about `pg_hba.conf` for information (please note that the link will take you to documentation for the most recent version of Postgres, however links for earlier versions can be found on that page). - -####`ipv6acls` -List of strings for access control for connection method, users, databases, IPv6 addresses; see [postgresql documentation](http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html) about `pg_hba.conf` for information (please note that the link will take you to documentation for the most recent version of Postgres, however links for earlier versions can be found on that page). - -####`initdb_path` -Path to the `initdb` command. - -####`createdb_path` -**Deprecated** -Path to the `createdb` command. - -####`psql_path` -Path to the `psql` command. - -####`pg_hba_conf_path` -Path to your `pg_hba.conf` file. - -####`pg_ident_conf_path` -Path to your `pg_ident.conf` file. - -####`postgresql_conf_path` -Path to your `postgresql.conf` file. - -####`recovery_conf_path` -Path to your `recovery.conf` file. - -####`pg_hba_conf_defaults` -If false, disables the defaults supplied with the module for `pg_hba.conf`. This is useful if you disagree with the defaults and wish to override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform basic `psql` operations for example. - -####`user` -This setting can be used to override the default postgresql super user and owner of postgresql related files in the file system. If not specified, the module will use the user name 'postgres'. - -####`group` -This setting can be used to override the default postgresql user group to be used for related files in the file system. If not specified, the module will use the group name 'postgres'. - -####`needs_initdb` -This setting can be used to explicitly call the initdb operation after server package is installed and before the postgresql service is started. If not specified, the module will decide whether to call initdb or not depending on your OS distro. - -####`encoding` -This will set the default encoding encoding for all databases created with this module. On certain operating systems this will be used during the `template1` initialization as well so it becomes a default outside of the module as well. Defaults to the operating system default. - -####`locale` -This will set the default database locale for all databases created with this module. On certain operating systems this will be used during the `template1` initialization as well so it becomes a default outside of the module as well. Defaults to `undef` which is effectively `C`. - -#####Debian - -On Debian you'll need to ensure that the 'locales-all' package is installed for full functionality of Postgres. - -####`manage_pg_hba_conf` -This value defaults to `true`. Whether or not manage the pg_hba.conf. If set to `true`, puppet will overwrite this file. If set to `false`, puppet will not modify the file. - -####`manage_pg_ident_conf` -This value defaults to `true`. Whether or not manage the pg_ident.conf. If set to `true`, puppet will overwrite this file. If set to `false`, puppet will not modify the file. - -####`manage_recovery_conf` -This value defaults to `false`. Whether or not manage the recovery.conf. If set to `true`, puppet will overwrite this file. If set to `false`, puppet will not create the file. - -###Class: postgresql::client - -This class installs postgresql client software. Alter the following parameters if you have a custom version you would like to install (Note: don't forget to make sure to add any necessary yum or apt repositories if specifying a custom version): - -####`validcon_script_path` -Path to validate connection script. Defaults to `/usr/local/bin/validate_postgresql_connection.sh`. - -####`package_name` -The name of the postgresql client package. - -####`package_ensure` -The ensure parameter passed on to postgresql client package resource. - - -###Class: postgresql::server::contrib -Installs the postgresql contrib package. - -####`package_name` -The name of the postgresql contrib package. +### Getting started with postgresql -####`package_ensure` -The ensure parameter passed on to postgresql contrib package resource. +To configure a basic default PostgreSQL server, declare the `postgresql::server` class. -###Class: postgresql::server::postgis -Installs the postgresql postgis packages. - -###Class: postgresql::lib::devel -Installs the packages containing the development libraries for PostgreSQL and -symlinks pg_config into `/usr/bin` (if not in `/usr/bin` or `/usr/local/bin`). - -####`package_ensure` -Override for the `ensure` parameter during package installation. Defaults to `present`. - -####`package_name` -Overrides the default package name for the distribution you are installing to. Defaults to `postgresql-devel` or `postgresql-devel` depending on your distro. - -####`link_pg_config` -By default on all but Debian systems, if the bin directory used by the PostgreSQL package is not `/usr/bin` or `/usr/local/bin`, -this class will symlink `pg_config` from the package's bin dir into `/usr/bin`. Set `link_pg_config` to -false to disable this behavior. - -###Class: postgresql::lib::java -This class installs postgresql bindings for Java (JDBC). Alter the following parameters if you have a custom version you would like to install (Note: don't forget to make sure to add any necessary yum or apt repositories if specifying a custom version): - -####`package_name` -The name of the postgresql java package. +```puppet +class { 'postgresql::server': +} +``` -####`package_ensure` -The ensure parameter passed on to postgresql java package resource. +## Usage -###Class: postgresql::lib::docs -This class installs postgresql bindings for Postgres-Docs. Alter the following parameters if you have a custom version you would like to install (Note: don't forget to make sure to add any necessary yum or apt repositories if specifying a custom version): +### Configure a server -####`package_name` -The name of the postgresql docs package. +For default settings, declare the `postgresql::server` class as above. To customize PostgreSQL server settings, specify the [parameters](#postgresqlserver) you want to change: -####`package_ensure` -The ensure parameter passed on to postgresql docs package resource. +```puppet +class { 'postgresql::server': + ip_mask_deny_postgres_user => '0.0.0.0/32', + ip_mask_allow_all_users => '0.0.0.0/0', + ipv4acls => ['hostssl all johndoe 192.168.0.0/24 cert'], + postgres_password => 'TPSrep0rt!', +} +``` +After configuration, test your settings from the command line: -###Class: postgresql::lib::perl -This class installs the postgresql Perl libraries. For customer requirements you can customise the following parameters: +```shell +psql -h localhost -U postgres +psql -h my.postgres.server -U +``` -####`package_name` -The name of the postgresql perl package. +If you get an error message from these commands, your permission settings restrict access from the location you're trying to connect from. Depending on whether you want to allow connections from that location, you might need to adjust your permissions. -####`package_ensure` -The ensure parameter passed on to postgresql perl package resource. +For more details about server configuration parameters, consult the [PostgreSQL Runtime Configuration documentation](http://www.postgresql.org/docs/current/static/runtime-config.html). -###Class: postgresql::server::plpython -This class installs the PL/Python procedural language for postgresql. +#### Selecting a version -####`package_name` -The name of the postgresql PL/Python package. +The version is intended to be supplied via `postgresql::globals`. +By default the module tries to derive the version based on the OS facts, but can be overridden. +This is typically used with the official postgresql.org packages: -####`package_ensure` -The ensure parameter passed on to postgresql PL/Python package resource. +```puppet +class { 'postgresql::globals': + manage_package_repo => true, + version => '16', +} -###Class: postgresql::lib::python -This class installs the postgresql Python libraries. For customer requirements you can customise the following parameters: +include postgresql::server +``` -####`package_name` -The name of the postgresql python package. +On EL 8 & 9 you can also use DNF modules: -####`package_ensure` -The ensure parameter passed on to postgresql python package resource. +```puppet +class { 'postgresql::globals': + manage_dnf_module => true, + version => '16', +} +include postgresql::server +``` -###Class: postgresql::server::plperl -This class installs the PL/Perl procedural language for postgresql. +If you manage the repositories yourself, overriding the version is sufficient. -####`package_name` -The name of the postgresql PL/Perl package. +```puppet +class { 'postgresql::globals': + version => '16', +} -####`package_ensure` -The ensure parameter passed on to postgresql PL/Perl package resource. +include postgresql::server +``` +### Configure an instance -###Resource: postgresql::server::config_entry -This resource can be used to modify your `postgresql.conf` configuration file. +This module supports managing multiple instances (the default instance is referred to as 'main' and managed via including the server.pp class) -Each resource maps to a line inside your `postgresql.conf` file, for example: +**NOTE:** This feature is currently tested on CentOS 8 Streams/RHEL8 with DNF Modules enabled. Different Linux platforms and/or the postgresql.org +packages distribute different systemd service files or use wrapper scripts with systemd to start PostgreSQL. Additional adjustmentments are needed to get this working on these platforms. - postgresql::server::config_entry { 'check_function_bodies': - value => 'off', - } +#### Working Platforms -####`namevar` -Name of the setting to change. +* Centos 8 Streams +* RHEL 8 -####`ensure` -Set to `absent` to remove an entry. +#### Background and example -####`value` -Value for the setting. +creating a new instance has the following advantages: +* files are owned by the postgres user +* instance is running under a different user, if the instance is hacked, the hacker has no access to the file system +* the instance user can be an LDAP user, higher security because of central login monitoring, password policies, password rotation policies +* main instance can be disabled -###Resource: postgresql::server::db -This is a convenience resource that creates a local database, user and assigns necessary permissions in one go. +Here is a profile which can be used to create instances -For example, to create a database called `test1` with a corresponding user of the same name, you can use: +```puppet +class profiles::postgres ( + Hash $instances = {}, + String $postgresql_version = '13', +) { + class { 'postgresql::globals': + encoding => 'UTF-8', + locale => 'en_US.UTF-8', + manage_package_repo => false, + manage_dnf_module => true, + needs_initdb => true, + version => $postgresql_version, + } + include postgresql::server - postgresql::server::db { 'test1': - user => 'test1', - password => 'test1', + $instances.each |String $instance, Hash $instance_settings| { + postgresql::server_instance { $instance: + * => $instance_settings, } + } +} +``` -####`namevar` -The namevar for the resource designates the name of the database. - -####`comment` -A comment to be stored about the database using the PostgreSQL COMMENT command. - -####`dbname` -The name of the database to be created. Defaults to `namevar`. - -####`owner` -Name of the database user who should be set as the owner of the database. Defaults to the $user variable set in `postgresql::server` or `postgresql::globals`. - -####`user` -User to create and assign access to the database upon creation. Mandatory. - -####`password` -Password for the created user. Mandatory. - -####`encoding` -Override the character set during creation of the database. Defaults to the default defined during installation. - -####`locale` -Override the locale during creation of the database. Defaults to the default defined during installation. - -####`grant` -Grant permissions during creation. Defaults to `ALL`. - -####`tablespace` -The name of the tablespace to allocate this database to. If not specifies, it defaults to the PostgreSQL default. - -####`template` -The name of the template database from which to build this database. Defaults to `template0`. - -####`istemplate` -Define database as a template. Defaults to `false`. +And here is data to create an instance called test1: + +```yaml +# stop default main instance +postgresql::server::service_ensure: "stopped" +postgresql::server::service_enable: false + +#define an instance +profiles::postgres::instances: + test1: + instance_user: "ins_test1" + instance_group: "ins_test1" + instance_directories: + "/opt/pgsql": + ensure: directory + "/opt/pgsql/backup": + ensure: directory + "/opt/pgsql/data": + ensure: directory + "/opt/pgsql/data/13": + ensure: directory + "/opt/pgsql/data/home": + ensure: directory + "/opt/pgsql/wal": + ensure: directory + "/opt/pgsql/log": + ensure: directory + "/opt/pgsql/log/13": + ensure: directory + "/opt/pgsql/log/13/test1": + ensure: directory + config_settings: + pg_hba_conf_path: "/opt/pgsql/data/13/test1/pg_hba.conf" + postgresql_conf_path: "/opt/pgsql/data/13/test1/postgresql.conf" + pg_ident_conf_path: "/opt/pgsql/data/13/test1/pg_ident.conf" + datadir: "/opt/pgsql/data/13/test1" + service_name: "postgresql@13-test1" + port: 5433 + pg_hba_conf_defaults: false + service_settings: + service_name: "postgresql@13-test1" + service_status: "systemctl status postgresql@13-test1.service" + service_ensure: "running" + service_enable: true + initdb_settings: + auth_local: "peer" + auth_host: "md5" + needs_initdb: true + datadir: "/opt/pgsql/data/13/test1" + encoding: "UTF-8" + lc_messages: "en_US.UTF8" + locale: "en_US.UTF8" + data_checksums: false + group: "postgres" + user: "postgres" + username: "ins_test1" + config_entries: + authentication_timeout: + value: "1min" + comment: "a test" + log_statement_stats: + value: "off" + autovacuum_vacuum_scale_factor: + value: 0.3 + databases: + testdb1: + encoding: "UTF8" + locale: "en_US.UTF8" + owner: "dba_test1" + testdb2: + encoding: "UTF8" + locale: "en_US.UTF8" + owner: "dba_test1" + roles: + "ins_test1": + superuser: true + login: true + "dba_test1": + createdb: true + login: true + "app_test1": + login: true + "rep_test1": + replication: true + login: true + "rou_test1": + login: true + pg_hba_rules: + "local all INSTANCE user": + type: "local" + database: "all" + user: "ins_test1" + auth_method: "peer" + order: 1 + "local all DB user": + type: "local" + database: "all" + user: "dba_test1" + auth_method: "peer" + order: 2 + "local all APP user": + type: "local" + database: "all" + user: "app_test1" + auth_method: "peer" + order: 3 + "local all READONLY user": + type: "local" + database: "all" + user: "rou_test1" + auth_method: "peer" + order: 4 + "remote all INSTANCE user PGADMIN server": + type: "host" + database: "all" + user: "ins_test1" + address: "192.168.22.131/32" + auth_method: "md5" + order: 5 + "local replication INSTANCE user": + type: "local" + database: "replication" + user: "ins_test1" + auth_method: "peer" + order: 6 + "local replication REPLICATION user": + type: "local" + database: "replication" + user: "rep_test1" + auth_method: "peer" + order: 7 +``` +### Create a database +You can set up a variety of PostgreSQL databases with the `postgresql::server::db` defined type. For instance, to set up a database for PuppetDB: -###Resource: postgresql::server::database -This defined type can be used to create a database with no users and no permissions, which is a rare use case. +```puppet +class { 'postgresql::server': +} -####`namevar` -The name of the database to create. +postgresql::server::db { 'mydatabasename': + user => 'mydatabaseuser', + password => postgresql::postgresql_password('mydatabaseuser', 'mypassword'), +} +``` -####`dbname` -The name of the database, defaults to the namevar. +### Manage users, roles, and permissions -####`owner` -Name of the database user who should be set as the owner of the database. Defaults to the $user variable set in `postgresql::server` or `postgresql::globals`. +To manage users, roles, and permissions: -####`tablespace` -Tablespace for where to create this database. Defaults to the defaults defined during PostgreSQL installation. +```puppet +class { 'postgresql::server': +} -####`template` -The name of the template database from which to build this database. Defaults to `template0`. +postgresql::server::role { 'marmot': + password_hash => postgresql::postgresql_password('marmot', 'mypasswd'), +} -####`encoding` -Override the character set during creation of the database. Defaults to the default defined during installation. +postgresql::server::database_grant { 'test1': + privilege => 'ALL', + db => 'test1', + role => 'marmot', +} -####`locale` -Override the locale during creation of the database. Defaults to the default defined during installation. +postgresql::server::table_grant { 'my_table of test2': + privilege => 'ALL', + table => 'my_table', + db => 'test2', + role => 'marmot', +} +``` -####`istemplate` -Define database as a template. Defaults to `false`. +This example grants **all** privileges on the test1 database and on the `my_table` table of the test2 database to the specified user or group. After the values are added into the PuppetDB config file, this database would be ready for use. -####`connect_settings` -Hash of environment variable used when connecting to a remote server. Defaults to connecting to the local Postgres instance. +### Manage ownership of DB objects -###Resource: postgresql::server::database_grant -This defined type manages grant based access privileges for users, wrapping the `postgresql::server::database_grant` for database specific permissions. Consult the PostgreSQL documentation for `grant` for more information. +To change the ownership of all objects within a database using REASSIGN OWNED: -####`namevar` -Used to uniquely identify this resource, but functionality not used during grant. +```puppet +postgresql::server::reassign_owned_by { 'new owner is meerkat': + db => 'test_db', + old_role => 'marmot', + new_role => 'meerkat', +} +``` -####`privilege` -Can be one of `SELECT`, `TEMPORARY`, `TEMP`, `CONNECT`. `ALL` is used as a synonym for `CREATE`. If you need to add multiple privileges, a space delimited string can be used. +This would run the PostgreSQL statement 'REASSIGN OWNED' to update to ownership of all tables, sequences, functions and views currently owned by the role 'marmot' to be owned by the role 'meerkat' instead. -####`db` -Database to grant access to. +This applies to objects within the nominated database, 'test_db' only. -####`role` -Role or user whom you are granting access for. +For Postgresql >= 9.3, the ownership of the database is also updated. -####`psql_db` -Database to execute the grant against. This should not ordinarily be changed from the default, which is `postgres`. +### Manage default permissions (PostgreSQL >= 9.6) -####`psql_user` -OS user for running `psql`. Defaults to the default user for the module, usually `postgres`. +To change default permissions for newly created objects using ALTER DEFAULT PRIVILEGES: -####`connect_settings` -Hash of environment variable used when connecting to a remote server. Defaults to connecting to the local Postgres instance. +```puppet +postgresql::server::default_privileges { 'marmot access to new tables on test_db': + db => 'test_db', + role => 'marmot', + privilege => 'ALL', + object_type => 'TABLES', +} +``` -###Resource: postgresql::server::extension -This defined type manages a postgresql extension for a given database. +### Override defaults -####`extension` -The extension to activate. If left blank, will use the name of the resource. +The `postgresql::globals` class allows you to configure the main settings for this module globally, so that other classes and defined resources can use them. By itself, it does nothing. -####`database` -The database on which to activate the extension. +For example, to overwrite the default `locale` and `encoding` for all classes, use the following: -####`ensure` -Whether to activate (`present`) or deactivate (`absent`) the extension. +```puppet +class { 'postgresql::globals': + encoding => 'UTF-8', + locale => 'en_US.UTF-8', +} -####`package_name` -If provided, this will install the given package prior to activating the extension. +class { 'postgresql::server': +} +``` -####`package_ensure` -By default, the package specified with `package_name` will be installed when the extension is activated, and removed when the extension is deactivated. You can override this behavior by setting the `ensure` value for the package. +### Manage remote users, roles, and permissions -###Resource: postgresql::server::grant -This defined type manages grant based access privileges for roles. Consult the PostgreSQL documentation for `grant` for more information. +Remote SQL objects are managed using the same Puppet resources as local SQL objects, along with a `$connect_settings` hash. This provides control over how Puppet connects to the remote Postgres instances and which version is used for generating SQL commands. -####`namevar` -Used to uniquely identify this resource, but functionality not used during grant. +The `connect_settings` hash can contain environment variables to control Postgres client connections, such as 'PGHOST', 'PGPORT', 'PGPASSWORD', 'PGUSER' and 'PGSSLKEY'. See the [PostgreSQL Environment Variables](https://www.postgresql.org/docs/current/libpq-envars.html) documentation for a complete list of variables. -####`db` -Database of object which you are granting access on. +Additionally, you can specify the target database version with the special value of 'DBVERSION'. If the `$connect_settings` hash is omitted or empty, then Puppet connects to the local PostgreSQL instance. -####`role` -Role or user whom you are granting access for. +**The $connect_settings hash has priority over the explicit variables like $port and $user** -####`privilege` -The privilege you are granting. Can be `ALL`, `ALL PRIVILEGES` or -`object_type` dependent string. +When a user provides only the `$port` parameter to a resource and no `$connect_settings`, `$port` will be used. When `$connect_settings` contains `PGPORT` and `$port` is set, `$connect_settings['PGPORT']` will be used. -####`object_type` -The type of object you are granting privileges on. Can be `DATABASE`, -`SCHEMA`, `SEQUENCE`, `ALL SEQUENCES IN SCHEMA`, `TABLE` or `ALL -TABLES IN SCHEMA`. +You can provide a `connect_settings` hash for each of the Puppet resources, or you can set a default `connect_settings` hash in `postgresql::globals`. Configuring `connect_settings` per resource allows SQL objects to be created on multiple databases by multiple users. -####`object_name` -Object of type `object_type` on which to grant access. +```puppet +$connection_settings_super2 = { + 'PGUSER' => 'super2', + 'PGPASSWORD' => 'foobar2', + 'PGHOST' => '127.0.0.1', + 'PGPORT' => '5432', + 'PGDATABASE' => 'postgres', +} -####`psql_db` -Database to execute the grant against. This should not ordinarily be changed from the default, which is `postgres`. +include postgresql::server -####`psql_user` -OS user for running `psql`. Defaults to the default user for the module, usually `postgres`. +# Connect with no special settings, i.e domain sockets, user postgres +postgresql::server::role { 'super2': + password_hash => 'foobar2', + superuser => true, -####`port` -Port to use when connecting. Default to 'undef' which generally defaults to 5432 depending on your PostgreSQL packaging. + connect_settings => {}, +} -####`connect_settings` -Hash of environment variable used when connecting to a remote server. Defaults to connecting to the local Postgres instance. +# Now using this new user connect via TCP +postgresql::server::database { 'db1': + connect_settings => $connection_settings_super2, + require => Postgresql::Server::Role['super2'], +} +``` -###Resource: postgresql::server::pg_hba_rule -This defined type allows you to create an access rule for `pg_hba.conf`. For more details see the [PostgreSQL documentation](http://www.postgresql.org/docs/8.2/static/auth-pg-hba-conf.html). +### Create an access rule for pg_hba.conf -For example: +To create an access rule for `pg_hba.conf`: - postgresql::server::pg_hba_rule { 'allow application network to access app database': - description => "Open up postgresql for access from 200.1.2.0/24", - type => 'host', - database => 'app', - user => 'app', - address => '200.1.2.0/24', - auth_method => 'md5', - } +```puppet +postgresql::server::pg_hba_rule { 'allow application network to access app database': + description => 'Open up PostgreSQL for access from 200.1.2.0/24', + type => 'host', + database => 'app', + user => 'app', + address => '200.1.2.0/24', + auth_method => 'md5', +} +``` This would create a ruleset in `pg_hba.conf` similar to: - # Rule Name: allow application network to access app database - # Description: Open up postgresql for access from 200.1.2.0/24 - # Order: 150 - host app app 200.1.2.0/24 md5 - -By default, `pg_hba_rule` requires that you include `postgresql::server`, however, you can override that behavior by setting target and postgresql_version when declaring your rule. That might look like the following. - - postgresql::server::pg_hba_rule { 'allow application network to access app database': - description => "Open up postgresql for access from 200.1.2.0/24", - type => 'host', - database => 'app', - user => 'app', - address => '200.1.2.0/24', - auth_method => 'md5', - target => '/path/to/pg_hba.conf', - postgresql_version => '9.4', - } - -####`namevar` -A unique identifier or short description for this rule. The namevar doesn't provide any functional usage, but it is stored in the comments of the produced `pg_hba.conf` so the originating resource can be identified. - -####`description` -A longer description for this rule if required. Defaults to `none`. This description is placed in the comments above the rule in `pg_hba.conf`. - -####`type` -The type of rule, this is usually one of: `local`, `host`, `hostssl` or `hostnossl`. - -####`database` -A comma separated list of databases that this rule matches. - -####`user` -A comma separated list of database users that this rule matches. - -####`address` -If the type is not 'local' you can provide a CIDR based address here for rule matching. - -####`auth_method` -The `auth_method` is described further in the `pg_hba.conf` documentation, but it provides the method that is used for authentication for the connection that this rule matches. - -####`auth_option` -For certain `auth_method` settings there are extra options that can be passed. Consult the PostgreSQL `pg_hba.conf` documentation for further details. - -####`order` -An order for placing the rule in `pg_hba.conf`. Defaults to `150`. - -####`target` -This provides the target for the rule, and is generally an internal only property. Use with caution. +``` +# Rule Name: allow application network to access app database +# Description: Open up PostgreSQL for access from 200.1.2.0/24 +# Order: 150 +host app app 200.1.2.0/24 md5 +``` -####`postgresql_version` -Defaults to the version set in `postgresql::server`. Use this if you want to manage `pg_hba.conf` without managing the entire PostgreSQL instance. +By default, `pg_hba_rule` requires that you include `postgresql::server`. However, you can override that behavior by setting target and postgresql_version when declaring your rule. That might look like the following: + +```puppet +postgresql::server::pg_hba_rule { 'allow application network to access app database': + description => 'Open up postgresql for access from 200.1.2.0/24', + type => 'host', + database => 'app', + user => 'app', + address => '200.1.2.0/24', + auth_method => 'md5', + target => '/path/to/pg_hba.conf', + postgresql_version => '9.4', +} +``` -###Resource: postgresql::server::pg_ident_rule -This defined type allows you to create user name maps for `pg_ident.conf`. For more details see the [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/auth-username-maps.html). +### Create user name maps for pg_ident.conf -For example: +To create a user name map for the pg_ident.conf: - postgresql::server::pg_ident_rule{ 'Map the SSL certificate of the backup server as a replication user': - map_name => 'sslrepli', - system_username => 'repli1.example.com', - database_username => 'replication', - } +```puppet +postgresql::server::pg_ident_rule { 'Map the SSL certificate of the backup server as a replication user': + map_name => 'sslrepli', + system_username => 'repli1.example.com', + database_username => 'replication', +} +``` This would create a user name map in `pg_ident.conf` similar to: - # Rule Name: Map the SSL certificate of the backup server as a replication user - # Description: none - # Order: 150 - sslrepli repli1.example.com replication - -####`namevar` -A unique identifier or short description for this rule. The namevar doesn't provide any functional usage, but it is stored in the comments of the produced `pg_ident.conf` so the originating resource can be identified. - -####`description` -A longer description for this rule if required. Defaults to `none`. This description is placed in the comments above the rule in `pg_ident.conf`. - -####`map_name` -Name of the user map, that is used to refer to this mapping in `pg_hba.conf`. - -####`system_username` -Operating system user name, the user name used to connect to the database. - -####`database_username` -Database user name, the user name of the the database user. The `system_username` will be mapped to this user name. - -####`order` -An order for placing the mapping in pg_ident.conf. Defaults to 150. - -####`target` -This provides the target for the rule, and is generally an internal only property. Use with caution. - -###Resource: postgresql::server::recovery -This defined type allows you to create the content for `recovery.conf`. For more details see the [PostgreSQL documentation](http://www.postgresql.org/docs/9.4/static/recovery-config.html). - -For example: - - postgresql::server::recovery{ 'Create a recovery.conf file with the following defined parameters': - restore_command => 'cp /mnt/server/archivedir/%f %p', - archive_cleanup_command => undef, - recovery_end_command => undef, - recovery_target_name => 'daily backup 2015-01-26', - recovery_target_time => '2015-02-08 22:39:00 EST', - recovery_target_xid => undef, - recovery_target_inclusive => true, - recovery_target => 'immediate', - recovery_target_timeline => 'latest', - pause_at_recovery_target => true, - standby_mode => 'on', - primary_conninfo => 'host=localhost port=5432', - primary_slot_name => undef, - trigger_file => undef, - recovery_min_apply_delay => 0, - } - -This would create a `recovery.conf` config file, similar to this: - - restore_command = 'cp /mnt/server/archivedir/%f %p' - recovery_target_name = 'daily backup 2015-01-26' - recovery_target_time = '2015-02-08 22:39:00 EST' - recovery_target_inclusive = true - recovery_target = 'immediate' - recovery_target_timeline = 'latest' - pause_at_recovery_target = true - standby_mode = on - primary_conninfo = 'host=localhost port=5432' - recovery_min_apply_delay = 0 - - -Only the specified parameters will be recognize in the template! The `recovery.conf` will be only create if at least one parameter set and [manage_recovery_conf](#manage_recovery_conf) set to true. - -Every param value is a String set in the template with inverted comma except `recovery_target_inclusive`, `pause_at_recovery_target`, `standby_mode` and `recovery_min_apply_delay`. -`standby_mode` is special, String ('on'/'off') and Boolean (true/false) is allowed, but the postgres documentation says it's a Boolean. - -A detailed description of all above listed parameters can be found in the [PostgreSQL documentation](http://www.postgresql.org/docs/9.4/static/recovery-config.html). - -The parameters are grouped into these three sections: - - -#### [`Archive Recovery Parameters`](http://www.postgresql.org/docs/9.4/static/archive-recovery-settings.html) -In this section the `restore_command`, `archive_cleanup_command` and `recovery_end_command` parameters are listed. - -#### [`Recovery Target Settings`](http://www.postgresql.org/docs/9.4/static/recovery-target-settings.html) -In this section the `recovery_target_name`, `recovery_target_time`, `recovery_target_xid`, `recovery_target_inclusive`, `recovery_target`, `recovery_target_timeline` and `pause_at_recovery_target` parameters are listed. - -#### [`Standby Server Settings`](http://www.postgresql.org/docs/9.4/static/standby-settings.html) -In this section the `standby_mode`, `primary_conninfo`, `primary_slot_name`, `trigger_file` and `recovery_min_apply_delay` parameters are listed. - -####`target` -This provides the target for the rule, and is generally an internal only property. Use with caution. - - -###Resource: postgresql::server::role -This resource creates a role or user in PostgreSQL. - -####`namevar` -The role name to create. - -####`password_hash` -The hash to use during password creation. If the password is not already pre-encrypted in a format that PostgreSQL supports, use the `postgresql_password` function to provide an MD5 hash here, for example: - - postgresql::server::role { "myusername": - password_hash => postgresql_password('myusername', 'mypassword'), - } - -####`createdb` -Whether to grant the ability to create new databases with this role. Defaults to `false`. - -####`createrole` -Whether to grant the ability to create new roles with this role. Defaults to `false`. - -####`login` -Whether to grant login capability for the new role. Defaults to `true`. - -####`inherit` -Whether to grant inherit capability for the new role. Defaults to `true`. - -####`superuser` -Whether to grant super user capability for the new role. Defaults to `false`. - -####`replication` -If `true` provides replication capabilities for this role. Defaults to `false`. - -####`connection_limit` -Specifies how many concurrent connections the role can make. Defaults to `-1` meaning no limit. - -####`username` -The username of the role to create, defaults to `namevar`. - -####`connect_settings` -Hash of environment variable used when connecting to a remote server. Defaults to connecting to the local Postgres instance. - -###Resource: postgresql::server::schema -This defined type can be used to create a schema. For example: - - postgresql::server::schema { 'isolated': - owner => 'jane', - db => 'janedb', - } - -It will create the schema `isolated` in the database `janedb` if neccessary, -assigning the user `jane` ownership permissions. - -####`namevar` -The schema name to create. - -###`db` -Name of the database in which to create this schema. This must be passed. - -####`owner` -The default owner of the schema. - -####`schema` -Name of the schma. Defaults to `namevar`. - -####`connect_settings` -Hash of environment variable used when connecting to a remote server. Defaults to connecting to the local Postgres instance. - - -###Resource: postgresql::server::table_grant -This defined type manages grant based access privileges for users. Consult the PostgreSQL documentation for `grant` for more information. - -####`namevar` -Used to uniquely identify this resource, but functionality not used during grant. - -####`privilege` -Can be one of `SELECT`, `INSERT`, `UPDATE`, `REFERENCES`. `ALL` is used as a synonym for `CREATE`. If you need to add multiple privileges, a space delimited string can be used. - -####`table` -Table to grant access on. - -####`db` -Database of table. - -####`role` -Role or user whom you are granting access for. - -####`psql_db` -Database to execute the grant against. This should not ordinarily be changed from the default, which is `postgres`. - -####`psql_user` -OS user for running `psql`. Defaults to the default user for the module, usually `postgres`. - -####`connect_settings` -Hash of environment variable used when connecting to a remote server. Defaults to connecting to the local Postgres instance. - -###Resource: postgresql::server::tablespace -This defined type can be used to create a tablespace. For example: - - postgresql::server::tablespace { 'tablespace1': - location => '/srv/space1', - } - -It will create the location if necessary, assigning it the same permissions as your -PostgreSQL server. - -####`namevar` -The tablespace name to create. +``` +#Rule Name: Map the SSL certificate of the backup server as a replication user +#Description: none +#Order: 150 +sslrepli repli1.example.com replication +``` -####`location` -The path to locate this tablespace. +### Create recovery configuration + +To create the recovery configuration file (`recovery.conf`): + +```puppet +postgresql::server::recovery { 'Create a recovery.conf file with the following defined parameters': + restore_command => 'cp /mnt/server/archivedir/%f %p', + archive_cleanup_command => undef, + recovery_end_command => undef, + recovery_target_name => 'daily backup 2015-01-26', + recovery_target_time => '2015-02-08 22:39:00 EST', + recovery_target_xid => undef, + recovery_target_inclusive => true, + recovery_target => 'immediate', + recovery_target_timeline => 'latest', + pause_at_recovery_target => true, + standby_mode => 'on', + primary_conninfo => 'host=localhost port=5432', + primary_slot_name => undef, + trigger_file => undef, + recovery_min_apply_delay => 0, +} +``` -####`owner` -The default owner of the tablespace. +The above creates this `recovery.conf` config file: -####`spcname` -Name of the tablespace. Defaults to `namevar`. +``` +restore_command = 'cp /mnt/server/archivedir/%f %p' +recovery_target_name = 'daily backup 2015-01-26' +recovery_target_time = '2015-02-08 22:39:00 EST' +recovery_target_inclusive = true +recovery_target = 'immediate' +recovery_target_timeline = 'latest' +pause_at_recovery_target = true +standby_mode = 'on' +primary_conninfo = 'host=localhost port=5432' +recovery_min_apply_delay = 0 +``` -####`connect_settings` -Hash of environment variable used when connecting to a remote server. Defaults to connecting to the local Postgres instance. +Only the specified parameters are recognized in the template. The `recovery.conf` is only created if at least one parameter is set **and** [manage_recovery_conf](#manage_recovery_conf) is set to true. -###Resource: postgresql::validate_db_connection +### Validate connectivity -This resource can be utilised inside composite manifests to validate that a client has a valid connection with a remote PostgreSQL database. It can be ran from any node where the PostgreSQL client software is installed to validate connectivity before commencing other dependent tasks in your Puppet manifests, so it is often used when chained to other tasks such as: starting an application server, performing a database migration. +To validate client connections to a remote PostgreSQL database before starting dependent tasks, use the `postgresql_conn_validator` resource. You can use this on any node where the PostgreSQL client software is installed. It is often chained to other tasks such as starting an application server or performing a database migration. Example usage: - postgresql::validate_db_connection { 'validate my postgres connection': - database_host => 'my.postgres.host', - database_username => 'mydbuser', - database_password => 'mydbpassword', - database_name => 'mydbname', - }-> - exec { 'rake db:migrate': - cwd => '/opt/myrubyapp', - } - -####`namevar` -Uniquely identify this resource, but functionally does nothing. - -####`database_host` -The hostname of the database you wish to test. Defaults to 'undef' which generally uses the designated local unix socket. - -####`database_port` -Port to use when connecting. Default to 'undef' which generally defaults to 5432 depending on your PostgreSQL packaging. - -####`database_name` -The name of the database you wish to test. Defaults to 'postgres'. - -####`database_username` -Username to connect with. Defaults to 'undef', which when using a unix socket and ident auth will be the user you are running as. If the host is remote you must provide a username. - -####`database_password` -Password to connect with. Can be left blank, but that is not recommended. - -####`connect_settings` -Hash of environment variable used when connecting to a remote server, this is an alternative to providing individual parameters (database_host, etc.). If provided the individual parameters take precedence. - -####`run_as` -The user to run the `psql` command with for authenticiation. This is important when trying to connect to a database locally using Unix sockets and `ident` authentication. It is not needed for remote testing. - -####`sleep` -Upon failure, sets the number of seconds to sleep for before trying again. - -####`tries` -Upon failure, sets the number of attempts before giving up and failing the resource. - -####`create_db_first` -This will ensure the database is created before running the test. This only really works if your test is local. Defaults to `true`. - - -### Custom Resource: postgresql_psql -This type allows puppet to run psql statements. - -#### `name` -An arbitrary tag for your own reference; the name of the message. This is the -namevar. - -#### `command` -The SQL command to execute via psql. Required. - -#### `cwd` -The working directory under which the psql command should be executed. Defaults -to '/tmp' - -#### `db` -The name of the database to execute the SQL command against. - -#### `environment` -Any additional environment variables you want to set for a SQL command. -Multiple environment variables should be specified as an array. - -#### `port` -The port of the database server to execute the SQL command against. - -#### `psql_group` -The system user group account under which the psql command should be executed. -Defaults to 'postgres' - -#### `psql_path` -The path to psql executable. Defaults to 'psql' - -#### `psql_user` -The system user account under which the psql command should be executed. -Defaults to "postgres" - -#### `refreshonly` -If 'true', then the SQL will only be executed via a notify/subscribe event. -Valid values are true or false. Defaults to false. - -#### `search_path` -The schema search path to use when executing the SQL command - -#### `unless` -An optional SQL command to execute prior to the main :command; this is -generally intended to be used for idempotency, to check for the existence of an -object in the database to determine whether or not the main SQL command needs -to be executed at all. - -### Custom Resource: postgresql_conf -This type allows puppet to manage postgresql.conf parameters. - -#### `name` -The postgresql parameter name to manage. This is the namevar. - -#### `target` -The path to postgresql.conf. Defaults to '/etc/postgresql.conf' - -#### `value` -The value to set for this parameter. - -### Custom Resource: postgresql_replication_slot -This type allows to create and destroy replication slots -to register warm standby replication on a Postgresql -master server. - -#### `name` -The name of the slot to create. Must be a validt replication slot name. This is the namevar. +```puppet +postgresql_conn_validator { 'validate my postgres connection': + host => 'my.postgres.host', + db_username => 'mydbuser', + db_password => 'mydbpassword', + db_name => 'mydbname', + psql_path => '/usr/bin/psql', +} +-> exec { 'rake db:migrate': + cwd => '/opt/myrubyapp', +} +``` -###Function: postgresql_password -If you need to generate a postgres encrypted password, use `postgresql_password`. You can call it from your production manifests if you don't mind them containing the clear text versions of your passwords, or you can call it from the command line and then copy and paste the encrypted password into your manifest: +### Backups - $ puppet apply --execute 'notify { "test": message => postgresql_password("username", "password") }' +This example demonstrates how to configure PostgreSQL backups with "pg_dump". This sets up a daily cron job to perform a full backup. Each backup will create a new directory. A cleanup job will automatically remove backups that are older than 15 days. -###Function: postgresql_acls_to_resources_hash(acl_array, id, order_offset) -This internal function converts a list of `pg_hba.conf` based acls (passed in as an array of strings) to a format compatible with the `postgresql::pg_hba_rule` resource. +``` +class { 'postgresql::server': + backup_enable => true, + backup_provider => 'pg_dump', + backup_options => { + db_user => 'backupuser', + db_password => 'secret', + manage_user => true, + rotate => 15, + }, + ... +} +``` -**This function should only be used internally by the module**. +It is possible to set parameter `$ensure` to `absent` in order to remove the backup job, user/role, backup script and password file. However, the actual backup files and directories will remain untouched. -Limitations ------------- +## Reference -Works with versions of PostgreSQL from 8.1 through 9.2. +For information on the classes and types, see the [REFERENCE.md](https://github.com/puppetlabs/puppetlabs-postgresql/blob/main/REFERENCE.md) -Current it is only actively tested with the following operating systems: +## Limitations -* Debian 6.x and 7.x -* Centos 5.x, 6.x, and 7.x. -* Ubuntu 10.04 and 12.04, 14.04 +Works with versions of PostgreSQL on supported OSes. -Although patches are welcome for making it work with other OS distros, it is considered best effort. +For an extensive list of supported operating systems, see [metadata.json](https://github.com/puppetlabs/puppetlabs-postgresql/blob/main/metadata.json) ### Apt module support -While this module supports both 1.x and 2.x versions of the puppetlabs-apt module, it does not support puppetlabs-apt 2.0.0 or 2.0.1. +While this module supports both 1.x and 2.x versions of the 'puppetlabs-apt' module, it does not support 'puppetlabs-apt' 2.0.0 or 2.0.1. -### Postgis support -Postgis is currently considered an unsupported feature as it doesn't work on -all platforms correctly. +### PostGIS support -### All versions of RHEL/Centos +PostGIS is currently considered an unsupported feature, as it doesn't work on all platforms correctly. -If you have selinux enabled you must add any custom ports you use to the postgresql_port_t context. You can do this as follows: +### All versions of RHEL/CentOS with manage_selinux => false -``` -# semanage port -a -t postgresql_port_t -p tcp $customport +If you have SELinux enabled and you are *not* using the selinux module to manage SELinux (this is the default configuration) you will need to label any custom ports you use with the `postgresql_port_t` context. The postgresql service will not start until this is done. To label a port use the semanage command as follows: + +```shell +semanage port -a -t postgresql_port_t -p tcp $customport ``` -Development ------------- +## License -Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can't access the huge number of platforms and myriad of hardware, software, and deployment configurations that Puppet is intended to serve. +This codebase is licensed under the Apache2.0 licensing, however due to the nature of the codebase the open source dependencies may also use a combination of [AGPL](https://opensource.org/license/agpl-v3/), [BSD-2](https://opensource.org/license/bsd-2-clause/), [BSD-3](https://opensource.org/license/bsd-3-clause/), [GPL2.0](https://opensource.org/license/gpl-2-0/), [LGPL](https://opensource.org/license/lgpl-3-0/), [MIT](https://opensource.org/license/mit/) and [MPL](https://opensource.org/license/mpl-2-0/) Licensing. -We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. +## Development -You can read the complete module contribution guide [on the Puppet Labs wiki.](http://projects.puppetlabs.com/projects/module-site/wiki/Module_contributing) +Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve. We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. For more information, see our [module contribution guide](https://puppet.com/docs/puppet/latest/contributing.html). ### Tests -There are two types of tests distributed with the module. Unit tests with rspec-puppet and system tests using rspec-system. +There are two types of tests distributed with this module. Unit tests with `rspec-puppet` and system tests using `rspec-system`. For unit testing, make sure you have: @@ -1195,55 +603,33 @@ For unit testing, make sure you have: Install the necessary gems: - bundle install --path=vendor +```shell +bundle install --path=vendor +``` And then run the unit tests: - bundle exec rake spec - -The unit tests are ran in Travis-CI as well, if you want to see the results of your own tests register the service hook through Travis-CI via the accounts section for your Github clone of this project. +```shell +bundle exec rake spec +``` -If you want to run the system tests, make sure you also have: +To run the system tests, make sure you also have: -* vagrant > 1.2.x -* Virtualbox > 4.2.10 +* Vagrant > 1.2.x +* VirtualBox > 4.2.10 Then run the tests using: - bundle exec rspec spec/acceptance - -To run the tests on different operating systems, see the sets available in .nodeset.yml and run the specific set with the following syntax: - - RSPEC_SET=debian-607-x64 bundle exec rspec spec/acceptance - -Transfer Notice ----------------- - -This Puppet module was originally authored by Inkling Systems. The maintainer preferred that Puppet Labs take ownership of the module for future improvement and maintenance as Puppet Labs is using it in the PuppetDB module. Existing pull requests and issues were transferred over, please fork and continue to contribute here instead of Inkling. - -Previously: [https://github.com/inkling/puppet-postgresql](https://github.com/inkling/puppet-postgresql) - -Contributors ------------- - - * Andrew Moon - * [Kenn Knowles](https://github.com/kennknowles) ([@kennknowles](https://twitter.com/KennKnowles)) - * Adrien Thebo - * Albert Koch - * Andreas Ntaflos - * Bret Comnes - * Brett Porter - * Chris Price - * dharwood - * Etienne Pelletier - * Florin Broasca - * Henrik - * Hunter Haugen - * Jari Bakken - * Jordi Boggiano - * Ken Barber - * nzakaria - * Richard Arends - * Spenser Gilliland - * stormcrow - * William Van Hevelingen +```shell +bundle exec rspec spec/acceptance +``` + +To run the tests on different operating systems, see the sets available in `.nodeset.yml` and run the specific set with the following syntax: + +```shell +RSPEC_SET=debian-607-x64 bundle exec rspec spec/acceptance +``` + +### Contributors + +View the full list of contributors on [Github](https://github.com/puppetlabs/puppetlabs-postgresql/graphs/contributors). diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 0000000000..bf3ffc306f --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,4941 @@ +# Reference + + + +## Table of Contents + +### Classes + +#### Public Classes + +* [`postgresql::client`](#postgresql--client): Installs PostgreSQL client software. Set the following parameters if you have a custom version you would like to install. +* [`postgresql::globals`](#postgresql--globals): Class for setting cross-class global overrides. +* [`postgresql::lib::devel`](#postgresql--lib--devel): This class installs postgresql development libraries. +* [`postgresql::lib::docs`](#postgresql--lib--docs): Installs PostgreSQL bindings for Postgres-Docs. Set the following parameters if you have a custom version you would like to install. +* [`postgresql::lib::java`](#postgresql--lib--java): This class installs the postgresql jdbc connector. +* [`postgresql::lib::perl`](#postgresql--lib--perl): This class installs the perl libs for postgresql. +* [`postgresql::lib::python`](#postgresql--lib--python): This class installs the python libs for postgresql. +* [`postgresql::server`](#postgresql--server): This installs a PostgreSQL server +* [`postgresql::server::contrib`](#postgresql--server--contrib): Install the contrib postgresql packaging. +* [`postgresql::server::plperl`](#postgresql--server--plperl): This class installs the PL/Perl procedural language for postgresql. +* [`postgresql::server::plpython`](#postgresql--server--plpython): This class installs the PL/Python procedural language for postgresql. +* [`postgresql::server::postgis`](#postgresql--server--postgis): Install the postgis postgresql packaging. + +#### Private Classes + +* `postgresql::backup::pg_dump`: "Provider" for pg_dump backup +* `postgresql::dnfmodule`: Manage the DNF module +* `postgresql::params` +* `postgresql::repo` +* `postgresql::repo::apt_postgresql_org` +* `postgresql::repo::yum_postgresql_org` +* `postgresql::server::config` +* `postgresql::server::initdb` +* `postgresql::server::install` +* `postgresql::server::late_initdb`: Manage the default encoding when database initialization is managed by the package +* `postgresql::server::passwd` +* `postgresql::server::reload` +* `postgresql::server::service` + +### Defined types + +#### Public Defined types + +* [`postgresql::server::config_entry`](#postgresql--server--config_entry): Manage a postgresql.conf entry. +* [`postgresql::server::database`](#postgresql--server--database): Define for creating a database. +* [`postgresql::server::database_grant`](#postgresql--server--database_grant): Manage a database grant. +* [`postgresql::server::db`](#postgresql--server--db): Define for conveniently creating a role, database and assigning the correct permissions. +* [`postgresql::server::default_privileges`](#postgresql--server--default_privileges): Manage a database defaults privileges. Only works with PostgreSQL version 9.6 and above. +* [`postgresql::server::extension`](#postgresql--server--extension): Activate an extension on a postgresql database. +* [`postgresql::server::grant`](#postgresql--server--grant): Define for granting permissions to roles. +* [`postgresql::server::grant_role`](#postgresql--server--grant_role): Define for granting membership to a role. +* [`postgresql::server::instance::config`](#postgresql--server--instance--config): Manages the config for a postgresql::server instance +* [`postgresql::server::instance::initdb`](#postgresql--server--instance--initdb): Manages initdb feature for a postgresql::server instance +* [`postgresql::server::instance::late_initdb`](#postgresql--server--instance--late_initdb): Manage the default encoding when database initialization is managed by the package +* [`postgresql::server::instance::passwd`](#postgresql--server--instance--passwd): Overrides the default PostgreSQL superuser +* [`postgresql::server::instance::reload`](#postgresql--server--instance--reload): Overrides the default reload or status command for your PostgreSQL service +* [`postgresql::server::instance::service`](#postgresql--server--instance--service): Manages the service for the postgres main instance (default) or additional instances +* [`postgresql::server::pg_hba_rule`](#postgresql--server--pg_hba_rule): This resource manages an individual rule that applies to the file defined in target. +* [`postgresql::server::pg_ident_rule`](#postgresql--server--pg_ident_rule): This resource manages an individual rule that applies to the file defined in target. +* [`postgresql::server::reassign_owned_by`](#postgresql--server--reassign_owned_by): Define for reassigning the ownership of objects within a database. +* [`postgresql::server::recovery`](#postgresql--server--recovery): This resource manages the parameters that applies to the recovery.conf template. +* [`postgresql::server::role`](#postgresql--server--role): Define for creating a database role. +* [`postgresql::server::schema`](#postgresql--server--schema): Create a new schema. +* [`postgresql::server::table_grant`](#postgresql--server--table_grant): This resource wraps the grant resource to manage table grants specifically. +* [`postgresql::server::tablespace`](#postgresql--server--tablespace): This module creates tablespace. +* [`postgresql::server_instance`](#postgresql--server_instance): define to install and manage additional postgresql instances + +#### Private Defined types + +* `postgresql::server::instance::systemd`: This define handles systemd drop-in files for the postgres main instance (default) or additional instances + +### Resource types + +* [`postgresql_conf`](#postgresql_conf): This type allows puppet to manage postgresql.conf parameters. +* [`postgresql_conn_validator`](#postgresql_conn_validator): Verify if a connection can be successfully established +* [`postgresql_psql`](#postgresql_psql): An arbitrary tag for your own reference; the name of the message. +* [`postgresql_replication_slot`](#postgresql_replication_slot): Manages Postgresql replication slots. + +### Functions + +#### Public Functions + +* [`postgresql::default`](#postgresql--default): This function pull default values from the `params` class or `globals` class if the value is not present in `params`. +* [`postgresql::postgresql_escape`](#postgresql--postgresql_escape): This function escapes a string using [Dollar Quoting](https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING) using a randomly generated tag if required. +* [`postgresql::postgresql_password`](#postgresql--postgresql_password): This function returns the postgresql password hash from the clear text username / password +* [`postgresql::prepend_sql_password`](#postgresql--prepend_sql_password): This function exists for usage of a role password that is a deferred function +* [`postgresql_escape`](#postgresql_escape): DEPRECATED. Use the namespaced function [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape) instead. +* [`postgresql_password`](#postgresql_password): DEPRECATED. Use the namespaced function [`postgresql::postgresql_password`](#postgresqlpostgresql_password) instead. + +#### Private Functions + +* `postgresql::postgresql_acls_to_resources_hash`: This internal function translates the ipv(4|6)acls format into a resource suitable for create_resources. + +### Data types + +* [`Postgresql::Pg_hba_rule`](#Postgresql--Pg_hba_rule): type for all parameters in the postgresql::server::hba_rule defined resource +* [`Postgresql::Pg_hba_rule_address`](#Postgresql--Pg_hba_rule_address): Supported address types +* [`Postgresql::Pg_hba_rule_type`](#Postgresql--Pg_hba_rule_type): enum for all different types for the pg_hba_conf +* [`Postgresql::Pg_hba_rules`](#Postgresql--Pg_hba_rules): validates a hash of entries for postgresql::server::pg_hab_conf +* [`Postgresql::Pg_password_encryption`](#Postgresql--Pg_password_encryption): the supported password_encryption + +### Tasks + +* [`sql`](#sql): Allows you to execute arbitary SQL + +## Classes + +### `postgresql::client` + +Installs PostgreSQL client software. Set the following parameters if you have a custom version you would like to install. + +* **Note** Make sure to add any necessary yum or apt repositories if specifying a custom version. + +#### Parameters + +The following parameters are available in the `postgresql::client` class: + +* [`file_ensure`](#-postgresql--client--file_ensure) +* [`validcon_script_path`](#-postgresql--client--validcon_script_path) +* [`package_name`](#-postgresql--client--package_name) +* [`package_ensure`](#-postgresql--client--package_ensure) + +##### `file_ensure` + +Data type: `Enum['file', 'absent']` + +Ensure the connection validation script is present + +Default value: `'file'` + +##### `validcon_script_path` + +Data type: `Stdlib::Absolutepath` + +Optional. Absolute path for the postgresql connection validation script. + +Default value: `$postgresql::params::validcon_script_path` + +##### `package_name` + +Data type: `String[1]` + +Sets the name of the PostgreSQL client package. + +Default value: `$postgresql::params::client_package_name` + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Ensure the client package is installed + +Default value: `'present'` + +### `postgresql::globals` + +Class for setting cross-class global overrides. + +* **Note** Most server-specific defaults should be overridden in the postgresql::server class. +This class should be used only if you are using a non-standard OS, or if you are changing elements that can only be changed here, such +as version or manage_package_repo. + +#### Parameters + +The following parameters are available in the `postgresql::globals` class: + +* [`client_package_name`](#-postgresql--globals--client_package_name) +* [`server_package_name`](#-postgresql--globals--server_package_name) +* [`contrib_package_name`](#-postgresql--globals--contrib_package_name) +* [`devel_package_name`](#-postgresql--globals--devel_package_name) +* [`java_package_name`](#-postgresql--globals--java_package_name) +* [`docs_package_name`](#-postgresql--globals--docs_package_name) +* [`perl_package_name`](#-postgresql--globals--perl_package_name) +* [`plperl_package_name`](#-postgresql--globals--plperl_package_name) +* [`plpython_package_name`](#-postgresql--globals--plpython_package_name) +* [`python_package_name`](#-postgresql--globals--python_package_name) +* [`postgis_package_name`](#-postgresql--globals--postgis_package_name) +* [`service_name`](#-postgresql--globals--service_name) +* [`service_provider`](#-postgresql--globals--service_provider) +* [`service_status`](#-postgresql--globals--service_status) +* [`default_database`](#-postgresql--globals--default_database) +* [`validcon_script_path`](#-postgresql--globals--validcon_script_path) +* [`initdb_path`](#-postgresql--globals--initdb_path) +* [`psql_path`](#-postgresql--globals--psql_path) +* [`pg_hba_conf_path`](#-postgresql--globals--pg_hba_conf_path) +* [`pg_ident_conf_path`](#-postgresql--globals--pg_ident_conf_path) +* [`postgresql_conf_path`](#-postgresql--globals--postgresql_conf_path) +* [`postgresql_conf_mode`](#-postgresql--globals--postgresql_conf_mode) +* [`recovery_conf_path`](#-postgresql--globals--recovery_conf_path) +* [`default_connect_settings`](#-postgresql--globals--default_connect_settings) +* [`pg_hba_conf_defaults`](#-postgresql--globals--pg_hba_conf_defaults) +* [`datadir`](#-postgresql--globals--datadir) +* [`confdir`](#-postgresql--globals--confdir) +* [`bindir`](#-postgresql--globals--bindir) +* [`xlogdir`](#-postgresql--globals--xlogdir) +* [`logdir`](#-postgresql--globals--logdir) +* [`log_line_prefix`](#-postgresql--globals--log_line_prefix) +* [`user`](#-postgresql--globals--user) +* [`group`](#-postgresql--globals--group) +* [`version`](#-postgresql--globals--version) +* [`postgis_version`](#-postgresql--globals--postgis_version) +* [`repo_proxy`](#-postgresql--globals--repo_proxy) +* [`repo_baseurl`](#-postgresql--globals--repo_baseurl) +* [`yum_repo_commonurl`](#-postgresql--globals--yum_repo_commonurl) +* [`apt_source_release`](#-postgresql--globals--apt_source_release) +* [`needs_initdb`](#-postgresql--globals--needs_initdb) +* [`encoding`](#-postgresql--globals--encoding) +* [`locale`](#-postgresql--globals--locale) +* [`data_checksums`](#-postgresql--globals--data_checksums) +* [`timezone`](#-postgresql--globals--timezone) +* [`password_encryption`](#-postgresql--globals--password_encryption) +* [`manage_pg_hba_conf`](#-postgresql--globals--manage_pg_hba_conf) +* [`manage_pg_ident_conf`](#-postgresql--globals--manage_pg_ident_conf) +* [`manage_recovery_conf`](#-postgresql--globals--manage_recovery_conf) +* [`manage_postgresql_conf_perms`](#-postgresql--globals--manage_postgresql_conf_perms) +* [`manage_selinux`](#-postgresql--globals--manage_selinux) +* [`manage_datadir`](#-postgresql--globals--manage_datadir) +* [`manage_logdir`](#-postgresql--globals--manage_logdir) +* [`manage_xlogdir`](#-postgresql--globals--manage_xlogdir) +* [`manage_package_repo`](#-postgresql--globals--manage_package_repo) +* [`manage_dnf_module`](#-postgresql--globals--manage_dnf_module) +* [`module_workdir`](#-postgresql--globals--module_workdir) + +##### `client_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL client package name. + +Default value: `undef` + +##### `server_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL server package name. + +Default value: `undef` + +##### `contrib_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL contrib package name. + +Default value: `undef` + +##### `devel_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL devel package name. + +Default value: `undef` + +##### `java_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL java package name. + +Default value: `undef` + +##### `docs_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL docs package name. + +Default value: `undef` + +##### `perl_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL Perl package name. + +Default value: `undef` + +##### `plperl_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL PL/Perl package name. + +Default value: `undef` + +##### `plpython_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL PL/Python package name. + +Default value: `undef` + +##### `python_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL Python package name. + +Default value: `undef` + +##### `postgis_package_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL PostGIS package name. + +Default value: `undef` + +##### `service_name` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL service name. + +Default value: `undef` + +##### `service_provider` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL service provider. + +Default value: `undef` + +##### `service_status` + +Data type: `Optional[String[1]]` + +Overrides the default status check command for your PostgreSQL service. + +Default value: `undef` + +##### `default_database` + +Data type: `Optional[String[1]]` + +Specifies the name of the default database to connect with. + +Default value: `undef` + +##### `validcon_script_path` + +Data type: `Optional[String[1]]` + +Scipt path for the connection validation check. + +Default value: `undef` + +##### `initdb_path` + +Data type: `Optional[Stdlib::Absolutepath]` + +Path to the initdb command. + +Default value: `undef` + +##### `psql_path` + +Data type: `Optional[Stdlib::Absolutepath]` + +Sets the path to the psql command. + +Default value: `undef` + +##### `pg_hba_conf_path` + +Data type: `Optional[Stdlib::Absolutepath]` + +Specifies the path to your pg_hba.conf file. + +Default value: `undef` + +##### `pg_ident_conf_path` + +Data type: `Optional[Stdlib::Absolutepath]` + +Specifies the path to your pg_ident.conf file. + +Default value: `undef` + +##### `postgresql_conf_path` + +Data type: `Optional[Stdlib::Absolutepath]` + +Sets the path to your postgresql.conf file. + +Default value: `undef` + +##### `postgresql_conf_mode` + +Data type: `Optional[Stdlib::Filemode]` + +Sets the mode of your postgresql.conf file. Only relevant if manage_postgresql_conf_perms is true. + +Default value: `undef` + +##### `recovery_conf_path` + +Data type: `Optional[Stdlib::Absolutepath]` + +Path to your recovery.conf file. + +Default value: `undef` + +##### `default_connect_settings` + +Data type: `Hash` + +Default connection settings. + +Default value: `{}` + +##### `pg_hba_conf_defaults` + +Data type: `Optional[Boolean]` + +Disables the defaults supplied with the module for pg_hba.conf if set to false. + +Default value: `undef` + +##### `datadir` + +Data type: `Optional[Stdlib::Absolutepath]` + +Overrides the default PostgreSQL data directory for the target platform. +Changing the datadir after installation causes the server to come to a full stop before making the change. +For Red Hat systems, the data directory must be labeled appropriately for SELinux. +On Ubuntu, you must explicitly set needs_initdb = true to allow Puppet to initialize the database in the new datadir (needs_initdb +defaults to true on other systems). +Warning! If datadir is changed from the default, Puppet does not manage purging of the original data directory, which causes it to fail +if the data directory is changed back to the original + +Default value: `undef` + +##### `confdir` + +Data type: `Optional[Stdlib::Absolutepath]` + +Overrides the default PostgreSQL configuration directory for the target platform. + +Default value: `undef` + +##### `bindir` + +Data type: `Optional[Stdlib::Absolutepath]` + +Overrides the default PostgreSQL binaries directory for the target platform. + +Default value: `undef` + +##### `xlogdir` + +Data type: `Optional[Stdlib::Absolutepath]` + +Overrides the default PostgreSQL xlog directory. + +Default value: `undef` + +##### `logdir` + +Data type: `Optional[Stdlib::Absolutepath]` + +Overrides the default PostgreSQL log directory. + +Default value: `undef` + +##### `log_line_prefix` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL log prefix. + +Default value: `undef` + +##### `user` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `undef` + +##### `group` + +Data type: `Optional[String[1]]` + +Overrides the default postgres user group to be used for related files in the file system. + +Default value: `undef` + +##### `version` + +Data type: `Optional[String[1]]` + +The version of PostgreSQL to install and manage. + +Default value: `undef` + +##### `postgis_version` + +Data type: `Optional[String[1]]` + +Defines the version of PostGIS to install, if you install PostGIS. + +Default value: `undef` + +##### `repo_proxy` + +Data type: `Optional[String[1]]` + +Sets the proxy option for the official PostgreSQL yum-repositories only. + +Default value: `undef` + +##### `repo_baseurl` + +Data type: `Optional[String[1]]` + +Sets the baseurl for the PostgreSQL repository. Useful if you host your own mirror of the repository. + +Default value: `undef` + +##### `yum_repo_commonurl` + +Data type: `Optional[String[1]]` + +Sets the url for the PostgreSQL common Yum repository. Useful if you host your own mirror of the YUM repository. + +Default value: `undef` + +##### `apt_source_release` + +Data type: `Optional[String[1]]` + +Overrides the default release for the apt source. + +Default value: `undef` + +##### `needs_initdb` + +Data type: `Optional[Boolean]` + +Explicitly calls the initdb operation after the server package is installed and before the PostgreSQL service is started. + +Default value: `undef` + +##### `encoding` + +Data type: `Optional[String[1]]` + +Sets the default encoding for all databases created with this module. +On certain operating systems, this is also used during the template1 initialization, +so it becomes a default outside of the module as well. + +Default value: `undef` + +##### `locale` + +Data type: `Optional[String[1]]` + +Sets the default database locale for all databases created with this module. +On certain operating systems, this is also used during the template1 initialization, +so it becomes a default outside of the module as well. +On Debian, you'll need to ensure that the 'locales-all' package is installed for full functionality of PostgreSQL. + +Default value: `undef` + +##### `data_checksums` + +Data type: `Optional[Boolean]` + +Use checksums on data pages to help detect corruption by the I/O system that would otherwise be silent. +Warning: This option is used during initialization by initdb, and cannot be changed later. + +Default value: `undef` + +##### `timezone` + +Data type: `Optional[String[1]]` + +Sets the default timezone of the postgresql server. The postgresql built-in default is taking the systems timezone information. + +Default value: `undef` + +##### `password_encryption` + +Data type: `Optional[Postgresql::Pg_password_encryption]` + +Specify the type of encryption set for the password. +Defaults to scram-sha-256 for PostgreSQL >= 14, otherwise md5. + +Default value: `undef` + +##### `manage_pg_hba_conf` + +Data type: `Optional[Boolean]` + +Allow Puppet to manage the pg_hba.conf file. + +Default value: `undef` + +##### `manage_pg_ident_conf` + +Data type: `Optional[Boolean]` + +Allow Puppet to manage the pg_ident.conf file. + +Default value: `undef` + +##### `manage_recovery_conf` + +Data type: `Optional[Boolean]` + +Allow Puppet to manage the recovery.conf file. + +Default value: `undef` + +##### `manage_postgresql_conf_perms` + +Data type: `Optional[Boolean]` + +Whether to manage the postgresql conf file permissions. This means owner, +group and mode. Contents are not managed but should be managed through +postgresql::server::config_entry. + +Default value: `undef` + +##### `manage_selinux` + +Data type: `Optional[Boolean]` + +Allows Puppet to manage the appropriate configuration file for selinux. + +Default value: `undef` + +##### `manage_datadir` + +Data type: `Optional[Boolean]` + +Set to false if you have file{ $datadir: } already defined + +Default value: `undef` + +##### `manage_logdir` + +Data type: `Optional[Boolean]` + +Set to false if you have file{ $logdir: } already defined + +Default value: `undef` + +##### `manage_xlogdir` + +Data type: `Optional[Boolean]` + +Set to false if you have file{ $xlogdir: } already defined + +Default value: `undef` + +##### `manage_package_repo` + +Data type: `Optional[Boolean]` + +Sets up official PostgreSQL repositories on your host if set to true. + +Default value: `undef` + +##### `manage_dnf_module` + +Data type: `Boolean` + +Manage the DNF module. This only makes sense on distributions that use DNF +package manager, such as EL8, EL9 or Fedora. + +Default value: `false` + +##### `module_workdir` + +Data type: `Optional[Stdlib::Absolutepath]` + +Specifies working directory under which the psql command should be executed. +May need to specify if '/tmp' is on volume mounted with noexec option. + +Default value: `undef` + +### `postgresql::lib::devel` + +This class installs postgresql development libraries. + +#### Parameters + +The following parameters are available in the `postgresql::lib::devel` class: + +* [`package_name`](#-postgresql--lib--devel--package_name) +* [`package_ensure`](#-postgresql--lib--devel--package_ensure) +* [`link_pg_config`](#-postgresql--lib--devel--link_pg_config) + +##### `package_name` + +Data type: `String` + +Override devel package name + +Default value: `$postgresql::params::devel_package_name` + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Ensure the development libraries are installed + +Default value: `'present'` + +##### `link_pg_config` + +Data type: `Boolean` + +If the bin directory used by the PostgreSQL page is not /usr/bin or /usr/local/bin, symlinks pg_config from the package's bin dir +into usr/bin (not applicable to Debian systems). Set to false to disable this behavior. + +Default value: `$postgresql::params::link_pg_config` + +### `postgresql::lib::docs` + +Installs PostgreSQL bindings for Postgres-Docs. Set the following parameters if you have a custom version you would like to install. + +* **Note** Make sure to add any necessary yum or apt repositories if specifying a custom version. + +#### Parameters + +The following parameters are available in the `postgresql::lib::docs` class: + +* [`package_name`](#-postgresql--lib--docs--package_name) +* [`package_ensure`](#-postgresql--lib--docs--package_ensure) + +##### `package_name` + +Data type: `String` + +Specifies the name of the PostgreSQL docs package. + +Default value: `$postgresql::params::docs_package_name` + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Whether the PostgreSQL docs package resource should be present. + +Default value: `'present'` + +### `postgresql::lib::java` + +This class installs the postgresql jdbc connector. + +* **Note** Make sure to add any necessary yum or apt repositories if specifying a custom version. + +#### Parameters + +The following parameters are available in the `postgresql::lib::java` class: + +* [`package_name`](#-postgresql--lib--java--package_name) +* [`package_ensure`](#-postgresql--lib--java--package_ensure) + +##### `package_name` + +Data type: `String` + +Specifies the name of the PostgreSQL java package. + +Default value: `$postgresql::params::java_package_name` + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Specifies whether the package is present. + +Default value: `'present'` + +### `postgresql::lib::perl` + +This class installs the perl libs for postgresql. + +#### Parameters + +The following parameters are available in the `postgresql::lib::perl` class: + +* [`package_name`](#-postgresql--lib--perl--package_name) +* [`package_ensure`](#-postgresql--lib--perl--package_ensure) + +##### `package_name` + +Data type: `String` + +Specifies the name of the PostgreSQL perl package to install. + +Default value: `$postgresql::params::perl_package_name` + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Ensure the perl libs for postgresql are installed. + +Default value: `'present'` + +### `postgresql::lib::python` + +This class installs the python libs for postgresql. + +#### Parameters + +The following parameters are available in the `postgresql::lib::python` class: + +* [`package_name`](#-postgresql--lib--python--package_name) +* [`package_ensure`](#-postgresql--lib--python--package_ensure) + +##### `package_name` + +Data type: `String[1]` + +The name of the PostgreSQL Python package. + +Default value: `$postgresql::params::python_package_name` + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Ensure the python libs for postgresql are installed. + +Default value: `'present'` + +### `postgresql::server` + +This installs a PostgreSQL server + +#### Parameters + +The following parameters are available in the `postgresql::server` class: + +* [`postgres_password`](#-postgresql--server--postgres_password) +* [`package_name`](#-postgresql--server--package_name) +* [`package_ensure`](#-postgresql--server--package_ensure) +* [`plperl_package_name`](#-postgresql--server--plperl_package_name) +* [`plpython_package_name`](#-postgresql--server--plpython_package_name) +* [`service_ensure`](#-postgresql--server--service_ensure) +* [`service_enable`](#-postgresql--server--service_enable) +* [`service_manage`](#-postgresql--server--service_manage) +* [`service_name`](#-postgresql--server--service_name) +* [`service_restart_on_change`](#-postgresql--server--service_restart_on_change) +* [`service_provider`](#-postgresql--server--service_provider) +* [`service_reload`](#-postgresql--server--service_reload) +* [`service_status`](#-postgresql--server--service_status) +* [`default_database`](#-postgresql--server--default_database) +* [`default_connect_settings`](#-postgresql--server--default_connect_settings) +* [`listen_addresses`](#-postgresql--server--listen_addresses) +* [`port`](#-postgresql--server--port) +* [`ip_mask_deny_postgres_user`](#-postgresql--server--ip_mask_deny_postgres_user) +* [`ip_mask_allow_all_users`](#-postgresql--server--ip_mask_allow_all_users) +* [`ipv4acls`](#-postgresql--server--ipv4acls) +* [`ipv6acls`](#-postgresql--server--ipv6acls) +* [`initdb_path`](#-postgresql--server--initdb_path) +* [`psql_path`](#-postgresql--server--psql_path) +* [`pg_hba_conf_path`](#-postgresql--server--pg_hba_conf_path) +* [`pg_ident_conf_path`](#-postgresql--server--pg_ident_conf_path) +* [`postgresql_conf_path`](#-postgresql--server--postgresql_conf_path) +* [`postgresql_conf_mode`](#-postgresql--server--postgresql_conf_mode) +* [`recovery_conf_path`](#-postgresql--server--recovery_conf_path) +* [`datadir`](#-postgresql--server--datadir) +* [`xlogdir`](#-postgresql--server--xlogdir) +* [`logdir`](#-postgresql--server--logdir) +* [`log_line_prefix`](#-postgresql--server--log_line_prefix) +* [`pg_hba_conf_defaults`](#-postgresql--server--pg_hba_conf_defaults) +* [`user`](#-postgresql--server--user) +* [`group`](#-postgresql--server--group) +* [`needs_initdb`](#-postgresql--server--needs_initdb) +* [`encoding`](#-postgresql--server--encoding) +* [`locale`](#-postgresql--server--locale) +* [`data_checksums`](#-postgresql--server--data_checksums) +* [`timezone`](#-postgresql--server--timezone) +* [`manage_pg_hba_conf`](#-postgresql--server--manage_pg_hba_conf) +* [`manage_pg_ident_conf`](#-postgresql--server--manage_pg_ident_conf) +* [`manage_recovery_conf`](#-postgresql--server--manage_recovery_conf) +* [`manage_postgresql_conf_perms`](#-postgresql--server--manage_postgresql_conf_perms) +* [`manage_selinux`](#-postgresql--server--manage_selinux) +* [`module_workdir`](#-postgresql--server--module_workdir) +* [`manage_datadir`](#-postgresql--server--manage_datadir) +* [`manage_logdir`](#-postgresql--server--manage_logdir) +* [`manage_xlogdir`](#-postgresql--server--manage_xlogdir) +* [`password_encryption`](#-postgresql--server--password_encryption) +* [`pg_hba_auth_password_encryption`](#-postgresql--server--pg_hba_auth_password_encryption) +* [`roles`](#-postgresql--server--roles) +* [`config_entries`](#-postgresql--server--config_entries) +* [`pg_hba_rules`](#-postgresql--server--pg_hba_rules) +* [`backup_enable`](#-postgresql--server--backup_enable) +* [`backup_options`](#-postgresql--server--backup_options) +* [`backup_provider`](#-postgresql--server--backup_provider) +* [`extra_systemd_config`](#-postgresql--server--extra_systemd_config) +* [`auth_host`](#-postgresql--server--auth_host) +* [`auth_local`](#-postgresql--server--auth_local) +* [`lc_messages`](#-postgresql--server--lc_messages) +* [`username`](#-postgresql--server--username) + +##### `postgres_password` + +Data type: `Optional[Variant[String[1], Sensitive[String[1]], Integer]]` + +Sets the password for the postgres user to your specified value. By default, this setting uses the superuser account in the Postgres +database, with a user called postgres and no password. + +Default value: `undef` + +##### `package_name` + +Data type: `String[1]` + +Specifies the name of the package to use for installing the server software. + +Default value: `$postgresql::params::server_package_name` + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Passes a value through to the package resource when creating the server instance. + +Default value: `$postgresql::params::package_ensure` + +##### `plperl_package_name` + +Data type: `Optional[String[1]]` + +Sets the default package name for the PL/Perl extension. + +Default value: `$postgresql::params::plperl_package_name` + +##### `plpython_package_name` + +Data type: `Optional[String[1]]` + +Sets the default package name for the PL/Python extension. + +Default value: `$postgresql::params::plpython_package_name` + +##### `service_ensure` + +Data type: `Variant[Enum['running', 'stopped'], Boolean]` + +Ensure service is installed + +Default value: `$postgresql::params::service_ensure` + +##### `service_enable` + +Data type: `Boolean` + +Enable the PostgreSQL service + +Default value: `$postgresql::params::service_enable` + +##### `service_manage` + +Data type: `Boolean` + +Defines whether or not Puppet should manage the service. + +Default value: `$postgresql::params::service_manage` + +##### `service_name` + +Data type: `String[1]` + +Overrides the default PostgreSQL service name. + +Default value: `$postgresql::params::service_name` + +##### `service_restart_on_change` + +Data type: `Boolean` + +Overrides the default behavior to restart your PostgreSQL service when a config entry has been changed that requires a service restart +to become active. + +Default value: `$postgresql::params::service_restart_on_change` + +##### `service_provider` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL service provider. + +Default value: `$postgresql::params::service_provider` + +##### `service_reload` + +Data type: `String[1]` + +Overrides the default reload command for your PostgreSQL service. + +Default value: `$postgresql::params::service_reload` + +##### `service_status` + +Data type: `Optional[String[1]]` + +Overrides the default status check command for your PostgreSQL service. + +Default value: `$postgresql::params::service_status` + +##### `default_database` + +Data type: `String[1]` + +Specifies the name of the default database to connect with. On most systems this is 'postgres'. + +Default value: `$postgresql::params::default_database` + +##### `default_connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. Becomes the default for other defined types, such as +postgresql::server::role. + +Default value: `$postgresql::globals::default_connect_settings` + +##### `listen_addresses` + +Data type: `Optional[Variant[String[1], Array[String[1]]]]` + +Address list on which the PostgreSQL service will listen + +Default value: `$postgresql::params::listen_addresses` + +##### `port` + +Data type: `Stdlib::Port` + +Specifies the port for the PostgreSQL server to listen on. +Note: The same port number is used for all IP addresses the server listens on. +Also, for Red Hat systems and early Debian systems, changing the port causes the server to come to a full stop before being able to make +the change. +Default value: 5432. Meaning the Postgres server listens on TCP port 5432. + +Default value: `$postgresql::params::port` + +##### `ip_mask_deny_postgres_user` + +Data type: `String[1]` + +Specifies the IP mask from which remote connections should be denied for the postgres superuser. +Default value: '0.0.0.0/0', which denies any remote connection. + +Default value: `$postgresql::params::ip_mask_deny_postgres_user` + +##### `ip_mask_allow_all_users` + +Data type: `String[1]` + +Overrides PostgreSQL defaults for remote connections. By default, PostgreSQL does not allow database user accounts to connect via TCP +from remote machines. If you'd like to allow this, you can override this setting. +Set to '0.0.0.0/0' to allow database users to connect from any remote machine, or '192.168.0.0/1' to allow connections from any machine +on your local '192.168' subnet. +Default value: '127.0.0.1/32'. + +Default value: `$postgresql::params::ip_mask_allow_all_users` + +##### `ipv4acls` + +Data type: `Array[String[1]]` + +Lists strings for access control for connection method, users, databases, IPv4 addresses; + +Default value: `$postgresql::params::ipv4acls` + +##### `ipv6acls` + +Data type: `Array[String[1]]` + +Lists strings for access control for connection method, users, databases, IPv6 addresses. + +Default value: `$postgresql::params::ipv6acls` + +##### `initdb_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to the initdb command. + +Default value: `$postgresql::params::initdb_path` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to the psql command. + +Default value: `$postgresql::params::psql_path` + +##### `pg_hba_conf_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to your pg_hba.conf file. + +Default value: `$postgresql::params::pg_hba_conf_path` + +##### `pg_ident_conf_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to your pg_ident.conf file. + +Default value: `$postgresql::params::pg_ident_conf_path` + +##### `postgresql_conf_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to your postgresql.conf file. + +Default value: `$postgresql::params::postgresql_conf_path` + +##### `postgresql_conf_mode` + +Data type: `Optional[Stdlib::Filemode]` + +Sets the mode of your postgresql.conf file. Only relevant if manage_postgresql_conf_perms is true. + +Default value: `$postgresql::params::postgresql_conf_mode` + +##### `recovery_conf_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to your recovery.conf file. + +Default value: `$postgresql::params::recovery_conf_path` + +##### `datadir` + +Data type: `Stdlib::Absolutepath` + +PostgreSQL data directory + +Default value: `$postgresql::params::datadir` + +##### `xlogdir` + +Data type: `Optional[Stdlib::Absolutepath]` + +PostgreSQL xlog directory + +Default value: `$postgresql::params::xlogdir` + +##### `logdir` + +Data type: `Optional[Stdlib::Absolutepath]` + +PostgreSQL log directory + +Default value: `$postgresql::params::logdir` + +##### `log_line_prefix` + +Data type: `Optional[String[1]]` + +PostgreSQL log line prefix + +Default value: `$postgresql::params::log_line_prefix` + +##### `pg_hba_conf_defaults` + +Data type: `Boolean` + +If false, disables the defaults supplied with the module for pg_hba.conf. This is useful if you disagree with the defaults and wish to +override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform +basic psql operations for example. + +Default value: `$postgresql::params::pg_hba_conf_defaults` + +##### `user` + +Data type: `String[1]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `$postgresql::params::user` + +##### `group` + +Data type: `String[1]` + +Overrides the default postgres user group to be used for related files in the file system. + +Default value: `$postgresql::params::group` + +##### `needs_initdb` + +Data type: `Boolean` + +Explicitly calls the initdb operation after server package is installed, and before the PostgreSQL service is started. + +Default value: `$postgresql::params::needs_initdb` + +##### `encoding` + +Data type: `Optional[String[1]]` + +Sets the default encoding for all databases created with this module. On certain operating systems this is also used during the +template1 initialization, so it becomes a default outside of the module as well. + +Default value: `$postgresql::params::encoding` + +##### `locale` + +Data type: `Optional[String[1]]` + +Sets the default database locale for all databases created with this module. On certain operating systems this is used during the +template1 initialization as well, so it becomes a default outside of the module. + +Default value: `$postgresql::params::locale` + +##### `data_checksums` + +Data type: `Optional[Boolean]` + +Use checksums on data pages to help detect corruption by the I/O system that would otherwise be silent. +Warning: This option is used during initialization by initdb, and cannot be changed later. +If set, checksums are calculated for all objects, in all databases. + +Default value: `$postgresql::params::data_checksums` + +##### `timezone` + +Data type: `Optional[String[1]]` + +Set timezone for the PostgreSQL instance + +Default value: `$postgresql::params::timezone` + +##### `manage_pg_hba_conf` + +Data type: `Boolean` + +Boolean. Whether to manage the pg_hba.conf. + +Default value: `$postgresql::params::manage_pg_hba_conf` + +##### `manage_pg_ident_conf` + +Data type: `Boolean` + +Boolean. Overwrites the pg_ident.conf file. + +Default value: `$postgresql::params::manage_pg_ident_conf` + +##### `manage_recovery_conf` + +Data type: `Boolean` + +Boolean. Specifies whether or not manage the recovery.conf. + +Default value: `$postgresql::params::manage_recovery_conf` + +##### `manage_postgresql_conf_perms` + +Data type: `Boolean` + +Whether to manage the postgresql conf file permissions. This means owner, +group and mode. Contents are not managed but should be managed through +postgresql::server::config_entry. + +Default value: `$postgresql::params::manage_postgresql_conf_perms` + +##### `manage_selinux` + +Data type: `Boolean` + +Specifies whether or not manage the conf file for selinux. + +Default value: `$postgresql::params::manage_selinux` + +##### `module_workdir` + +Data type: `Stdlib::Absolutepath` + +Working directory for the PostgreSQL module + +Default value: `$postgresql::params::module_workdir` + +##### `manage_datadir` + +Data type: `Boolean` + +Set to false if you have file{ $datadir: } already defined + +Default value: `$postgresql::params::manage_datadir` + +##### `manage_logdir` + +Data type: `Boolean` + +Set to false if you have file{ $logdir: } already defined + +Default value: `$postgresql::params::manage_logdir` + +##### `manage_xlogdir` + +Data type: `Boolean` + +Set to false if you have file{ $xlogdir: } already defined + +Default value: `$postgresql::params::manage_xlogdir` + +##### `password_encryption` + +Data type: `Postgresql::Pg_password_encryption` + +Specify the type of encryption set for the password. + +Default value: `$postgresql::params::password_encryption` + +##### `pg_hba_auth_password_encryption` + +Data type: `Optional[Postgresql::Pg_password_encryption]` + +Specify the type of encryption set for the password in pg_hba_conf, +this value is usefull if you want to start enforcing scram-sha-256, but give users transition time. + +Default value: `undef` + +##### `roles` + +Data type: `Hash[String, Hash]` + +Specifies a hash from which to generate postgresql::server::role resources. + +Default value: `{}` + +##### `config_entries` + +Data type: `Hash[String, Any]` + +Specifies a hash from which to generate postgresql::server::config_entry resources. + +Default value: `{}` + +##### `pg_hba_rules` + +Data type: `Postgresql::Pg_hba_rules` + +Specifies a hash from which to generate postgresql::server::pg_hba_rule resources. + +Default value: `{}` + +##### `backup_enable` + +Data type: `Boolean` + +Whether a backup job should be enabled. + +Default value: `$postgresql::params::backup_enable` + +##### `backup_options` + +Data type: `Hash` + +A hash of options that should be passed through to the backup provider. + +Default value: `{}` + +##### `backup_provider` + +Data type: `Enum['pg_dump']` + +Specifies the backup provider to use. + +Default value: `$postgresql::params::backup_provider` + +##### `extra_systemd_config` + +Data type: `Optional[String]` + +Adds extra config to systemd config file, can for instance be used to add extra openfiles. This can be a multi line string + +Default value: `$postgresql::params::extra_systemd_config` + +##### `auth_host` + +Data type: `Optional[String[1]]` + +auth method used by default for host authorization + +Default value: `undef` + +##### `auth_local` + +Data type: `Optional[String[1]]` + +auth method used by default for local authorization + +Default value: `undef` + +##### `lc_messages` + +Data type: `Optional[String[1]]` + +locale used for logging and system messages + +Default value: `undef` + +##### `username` + +Data type: `Optional[String[1]]` + +username of user running the postgres instance + +Default value: `$user` + +### `postgresql::server::contrib` + +Install the contrib postgresql packaging. + +#### Parameters + +The following parameters are available in the `postgresql::server::contrib` class: + +* [`package_name`](#-postgresql--server--contrib--package_name) +* [`package_ensure`](#-postgresql--server--contrib--package_ensure) + +##### `package_name` + +Data type: `Optional[String[1]]` + +The name of the PostgreSQL contrib package. + +Default value: `$postgresql::params::contrib_package_name` + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Ensure the contrib package is installed. + +Default value: `'present'` + +### `postgresql::server::plperl` + +This class installs the PL/Perl procedural language for postgresql. + +#### Parameters + +The following parameters are available in the `postgresql::server::plperl` class: + +* [`package_ensure`](#-postgresql--server--plperl--package_ensure) +* [`package_name`](#-postgresql--server--plperl--package_name) + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +The ensure parameter passed on to PostgreSQL PL/Perl package resource. + +Default value: `'present'` + +##### `package_name` + +Data type: `Optional[String[1]]` + +The name of the PostgreSQL PL/Perl package. + +Default value: `$postgresql::server::plperl_package_name` + +### `postgresql::server::plpython` + +This class installs the PL/Python procedural language for postgresql. + +#### Parameters + +The following parameters are available in the `postgresql::server::plpython` class: + +* [`package_ensure`](#-postgresql--server--plpython--package_ensure) +* [`package_name`](#-postgresql--server--plpython--package_name) + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Specifies whether the package is present. + +Default value: `'present'` + +##### `package_name` + +Data type: `Optional[String[1]]` + +Specifies the name of the postgresql PL/Python package. + +Default value: `$postgresql::server::plpython_package_name` + +### `postgresql::server::postgis` + +Install the postgis postgresql packaging. + +#### Parameters + +The following parameters are available in the `postgresql::server::postgis` class: + +* [`package_name`](#-postgresql--server--postgis--package_name) +* [`package_ensure`](#-postgresql--server--postgis--package_ensure) + +##### `package_name` + +Data type: `String` + +Sets the package name. + +Default value: `$postgresql::params::postgis_package_name` + +##### `package_ensure` + +Data type: `Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]` + +Specifies if the package is present or not. + +Default value: `'present'` + +## Defined types + +### `postgresql::server::config_entry` + +Manage a postgresql.conf entry. + +#### Parameters + +The following parameters are available in the `postgresql::server::config_entry` defined type: + +* [`ensure`](#-postgresql--server--config_entry--ensure) +* [`key`](#-postgresql--server--config_entry--key) +* [`value`](#-postgresql--server--config_entry--value) +* [`path`](#-postgresql--server--config_entry--path) +* [`comment`](#-postgresql--server--config_entry--comment) +* [`instance_name`](#-postgresql--server--config_entry--instance_name) + +##### `ensure` + +Data type: `Enum['present', 'absent']` + +Removes an entry if set to 'absent'. + +Default value: `'present'` + +##### `key` + +Data type: `String[1]` + +Defines the key/name for the setting. Defaults to $name + +Default value: `$name` + +##### `value` + +Data type: `Optional[Variant[String[1], Numeric, Array[String[1]]]]` + +Defines the value for the setting. + +Default value: `undef` + +##### `path` + +Data type: `Stdlib::Absolutepath` + +Path for postgresql.conf + +Default value: `$postgresql::server::postgresql_conf_path` + +##### `comment` + +Data type: `Optional[String[1]]` + +Defines the comment for the setting. The # is added by default. + +Default value: `undef` + +##### `instance_name` + +Data type: `String[1]` + +The name of the instance. + +Default value: `'main'` + +### `postgresql::server::database` + +Define for creating a database. + +#### Parameters + +The following parameters are available in the `postgresql::server::database` defined type: + +* [`comment`](#-postgresql--server--database--comment) +* [`dbname`](#-postgresql--server--database--dbname) +* [`owner`](#-postgresql--server--database--owner) +* [`tablespace`](#-postgresql--server--database--tablespace) +* [`template`](#-postgresql--server--database--template) +* [`encoding`](#-postgresql--server--database--encoding) +* [`locale`](#-postgresql--server--database--locale) +* [`istemplate`](#-postgresql--server--database--istemplate) +* [`instance`](#-postgresql--server--database--instance) +* [`connect_settings`](#-postgresql--server--database--connect_settings) +* [`psql_path`](#-postgresql--server--database--psql_path) +* [`default_db`](#-postgresql--server--database--default_db) +* [`user`](#-postgresql--server--database--user) +* [`group`](#-postgresql--server--database--group) +* [`port`](#-postgresql--server--database--port) + +##### `comment` + +Data type: `Optional[String[1]]` + +Sets a comment on the database. + +Default value: `undef` + +##### `dbname` + +Data type: `String[1]` + +Sets the name of the database. + +Default value: `$title` + +##### `owner` + +Data type: `Optional[String[1]]` + +Sets name of the database owner. + +Default value: `undef` + +##### `tablespace` + +Data type: `Optional[String[1]]` + +Sets tablespace for where to create this database. + +Default value: `undef` + +##### `template` + +Data type: `String[1]` + +Specifies the name of the template database from which to build this database. Default value: 'template0'. + +Default value: `'template0'` + +##### `encoding` + +Data type: `Optional[String[1]]` + +Overrides the character set during creation of the database. + +Default value: `$postgresql::server::encoding` + +##### `locale` + +Data type: `Optional[String[1]]` + +Overrides the locale during creation of the database. + +Default value: `$postgresql::server::locale` + +##### `istemplate` + +Data type: `Boolean` + +Defines the database as a template if set to true. + +Default value: `false` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `$postgresql::server::default_connect_settings` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to the psql command. + +Default value: `$postgresql::server::psql_path` + +##### `default_db` + +Data type: `String[1]` + +Specifies the name of the default database to connect with. On most systems this is 'postgres'. + +Default value: `$postgresql::server::default_database` + +##### `user` + +Data type: `String[1]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `$postgresql::server::user` + +##### `group` + +Data type: `String[1]` + +Overrides the default postgres user group to be used for related files in the file system. + +Default value: `$postgresql::server::group` + +##### `port` + +Data type: `Stdlib::Port` + +Specifies the port for the PostgreSQL server to listen on. + +Default value: `$postgresql::server::port` + +### `postgresql::server::database_grant` + +Manage a database grant. + +#### Parameters + +The following parameters are available in the `postgresql::server::database_grant` defined type: + +* [`privilege`](#-postgresql--server--database_grant--privilege) +* [`db`](#-postgresql--server--database_grant--db) +* [`role`](#-postgresql--server--database_grant--role) +* [`ensure`](#-postgresql--server--database_grant--ensure) +* [`psql_db`](#-postgresql--server--database_grant--psql_db) +* [`psql_user`](#-postgresql--server--database_grant--psql_user) +* [`psql_group`](#-postgresql--server--database_grant--psql_group) +* [`connect_settings`](#-postgresql--server--database_grant--connect_settings) +* [`port`](#-postgresql--server--database_grant--port) +* [`instance`](#-postgresql--server--database_grant--instance) + +##### `privilege` + +Data type: `Enum['ALL', 'CREATE', 'CONNECT', 'TEMPORARY', 'TEMP', 'all', 'create', 'connect', 'temporary', 'temp']` + +Specifies comma-separated list of privileges to grant. Valid options: 'ALL', 'CREATE', 'CONNECT', 'TEMPORARY', 'TEMP'. + +##### `db` + +Data type: `String[1]` + +Specifies the database to which you are granting access. + +##### `role` + +Data type: `String[1]` + +Specifies the role or user whom you are granting access to. + +##### `ensure` + +Data type: `Optional[Enum['present', 'absent']]` + +Specifies whether to grant or revoke the privilege. Revoke or 'absent' works only in PostgreSQL version 9.1.24 or later. + +Default value: `undef` + +##### `psql_db` + +Data type: `Optional[String[1]]` + +Defines the database to execute the grant against. This should not ordinarily be changed from the default + +Default value: `undef` + +##### `psql_user` + +Data type: `String[1]` + +Specifies the OS user for running psql. Default value: The default user for the module, usually 'postgres'. + +Default value: `$postgresql::server::user` + +##### `psql_group` + +Data type: `String[1]` + +Overrides the default postgres user group to be used for related files in the file system. + +Default value: `$postgresql::server::group` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `$postgresql::server::default_connect_settings` + +##### `port` + +Data type: `Stdlib::Port` + +Port to use when connecting. + +Default value: `$postgresql::server::port` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +### `postgresql::server::db` + +Define for conveniently creating a role, database and assigning the correct permissions. + +#### Parameters + +The following parameters are available in the `postgresql::server::db` defined type: + +* [`user`](#-postgresql--server--db--user) +* [`password`](#-postgresql--server--db--password) +* [`comment`](#-postgresql--server--db--comment) +* [`dbname`](#-postgresql--server--db--dbname) +* [`encoding`](#-postgresql--server--db--encoding) +* [`locale`](#-postgresql--server--db--locale) +* [`grant`](#-postgresql--server--db--grant) +* [`tablespace`](#-postgresql--server--db--tablespace) +* [`template`](#-postgresql--server--db--template) +* [`istemplate`](#-postgresql--server--db--istemplate) +* [`owner`](#-postgresql--server--db--owner) +* [`port`](#-postgresql--server--db--port) +* [`psql_user`](#-postgresql--server--db--psql_user) +* [`psql_group`](#-postgresql--server--db--psql_group) +* [`instance`](#-postgresql--server--db--instance) + +##### `user` + +Data type: `String[1]` + +User to assign access to the database upon creation (will be created if not defined elsewhere). Mandatory. + +##### `password` + +Data type: `Optional[Variant[String, Sensitive[String]]]` + +Sets the password for the created user (if a user is created). + +Default value: `undef` + +##### `comment` + +Data type: `Optional[String[1]]` + +Defines a comment to be stored about the database using the PostgreSQL COMMENT command. + +Default value: `undef` + +##### `dbname` + +Data type: `String[1]` + +Sets the name of the database to be created. + +Default value: `$title` + +##### `encoding` + +Data type: `Optional[String[1]]` + +Overrides the character set during creation of the database. + +Default value: `$postgresql::server::encoding` + +##### `locale` + +Data type: `Optional[String[1]]` + +Overrides the locale during creation of the database. + +Default value: `$postgresql::server::locale` + +##### `grant` + +Data type: `Variant[String[1], Array[String[1]]]` + +Specifies the permissions to grant during creation. Default value: 'ALL'. + +Default value: `'ALL'` + +##### `tablespace` + +Data type: `Optional[String[1]]` + +Defines the name of the tablespace to allocate the created database to. + +Default value: `undef` + +##### `template` + +Data type: `String[1]` + +Specifies the name of the template database from which to build this database. Defaults value: template0. + +Default value: `'template0'` + +##### `istemplate` + +Data type: `Boolean` + +Specifies that the database is a template, if set to true. + +Default value: `false` + +##### `owner` + +Data type: `Optional[String[1]]` + +Sets a user as the owner of the database. + +Default value: `undef` + +##### `port` + +Data type: `Optional[Stdlib::Port]` + +Specifies the port where the PostgreSQL server is listening on. + +Default value: `undef` + +##### `psql_user` + +Data type: `String[1]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `$postgresql::server::user` + +##### `psql_group` + +Data type: `String[1]` + +Overrides the default PostgreSQL user group to be used for related files in the file system. + +Default value: `$postgresql::server::group` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +### `postgresql::server::default_privileges` + +Manage a database defaults privileges. Only works with PostgreSQL version 9.6 and above. + +#### Parameters + +The following parameters are available in the `postgresql::server::default_privileges` defined type: + +* [`target_role`](#-postgresql--server--default_privileges--target_role) +* [`ensure`](#-postgresql--server--default_privileges--ensure) +* [`role`](#-postgresql--server--default_privileges--role) +* [`db`](#-postgresql--server--default_privileges--db) +* [`object_type`](#-postgresql--server--default_privileges--object_type) +* [`privilege`](#-postgresql--server--default_privileges--privilege) +* [`schema`](#-postgresql--server--default_privileges--schema) +* [`psql_db`](#-postgresql--server--default_privileges--psql_db) +* [`psql_user`](#-postgresql--server--default_privileges--psql_user) +* [`psql_path`](#-postgresql--server--default_privileges--psql_path) +* [`port`](#-postgresql--server--default_privileges--port) +* [`connect_settings`](#-postgresql--server--default_privileges--connect_settings) +* [`instance`](#-postgresql--server--default_privileges--instance) +* [`group`](#-postgresql--server--default_privileges--group) + +##### `target_role` + +Data type: `Optional[String]` + +Target role whose created objects will receive the default privileges. Defaults to the current user. + +Default value: `undef` + +##### `ensure` + +Data type: `Enum['present', 'absent']` + +Specifies whether to grant or revoke the privilege. + +Default value: `'present'` + +##### `role` + +Data type: `String` + +Specifies the role or user whom you are granting access to. + +##### `db` + +Data type: `String` + +Specifies the database to which you are granting access. + +##### `object_type` + +Data type: + +```puppet +Pattern[ + /(?i:^FUNCTIONS$)/, + /(?i:^ROUTINES$)/, + /(?i:^SEQUENCES$)/, + /(?i:^TABLES$)/, + /(?i:^TYPES$)/, + /(?i:^SCHEMAS$)/ + ] +``` + +Specify target object type: 'FUNCTIONS', 'ROUTINES', 'SEQUENCES', 'TABLES', 'TYPES'. + +##### `privilege` + +Data type: `String` + +Specifies comma-separated list of privileges to grant. Valid options: depends on object type. + +##### `schema` + +Data type: `String` + +Target schema. Defaults to 'public'. Can be set to '' to apply to all schemas. + +Default value: `'public'` + +##### `psql_db` + +Data type: `String` + +Defines the database to execute the grant against. This should not ordinarily be changed from the default. + +Default value: `$postgresql::server::default_database` + +##### `psql_user` + +Data type: `String` + +Specifies the OS user for running psql. Default value: The default user for the module, usually 'postgres'. + +Default value: `$postgresql::server::user` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the OS user for running psql. Default value: The default user for the module, usually 'postgres'. + +Default value: `$postgresql::server::psql_path` + +##### `port` + +Data type: `Stdlib::Port` + +Specifies the port to access the server. Default value: The default user for the module, usually '5432'. + +Default value: `$postgresql::server::port` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `$postgresql::server::default_connect_settings` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +##### `group` + +Data type: `String` + +Specifies the user group to which the privileges will be granted. + +Default value: `$postgresql::server::group` + +### `postgresql::server::extension` + +Activate an extension on a postgresql database. + +#### Parameters + +The following parameters are available in the `postgresql::server::extension` defined type: + +* [`database`](#-postgresql--server--extension--database) +* [`extension`](#-postgresql--server--extension--extension) +* [`schema`](#-postgresql--server--extension--schema) +* [`version`](#-postgresql--server--extension--version) +* [`ensure`](#-postgresql--server--extension--ensure) +* [`package_name`](#-postgresql--server--extension--package_name) +* [`package_ensure`](#-postgresql--server--extension--package_ensure) +* [`port`](#-postgresql--server--extension--port) +* [`connect_settings`](#-postgresql--server--extension--connect_settings) +* [`database_resource_name`](#-postgresql--server--extension--database_resource_name) +* [`instance`](#-postgresql--server--extension--instance) +* [`psql_path`](#-postgresql--server--extension--psql_path) +* [`user`](#-postgresql--server--extension--user) +* [`group`](#-postgresql--server--extension--group) + +##### `database` + +Data type: `String[1]` + +Specifies the database on which to activate the extension. + +##### `extension` + +Data type: `String[1]` + +Specifies the extension to activate. If left blank, uses the name of the resource. + +Default value: `$name` + +##### `schema` + +Data type: `Optional[String[1]]` + +Specifies the schema on which to activate the extension. + +Default value: `undef` + +##### `version` + +Data type: `Optional[String[1]]` + +Specifies the version of the extension which the database uses. When an extension package is updated, this does not automatically +change the effective version in each database. +This needs be updated using the PostgreSQL-specific SQL ALTER EXTENSION... +version may be set to latest, in which case the SQL ALTER EXTENSION "extension" UPDATE is applied to this database (only). +version may be set to a specific version, in which case the extension is updated using ALTER EXTENSION "extension" UPDATE TO 'version' +eg. If extension is set to postgis and version is set to 2.3.3, this will apply the SQL ALTER EXTENSION "postgis" UPDATE TO '2.3.3' to +this database only. +version may be omitted, in which case no ALTER EXTENSION... SQL is applied, and the version will be left unchanged. + +Default value: `undef` + +##### `ensure` + +Data type: `Enum['present', 'absent']` + +Specifies whether to activate or deactivate the extension. Valid options: 'present' or 'absent'. + +Default value: `'present'` + +##### `package_name` + +Data type: `Optional[String[1]]` + +Specifies a package to install prior to activating the extension. + +Default value: `undef` + +##### `package_ensure` + +Data type: `Optional[Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]]` + +Overrides default package deletion behavior. By default, the package specified with package_name is installed when the extension is +activated and removed when the extension is deactivated. To override this behavior, set the ensure value for the package. + +Default value: `undef` + +##### `port` + +Data type: `Stdlib::Port` + +Port to use when connecting. + +Default value: `postgresql::default('port')` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `postgresql::default('default_connect_settings')` + +##### `database_resource_name` + +Data type: `String[1]` + +Specifies the resource name of the DB being managed. Defaults to the parameter $database, if left blank. + +Default value: `$database` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to the psql command. + +Default value: `postgresql::default('psql_path')` + +##### `user` + +Data type: `String[1]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `postgresql::default('user')` + +##### `group` + +Data type: `String[1]` + +Overrides the default postgres user group to be used for related files in the file system. + +Default value: `postgresql::default('group')` + +### `postgresql::server::grant` + +Define for granting permissions to roles. + +#### Parameters + +The following parameters are available in the `postgresql::server::grant` defined type: + +* [`role`](#-postgresql--server--grant--role) +* [`db`](#-postgresql--server--grant--db) +* [`privilege`](#-postgresql--server--grant--privilege) +* [`object_type`](#-postgresql--server--grant--object_type) +* [`object_name`](#-postgresql--server--grant--object_name) +* [`object_arguments`](#-postgresql--server--grant--object_arguments) +* [`psql_db`](#-postgresql--server--grant--psql_db) +* [`psql_user`](#-postgresql--server--grant--psql_user) +* [`port`](#-postgresql--server--grant--port) +* [`onlyif_exists`](#-postgresql--server--grant--onlyif_exists) +* [`connect_settings`](#-postgresql--server--grant--connect_settings) +* [`ensure`](#-postgresql--server--grant--ensure) +* [`group`](#-postgresql--server--grant--group) +* [`psql_path`](#-postgresql--server--grant--psql_path) +* [`instance`](#-postgresql--server--grant--instance) + +##### `role` + +Data type: `String` + +Specifies the role or user whom you are granting access to. + +##### `db` + +Data type: `String` + +Specifies the database to which you are granting access. + +##### `privilege` + +Data type: `String` + +Specifies the privilege to grant. Valid options: 'ALL', 'ALL PRIVILEGES' or 'object_type' dependent string. + +Default value: `''` + +##### `object_type` + +Data type: + +```puppet +Pattern[#/(?i:^COLUMN$)/, + /(?i:^ALL SEQUENCES IN SCHEMA$)/, + /(?i:^ALL TABLES IN SCHEMA$)/, + /(?i:^DATABASE$)/, + #/(?i:^FOREIGN DATA WRAPPER$)/, + #/(?i:^FOREIGN SERVER$)/, + /(?i:^FUNCTION$)/, + /(?i:^LANGUAGE$)/, + #/(?i:^PROCEDURAL LANGUAGE$)/, + /(?i:^TABLE$)/, + #/(?i:^TABLESPACE$)/, + /(?i:^SCHEMA$)/, + /(?i:^SEQUENCE$)/ + #/(?i:^VIEW$)/ + ] +``` + +Specifies the type of object to which you are granting privileges. +Valid options: 'DATABASE', 'SCHEMA', 'SEQUENCE', 'ALL SEQUENCES IN SCHEMA', 'TABLE' or 'ALL TABLES IN SCHEMA'. + +Default value: `'database'` + +##### `object_name` + +Data type: `Optional[Variant[Array[String,2,2],String[1]]]` + +Specifies name of object_type to which to grant access, can be either a string or a two element array. +String: 'object_name' Array: ['schema_name', 'object_name'] + +Default value: `undef` + +##### `object_arguments` + +Data type: `Array[String[1],0]` + +Specifies any arguments to be passed alongisde the access grant. + +Default value: `[]` + +##### `psql_db` + +Data type: `String` + +Specifies the database to execute the grant against. This should not ordinarily be changed from the default + +Default value: `$postgresql::server::default_database` + +##### `psql_user` + +Data type: `String` + +Sets the OS user to run psql. + +Default value: `$postgresql::server::user` + +##### `port` + +Data type: `Stdlib::Port` + +Port to use when connecting. + +Default value: `$postgresql::server::port` + +##### `onlyif_exists` + +Data type: `Boolean` + +Create grant only if doesn't exist + +Default value: `false` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `$postgresql::server::default_connect_settings` + +##### `ensure` + +Data type: `Enum['present', 'absent']` + +Specifies whether to grant or revoke the privilege. Default is to grant the privilege. Valid values: 'present', 'absent'. + +Default value: `'present'` + +##### `group` + +Data type: `String` + +Sets the OS group to run psql + +Default value: `$postgresql::server::group` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Sets the path to psql command + +Default value: `$postgresql::server::psql_path` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +### `postgresql::server::grant_role` + +Define for granting membership to a role. + +#### Parameters + +The following parameters are available in the `postgresql::server::grant_role` defined type: + +* [`group`](#-postgresql--server--grant_role--group) +* [`role`](#-postgresql--server--grant_role--role) +* [`ensure`](#-postgresql--server--grant_role--ensure) +* [`psql_db`](#-postgresql--server--grant_role--psql_db) +* [`psql_user`](#-postgresql--server--grant_role--psql_user) +* [`port`](#-postgresql--server--grant_role--port) +* [`connect_settings`](#-postgresql--server--grant_role--connect_settings) +* [`instance`](#-postgresql--server--grant_role--instance) + +##### `group` + +Data type: `String[1]` + +Specifies the group role to which you are assigning a role. + +##### `role` + +Data type: `String[1]` + +Specifies the role you want to assign to a group. If left blank, uses the name of the resource. + +Default value: `$name` + +##### `ensure` + +Data type: `Enum['present', 'absent']` + +Specifies whether to grant or revoke the membership. Valid options: 'present' or 'absent'. + +Default value: `'present'` + +##### `psql_db` + +Data type: `String[1]` + +Specifies the database to execute the grant against. This should not ordinarily be changed from the default + +Default value: `$postgresql::server::default_database` + +##### `psql_user` + +Data type: `String[1]` + +Sets the OS user to run psql. + +Default value: `$postgresql::server::user` + +##### `port` + +Data type: `Stdlib::Port` + +Port to use when connecting. + +Default value: `$postgresql::server::port` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `$postgresql::server::default_connect_settings` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +### `postgresql::server::instance::config` + +Manages the config for a postgresql::server instance + +#### Parameters + +The following parameters are available in the `postgresql::server::instance::config` defined type: + +* [`ip_mask_deny_postgres_user`](#-postgresql--server--instance--config--ip_mask_deny_postgres_user) +* [`ip_mask_allow_all_users`](#-postgresql--server--instance--config--ip_mask_allow_all_users) +* [`listen_addresses`](#-postgresql--server--instance--config--listen_addresses) +* [`port`](#-postgresql--server--instance--config--port) +* [`ipv4acls`](#-postgresql--server--instance--config--ipv4acls) +* [`ipv6acls`](#-postgresql--server--instance--config--ipv6acls) +* [`pg_hba_conf_path`](#-postgresql--server--instance--config--pg_hba_conf_path) +* [`pg_ident_conf_path`](#-postgresql--server--instance--config--pg_ident_conf_path) +* [`postgresql_conf_path`](#-postgresql--server--instance--config--postgresql_conf_path) +* [`postgresql_conf_mode`](#-postgresql--server--instance--config--postgresql_conf_mode) +* [`recovery_conf_path`](#-postgresql--server--instance--config--recovery_conf_path) +* [`pg_hba_conf_defaults`](#-postgresql--server--instance--config--pg_hba_conf_defaults) +* [`user`](#-postgresql--server--instance--config--user) +* [`group`](#-postgresql--server--instance--config--group) +* [`version`](#-postgresql--server--instance--config--version) +* [`manage_pg_hba_conf`](#-postgresql--server--instance--config--manage_pg_hba_conf) +* [`manage_pg_ident_conf`](#-postgresql--server--instance--config--manage_pg_ident_conf) +* [`manage_recovery_conf`](#-postgresql--server--instance--config--manage_recovery_conf) +* [`manage_postgresql_conf_perms`](#-postgresql--server--instance--config--manage_postgresql_conf_perms) +* [`datadir`](#-postgresql--server--instance--config--datadir) +* [`logdir`](#-postgresql--server--instance--config--logdir) +* [`service_name`](#-postgresql--server--instance--config--service_name) +* [`service_enable`](#-postgresql--server--instance--config--service_enable) +* [`log_line_prefix`](#-postgresql--server--instance--config--log_line_prefix) +* [`timezone`](#-postgresql--server--instance--config--timezone) +* [`password_encryption`](#-postgresql--server--instance--config--password_encryption) +* [`pg_hba_auth_password_encryption`](#-postgresql--server--instance--config--pg_hba_auth_password_encryption) +* [`extra_systemd_config`](#-postgresql--server--instance--config--extra_systemd_config) +* [`manage_selinux`](#-postgresql--server--instance--config--manage_selinux) + +##### `ip_mask_deny_postgres_user` + +Data type: `String[1]` + +Specifies the IP mask from which remote connections should be denied for the postgres superuser. +Default value: '0.0.0.0/0', which denies any remote connection. + +Default value: `$postgresql::server::ip_mask_deny_postgres_user` + +##### `ip_mask_allow_all_users` + +Data type: `String[1]` + +Overrides PostgreSQL defaults for remote connections. By default, PostgreSQL does not allow database user accounts to connect via TCP +from remote machines. If you'd like to allow this, you can override this setting. +Set to '0.0.0.0/0' to allow database users to connect from any remote machine, or '192.168.0.0/1' to allow connections from any machine +on your local '192.168' subnet. +Default value: '127.0.0.1/32'. + +Default value: `$postgresql::server::ip_mask_allow_all_users` + +##### `listen_addresses` + +Data type: `Optional[Variant[String[1], Array[String[1]]]]` + +Address list on which the PostgreSQL service will listen + +Default value: `$postgresql::server::listen_addresses` + +##### `port` + +Data type: `Stdlib::Port` + +Specifies the port for the PostgreSQL server to listen on. +Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +changing the port causes the server to come to a full stop before being able to make the change. +Default value: 5432. Meaning the Postgres server listens on TCP port 5432. + +Default value: `$postgresql::server::port` + +##### `ipv4acls` + +Data type: `Array[String[1]]` + +Lists strings for access control for connection method, users, databases, IPv4 addresses. + +Default value: `$postgresql::server::ipv4acls` + +##### `ipv6acls` + +Data type: `Array[String[1]]` + +Lists strings for access control for connection method, users, databases, IPv6 addresses. + +Default value: `$postgresql::server::ipv6acls` + +##### `pg_hba_conf_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to your pg_hba.conf file. + +Default value: `$postgresql::server::pg_hba_conf_path` + +##### `pg_ident_conf_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to your pg_ident.conf file. + +Default value: `$postgresql::server::pg_ident_conf_path` + +##### `postgresql_conf_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to your postgresql.conf file. + +Default value: `$postgresql::server::postgresql_conf_path` + +##### `postgresql_conf_mode` + +Data type: `Optional[Stdlib::Filemode]` + +Sets the mode of your postgresql.conf file. Only relevant if manage_postgresql_conf_perms is true. + +Default value: `$postgresql::server::postgresql_conf_mode` + +##### `recovery_conf_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to your recovery.conf file. + +Default value: `$postgresql::server::recovery_conf_path` + +##### `pg_hba_conf_defaults` + +Data type: `Boolean` + +If false, disables the defaults supplied with the module for pg_hba.conf. This is useful if you disagree with the defaults and wish to +override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform +basic psql operations for example. + +Default value: `$postgresql::server::pg_hba_conf_defaults` + +##### `user` + +Data type: `String[1]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `$postgresql::server::user` + +##### `group` + +Data type: `String[1]` + +Overrides the default postgres user group to be used for related files in the file system. + +Default value: `$postgresql::server::group` + +##### `version` + +Data type: `Optional[String[1]]` + +Sets PostgreSQL version + +Default value: `$postgresql::server::_version` + +##### `manage_pg_hba_conf` + +Data type: `Boolean` + +Boolean. Whether to manage the pg_hba.conf. + +Default value: `$postgresql::server::manage_pg_hba_conf` + +##### `manage_pg_ident_conf` + +Data type: `Boolean` + +Boolean. Overwrites the pg_ident.conf file. + +Default value: `$postgresql::server::manage_pg_ident_conf` + +##### `manage_recovery_conf` + +Data type: `Boolean` + +Boolean. Specifies whether or not manage the recovery.conf. + +Default value: `$postgresql::server::manage_recovery_conf` + +##### `manage_postgresql_conf_perms` + +Data type: `Boolean` + +Whether to manage the postgresql conf file permissions. This means owner, +group and mode. Contents are not managed but should be managed through +postgresql::server::config_entry. + +Default value: `$postgresql::server::manage_postgresql_conf_perms` + +##### `datadir` + +Data type: `Stdlib::Absolutepath` + +PostgreSQL data directory + +Default value: `$postgresql::server::datadir` + +##### `logdir` + +Data type: `Optional[Stdlib::Absolutepath]` + +PostgreSQL log directory + +Default value: `$postgresql::server::logdir` + +##### `service_name` + +Data type: `String[1]` + +Overrides the default PostgreSQL service name. + +Default value: `$postgresql::server::service_name` + +##### `service_enable` + +Data type: `Boolean` + +Enable the PostgreSQL service + +Default value: `$postgresql::server::service_enable` + +##### `log_line_prefix` + +Data type: `Optional[String[1]]` + +PostgreSQL log line prefix + +Default value: `$postgresql::server::log_line_prefix` + +##### `timezone` + +Data type: `Optional[String[1]]` + +Set timezone for the PostgreSQL instance + +Default value: `$postgresql::server::timezone` + +##### `password_encryption` + +Data type: `Postgresql::Pg_password_encryption` + +Specify the type of encryption set for the password. + +Default value: `$postgresql::server::password_encryption` + +##### `pg_hba_auth_password_encryption` + +Data type: `Optional[Postgresql::Pg_password_encryption]` + +Specify the type of encryption set for the password in pg_hba_conf, +this value is usefull if you want to start enforcing scram-sha-256, but give users transition time. + +Default value: `$postgresql::server::pg_hba_auth_password_encryption` + +##### `extra_systemd_config` + +Data type: `Optional[String]` + +Adds extra config to systemd config file, can for instance be used to add extra openfiles. This can be a multi line string + +Default value: `$postgresql::server::extra_systemd_config` + +##### `manage_selinux` + +Data type: `Boolean` + +Specifies whether or not manage the conf file for selinux. + +Default value: `$postgresql::server::manage_selinux` + +### `postgresql::server::instance::initdb` + +Manages initdb feature for a postgresql::server instance + +#### Parameters + +The following parameters are available in the `postgresql::server::instance::initdb` defined type: + +* [`auth_host`](#-postgresql--server--instance--initdb--auth_host) +* [`auth_local`](#-postgresql--server--instance--initdb--auth_local) +* [`data_checksums`](#-postgresql--server--instance--initdb--data_checksums) +* [`datadir`](#-postgresql--server--instance--initdb--datadir) +* [`encoding`](#-postgresql--server--instance--initdb--encoding) +* [`group`](#-postgresql--server--instance--initdb--group) +* [`initdb_path`](#-postgresql--server--instance--initdb--initdb_path) +* [`lc_messages`](#-postgresql--server--instance--initdb--lc_messages) +* [`locale`](#-postgresql--server--instance--initdb--locale) +* [`logdir`](#-postgresql--server--instance--initdb--logdir) +* [`manage_datadir`](#-postgresql--server--instance--initdb--manage_datadir) +* [`manage_logdir`](#-postgresql--server--instance--initdb--manage_logdir) +* [`manage_xlogdir`](#-postgresql--server--instance--initdb--manage_xlogdir) +* [`module_workdir`](#-postgresql--server--instance--initdb--module_workdir) +* [`needs_initdb`](#-postgresql--server--instance--initdb--needs_initdb) +* [`user`](#-postgresql--server--instance--initdb--user) +* [`username`](#-postgresql--server--instance--initdb--username) +* [`xlogdir`](#-postgresql--server--instance--initdb--xlogdir) +* [`port`](#-postgresql--server--instance--initdb--port) +* [`psql_path`](#-postgresql--server--instance--initdb--psql_path) + +##### `auth_host` + +Data type: `Optional[String[1]]` + +auth method used by default for host authorization + +Default value: `$postgresql::server::auth_host` + +##### `auth_local` + +Data type: `Optional[String[1]]` + +auth method used by default for local authorization + +Default value: `$postgresql::server::auth_local` + +##### `data_checksums` + +Data type: `Optional[Boolean]` + +Boolean. Use checksums on data pages to help detect corruption by the I/O system that would otherwise be silent. + +Default value: `$postgresql::server::data_checksums` + +##### `datadir` + +Data type: `Stdlib::Absolutepath` + +PostgreSQL data directory + +Default value: `$postgresql::server::datadir` + +##### `encoding` + +Data type: `Optional[String[1]]` + +Sets the default encoding for all databases created with this module. +On certain operating systems this is also used during the template1 initialization, +so it becomes a default outside of the module as well. + +Default value: `$postgresql::server::encoding` + +##### `group` + +Data type: `String[1]` + +Overrides the default postgres user group to be used for related files in the file system. + +Default value: `$postgresql::server::group` + +##### `initdb_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to the initdb command. + +Default value: `$postgresql::server::initdb_path` + +##### `lc_messages` + +Data type: `Optional[String[1]]` + +locale used for logging and system messages + +Default value: `$postgresql::server::lc_messages` + +##### `locale` + +Data type: `Optional[String[1]]` + +Sets the default database locale for all databases created with this module. +On certain operating systems this is used during the template1 initialization as well, so it becomes a default outside of the module. +Warning: This option is used during initialization by initdb, and cannot be changed later. +If set, checksums are calculated for all objects, in all databases. + +Default value: `$postgresql::server::locale` + +##### `logdir` + +Data type: `Optional[Stdlib::Absolutepath]` + +PostgreSQL log directory + +Default value: `$postgresql::server::logdir` + +##### `manage_datadir` + +Data type: `Boolean` + +Set to false if you have file{ $datadir: } already defined + +Default value: `$postgresql::server::manage_datadir` + +##### `manage_logdir` + +Data type: `Boolean` + +Set to false if you have file{ $logdir: } already defined + +Default value: `$postgresql::server::manage_logdir` + +##### `manage_xlogdir` + +Data type: `Boolean` + +Set to false if you have file{ $xlogdir: } already defined + +Default value: `$postgresql::server::manage_xlogdir` + +##### `module_workdir` + +Data type: `Stdlib::Absolutepath` + +Working directory for the PostgreSQL module + +Default value: `$postgresql::server::module_workdir` + +##### `needs_initdb` + +Data type: `Boolean` + +Explicitly calls the initdb operation after server package is installed +and before the PostgreSQL service is started. + +Default value: `$postgresql::server::needs_initdb` + +##### `user` + +Data type: `String[1]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `$postgresql::server::user` + +##### `username` + +Data type: `Optional[String[1]]` + +username of user running the postgres instance + +Default value: `$postgresql::server::username` + +##### `xlogdir` + +Data type: `Optional[Stdlib::Absolutepath]` + +PostgreSQL xlog/WAL directory + +Default value: `$postgresql::server::xlogdir` + +##### `port` + +Data type: `Stdlib::Port` + +Specifies the port for the PostgreSQL server to listen on. +Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +changing the port causes the server to come to a full stop before being able to make the change. + +Default value: `$postgresql::server::port` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to the psql command. + +Default value: `$postgresql::server::psql_path` + +### `postgresql::server::instance::late_initdb` + +Manage the default encoding when database initialization is managed by the package + +#### Parameters + +The following parameters are available in the `postgresql::server::instance::late_initdb` defined type: + +* [`encoding`](#-postgresql--server--instance--late_initdb--encoding) +* [`user`](#-postgresql--server--instance--late_initdb--user) +* [`group`](#-postgresql--server--instance--late_initdb--group) +* [`psql_path`](#-postgresql--server--instance--late_initdb--psql_path) +* [`port`](#-postgresql--server--instance--late_initdb--port) +* [`module_workdir`](#-postgresql--server--instance--late_initdb--module_workdir) + +##### `encoding` + +Data type: `Optional[String[1]]` + +Sets the default encoding for all databases created with this module. On certain operating systems this is also used during the +template1 initialization, so it becomes a default outside of the module as well. + +Default value: `$postgresql::server::encoding` + +##### `user` + +Data type: `String[1]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `$postgresql::server::user` + +##### `group` + +Data type: `String[1]` + +Overrides the default postgres user group to be used for related files in the file system. + +Default value: `$postgresql::server::group` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to the psql command. + +Default value: `$postgresql::server::psql_path` + +##### `port` + +Data type: `Stdlib::Port` + +Specifies the port for the PostgreSQL server to listen on. +Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +changing the port causes the server to come to a full stop before being able to make the change. + +Default value: `$postgresql::server::port` + +##### `module_workdir` + +Data type: `Stdlib::Absolutepath` + +Working directory for the PostgreSQL module + +Default value: `$postgresql::server::module_workdir` + +### `postgresql::server::instance::passwd` + +Overrides the default PostgreSQL superuser + +#### Parameters + +The following parameters are available in the `postgresql::server::instance::passwd` defined type: + +* [`user`](#-postgresql--server--instance--passwd--user) +* [`group`](#-postgresql--server--instance--passwd--group) +* [`psql_path`](#-postgresql--server--instance--passwd--psql_path) +* [`port`](#-postgresql--server--instance--passwd--port) +* [`database`](#-postgresql--server--instance--passwd--database) +* [`module_workdir`](#-postgresql--server--instance--passwd--module_workdir) +* [`postgres_password`](#-postgresql--server--instance--passwd--postgres_password) + +##### `user` + +Data type: `String[1]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `$postgresql::server::user` + +##### `group` + +Data type: `String[1]` + +Overrides the default postgres user group to be used for related files in the file system. +Default value: 5432. Meaning the Postgres server listens on TCP port 5432. + +Default value: `$postgresql::server::group` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to the psql command. + +Default value: `$postgresql::server::psql_path` + +##### `port` + +Data type: `Stdlib::Port` + +Specifies the port for the PostgreSQL server to listen on. +Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +changing the port causes the server to come to a full stop before being able to make the change. + +Default value: `$postgresql::server::port` + +##### `database` + +Data type: `String[1]` + +Specifies the name of the database to connect with. On most systems this is 'postgres'. + +Default value: `$postgresql::server::default_database` + +##### `module_workdir` + +Data type: `Stdlib::Absolutepath` + +Working directory for the PostgreSQL module + +Default value: `$postgresql::server::module_workdir` + +##### `postgres_password` + +Data type: `Optional[Variant[String[1], Sensitive[String[1]], Integer]]` + +Sets the password for the postgres user to your specified value. By default, this setting uses the superuser account in the Postgres +database, with a user called postgres and no password. + +Default value: `$postgresql::server::postgres_password` + +### `postgresql::server::instance::reload` + +Overrides the default reload or status command for your PostgreSQL service + +#### Parameters + +The following parameters are available in the `postgresql::server::instance::reload` defined type: + +* [`service_reload`](#-postgresql--server--instance--reload--service_reload) +* [`service_status`](#-postgresql--server--instance--reload--service_status) + +##### `service_reload` + +Data type: `String[1]` + +Overrides the default reload command for your PostgreSQL service. + +Default value: `$postgresql::server::service_reload` + +##### `service_status` + +Data type: `String[1]` + +Overrides the default status check command for your PostgreSQL service. + +Default value: `$postgresql::server::service_status` + +### `postgresql::server::instance::service` + +Manages the service for the postgres main instance (default) or additional instances + +#### Parameters + +The following parameters are available in the `postgresql::server::instance::service` defined type: + +* [`service_ensure`](#-postgresql--server--instance--service--service_ensure) +* [`service_enable`](#-postgresql--server--instance--service--service_enable) +* [`service_manage`](#-postgresql--server--instance--service--service_manage) +* [`service_name`](#-postgresql--server--instance--service--service_name) +* [`service_provider`](#-postgresql--server--instance--service--service_provider) +* [`service_status`](#-postgresql--server--instance--service--service_status) +* [`user`](#-postgresql--server--instance--service--user) +* [`port`](#-postgresql--server--instance--service--port) +* [`default_database`](#-postgresql--server--instance--service--default_database) +* [`psql_path`](#-postgresql--server--instance--service--psql_path) +* [`connect_settings`](#-postgresql--server--instance--service--connect_settings) + +##### `service_ensure` + +Data type: `Variant[Enum['running', 'stopped'], Boolean]` + +Ensure service is installed + +Default value: `$postgresql::server::service_ensure` + +##### `service_enable` + +Data type: `Boolean` + +Enable the PostgreSQL service + +Default value: `$postgresql::server::service_enable` + +##### `service_manage` + +Data type: `Boolean` + +Defines whether or not Puppet should manage the service. + +Default value: `$postgresql::server::service_manage` + +##### `service_name` + +Data type: `String[1]` + +Overrides the default PostgreSQL service name. + +Default value: `$postgresql::server::service_name` + +##### `service_provider` + +Data type: `Optional[String[1]]` + +Overrides the default PostgreSQL service provider. + +Default value: `$postgresql::server::service_provider` + +##### `service_status` + +Data type: `String[1]` + +Overrides the default status check command for your PostgreSQL service. + +Default value: `$postgresql::server::service_status` + +##### `user` + +Data type: `String[1]` + +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: `$postgresql::server::user` + +##### `port` + +Data type: `Stdlib::Port` + +Specifies the port for the PostgreSQL server to listen on. +Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +changing the port causes the server to come to a full stop before being able to make the change. +Default value: 5432. Meaning the Postgres server listens on TCP port 5432. + +Default value: `$postgresql::server::port` + +##### `default_database` + +Data type: `String[1]` + +Specifies the name of the default database to connect with. On most systems this is 'postgres'. + +Default value: `$postgresql::server::default_database` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Specifies the path to the psql command. + +Default value: `$postgresql::server::psql_path` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. Becomes the default for other defined types, +such as postgresql::server::role. + +Default value: `$postgresql::server::default_connect_settings` + +### `postgresql::server::pg_hba_rule` + +This resource manages an individual rule that applies to the file defined in target. + +#### Parameters + +The following parameters are available in the `postgresql::server::pg_hba_rule` defined type: + +* [`type`](#-postgresql--server--pg_hba_rule--type) +* [`database`](#-postgresql--server--pg_hba_rule--database) +* [`user`](#-postgresql--server--pg_hba_rule--user) +* [`auth_method`](#-postgresql--server--pg_hba_rule--auth_method) +* [`address`](#-postgresql--server--pg_hba_rule--address) +* [`description`](#-postgresql--server--pg_hba_rule--description) +* [`auth_option`](#-postgresql--server--pg_hba_rule--auth_option) +* [`order`](#-postgresql--server--pg_hba_rule--order) +* [`target`](#-postgresql--server--pg_hba_rule--target) +* [`postgresql_version`](#-postgresql--server--pg_hba_rule--postgresql_version) + +##### `type` + +Data type: `Postgresql::Pg_hba_rule_type` + +Sets the type of rule. + +##### `database` + +Data type: `String[1]` + +Sets a comma-separated list of databases that this rule matches. + +##### `user` + +Data type: `String[1]` + +Sets a comma-separated list of users that this rule matches. + +##### `auth_method` + +Data type: `String[1]` + +Provides the method that is used for authentication for the connection that this rule matches. +Described further in the PostgreSQL pg_hba.conf documentation. + +##### `address` + +Data type: `Optional[Postgresql::Pg_hba_rule_address]` + +Sets a address for this rule matching when the type is not 'local'. +Value can either be IPv4 CIDR, IPv6 CIDR, a FQDN, the strings 'all', 'samehost' or 'samenet' or a domain either with or without starting +dot (.) https://www.postgresql.org/docs/current/auth-pg-hba-conf.html + +Default value: `undef` + +##### `description` + +Data type: `String[1]` + +Defines a longer description for this rule, if required. This description is placed in the comments above the rule in pg_hba.conf. +Default value: 'none'. + +Default value: `'none'` + +##### `auth_option` + +Data type: `Optional[String]` + +For certain auth_method settings there are extra options that can be passed. Consult the PostgreSQL pg_hba.conf documentation for +further details. + +Default value: `undef` + +##### `order` + +Data type: `Variant[String, Integer]` + +Sets an order for placing the rule in pg_hba.conf. This can be either a string or an integer. If it is an integer, it will be converted +to a string by zero-padding it to three digits. E.g. 42 will be zero-padded to the string '042'. The pg_hba_rule fragments are sorted +using the alpha sorting order. +Default value: 150. + +Default value: `150` + +##### `target` + +Data type: `Stdlib::Absolutepath` + +Provides the target for the rule, and is generally an internal only property. Use with caution. + +Default value: `$postgresql::server::pg_hba_conf_path` + +##### `postgresql_version` + +Data type: `String` + +Manages pg_hba.conf without managing the entire PostgreSQL instance. + +Default value: `$postgresql::server::_version` + +### `postgresql::server::pg_ident_rule` + +This resource manages an individual rule that applies to the file defined in target. + +#### Parameters + +The following parameters are available in the `postgresql::server::pg_ident_rule` defined type: + +* [`map_name`](#-postgresql--server--pg_ident_rule--map_name) +* [`system_username`](#-postgresql--server--pg_ident_rule--system_username) +* [`database_username`](#-postgresql--server--pg_ident_rule--database_username) +* [`description`](#-postgresql--server--pg_ident_rule--description) +* [`order`](#-postgresql--server--pg_ident_rule--order) +* [`target`](#-postgresql--server--pg_ident_rule--target) + +##### `map_name` + +Data type: `String[1]` + +Sets the name of the user map that is used to refer to this mapping in pg_hba.conf. + +##### `system_username` + +Data type: `String[1]` + +Specifies the operating system user name (the user name used to connect to the database). + +##### `database_username` + +Data type: `String[1]` + +Specifies the user name of the database user. +The system_username is mapped to this user name. + +##### `description` + +Data type: `String[1]` + +Sets a longer description for this rule if required. +This description is placed in the comments above the rule in pg_ident.conf. + +Default value: `'none'` + +##### `order` + +Data type: `String[1]` + +Defines an order for placing the mapping in pg_ident.conf. Default value: 150. + +Default value: `'150'` + +##### `target` + +Data type: `Stdlib::Absolutepath` + +Provides the target for the rule and is generally an internal only property. Use with caution. + +Default value: `$postgresql::server::pg_ident_conf_path` + +### `postgresql::server::reassign_owned_by` + +Define for reassigning the ownership of objects within a database. + +* **Note** This enables us to force the a particular ownership for objects within a database + +#### Parameters + +The following parameters are available in the `postgresql::server::reassign_owned_by` defined type: + +* [`old_role`](#-postgresql--server--reassign_owned_by--old_role) +* [`new_role`](#-postgresql--server--reassign_owned_by--new_role) +* [`db`](#-postgresql--server--reassign_owned_by--db) +* [`psql_user`](#-postgresql--server--reassign_owned_by--psql_user) +* [`port`](#-postgresql--server--reassign_owned_by--port) +* [`connect_settings`](#-postgresql--server--reassign_owned_by--connect_settings) +* [`group`](#-postgresql--server--reassign_owned_by--group) +* [`psql_path`](#-postgresql--server--reassign_owned_by--psql_path) +* [`instance`](#-postgresql--server--reassign_owned_by--instance) + +##### `old_role` + +Data type: `String` + +Specifies the role or user who is the current owner of the objects in the specified db + +##### `new_role` + +Data type: `String` + +Specifies the role or user who will be the new owner of these objects + +##### `db` + +Data type: `String` + +Specifies the database to which the 'REASSIGN OWNED' will be applied + +##### `psql_user` + +Data type: `String` + +Specifies the OS user for running psql. + +Default value: `$postgresql::server::user` + +##### `port` + +Data type: `Stdlib::Port` + +Port to use when connecting. + +Default value: `$postgresql::server::port` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `$postgresql::server::default_connect_settings` + +##### `group` + +Data type: `String[1]` + +Sets the OS group to run psql + +Default value: `$postgresql::server::group` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Sets the path to psql command + +Default value: `$postgresql::server::psql_path` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +### `postgresql::server::recovery` + +This resource manages the parameters that applies to the recovery.conf template. + +* **Note** Allows you to create the content for recovery.conf. For more details see the usage example and the PostgreSQL documentation. +Every parameter value is a string set in the template except recovery_target_inclusive, pause_at_recovery_target, standby_mode and +recovery_min_apply_delay. +A detailed description of all listed parameters can be found in the PostgreSQL documentation. +Only the specified parameters are recognized in the template. The recovery.conf is only created if at least one parameter is set and +manage_recovery_conf is set to true. + +#### Parameters + +The following parameters are available in the `postgresql::server::recovery` defined type: + +* [`restore_command`](#-postgresql--server--recovery--restore_command) +* [`archive_cleanup_command`](#-postgresql--server--recovery--archive_cleanup_command) +* [`recovery_end_command`](#-postgresql--server--recovery--recovery_end_command) +* [`recovery_target_name`](#-postgresql--server--recovery--recovery_target_name) +* [`recovery_target_time`](#-postgresql--server--recovery--recovery_target_time) +* [`recovery_target_xid`](#-postgresql--server--recovery--recovery_target_xid) +* [`recovery_target_inclusive`](#-postgresql--server--recovery--recovery_target_inclusive) +* [`recovery_target`](#-postgresql--server--recovery--recovery_target) +* [`recovery_target_timeline`](#-postgresql--server--recovery--recovery_target_timeline) +* [`pause_at_recovery_target`](#-postgresql--server--recovery--pause_at_recovery_target) +* [`standby_mode`](#-postgresql--server--recovery--standby_mode) +* [`primary_conninfo`](#-postgresql--server--recovery--primary_conninfo) +* [`primary_slot_name`](#-postgresql--server--recovery--primary_slot_name) +* [`trigger_file`](#-postgresql--server--recovery--trigger_file) +* [`recovery_min_apply_delay`](#-postgresql--server--recovery--recovery_min_apply_delay) +* [`target`](#-postgresql--server--recovery--target) + +##### `restore_command` + +Data type: `Optional[String]` + +The shell command to execute to retrieve an archived segment of the WAL file series. + +Default value: `undef` + +##### `archive_cleanup_command` + +Data type: `Optional[String[1]]` + +This optional parameter specifies a shell command that will be executed at every restartpoint. + +Default value: `undef` + +##### `recovery_end_command` + +Data type: `Optional[String[1]]` + +This parameter specifies a shell command that will be executed once only at the end of recovery. + +Default value: `undef` + +##### `recovery_target_name` + +Data type: `Optional[String[1]]` + +This parameter specifies the named restore point (created with pg_create_restore_point()) to which recovery will proceed. + +Default value: `undef` + +##### `recovery_target_time` + +Data type: `Optional[String[1]]` + +This parameter specifies the time stamp up to which recovery will proceed. + +Default value: `undef` + +##### `recovery_target_xid` + +Data type: `Optional[String[1]]` + +This parameter specifies the transaction ID up to which recovery will proceed. + +Default value: `undef` + +##### `recovery_target_inclusive` + +Data type: `Optional[Boolean]` + +Specifies whether to stop just after the specified recovery target (true), or just before the recovery target (false). + +Default value: `undef` + +##### `recovery_target` + +Data type: `Optional[String[1]]` + +This parameter specifies that recovery should end as soon as a consistent state is reached, i.e. as early as possible. + +Default value: `undef` + +##### `recovery_target_timeline` + +Data type: `Optional[String[1]]` + +Specifies recovering into a particular timeline. + +Default value: `undef` + +##### `pause_at_recovery_target` + +Data type: `Optional[Boolean]` + +Specifies whether recovery should pause when the recovery target is reached. + +Default value: `undef` + +##### `standby_mode` + +Data type: `Optional[String[1]]` + +Specifies whether to start the PostgreSQL server as a standby. + +Default value: `undef` + +##### `primary_conninfo` + +Data type: `Optional[String[1]]` + +Specifies a connection string to be used for the standby server to connect with the primary. + +Default value: `undef` + +##### `primary_slot_name` + +Data type: `Optional[String[1]]` + +Optionally specifies an existing replication slot to be used when connecting to the primary via streaming replication to control +resource removal on the upstream node. + +Default value: `undef` + +##### `trigger_file` + +Data type: `Optional[String[1]]` + +Specifies a trigger file whose presence ends recovery in the standby. + +Default value: `undef` + +##### `recovery_min_apply_delay` + +Data type: `Optional[Integer]` + +This parameter allows you to delay recovery by a fixed period of time, measured in milliseconds if no unit is specified. + +Default value: `undef` + +##### `target` + +Data type: `Stdlib::Absolutepath` + +Provides the target for the rule, and is generally an internal only property. Use with caution. + +Default value: `$postgresql::server::recovery_conf_path` + +### `postgresql::server::role` + +Define for creating a database role. + +#### Parameters + +The following parameters are available in the `postgresql::server::role` defined type: + +* [`update_password`](#-postgresql--server--role--update_password) +* [`password_hash`](#-postgresql--server--role--password_hash) +* [`createdb`](#-postgresql--server--role--createdb) +* [`createrole`](#-postgresql--server--role--createrole) +* [`db`](#-postgresql--server--role--db) +* [`port`](#-postgresql--server--role--port) +* [`login`](#-postgresql--server--role--login) +* [`inherit`](#-postgresql--server--role--inherit) +* [`superuser`](#-postgresql--server--role--superuser) +* [`replication`](#-postgresql--server--role--replication) +* [`valid_until`](#-postgresql--server--role--valid_until) +* [`connection_limit`](#-postgresql--server--role--connection_limit) +* [`username`](#-postgresql--server--role--username) +* [`connect_settings`](#-postgresql--server--role--connect_settings) +* [`ensure`](#-postgresql--server--role--ensure) +* [`psql_user`](#-postgresql--server--role--psql_user) +* [`psql_group`](#-postgresql--server--role--psql_group) +* [`psql_path`](#-postgresql--server--role--psql_path) +* [`module_workdir`](#-postgresql--server--role--module_workdir) +* [`hash`](#-postgresql--server--role--hash) +* [`salt`](#-postgresql--server--role--salt) +* [`instance`](#-postgresql--server--role--instance) + +##### `update_password` + +Data type: `Boolean` + +If set to true, updates the password on changes. Set this to false to not modify the role's password after creation. + +Default value: `true` + +##### `password_hash` + +Data type: `Variant[Boolean, String, Sensitive[String]]` + +Sets the hash to use during password creation. + +Default value: `false` + +##### `createdb` + +Data type: `Boolean` + +Specifies whether to grant the ability to create new databases with this role. + +Default value: `false` + +##### `createrole` + +Data type: `Boolean` + +Specifies whether to grant the ability to create new roles with this role. + +Default value: `false` + +##### `db` + +Data type: `String[1]` + +Database used to connect to. + +Default value: `$postgresql::server::default_database` + +##### `port` + +Data type: `Stdlib::Port` + +Port to use when connecting. + +Default value: `postgresql::default('port')` + +##### `login` + +Data type: `Boolean` + +Specifies whether to grant login capability for the new role. + +Default value: `true` + +##### `inherit` + +Data type: `Boolean` + +Specifies whether to grant inherit capability for the new role. + +Default value: `true` + +##### `superuser` + +Data type: `Boolean` + +Specifies whether to grant super user capability for the new role. + +Default value: `false` + +##### `replication` + +Data type: `Boolean` + +Provides provides replication capabilities for this role if set to true. + +Default value: `false` + +##### `valid_until` + +Data type: `Optional[String[1]]` + +Specifies whether to set a valid until date for the role. + +Default value: `undef` + +##### `connection_limit` + +Data type: `String[1]` + +Specifies how many concurrent connections the role can make. Default value: '-1', meaning no limit. + +Default value: `'-1'` + +##### `username` + +Data type: `String[1]` + +Defines the username of the role to create. + +Default value: `$title` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `$postgresql::server::default_connect_settings` + +##### `ensure` + +Data type: `Enum['present', 'absent']` + +Specify whether to create or drop the role. Specifying 'present' creates the role. Specifying 'absent' drops the role. + +Default value: `'present'` + +##### `psql_user` + +Data type: `String[1]` + +Sets the OS user to run psql + +Default value: `$postgresql::server::user` + +##### `psql_group` + +Data type: `String[1]` + +Sets the OS group to run psql + +Default value: `$postgresql::server::group` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Sets path to psql command + +Default value: `$postgresql::server::psql_path` + +##### `module_workdir` + +Data type: `String[1]` + +Specifies working directory under which the psql command should be executed. +May need to specify if '/tmp' is on volume mounted with noexec option. + +Default value: `$postgresql::server::module_workdir` + +##### `hash` + +Data type: `Optional[Enum['md5', 'scram-sha-256']]` + +Specify the hash method for pg password + +Default value: `undef` + +##### `salt` + +Data type: `Optional[Variant[String[1], Integer]]` + +Specify the salt use for the scram-sha-256 encoding password (default username) + +Default value: `undef` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +### `postgresql::server::schema` + +Create a new schema. + +* **Note** The database must exist and the PostgreSQL user should have enough privileges + +#### Examples + +##### + +```puppet +postgresql::server::schema {'private': + db => 'template1', +} +``` + +#### Parameters + +The following parameters are available in the `postgresql::server::schema` defined type: + +* [`db`](#-postgresql--server--schema--db) +* [`owner`](#-postgresql--server--schema--owner) +* [`schema`](#-postgresql--server--schema--schema) +* [`connect_settings`](#-postgresql--server--schema--connect_settings) +* [`port`](#-postgresql--server--schema--port) +* [`user`](#-postgresql--server--schema--user) +* [`group`](#-postgresql--server--schema--group) +* [`psql_path`](#-postgresql--server--schema--psql_path) +* [`module_workdir`](#-postgresql--server--schema--module_workdir) +* [`instance`](#-postgresql--server--schema--instance) + +##### `db` + +Data type: `String[1]` + +Required. Sets the name of the database in which to create this schema. + +Default value: `$postgresql::server::default_database` + +##### `owner` + +Data type: `Optional[String[1]]` + +Sets the default owner of the schema. + +Default value: `undef` + +##### `schema` + +Data type: `String[1]` + +Sets the name of the schema. + +Default value: `$title` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `$postgresql::server::default_connect_settings` + +##### `port` + +Data type: `Stdlib::Port` + +the post the postgresql instance is listening on. + +Default value: `$postgresql::server::port` + +##### `user` + +Data type: `String[1]` + +Sets the OS user to run psql + +Default value: `$postgresql::server::user` + +##### `group` + +Data type: `String[1]` + +Sets the OS group to run psql + +Default value: `$postgresql::server::group` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Sets path to psql command + +Default value: `$postgresql::server::psql_path` + +##### `module_workdir` + +Data type: `Stdlib::Absolutepath` + +Specifies working directory under which the psql command should be executed. +May need to specify if '/tmp' is on volume mounted with noexec option. + +Default value: `$postgresql::server::module_workdir` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +### `postgresql::server::table_grant` + +This resource wraps the grant resource to manage table grants specifically. + +#### Parameters + +The following parameters are available in the `postgresql::server::table_grant` defined type: + +* [`privilege`](#-postgresql--server--table_grant--privilege) +* [`table`](#-postgresql--server--table_grant--table) +* [`db`](#-postgresql--server--table_grant--db) +* [`role`](#-postgresql--server--table_grant--role) +* [`ensure`](#-postgresql--server--table_grant--ensure) +* [`port`](#-postgresql--server--table_grant--port) +* [`psql_db`](#-postgresql--server--table_grant--psql_db) +* [`psql_user`](#-postgresql--server--table_grant--psql_user) +* [`connect_settings`](#-postgresql--server--table_grant--connect_settings) +* [`onlyif_exists`](#-postgresql--server--table_grant--onlyif_exists) +* [`instance`](#-postgresql--server--table_grant--instance) + +##### `privilege` + +Data type: + +```puppet +Enum['ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER', 'all', 'select', 'insert', 'update', 'delete', + 'truncate', 'references', 'trigger'] +``` + +Specifies comma-separated list of privileges to grant. +Valid options: 'ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER'. + +##### `table` + +Data type: `String[1]` + +Specifies the table to which you are granting access. + +##### `db` + +Data type: `String[1]` + +Specifies which database the table is in. + +##### `role` + +Data type: `String[1]` + +Specifies the role or user to whom you are granting access. + +##### `ensure` + +Data type: `Optional[Enum['present', 'absent']]` + +Specifies whether to grant or revoke the privilege. Default is to grant the privilege. + +Default value: `undef` + +##### `port` + +Data type: `Optional[Stdlib::Port]` + +Port to use when connecting. + +Default value: `undef` + +##### `psql_db` + +Data type: `Optional[String[1]]` + +Specifies the database to execute the grant against. This should not ordinarily be changed from the default. + +Default value: `undef` + +##### `psql_user` + +Data type: `Optional[String[1]]` + +Specifies the OS user for running psql. + +Default value: `undef` + +##### `connect_settings` + +Data type: `Optional[Hash]` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `undef` + +##### `onlyif_exists` + +Data type: `Boolean` + +Create grant only if it doesn't exist. + +Default value: `false` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +### `postgresql::server::tablespace` + +This module creates tablespace. + +#### Parameters + +The following parameters are available in the `postgresql::server::tablespace` defined type: + +* [`location`](#-postgresql--server--tablespace--location) +* [`manage_location`](#-postgresql--server--tablespace--manage_location) +* [`owner`](#-postgresql--server--tablespace--owner) +* [`spcname`](#-postgresql--server--tablespace--spcname) +* [`connect_settings`](#-postgresql--server--tablespace--connect_settings) +* [`port`](#-postgresql--server--tablespace--port) +* [`user`](#-postgresql--server--tablespace--user) +* [`group`](#-postgresql--server--tablespace--group) +* [`psql_path`](#-postgresql--server--tablespace--psql_path) +* [`module_workdir`](#-postgresql--server--tablespace--module_workdir) +* [`instance`](#-postgresql--server--tablespace--instance) + +##### `location` + +Data type: `String[1]` + +Specifies the path to locate this tablespace. + +##### `manage_location` + +Data type: `Boolean` + +Set to false if you have file{ $location: } already defined + +Default value: `true` + +##### `owner` + +Data type: `Optional[String[1]]` + +Specifies the default owner of the tablespace. + +Default value: `undef` + +##### `spcname` + +Data type: `String[1]` + +Specifies the name of the tablespace. + +Default value: `$title` + +##### `connect_settings` + +Data type: `Hash` + +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: `$postgresql::server::default_connect_settings` + +##### `port` + +Data type: `Stdlib::Port` + +the port of the postgresql instance that sould be used. + +Default value: `$postgresql::server::port` + +##### `user` + +Data type: `String[1]` + +Sets the OS user to run psql + +Default value: `$postgresql::server::user` + +##### `group` + +Data type: `String[1]` + +Sets the OS group to run psql + +Default value: `$postgresql::server::group` + +##### `psql_path` + +Data type: `Stdlib::Absolutepath` + +Sets path to psql command + +Default value: `$postgresql::server::psql_path` + +##### `module_workdir` + +Data type: `String[1]` + +Specifies working directory under which the psql command should be executed. +May need to specify if '/tmp' is on volume mounted with noexec option. + +Default value: `$postgresql::server::module_workdir` + +##### `instance` + +Data type: `String[1]` + +The name of the Postgresql database instance. + +Default value: `'main'` + +### `postgresql::server_instance` + +define to install and manage additional postgresql instances + +#### Parameters + +The following parameters are available in the `postgresql::server_instance` defined type: + +* [`instance_name`](#-postgresql--server_instance--instance_name) +* [`instance_user`](#-postgresql--server_instance--instance_user) +* [`instance_group`](#-postgresql--server_instance--instance_group) +* [`instance_user_homedirectory`](#-postgresql--server_instance--instance_user_homedirectory) +* [`manage_instance_user_and_group`](#-postgresql--server_instance--manage_instance_user_and_group) +* [`instance_directories`](#-postgresql--server_instance--instance_directories) +* [`initdb_settings`](#-postgresql--server_instance--initdb_settings) +* [`config_settings`](#-postgresql--server_instance--config_settings) +* [`service_settings`](#-postgresql--server_instance--service_settings) +* [`passwd_settings`](#-postgresql--server_instance--passwd_settings) +* [`roles`](#-postgresql--server_instance--roles) +* [`config_entries`](#-postgresql--server_instance--config_entries) +* [`pg_hba_rules`](#-postgresql--server_instance--pg_hba_rules) +* [`databases`](#-postgresql--server_instance--databases) +* [`databases_and_users`](#-postgresql--server_instance--databases_and_users) +* [`database_grants`](#-postgresql--server_instance--database_grants) +* [`table_grants`](#-postgresql--server_instance--table_grants) + +##### `instance_name` + +Data type: `String[1]` + +The name of the instance. + +Default value: `$name` + +##### `instance_user` + +Data type: `String[1]` + +The user to run the instance as. + +Default value: `$instance_name` + +##### `instance_group` + +Data type: `String[1]` + +The group to run the instance as. + +Default value: `$instance_name` + +##### `instance_user_homedirectory` + +Data type: `Stdlib::Absolutepath` + +The home directory of the instance user. + +Default value: `"/opt/pgsql/data/home/${instance_user}"` + +##### `manage_instance_user_and_group` + +Data type: `Boolean` + +Should Puppet manage the instance user and it's primary group?. + +Default value: `true` + +##### `instance_directories` + +Data type: `Hash` + +directories needed for the instance. Option to manage the directory properties for each directory. + +Default value: `{}` + +##### `initdb_settings` + +Data type: `Hash` + +Specifies a hash witn parameters for postgresql::server::instance::initdb + +Default value: `{}` + +##### `config_settings` + +Data type: `Hash` + +Specifies a hash with parameters for postgresql::server::instance::config + +Default value: `{}` + +##### `service_settings` + +Data type: `Hash` + +Specifies a hash with parameters for postgresql::server:::instance::service + +Default value: `{}` + +##### `passwd_settings` + +Data type: `Hash` + +Specifies a hash with parameters for postgresql::server::instance::passwd + +Default value: `{}` + +##### `roles` + +Data type: `Hash` + +Specifies a hash from which to generate postgresql::server::role resources. + +Default value: `{}` + +##### `config_entries` + +Data type: `Hash` + +Specifies a hash from which to generate postgresql::server::config_entry resources. + +Default value: `{}` + +##### `pg_hba_rules` + +Data type: `Hash` + +Specifies a hash from which to generate postgresql::server::pg_hba_rule resources. + +Default value: `{}` + +##### `databases` + +Data type: `Hash` + +Specifies a hash from which to generate postgresql::server::database resources. + +Default value: `{}` + +##### `databases_and_users` + +Data type: `Hash` + +Specifies a hash from which to generate postgresql::server::db resources. + +Default value: `{}` + +##### `database_grants` + +Data type: `Hash` + +Specifies a hash from which to generate postgresql::server::database_grant resources. + +Default value: `{}` + +##### `table_grants` + +Data type: `Hash` + +Specifies a hash from which to generate postgresql::server::table_grant resources. + +Default value: `{}` + +## Resource types + +### `postgresql_conf` + +This type allows puppet to manage postgresql.conf parameters. + +#### Properties + +The following properties are available in the `postgresql_conf` type. + +##### `comment` + +Valid values: `%r{^[\w\W]+$}` + +The comment to set for this parameter. + +##### `ensure` + +Valid values: `present`, `absent` + +The basic property that the resource should be in. + +Default value: `present` + +##### `value` + +Valid values: `%r{^(\S.*)?$}` + +The value to set for this parameter. + +#### Parameters + +The following parameters are available in the `postgresql_conf` type. + +* [`key`](#-postgresql_conf--key) +* [`name`](#-postgresql_conf--name) +* [`provider`](#-postgresql_conf--provider) +* [`target`](#-postgresql_conf--target) + +##### `key` + +Valid values: `%r{^[\w.]+$}` + +The Postgresql parameter to manage. + +##### `name` + +Valid values: `%r{^[\w.]+$}` + +namevar + +A unique title for the resource. + +##### `provider` + +The specific backend to use for this `postgresql_conf` resource. You will seldom need to specify this --- Puppet will +usually discover the appropriate provider for your platform. + +##### `target` + +Valid values: `%r{^/\S+[a-z0-9(/)-]*\w+.conf$}` + +The path to the postgresql config file + +### `postgresql_conn_validator` + +Verify that a connection can be successfully established between a node +and the PostgreSQL server. Its primary use is as a precondition to +prevent configuration changes from being applied if the PostgreSQL +server cannot be reached, but it could potentially be used for other +purposes such as monitoring. + +#### Properties + +The following properties are available in the `postgresql_conn_validator` type. + +##### `ensure` + +Valid values: `present`, `absent` + +Ensure connection validation + +Default value: `present` + +#### Parameters + +The following parameters are available in the `postgresql_conn_validator` type. + +* [`command`](#-postgresql_conn_validator--command) +* [`connect_settings`](#-postgresql_conn_validator--connect_settings) +* [`db_name`](#-postgresql_conn_validator--db_name) +* [`db_password`](#-postgresql_conn_validator--db_password) +* [`db_username`](#-postgresql_conn_validator--db_username) +* [`host`](#-postgresql_conn_validator--host) +* [`name`](#-postgresql_conn_validator--name) +* [`port`](#-postgresql_conn_validator--port) +* [`provider`](#-postgresql_conn_validator--provider) +* [`psql_path`](#-postgresql_conn_validator--psql_path) +* [`run_as`](#-postgresql_conn_validator--run_as) +* [`sleep`](#-postgresql_conn_validator--sleep) +* [`tries`](#-postgresql_conn_validator--tries) + +##### `command` + +Command to run against target database. + +Default value: `SELECT 1` + +##### `connect_settings` + +Hash of environment variables for connection to a db. + +##### `db_name` + +The name of the database you are trying to validate a connection with. + +##### `db_password` + +The password required to access the target PostgreSQL database. + +##### `db_username` + +A user that has access to the target PostgreSQL database. + +##### `host` + +The DNS name or IP address of the server where PostgreSQL should be running. + +##### `name` + +namevar + +An arbitrary name used as the identity of the resource. + +##### `port` + +The port that the PostgreSQL server should be listening on. + +##### `provider` + +The specific backend to use for this `postgresql_conn_validator` resource. You will seldom need to specify this --- +Puppet will usually discover the appropriate provider for your platform. + +##### `psql_path` + +Path to the psql command. + +##### `run_as` + +System user that will run the psql command. + +##### `sleep` + +The length of sleep time between connection tries. + +Default value: `2` + +##### `tries` + +The number of tries to validate the connection to the target PostgreSQL database. + +Default value: `10` + +### `postgresql_psql` + +An arbitrary tag for your own reference; the name of the message. + +#### Properties + +The following properties are available in the `postgresql_psql` type. + +##### `command` + +The SQL command to execute via psql. + +#### Parameters + +The following parameters are available in the `postgresql_psql` type. + +* [`connect_settings`](#-postgresql_psql--connect_settings) +* [`cwd`](#-postgresql_psql--cwd) +* [`db`](#-postgresql_psql--db) +* [`environment`](#-postgresql_psql--environment) +* [`instance`](#-postgresql_psql--instance) +* [`name`](#-postgresql_psql--name) +* [`onlyif`](#-postgresql_psql--onlyif) +* [`port`](#-postgresql_psql--port) +* [`provider`](#-postgresql_psql--provider) +* [`psql_group`](#-postgresql_psql--psql_group) +* [`psql_path`](#-postgresql_psql--psql_path) +* [`psql_user`](#-postgresql_psql--psql_user) +* [`refreshonly`](#-postgresql_psql--refreshonly) +* [`search_path`](#-postgresql_psql--search_path) +* [`sensitive`](#-postgresql_psql--sensitive) +* [`unless`](#-postgresql_psql--unless) + +##### `connect_settings` + +Connection settings that will be used when connecting to postgres + +##### `cwd` + +The working directory under which the psql command should be executed. + +Default value: `/tmp` + +##### `db` + +The name of the database to execute the SQL command against, this overrides any PGDATABASE value in connect_settings + +##### `environment` + +Any additional environment variables you want to set for a +SQL command. Multiple environment variables should be +specified as an array. + +##### `instance` + +The postgresql instance under which the psql command should be executed. + +Default value: `main` + +##### `name` + +namevar + +An arbitrary tag for your own reference; the name of the message. + +##### `onlyif` + +An optional SQL command to execute prior to the main :command; +this is generally intended to be used for idempotency, to check +for the existence of an object in the database to determine whether +or not the main SQL command needs to be executed at all. + +##### `port` + +The port of the database server to execute the SQL command against, this overrides any PGPORT value in connect_settings. + +##### `provider` + +The specific backend to use for this `postgresql_psql` resource. You will seldom need to specify this --- Puppet will +usually discover the appropriate provider for your platform. + +##### `psql_group` + +The system user group account under which the psql command should be executed. + +Default value: `postgres` + +##### `psql_path` + +The path to psql executable. + +Default value: `psql` + +##### `psql_user` + +The system user account under which the psql command should be executed. + +Default value: `postgres` + +##### `refreshonly` + +Valid values: `true`, `false` + +If 'true', then the SQL will only be executed via a notify/subscribe event. + +Default value: `false` + +##### `search_path` + +The schema search path to use when executing the SQL command + +##### `sensitive` + +Valid values: `true`, `false` + +If 'true', then the executed command will not be echoed into the log. Use this to protect sensitive information passing +through. + +Default value: `false` + +##### `unless` + +An optional SQL command to execute prior to the main :command; +this is generally intended to be used for idempotency, to check +for the existence of an object in the database to determine whether +or not the main SQL command needs to be executed at all.' + +### `postgresql_replication_slot` + +This type allows to create and destroy replication slots +to register warm standby replication on a Postgresql +primary server. + +#### Properties + +The following properties are available in the `postgresql_replication_slot` type. + +##### `ensure` + +Valid values: `present`, `absent` + +The basic property that the resource should be in. + +Default value: `present` + +#### Parameters + +The following parameters are available in the `postgresql_replication_slot` type. + +* [`name`](#-postgresql_replication_slot--name) +* [`provider`](#-postgresql_replication_slot--provider) + +##### `name` + +Valid values: `%r{^[a-z0-9_]+$}` + +namevar + +The name of the slot to create. Must be a valid replication slot name. + +##### `provider` + +The specific backend to use for this `postgresql_replication_slot` resource. You will seldom need to specify this --- +Puppet will usually discover the appropriate provider for your platform. + +## Functions + +### `postgresql::default` + +Type: Puppet Language + +This function pull default values from the `params` class or `globals` class if the value is not present in `params`. + +#### Examples + +##### + +```puppet +postgresql::default('variable') +``` + +#### `postgresql::default(String $parameter_name)` + +The postgresql::default function. + +Returns: `Any` + +##### Examples + +###### + +```puppet +postgresql::default('variable') +``` + +##### `parameter_name` + +Data type: `String` + + + +### `postgresql::postgresql_escape` + +Type: Ruby 4.x API + +This function escapes a string using [Dollar Quoting](https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING) using a randomly generated tag if required. + +#### `postgresql::postgresql_escape(String[1] $input_string)` + +The postgresql::postgresql_escape function. + +Returns: `String` A `Dollar Quoted` string + +##### `input_string` + +Data type: `String[1]` + +The unescaped string you want to escape using `dollar quoting` + +### `postgresql::postgresql_password` + +Type: Ruby 4.x API + +This function returns the postgresql password hash from the clear text username / password + +#### `postgresql::postgresql_password(Variant[String[1], Integer] $username, Variant[String[1], Sensitive[String[1]], Integer] $password, Optional[Boolean] $sensitive, Optional[Optional[Postgresql::Pg_password_encryption]] $hash, Optional[Optional[Variant[String[1], Integer]]] $salt)` + +The postgresql::postgresql_password function. + +Returns: `Variant[String, Sensitive[String]]` The postgresql password hash from the clear text username / password. + +##### `username` + +Data type: `Variant[String[1], Integer]` + +The clear text `username` + +##### `password` + +Data type: `Variant[String[1], Sensitive[String[1]], Integer]` + +The clear text `password` + +##### `sensitive` + +Data type: `Optional[Boolean]` + +If the Postgresql-Passwordhash should be of Datatype Sensitive[String] + +##### `hash` + +Data type: `Optional[Optional[Postgresql::Pg_password_encryption]]` + +Set type for password hash + +Default value comes from `postgresql::params::password_encryption` and changes based on the `postgresql::globals::version`. + +##### `salt` + +Data type: `Optional[Optional[Variant[String[1], Integer]]]` + +Use a specific salt value for scram-sha-256, default is username + +### `postgresql::prepend_sql_password` + +Type: Ruby 4.x API + +This function exists for usage of a role password that is a deferred function + +#### `postgresql::prepend_sql_password(String $password)` + +The postgresql::prepend_sql_password function. + +Returns: `String` + +##### `password` + +Data type: `String` + +The clear text `password` + +### `postgresql_escape` + +Type: Ruby 4.x API + +DEPRECATED. Use the namespaced function [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape) instead. + +#### `postgresql_escape(Any *$args)` + +The postgresql_escape function. + +Returns: `Any` + +##### `*args` + +Data type: `Any` + + + +### `postgresql_password` + +Type: Ruby 4.x API + +DEPRECATED. Use the namespaced function [`postgresql::postgresql_password`](#postgresqlpostgresql_password) instead. + +#### `postgresql_password(Any *$args)` + +The postgresql_password function. + +Returns: `Any` + +##### `*args` + +Data type: `Any` + + + +## Data types + +### `Postgresql::Pg_hba_rule` + +type for all parameters in the postgresql::server::hba_rule defined resource + +* **See also** + * https://github.com/puppetlabs/puppetlabs-postgresql/blob/main/manifests/server/pg_hba_rule.pp + +Alias of + +```puppet +Struct[{ + Optional[description] => String, + type => Postgresql::Pg_hba_rule_type, + database => String, + user => String, + Optional[address] => Optional[Postgresql::Pg_hba_rule_address], + auth_method => String, + Optional[auth_option] => Optional[String], + Optional[order] => Variant[String,Integer], + Optional[target] => Stdlib::Absolutepath, + Optional[postgresql_version] => String, +}] +``` + +### `Postgresql::Pg_hba_rule_address` + +Supported address types + +* **See also** + * https://www.postgresql.org/docs/current/auth-pg-hba-conf.html + +Alias of `Variant[Stdlib::IP::Address::V4::CIDR, Stdlib::IP::Address::V6::CIDR, Stdlib::Fqdn, Enum['all', 'samehost', 'samenet'], Pattern[/^\.(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$/]]` + +### `Postgresql::Pg_hba_rule_type` + +enum for all different types for the pg_hba_conf + +* **See also** + * https://www.postgresql.org/docs/current/auth-pg-hba-conf.html + +Alias of `Enum['local', 'host', 'hostssl', 'hostnossl', 'hostgssenc', 'hostnogssenc']` + +### `Postgresql::Pg_hba_rules` + +validates a hash of entries for postgresql::server::pg_hab_conf + +* **See also** + * https://github.com/puppetlabs/puppetlabs-postgresql/blob/main/manifests/server/pg_hba_rule.pp + +Alias of `Hash[String[1], Postgresql::Pg_hba_rule]` + +### `Postgresql::Pg_password_encryption` + +the supported password_encryption + +Alias of `Enum['md5', 'scram-sha-256']` + +## Tasks + +### `sql` + +Allows you to execute arbitary SQL + +**Supports noop?** false + +#### Parameters + +##### `database` + +Data type: `Optional[String[1]]` + +Database to connect to + +##### `host` + +Data type: `Optional[String[1]]` + +Hostname to connect to + +##### `password` + +Data type: `Optional[String[1]]` + +The password + +##### `port` + +Data type: `Optional[String[1]]` + +The port + +##### `sql` + +Data type: `String[1]` + +The SQL you want to execute + +##### `user` + +Data type: `Optional[String[1]]` + +The user + diff --git a/Rakefile b/Rakefile index 181157e6e0..32f4fa9e14 100644 --- a/Rakefile +++ b/Rakefile @@ -1,10 +1,11 @@ +# frozen_string_literal: true + +require 'bundler' +require 'puppet_litmus/rake_tasks' if Gem.loaded_specs.key? 'puppet_litmus' require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-lint/tasks/puppet-lint' +require 'puppet-syntax/tasks/puppet-syntax' +require 'puppet-strings/tasks' if Gem.loaded_specs.key? 'puppet-strings' -PuppetLint.configuration.fail_on_warnings = true -PuppetLint.configuration.send('relative') -PuppetLint.configuration.send('disable_80chars') -PuppetLint.configuration.send('disable_class_inherits_from_params_class') -PuppetLint.configuration.send('disable_documentation') -PuppetLint.configuration.send('disable_single_quote_string_with_variables') -PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] +PuppetLint.configuration.send('disable_relative') +PuppetLint.configuration.send('disable_anchor_resource') +PuppetLint.configuration.send('disable_params_empty_string_assignment') diff --git a/data/common.yaml b/data/common.yaml new file mode 100644 index 0000000000..2fbf0ffd71 --- /dev/null +++ b/data/common.yaml @@ -0,0 +1 @@ +--- {} diff --git a/data/os/Ubuntu/18.04.yaml b/data/os/Ubuntu/18.04.yaml new file mode 100644 index 0000000000..7d66bfac7e --- /dev/null +++ b/data/os/Ubuntu/18.04.yaml @@ -0,0 +1,3 @@ +--- +postgresql::repo::baseurl: https://apt-archive.postgresql.org/pub/repos/apt/ +postgresql::repo::release: "%{facts.os.distro.codename}-pgdg-archive" diff --git a/files/ACCC4CF8.asc b/files/ACCC4CF8.asc new file mode 100644 index 0000000000..8480576ece --- /dev/null +++ b/files/ACCC4CF8.asc @@ -0,0 +1,77 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBE6XR8IBEACVdDKT2HEH1IyHzXkb4nIWAY7echjRxo7MTcj4vbXAyBKOfjja +UrBEJWHN6fjKJXOYWXHLIYg0hOGeW9qcSiaa1/rYIbOzjfGfhE4x0Y+NJHS1db0V +G6GUj3qXaeyqIJGS2z7m0Thy4Lgr/LpZlZ78Nf1fliSzBlMo1sV7PpP/7zUO+aA4 +bKa8Rio3weMXQOZgclzgeSdqtwKnyKTQdXY5MkH1QXyFIk1nTfWwyqpJjHlgtwMi +c2cxjqG5nnV9rIYlTTjYG6RBglq0SmzF/raBnF4Lwjxq4qRqvRllBXdFu5+2pMfC +IZ10HPRdqDCTN60DUix+BTzBUT30NzaLhZbOMT5RvQtvTVgWpeIn20i2NrPWNCUh +hj490dKDLpK/v+A5/i8zPvN4c6MkDHi1FZfaoz3863dylUBR3Ip26oM0hHXf4/2U +A/oA4pCl2W0hc4aNtozjKHkVjRx5Q8/hVYu+39csFWxo6YSB/KgIEw+0W8DiTII3 +RQj/OlD68ZDmGLyQPiJvaEtY9fDrcSpI0Esm0i4sjkNbuuh0Cvwwwqo5EF1zfkVj +Tqz2REYQGMJGc5LUbIpk5sMHo1HWV038TWxlDRwtOdzw08zQA6BeWe9FOokRPeR2 +AqhyaJJwOZJodKZ76S+LDwFkTLzEKnYPCzkoRwLrEdNt1M7wQBThnC5z6wARAQAB +tBxQb3N0Z3JlU1FMIERlYmlhbiBSZXBvc2l0b3J5iQJOBBMBCAA4AhsDBQsJCAcD +BRUKCQgLBRYCAwEAAh4BAheAFiEEuXsK/KoaR/BE8kSgf8x9RqzMTPgFAlhtCD8A +CgkQf8x9RqzMTPgECxAAk8uL+dwveTv6eH21tIHcltt8U3Ofajdo+D/ayO53LiYO +xi27kdHD0zvFMUWXLGxQtWyeqqDRvDagfWglHucIcaLxoxNwL8+e+9hVFIEskQAY +kVToBCKMXTQDLarz8/J030Pmcv3ihbwB+jhnykMuyyNmht4kq0CNgnlcMCdVz0d3 +z/09puryIHJrD+A8y3TD4RM74snQuwc9u5bsckvRtRJKbP3GX5JaFZAqUyZNRJRJ +Tn2OQRBhCpxhlZ2afkAPFIq2aVnEt/Ie6tmeRCzsW3lOxEH2K7MQSfSu/kRz7ELf +Cz3NJHj7rMzC+76Rhsas60t9CjmvMuGONEpctijDWONLCuch3Pdj6XpC+MVxpgBy +2VUdkunb48YhXNW0jgFGM/BFRj+dMQOUbY8PjJjsmVV0joDruWATQG/M4C7O8iU0 +B7o6yVv4m8LDEN9CiR6r7H17m4xZseT3f+0QpMe7iQjz6XxTUFRQxXqzmNnloA1T +7VjwPqIIzkj/u0V8nICG/ktLzp1OsCFatWXh7LbU+hwYl6gsFH/mFDqVxJ3+DKQi +vyf1NatzEwl62foVjGUSpvh3ymtmtUQ4JUkNDsXiRBWczaiGSuzD9Qi0ONdkAX3b +ewqmN4TfE+XIpCPxxHXwGq9Rv1IFjOdCX0iG436GHyTLC1tTUIKF5xV4Y0+cXIOI +RgQQEQgABgUCTpdI7gAKCRDFr3dKWFELWqaPAKD1TtT5c3sZz92Fj97KYmqbNQZP ++ACfSC6+hfvlj4GxmUjp1aepoVTo3weJAhwEEAEIAAYFAk6XSQsACgkQTFprqxLS +p64F8Q//cCcutwrH50UoRFejg0EIZav6LUKejC6kpLeubbEtuaIH3r2zMblPGc4i ++eMQKo/PqyQrceRXeNNlqO6/exHozYi2meudxa6IudhwJIOn1MQykJbNMSC2sGUp +1W5M1N5EYgt4hy+qhlfnD66LR4G+9t5FscTJSy84SdiOuqgCOpQmPkVRm1HX5X1+ +dmnzMOCk5LHHQuiacV0qeGO7JcBCVEIDr+uhU1H2u5GPFNHm5u15n25tOxVivb94 +xg6NDjouECBH7cCVuW79YcExH/0X3/9G45rjdHlKPH1OIUJiiX47OTxdG3dAbB4Q +fnViRJhjehFscFvYWSqXo3pgWqUsEvv9qJac2ZEMSz9x2mj0ekWxuM6/hGWxJdB+ ++985rIelPmc7VRAXOjIxWknrXnPCZAMlPlDLu6+vZ5BhFX0Be3y38f7GNCxFkJzl +hWZ4Cj3WojMj+0DaC1eKTj3rJ7OJlt9S9xnO7OOPEUTGyzgNIDAyCiu8F4huLPaT +ape6RupxOMHZeoCVlqx3ouWctelB2oNXcxxiQ/8y+21aHfD4n/CiIFwDvIQjl7dg +mT3u5Lr6yxuosR3QJx1P6rP5ZrDTP9khT30t+HZCbvs5Pq+v/9m6XDmi+NlU7Zuh +Ehy97tL3uBDgoL4b/5BpFL5U9nruPlQzGq1P9jj40dxAaDAX/WKJAj0EEwEIACcC +GwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlB5KywFCQPDFt8ACgkQf8x9RqzM +TPhuCQ//QAjRSAOCQ02qmUAikT+mTB6baOAakkYq6uHbEO7qPZkv4E/M+HPIJ4wd +nBNeSQjfvdNcZBA/x0hr5EMcBneKKPDj4hJ0panOIRQmNSTThQw9OU351gm3YQct +AMPRUu1fTJAL/AuZUQf9ESmhyVtWNlH/56HBfYjE4iVeaRkkNLJyX3vkWdJSMwC/ +LO3Lw/0M3R8itDsm74F8w4xOdSQ52nSRFRh7PunFtREl+QzQ3EA/WB4AIj3VohIG +kWDfPFCzV3cyZQiEnjAe9gG5pHsXHUWQsDFZ12t784JgkGyO5wT26pzTiuApWM3k +/9V+o3HJSgH5hn7wuTi3TelEFwP1fNzI5iUUtZdtxbFOfWMnZAypEhaLmXNkg4zD +kH44r0ss9fR0DAgUav1a25UnbOn4PgIEQy2fgHKHwRpCy20d6oCSlmgyWsR40EPP +YvtGq49A2aK6ibXmdvvFT+Ts8Z+q2SkFpoYFX20mR2nsF0fbt1lfH65P64dukxeR +GteWIeNakDD40bAAOH8+OaoTGVBJ2ACJfLVNM53PEoftavAwUYMrR910qvwYfd/4 +6rh46g1Frr9SFMKYE9uvIJIgDsQB3QBp71houU4H55M5GD8XURYs+bfiQpJG1p7e +B8e5jZx1SagNWc4XwL2FzQ9svrkbg1Y+359buUiP7T6QXX2zY++JAj0EEwEIACcC +GwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlEqbZUFCQg2wEEACgkQf8x9RqzM +TPhFMQ//WxAfKMdpSIA9oIC/yPD/dJpY/+DyouOljpE6MucMy/ArBECjFTBwi/j9 +NYM4ynAk34IkhuNexc1i9/05f5RM6+riLCLgAOsADDbHD4miZzoSxiVr6GQ3YXMb +OGld9kV9Sy6mGNjcUov7iFcf5Hy5w3AjPfKuR9zXswyfzIU1YXObiiZT38l55pp/ +BSgvGVQsvbNjsff5CbEKXS7q3xW+WzN0QWF6YsfNVhFjRGj8hKtHvwKcA02wwjLe +LXVTm6915ZUKhZXUFc0vM4Pj4EgNswH8Ojw9AJaKWJIZmLyW+aP+wpu6YwVCicxB +Y59CzBO2pPJDfKFQzUtrErk9irXeuCCLesDyirxJhv8o0JAvmnMAKOLhNFUrSQ2m ++3EnF7zhfz70gHW+EG8X8mL/EN3/dUM09j6TVrjtw43RLxBzwMDeariFF9yC+5bL +tnGgxjsB9Ik6GV5v34/NEEGf1qBiAzFmDVFRZlrNDkq6gmpvGnA5hUWNr+y0i01L +jGyaLSWHYjgw2UEQOqcUtTFK9MNzbZze4mVaHMEz9/aMfX25R6qbiNqCChveIm8m +Yr5Ds2zdZx+G5bAKdzX7nx2IUAxFQJEE94VLSp3npAaTWv3sHr7dR8tSyUJ9poDw +gw4W9BIcnAM7zvFYbLF5FNggg/26njHCCN70sHt8zGxKQINMc6SJAj0EEwEIACcC +GwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlLpFRkFCQ6EJy0ACgkQf8x9RqzM +TPjOZA//Zp0e25pcvle7cLc0YuFr9pBv2JIkLzPm83nkcwKmxaWayUIG4Sv6pH6h +m8+S/CHQij/yFCX+o3ngMw2J9HBUvafZ4bnbI0RGJ70GsAwraQ0VlkIfg7GUw3Tz +voGYO42rZTru9S0K/6nFP6D1HUu+U+AsJONLeb6oypQgInfXQExPZyliUnHdipei +4WR1YFW6sjSkZT/5C3J1wkAvPl5lvOVthI9Zs6bZlJLZwusKxU0UM4Btgu1Sf3nn +JcHmzisixwS9PMHE+AgPWIGSec/N27a0KmTTvImV6K6nEjXJey0K2+EYJuIBsYUN +orOGBwDFIhfRk9qGlpgt0KRyguV+AP5qvgry95IrYtrOuE7307SidEbSnvO5ezNe +mE7gT9Z1tM7IMPfmoKph4BfpNoH7aXiQh1Wo+ChdP92hZUtQrY2Nm13cmkxYjQ4Z +gMWfYMC+DA/GooSgZM5i6hYqyyfAuUD9kwRN6BqTbuAUAp+hCWYeN4D88sLYpFh3 +paDYNKJ+Gf7Yyi6gThcV956RUFDH3ys5Dk0vDL9NiWwdebWfRFbzoRM3dyGP889a +OyLzS3mh6nHzZrNGhW73kslSQek8tjKrB+56hXOnb4HaElTZGDvD5wmrrhN94kby +Gtz3cydIohvNO9d90+29h0eGEDYti7j7maHkBKUAwlcPvMg5m3Y= +=DA1T +-----END PGP PUBLIC KEY BLOCK----- diff --git a/files/RPM-GPG-KEY-PGDG b/files/RPM-GPG-KEY-PGDG index 065274e0d9..a6f86f350a 100644 --- a/files/RPM-GPG-KEY-PGDG +++ b/files/RPM-GPG-KEY-PGDG @@ -1,30 +1,41 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.7 (GNU/Linux) -mQGiBEeD8koRBACC1VBRsUwGr9gxFFRho9kZpdRUjBJoPhkeOTvp9LzkdAQMFngr -BFi6N0ov1kCX7LLwBmDG+JPR7N+XcH9YR1coSHpLVg+JNy2kFDd4zAyWxJafjZ3a -9zFg9Yx+0va1BJ2t4zVcmKS4aOfbgQ5KwIOWUujalQW5Y+Fw39Gn86qjbwCg5dIo -tkM0l19h2sx50D027pV5aPsD/2c9pfcFTbMhB0CcKS836GH1qY+NCAdUwPs646ee -Ex/k9Uy4qMwhl3HuCGGGa+N6Plyon7V0TzZuRGp/1742dE8IO+I/KLy2L1d1Fxrn -XOTBZd8qe6nBwh12OMcKrsPBVBxn+iSkaG3ULsgOtx+HHLfa1/p22L5+GzGdxizr -peBuA/90cCp+lYcEwdYaRoFVR501yDOTmmzBc1DrsyWP79QMEGzMqa393G0VnqXt -L4pGmunq66Agw2EhPcIt3pDYiCmEt/obdVtSJH6BtmSDB/zYhbE8u3vLP3jfFDa9 -KXxgtYj0NvuUVoRmxSKm8jtfmj1L7zoKNz3jl+Ba3L0WxIv4+bRBUG9zdGdyZVNR -TCBSUE0gQnVpbGRpbmcgUHJvamVjdCA8cGdzcWxycG1zLWhhY2tlcnNAcGdmb3Vu -ZHJ5Lm9yZz6IYAQTEQIAIAUCR4PySgIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheA -AAoJEB8W0uFELfD4jnkAoMqd6ZwwsgYHZ3hP9vt+DJt1uDW7AKDbRwP8ESKFhwdJ -8m91RPBeJW/tMLkCDQRHg/JKEAgA64+ZXgcERPYfZYo4p+yMTJAAa9aqnE3U4Ni6 -ZMB57GPuEy8NfbNya+HiftO8hoozmJdcI6XFyRBCDUVCdZ8SE+PJdOx2FFqZVIu6 -dKnr8ykhgLpNNEFDG3boK9UfLj/5lYQ3Y550Iym1QKOgyrJYeAp6sZ+Nx2PavsP3 -nMFCSD67BqAbcLCVQN7a2dAUXfEbfXJjPHXTbo1/kxtzE+KCRTLdXEbSEe3nHO04 -K/EgTBjeBUOxnciH5RylJ2oGy/v4xr9ed7R1jJtshsDKMdWApwoLlCBJ63jg/4T/ -z/OtXmu4AvmWaJxaTl7fPf2GqSqqb6jLCrQAH7AIhXr9V0zPZwADBQgAlpptNQHl -u7euIdIujFwwcxyQGfee6BG+3zaNSEHMVQMuc6bxuvYmgM9r7aki/b0YMfjJBk8v -OJ3Eh1vDH/woJi2iJ13vQ21ot+1JP3fMd6NPR8/qEeDnmVXu7QAtlkmSKI9Rdnjz -FFSUJrQPHnKsH4V4uvAM+njwYD+VFiwlBPTKNeL8cdBb4tPN2cdVJzoAp57wkZAN -VA2tKxNsTJKBi8wukaLWX8+yPHiWCNWItvyB4WCEp/rZKG4A868NM5sZQMAabpLd -l4fTiGu68OYgK9qUPZvhEAL2C1jPDVHPkLm+ZsD+90Pe66w9vB00cxXuHLzm8Pad -GaCXCY8h3xi6VIhJBBgRAgAJBQJHg/JKAhsMAAoJEB8W0uFELfD4K4cAoJ4yug8y -1U0cZEiF5W25HDzMTtaDAKCaM1m3Cbd+AZ0NGWNg/VvIX9MsPA== -=au6K ------END PGP PUBLIC KEY BLOCK----- +mQGNBGWBr8EBDAC+atC3Hl2yKkFg0F4tDg4ABCTvvhgMn7g7oZ0vJqpaUAwUgijU ++jLXH8qVSkyhk2eruSXlbj4dIMHhsbRQ1wUnd+tb8pZPdRaBFR9MzFMjvDzobAlZ +RH6cUbgm2EdAHrrZFVQJuIb6SRzQzkk4QEWTkWP6CHzvxnlVpkI7T1yjsJnmLefN +TT/J+r0gxC1DRXOKwSMmWUCzYcRXiv/RZcp+IwM04e5BXOj6xoLIpAwhSGZ0LR6b +dwliBpMSFuVyXFIu+7AS2M8tEO1cGK+ywDhg7TriMc/rgjZjeu11WusXFwbvEUeM +FIYM9oXQlAlWDIob85YcGtNXV4EVGovQ2nFd4Ivl9OYq+HixAhWBLulkEAUREKq8 +uXV8HDjxOfYa8VhczphvkCLr5UEMzXmC2eDc6nCH2hveAqSVLnFNkhtExvVOPRBB +gRsviaGWvdOA3eNeEofHX9YWtSzM43tWABKUzI/oTMcdFJlkJ465bvh4p7KyHDth +5I46iBUZmfP4RckAEQEAAbQ+UG9zdGdyZVNRTCBSUE0gUmVwb3NpdG9yeSA8cGdz +cWwtcGtnLXl1bUBsaXN0cy5wb3N0Z3Jlc3FsLm9yZz6JAdIEEwEIADwWIQTUvwiu +Z6C0x6HbzNJAvKK0CLQNIAUCZYGvwQIbAwULCQgHAgMiAgEGFQoJCAsCBBYCAwEC +HgcCF4AACgkQQLyitAi0DSBwkwwAvE1vGNMiP8Qvqvpk5otuJOvz5meELUwmhT60 +IOWNr9RMroKfb27mnc5RHlOmMk/0SPyboFX9qtOdwFUq3cYbjsP+bqI9vuQuQ4Gz +siLIvSZPtQrdtUP8wdndndeKNpDIvRdYwvaPfIrBxxCSslB8iuCtjbyCl2rzlika +sCOWi7oTwuNB4eKHCRt9oh7NHFas92bF2JiaR7hvmXlCU058/lnR+jXCp/NWiGfE +QV37xAu/ssRH5MykGweEzQ3mX2EKppdKmmoOaJsTfS7UNujeZQqo1uqZg9yRHgwf +PaquIwgdXBY6JkMUM4Zhn7QkP5ssD6g+GzWe2UAMN+K8Xe3QwEMfp9AF7sEEM/Zp ++p5m7D1GlOho/m9juxcRa5r7VfvCFL05uyXdDoefOCFal/pDmwvZofK+pqtDZfKt ++AnF/Y6Z3ewvJ0ZRNBX/0Iw30uJusDIgkXaHwxEeDOnlKi8jVyBCMr1In2QKrb1+ +N9PR5P5ZKKq40WNvbiPfoUeKwKKSuQGNBGWBr8EBDAD1nXgbf+Qki5Z0H2k0xLbI +GYhxnousjVlrWcxOTYqVilSvBig7RKuVFGt0D3yuBWrAS7+MCUvpuCshHcc+w97G +iWmRskIHqZoD26kkU8PhgYayyArqepZp50ALIdOhedOp9b/NUkSPEL4BJow9H8Lp +a28WEXpHZcam43RDMzLMUvJBWem474APx5674EZYX+994lT2cNSAFrnJK956lKmc +ZdzzKuMTcIVGyRF6+KXCmScLAyQks8lHuTJb+AA4eseZnbOsnwnA1xuVfYIfMF/F +bLlR7vl5Autmgnz1SdCaUqIp4MO54GZOgh4MjVadsxIWj8H0cN3uTfukuW4A0+dP +d0YrOKb52Mnejh7x39qWIsMtT8DgcufGcVsuVhC/5LCiHB3pB73J9SMxBafcyGyK +XfLFL5FoDkKTU5KkBfqMQ4k//27mLbJ4kWxHHtNsvnn/6a5m7rRYxFD4dxBWn1CU +BpMjf3m9B3xLc7lKlQZiLLNC7p15gHS51yMvCGxCaHcAEQEAAYkBtgQYAQgAIBYh +BNS/CK5noLTHodvM0kC8orQItA0gBQJlga/BAhsMAAoJEEC8orQItA0guy0L/1ze +AHxV8pxPawOIlgDWoALLb/tqvmG+yz8SN5IWDfvMkMW5kbVoY8zi9SnJtOHVULBC +sdiYN4Dn/Ox1eLlW50F4Z76RI2r/O9rBlHzUk/jAQOcDDCRWjj4a+pYX9I4atU6e ++qOOzxMBsFD0vK84NYJ6caC0LHR64xWnyvXStkDEPSzgHhAlhdn9oTqbIoXuDhSx +zBVSXyowi+cBL8tNsAH4Zlj0li1Gii6bM4DFseQGhKIiTFbx1HD47DT6Pu0X2PSA +pIuZ47n8rP2uTLCYjtnfpXbMwmVOXWxIojhUqIceF+KRr4vRsspSbMxMKg0yeGka +RfQX29x8baM4mdKVBmU9KQxRgno6lcks14STnawqf6o9nHxKp80VQrcNTsYHlq2B +PGAanK8G4WeYojQWCQHBi73qCoTERMpBG73gpTIr836TBinGZaSZ8I1deUS89Hnw +A62QO1TS57zxMTrstzaawLoCIHTqyJ2VeZrVC1INV4ENnyVsud3NaZtfWuIk7Q== +=Elfg +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/files/RPM-GPG-KEY-PGDG-7 b/files/RPM-GPG-KEY-PGDG-7 new file mode 100644 index 0000000000..fae9ac829e --- /dev/null +++ b/files/RPM-GPG-KEY-PGDG-7 @@ -0,0 +1,41 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.22 (GNU/Linux) + +mQGNBGWBsHEBDACzg9nBu9GXrquREAEVTObf6k3YIWagkv1qlX61dqQpyx8XT36A ++wx9qc7vk1mJoyzjq0gBH/C0ebaJntoCG/rv3j8DP4tQO+CApWN5XqrZJI+vYjRt +bJhrkxUt4fm8dozRykR9GdB05x35XVkzLsPVMqP6EqmBu9i2WgE30LlkPShzHyuf +P4W42zY4JVpKRK4CqLnWX3+PXY2tENYqkARK37j8r4klxIVku9UpE3W7XXIud9Nh +dVOtj0P8/t3mAHLgRjLqaGLVGz4k2b3phzDcG7sDvfwVXMPKDAVY5IymK4yTjeZU +6x3E63pNpQV4KfccHAKFJ++wOQmhfF5H+ViWTytIgyRMKn9eR+715nEZG8suRPSG +GnulJj9sUw6dONmPxCd6gCFQ0BAm/h7Bn8cODdPzJn6h/yMNs7SeH9yv8zlZvJdf +Sb5rTQLaFBaNP5yQ3rHb+gpDno7dwLxcx10qghPSz6TY96nCJNtrlj04P699UR4a +KIK2X6miJMwENE0AEQEAAbQ+UG9zdGdyZVNRTCBSUE0gUmVwb3NpdG9yeSA8cGdz +cWwtcGtnLXl1bUBsaXN0cy5wb3N0Z3Jlc3FsLm9yZz6JAbkEEwECACMFAmWBsHEC +GwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBk+s4Rc+O5B3MPC/4r2mTL +Oy7kuT48faVqDMovPsezJm//G/ur2dXMGYdr2QyzX1V6YXprtrY90bLt+mt/b/9C +pY0r5vDgI1uDkp5mX0tcCJJlAV8sDMC/r1a1rlh6KFxqRIOq5/hkPSkxHL4XVtdi +GvxgFcOj5vGWuBpmKaL+CeglBFzWFyPQV6+e+eJ4RG7MOOPHUUAODy58uDztSoyP +C8WLZR2vShTA5OZoyWdzwRkHeFMXWdcTw6wwff+sl942cwzkw5XotmkxS3Mpg4PI +IkGWeDvh2AoqjSIiLyAAB6vRhRjGwT+JLzQp0Yn9kfUQwMeCEOESO0mdnxd37WXq ++HvMY1I40J+OCl7XKE0kleWfsuv5/Hk+pHW4KxCHVtMKMpTzOT1Koq0dkx9H51p+ +pubZZa5umPnhm9+0SkqotXaaBnxs+MBnQpu98TrJ0eOkpVRWqpkybXbrZKgx+oJN +xNctGxbgFRq3K7QMLGjor8vF5Mg6qTzxM5RwZ7QaT/Msjh8VyUZ6ch7kNcu5AY0E +ZYGwcQEMANOcY0IKEf4sMl3s2FHoZrxnjrX4cDdcS9NNYcYvDG1Y2BXiqEh6A5i1 +ZpZQpUZitqXbFsU2GSEjC9IBKMklp0xTNt9lBC/WmlOFrwDgm0ufxMqiE77QlIyr +yVj+6XOMN8EotXF2a8ZxmqbYaG5L7eAqGsDda2ZYCqgwKQUkdXJ7QNq9ikQ31Toj +Qd0zzh1czDwDyj9bZCoPjZiCDZVmK5We87ZYWekDTIq9Wdh0teXzZrLb6UsFCMLO +zZDKlH4+5+zlYHyFvEjTxrrQs2YOkLLMcouRQKe/pR4DwKJvA9mLmofQWAHCH0uv +9SY08RXm+bqoNWwrCmCjdN775wUU9IsDaKXbdtybl6PprAQhwLceXysbr3HmorjV +nvJYujuwQMN6JUavKKLC3zJSDOnBlZBGfoR00QWG5mHSgRxXLNVtaAWAqxrNcofc +wOu0Rr9O89AAePHzvZKXCu6aeWeBfhgKAz+wIjh9VjNFjAFLLVP3nWOIPbjN+Blv +Wy/OXDWFXwARAQABiQGfBBgBAgAJBQJlgbBxAhsMAAoJEGT6zhFz47kHJHcL/A0m +Jme0ERyl2d9z9wfmH4/mJ3lEsSmYRk1y8cQLJ3yXSdD0iYFRDaiLdhuV6CZQQHee +ong6TpGTe1REmmKBSOD6zdCfCcAMsk+SKQHADJD9es0ZleQOpdcVRgnLKGcze2qx +JzS4+0OoNkPg0Wf5pdDlKi0nJIr/t1qLU7TVOWTcUaYhjnrHy8iCWVNvrmm9tPLJ +4dS3OCxdzuTApUQAC26Lo6T0SOIc7COyshuhZe90IK/cRMuDuvf+8TqWBOE2sMJ0 +2WNS8In5xWItAfoepmFLSOeWbCHo/yzuVFFI7Oo4DJ5cvKJ+Vo3iAWl8RPsN6iKE +Ocmphnc2clno8y4lSc4NckEbL+teZZyww12kHph5NUDReITO4H/4XGEpq4PATT6P +9aMDQQVK4GpmIZ6pLn+yYOV/ZLkHIcJUBVPjLtds5FOsVEpX4JaMowzk4jT6lp/F +7inS2V/87DcrYMl+NcBm09BZ6M4X1OYEumq7qXKtScmHAfp2yG2A1lJ5RtXrSQ== +=fPP0 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/files/validate_postgresql_connection.sh b/files/validate_postgresql_connection.sh index f126d99be4..1c3506c71a 100644 --- a/files/validate_postgresql_connection.sh +++ b/files/validate_postgresql_connection.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # usage is: validate_db_connection 2 50 psql @@ -8,7 +8,9 @@ PSQL=$3 STATE=1 -for (( c=1; c<=$TRIES; c++ )) +c=1 + +while [ $c -le $TRIES ] do echo $c if [ $c -gt 1 ] @@ -24,6 +26,7 @@ do then exit 0 fi + c=$((c+1)) done echo 'Unable to connect to postgresql' diff --git a/functions/default.pp b/functions/default.pp new file mode 100644 index 0000000000..41b500642b --- /dev/null +++ b/functions/default.pp @@ -0,0 +1,14 @@ +# @summary This function pull default values from the `params` class or `globals` class if the value is not present in `params`. +# +# @example +# postgresql::default('variable') +# +function postgresql::default( + String $parameter_name +) { + include postgresql::params + + # Search for the variable name in params. + # params inherits from globals, so it will also catch these variables. + pick(getvar("postgresql::params::${parameter_name}")) +} diff --git a/hiera.yaml b/hiera.yaml new file mode 100644 index 0000000000..545fff3272 --- /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/lib/puppet/functions/postgresql/postgresql_acls_to_resources_hash.rb b/lib/puppet/functions/postgresql/postgresql_acls_to_resources_hash.rb new file mode 100644 index 0000000000..5f18040c0d --- /dev/null +++ b/lib/puppet/functions/postgresql/postgresql_acls_to_resources_hash.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +# @summary This internal function translates the ipv(4|6)acls format into a resource suitable for create_resources. +# @api private +Puppet::Functions.create_function(:'postgresql::postgresql_acls_to_resources_hash') do + # @param acls + # An array of strings that are pg_hba.conf rules. + # @param id + # An identifier that will be included in the namevar to provide uniqueness. + # @param offset + # An order offset, so you can start the order at an arbitrary starting point. + # + # @return [Hash] + # A hash that can be fed into create_resources to create multiple individual pg_hba_rule resources. + dispatch :default_impl do + param 'Array[String]', :acls + param 'String[1]', :id + param 'Integer[0]', :offset + end + + def default_impl(acls, id, offset) + resources = {} + acls.each do |acl| + index = acls.index(acl) + + parts = acl.split + + unless parts.length >= 4 + raise(Puppet::ParseError, "postgresql::postgresql_acls_to_resources_hash(): acl line #{index} does not " \ + 'have enough parts') + end + + resource = { + 'type' => parts[0], + 'database' => parts[1], + 'user' => parts[2], + 'order' => '%03d' % (offset + index) + } + if parts[0] == 'local' + resource['auth_method'] = parts[3] + resource['auth_option'] = parts.last(parts.length - 4).join(' ') if parts.length > 4 + elsif %r{^\d}.match?(parts[4]) + resource['address'] = "#{parts[3]} #{parts[4]}" + resource['auth_method'] = parts[5] + + resource['auth_option'] = parts.last(parts.length - 6).join(' ') if parts.length > 6 + else + resource['address'] = parts[3] + resource['auth_method'] = parts[4] + + resource['auth_option'] = parts.last(parts.length - 5).join(' ') if parts.length > 5 + end + resources["postgresql class generated rule #{id} #{index}"] = resource + end + resources + end +end diff --git a/lib/puppet/functions/postgresql/postgresql_escape.rb b/lib/puppet/functions/postgresql/postgresql_escape.rb new file mode 100644 index 0000000000..10c19e11af --- /dev/null +++ b/lib/puppet/functions/postgresql/postgresql_escape.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'digest/md5' + +# @summary This function escapes a string using [Dollar Quoting](https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING) using a randomly generated tag if required. +Puppet::Functions.create_function(:'postgresql::postgresql_escape') do + # @param input_string + # The unescaped string you want to escape using `dollar quoting` + # + # @return [String] + # A `Dollar Quoted` string + dispatch :default_impl do + param 'String[1]', :input_string + end + + def default_impl(input_string) + # Where allowed, just return the original string wrapped in `$$` + return "$$#{input_string}$$" unless tag_needed?(input_string) + + # Keep generating possible values for tag until we find one that doesn't appear in the input string + tag = Digest::MD5.hexdigest(input_string)[0..5].gsub(%r{\d}, '') + tag = Digest::MD5.hexdigest(tag)[0..5].gsub(%r{\d}, '') until input_string !~ %r{#{tag}} + + "$#{tag}$#{input_string}$#{tag}$" + end + + def tag_needed?(input_string) + input_string.include?('$$') || input_string.end_with?('$') + end +end diff --git a/lib/puppet/functions/postgresql/postgresql_password.rb b/lib/puppet/functions/postgresql/postgresql_password.rb new file mode 100644 index 0000000000..9ca4d81dbb --- /dev/null +++ b/lib/puppet/functions/postgresql/postgresql_password.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +require 'openssl' +require 'base64' + +# @summary This function returns the postgresql password hash from the clear text username / password +Puppet::Functions.create_function(:'postgresql::postgresql_password') do + # @param username + # The clear text `username` + # @param password + # The clear text `password` + # @param sensitive + # If the Postgresql-Passwordhash should be of Datatype Sensitive[String] + # @param hash + # Set type for password hash + # + # Default value comes from `postgresql::params::password_encryption` and changes based on the `postgresql::globals::version`. + # @param salt + # Use a specific salt value for scram-sha-256, default is username + # + # @return + # The postgresql password hash from the clear text username / password. + dispatch :default_impl do + required_param 'Variant[String[1], Integer]', :username + required_param 'Variant[String[1], Sensitive[String[1]], Integer]', :password + optional_param 'Boolean', :sensitive + # The following Enum is also defined in `types/pg_password_encryption.pp` but type alias can't be used in Deferred functions. + optional_param 'Optional[Enum["md5", "scram-sha-256"]]', :hash + optional_param 'Optional[Variant[String[1], Integer]]', :salt + return_type 'Variant[String, Sensitive[String]]' + end + + def default_impl(username, password, sensitive = false, hash = nil, salt = nil) + hash = call_function('postgresql::default', 'password_encryption') if hash.nil? + password = password.unwrap if password.respond_to?(:unwrap) + if password.is_a?(String) && password.match?(%r{^(md5[0-9a-f]{32}$|SCRAM-SHA-256\$)}) + return Puppet::Pops::Types::PSensitiveType::Sensitive.new(password) if sensitive + + return password + end + pass = case hash + when 'md5', nil # ensure default value when definded with nil + "md5#{Digest::MD5.hexdigest(password.to_s + username.to_s)}" + when 'scram-sha-256' + pg_sha256(password, (salt || username)) + else + raise(Puppet::ParseError, "postgresql::postgresql_password(): got unkown hash type '#{hash}'") + end + if sensitive + Puppet::Pops::Types::PSensitiveType::Sensitive.new(pass) + else + pass + end + end + + def pg_sha256(password, salt) + digest = digest_key(password, salt) + 'SCRAM-SHA-256$%{iterations}:%{salt}$%{client_key}:%{server_key}' % { + iterations: '4096', + salt: Base64.strict_encode64(salt), + client_key: Base64.strict_encode64(client_key(digest)), + server_key: Base64.strict_encode64(server_key(digest)) + } + end + + def digest_key(password, salt) + OpenSSL::KDF.pbkdf2_hmac( + password, + salt: salt, + iterations: 4096, + length: 32, + hash: OpenSSL::Digest.new('SHA256'), + ) + end + + def client_key(digest_key) + hmac = OpenSSL::HMAC.new(digest_key, OpenSSL::Digest.new('SHA256')) + hmac << 'Client Key' + hmac.digest + OpenSSL::Digest.new('SHA256').digest hmac.digest + end + + def server_key(digest_key) + hmac = OpenSSL::HMAC.new(digest_key, OpenSSL::Digest.new('SHA256')) + hmac << 'Server Key' + hmac.digest + end +end diff --git a/lib/puppet/functions/postgresql/prepend_sql_password.rb b/lib/puppet/functions/postgresql/prepend_sql_password.rb new file mode 100644 index 0000000000..f90f65e11a --- /dev/null +++ b/lib/puppet/functions/postgresql/prepend_sql_password.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# @summary This function exists for usage of a role password that is a deferred function +Puppet::Functions.create_function(:'postgresql::prepend_sql_password') do + # @param password + # The clear text `password` + dispatch :default_impl do + required_param 'String', :password + return_type 'String' + end + def default_impl(password) + "ENCRYPTED PASSWORD '#{password}'" + end +end diff --git a/lib/puppet/functions/postgresql_escape.rb b/lib/puppet/functions/postgresql_escape.rb new file mode 100644 index 0000000000..56288f2636 --- /dev/null +++ b/lib/puppet/functions/postgresql_escape.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# @summary DEPRECATED. Use the namespaced function [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape) instead. +Puppet::Functions.create_function(:postgresql_escape) do + dispatch :deprecation_gen do + repeated_param 'Any', :args + end + def deprecation_gen(*args) + call_function('deprecation', 'postgresql_escape', 'This method is deprecated, please use postgresql::postgresql_escape instead.') + call_function('postgresql::postgresql_escape', *args) + end +end diff --git a/lib/puppet/functions/postgresql_password.rb b/lib/puppet/functions/postgresql_password.rb new file mode 100644 index 0000000000..e6799f1856 --- /dev/null +++ b/lib/puppet/functions/postgresql_password.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# @summary DEPRECATED. Use the namespaced function [`postgresql::postgresql_password`](#postgresqlpostgresql_password) instead. +Puppet::Functions.create_function(:postgresql_password) do + dispatch :deprecation_gen do + repeated_param 'Any', :args + end + def deprecation_gen(*args) + call_function('deprecation', 'postgresql_password', 'This method is deprecated, please use postgresql::postgresql_password instead.') + call_function('postgresql::postgresql_password', *args) + end +end diff --git a/lib/puppet/parser/functions/postgresql_acls_to_resources_hash.rb b/lib/puppet/parser/functions/postgresql_acls_to_resources_hash.rb deleted file mode 100644 index 7fa785486c..0000000000 --- a/lib/puppet/parser/functions/postgresql_acls_to_resources_hash.rb +++ /dev/null @@ -1,76 +0,0 @@ -module Puppet::Parser::Functions - newfunction(:postgresql_acls_to_resources_hash, :type => :rvalue, :doc => <<-EOS - This internal function translates the ipv(4|6)acls format into a resource - suitable for create_resources. It is not intended to be used outside of the - postgresql internal classes/defined resources. - - This function accepts an array of strings that are pg_hba.conf rules. It - will return a hash that can be fed into create_resources to create multiple - individual pg_hba_rule resources. - - The second parameter is an identifier that will be included in the namevar - to provide uniqueness. It must be a string. - - The third parameter is an order offset, so you can start the order at an - arbitrary starting point. - EOS - ) do |args| - func_name = "postgresql_acls_to_resources_hash()" - - raise(Puppet::ParseError, "#{func_name}: Wrong number of arguments " + - "given (#{args.size} for 3)") if args.size != 3 - - acls = args[0] - raise(Puppet::ParseError, "#{func_name}: first argument must be an array") \ - unless acls.instance_of? Array - - id = args[1] - raise(Puppet::ParseError, "#{func_name}: second argument must be a string") \ - unless id.instance_of? String - - offset = args[2].to_i - raise(Puppet::ParseError, "#{func_name}: third argument must be a number") \ - unless offset.instance_of? Fixnum - - resources = {} - acls.each do |acl| - index = acls.index(acl) - - parts = acl.split - - raise(Puppet::ParseError, "#{func_name}: acl line #{index} does not " + - "have enough parts") unless parts.length >= 4 - - resource = { - 'type' => parts[0], - 'database' => parts[1], - 'user' => parts[2], - 'order' => format('%03d', offset + index), - } - if parts[0] == 'local' then - resource['auth_method'] = parts[3] - if parts.length > 4 then - resource['auth_option'] = parts.last(parts.length - 4).join(" ") - end - else - if parts[4] =~ /^\d/ - resource['address'] = parts[3] + ' ' + parts[4] - resource['auth_method'] = parts[5] - - if parts.length > 6 then - resource['auth_option'] = parts.last(parts.length - 6).join(" ") - end - else - resource['address'] = parts[3] - resource['auth_method'] = parts[4] - - if parts.length > 5 then - resource['auth_option'] = parts.last(parts.length - 5).join(" ") - end - end - end - resources["postgresql class generated rule #{id} #{index}"] = resource - end - resources - end -end diff --git a/lib/puppet/parser/functions/postgresql_escape.rb b/lib/puppet/parser/functions/postgresql_escape.rb deleted file mode 100644 index 4089a4e94d..0000000000 --- a/lib/puppet/parser/functions/postgresql_escape.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'digest/md5' - -module Puppet::Parser::Functions - newfunction(:postgresql_escape, :type => :rvalue, :doc => <<-EOS - Safely escapes a string using $$ using a random tag which should be consistent - EOS - ) do |args| - - raise(Puppet::ParseError, "postgresql_escape(): Wrong number of arguments " + - "given (#{args.size} for 1)") if args.size != 1 - - password = args[0] - - if password !~ /\$\$/ - retval = "$$#{password}$$" - else - escape = Digest::MD5.hexdigest(password)[0..5].gsub(/\d/,'') - until password !~ /#{escape}/ - escape = Digest::MD5.hexdigest(escape)[0..5].gsub(/\d/,'') - end - retval = "$#{escape}$#{password}$#{escape}$" - end - retval - end -end diff --git a/lib/puppet/parser/functions/postgresql_password.rb b/lib/puppet/parser/functions/postgresql_password.rb deleted file mode 100644 index 0689e0e5b0..0000000000 --- a/lib/puppet/parser/functions/postgresql_password.rb +++ /dev/null @@ -1,18 +0,0 @@ -# hash a string as mysql's "PASSWORD()" function would do it -require 'digest/md5' - -module Puppet::Parser::Functions - newfunction(:postgresql_password, :type => :rvalue, :doc => <<-EOS - Returns the postgresql password hash from the clear text username / password. - EOS - ) do |args| - - raise(Puppet::ParseError, "postgresql_password(): Wrong number of arguments " + - "given (#{args.size} for 2)") if args.size != 2 - - username = args[0] - password = args[1] - - 'md5' + Digest::MD5.hexdigest(password + username) - end -end diff --git a/lib/puppet/provider/postgresql_conf/parsed.rb b/lib/puppet/provider/postgresql_conf/parsed.rb deleted file mode 100644 index ebe1f70941..0000000000 --- a/lib/puppet/provider/postgresql_conf/parsed.rb +++ /dev/null @@ -1,42 +0,0 @@ -require 'puppet/provider/parsedfile' - -Puppet::Type.type(:postgresql_conf).provide( - :parsed, - :parent => Puppet::Provider::ParsedFile, - :default_target => '/etc/postgresql.conf', - :filetype => :flat -) do - desc "Set key/values in postgresql.conf." - - text_line :comment, :match => /^\s*#/ - text_line :blank, :match => /^\s*$/ - - record_line :parsed, - :fields => %w{name value comment}, - :optional => %w{comment}, - :match => /^\s*([\w\.]+)\s*=?\s*(.*?)(?:\s*#\s*(.*))?\s*$/, - :to_line => proc { |h| - - # simple string and numeric values don't need to be enclosed in quotes - if h[:value].is_a?(Fixnum) - val = h[:value].to_s - else - val = h[:value] - end - dontneedquote = val.match(/^(\w+)$/) - dontneedequal = h[:name].match(/^(include|include_if_exists)$/i) - - str = h[:name].downcase # normalize case - str += dontneedequal ? ' ' : ' = ' - str += "'" unless dontneedquote && !dontneedequal - str += val - str += "'" unless dontneedquote && !dontneedequal - str += " # #{h[:comment]}" unless (h[:comment].nil? or h[:comment] == :absent) - str - }, - :post_parse => proc { |h| - h[:name].downcase! # normalize case - h[:value].gsub!(/(^'|'$)/, '') # strip out quotes - } - -end diff --git a/lib/puppet/provider/postgresql_conf/ruby.rb b/lib/puppet/provider/postgresql_conf/ruby.rb new file mode 100644 index 0000000000..f21caf2b5c --- /dev/null +++ b/lib/puppet/provider/postgresql_conf/ruby.rb @@ -0,0 +1,158 @@ +# frozen_string_literal: true + +# This provider is used to manage postgresql.conf files +# It uses ruby to parse the config file and +# to add, remove or modify settings. +# +# The provider is able to parse postgresql.conf files with the following format: +# key = value # comment + +Puppet::Type.type(:postgresql_conf).provide(:ruby) do + desc 'Set keys, values and comments in a postgresql config file.' + + # The function parses the postgresql.conf and figures out which active settings exist in a config file and returns an array of hashes + # + def parse_config + # regex to match active keys, values and comments + active_values_regex = %r{^\s*(?[\w.]+)\s*=?\s*(?.*?)(?:\s*#\s*(?.*))?\s*$} + # empty array to be filled with hashes + active_settings = [] + # iterate the file and construct a hash for every matching/active setting + # the hash is pushed to the array and the array is returned + File.foreach(resource[:target]).with_index(1) do |line, line_number| + matches = line.match(active_values_regex) + if matches + value = if matches[:value].to_i.to_s == matches[:value] + matches[:value].to_i + elsif matches[:value].to_f.to_s == matches[:value] + matches[:value].to_f + else + matches[:value].delete("'") + end + attributes_hash = { line_number: line_number, key: matches[:key], ensure: 'present', value: value, comment: matches[:comment] } + active_settings.push(attributes_hash) + end + end + Puppet.debug("DEBUG: parse_config Active Settings found in PostgreSQL config file: #{active_settings}") + active_settings + end + + # Deletes an existing header from a parsed postgresql.conf configuration file + # + # @param [Array] lines of the parsed postgresql configuration file + def delete_header(lines) + header_regex = %r{^# HEADER:.*} + lines.delete_if do |entry| + entry.match?(header_regex) + end + end + + # Adds a header to a parsed postgresql.conf configuration file, after all other changes are made + # + # @param [Array] lines of the parsed postgresql configuration file + def add_header(lines) + timestamp = Time.now.strftime('%F %T %z') + header = ["# HEADER: This file was autogenerated at #{timestamp}\n", + "# HEADER: by puppet. While it can still be managed manually, it\n", + "# HEADER: is definitely not recommended.\n"] + header + lines + end + + # This function writes the config file, it removes the old header, adds a new one and writes the file + # + # @param [Array] lines of the parsed postgresql configuration file + def write_config(lines) + lines = delete_header(lines) + lines = add_header(lines) + File.write(resource[:target], lines.join) + end + + # check, if resource exists in postgresql.conf file + def exists? + select = parse_config.select { |hash| hash[:key] == resource[:key] } + raise Puppet::Error, "found multiple config items of #{resource[:key]}, please fix this" if select.length > 1 + return false if select.empty? + + @result = select.first + Puppet.debug("DEBUG: exists? @result: #{@result}") + true + end + + # remove resource if exists and is set to absent + def destroy + entry_regex = %r{#{resource[:key]}.*=.*#{resource[:value]}} + lines = File.readlines(resource[:target]) + + lines.delete_if do |entry| + entry.match?(entry_regex) + end + write_config(lines) + end + + # create resource if it does not exists + def create + lines = File.readlines(resource[:target]) + new_line = line(key: resource[:key], value: resource[:value], comment: resource[:comment]) + + lines.push(new_line) + write_config(lines) + end + + # getter - get value of a resource + def value + @result[:value] + end + + # getter - get comment of a resource + def comment + @result[:comment] + end + + # setter - set value of a resource + def value=(_value) + lines = File.readlines(resource[:target]) + active_values_regex = %r{^\s*(?[\w.]+)\s*=?\s*(?.*?)(?:\s*#\s*(?.*))?\s*$} + new_line = line(key: resource[:key], value: resource[:value], comment: resource[:comment]) + + lines.each_with_index do |line, index| + matches = line.to_s.match(active_values_regex) + lines[index] = new_line if matches && (matches[:key] == resource[:key] && matches[:value] != resource[:value]) + end + write_config(lines) + end + + # setter - set comment of a resource + def comment=(_comment) + lines = File.readlines(resource[:target]) + active_values_regex = %r{^\s*(?[\w.]+)\s*=?\s*(?.*?)(?:\s*#\s*(?.*))?\s*$} + new_line = line(key: resource[:key], value: resource[:value], comment: resource[:comment]) + + lines.each_with_index do |line, index| + matches = line.to_s.match(active_values_regex) + lines[index] = new_line if matches && (matches[:key] == resource[:key] && matches[:comment] != resource[:comment]) + end + write_config(lines) + end + + private + + # Takes elements for a postgresql.conf configuration line and formats them properly + # + # @param [String] key postgresql.conf configuration option + # @param [String] value the value for the configuration option + # @param [String] comment optional comment that will be added at the end of the line + # @return [String] line the whole line for the config file, with \n + def line(key: '', value: '', comment: nil) + value = value.to_s if value.is_a?(Numeric) + dontneedquote = value.match(%r{^(\d+.?\d+|\w+)$}) + dontneedequal = key.match(%r{^(include|include_if_exists)$}i) + line = key.downcase # normalize case + line += dontneedequal ? ' ' : ' = ' + line += "'" unless dontneedquote && !dontneedequal + line += value + line += "'" unless dontneedquote && !dontneedequal + line += " # #{comment}" unless comment.nil? || comment == :absent + line += "\n" + line + end +end diff --git a/lib/puppet/provider/postgresql_conn_validator/ruby.rb b/lib/puppet/provider/postgresql_conn_validator/ruby.rb new file mode 100644 index 0000000000..79b8cff1ff --- /dev/null +++ b/lib/puppet/provider/postgresql_conn_validator/ruby.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) +require 'puppet/util/postgresql_validator' + +# This file contains a provider for the resource type `postgresql_conn_validator`, +# which validates the puppetdb connection by attempting an https connection. + +Puppet::Type.type(:postgresql_conn_validator).provide(:ruby) do + desc "A provider for the resource type `postgresql_conn_validator`, + which validates the PostgreSQL connection by attempting a query + to the target PostgreSQL server." + + # Test to see if the resource exists, returns true if it does, false if it + # does not. + # + # Here we simply monopolize the resource API, to execute a test to see if the + # database is connectable. When we return a state of `false` it triggers the + # create method where we can return an error message. + # + # @return [bool] did the test succeed? + def exists? + validator.attempt_connection(resource[:sleep], resource[:tries]) + end + + # This method is called when the exists? method returns false. + # + # @return [void] + def create + # If `#create` is called, that means that `#exists?` returned false, which + # means that the connection could not be established... so we need to + # cause a failure here. + raise Puppet::Error, "Unable to connect to PostgreSQL server! (#{resource[:host]}:#{resource[:port]})" + end + + # Returns the existing validator, if one exists otherwise creates a new object + # from the class. + # + # @api private + def validator + @validator ||= Puppet::Util::PostgresqlValidator.new(resource) + end +end diff --git a/lib/puppet/provider/postgresql_psql/ruby.rb b/lib/puppet/provider/postgresql_psql/ruby.rb index 690e437be3..671d6679bc 100644 --- a/lib/puppet/provider/postgresql_psql/ruby.rb +++ b/lib/puppet/provider/postgresql_psql/ruby.rb @@ -1,22 +1,22 @@ -Puppet::Type.type(:postgresql_psql).provide(:ruby) do +# frozen_string_literal: true +Puppet::Type.type(:postgresql_psql).provide(:ruby) do + desc 'Postgres psql provider' def run_unless_sql_command(sql) # for the 'unless' queries, we wrap the user's query in a 'SELECT COUNT', # which makes it easier to parse and process the output. - run_sql_command('SELECT COUNT(*) FROM (' << sql << ') count') + run_sql_command("SELECT COUNT(*) FROM (#{sql}) count") end def run_sql_command(sql) - if resource[:search_path] - sql = "set search_path to #{Array(resource[:search_path]).join(',')}; #{sql}" - end + sql = "set search_path to #{Array(resource[:search_path]).join(',')}; #{sql}" if resource[:search_path] command = [resource[:psql_path]] - command.push("-d", resource[:db]) if resource[:db] - command.push("-p", resource[:port]) if resource[:port] - command.push("-t", "-c", '"' + sql.gsub('"', '\"') + '"') + command.push('-d', resource[:db]) if resource[:db] + command.push('-p', resource[:port].to_s) if resource[:port] + command.push('-t', '-X', '-c', sql) - environment = get_environment + environment = fetch_environment if resource[:cwd] Dir.chdir resource[:cwd] do @@ -29,49 +29,39 @@ def run_sql_command(sql) private - def get_environment - environment = resource[:connect_settings] || {} - if envlist = resource[:environment] - envlist = [envlist] unless envlist.is_a? Array - envlist.each do |setting| - if setting =~ /^(\w+)=((.|\n)+)$/ - env_name = $1 - value = $2 - if environment.include?(env_name) || environment.include?(env_name.to_sym) + def fetch_environment + environment = (resource[:connect_settings] || {}).dup + envlist = resource[:environment] + return environment unless envlist + + envlist = [envlist] unless envlist.is_a? Array + envlist.each do |setting| + if setting =~ %r{^(\w+)=((.|\n)+)$} + env_name = Regexp.last_match(1) + value = Regexp.last_match(2) + if environment.include?(env_name) || environment.include?(env_name.to_sym) + if env_name == 'NEWPGPASSWD' + warning "Overriding environment setting '#{env_name}' with '****'" + else warning "Overriding environment setting '#{env_name}' with '#{value}'" end - environment[env_name] = value - else - warning "Cannot understand environment setting #{setting.inspect}" end + environment[env_name] = value + else + warning "Cannot understand environment setting #{setting.inspect}" end end - return environment + environment end def run_command(command, user, group, environment) - command = command.join ' ' - environment = get_environment - if Puppet::PUPPETVERSION.to_f < 3.0 - require 'puppet/util/execution' - Puppet::Util::Execution.withenv environment do - Puppet::Util::SUIDManager.run_and_capture(command, user, group) - end - elsif Puppet::PUPPETVERSION.to_f < 3.4 - Puppet::Util.withenv environment do - Puppet::Util::SUIDManager.run_and_capture(command, user, group) - end - else - output = Puppet::Util::Execution.execute(command, { - :uid => user, - :gid => group, - :failonfail => false, - :combine => true, - :override_locale => true, - :custom_environment => environment, - }) - [output, $CHILD_STATUS.dup] - end + output = Puppet::Util::Execution.execute(command, uid: user, + gid: group, + failonfail: false, + combine: true, + override_locale: true, + custom_environment: environment, + sensitive: resource[:sensitive] == :true) + [output, $CHILD_STATUS.dup] end - end diff --git a/lib/puppet/provider/postgresql_replication_slot/ruby.rb b/lib/puppet/provider/postgresql_replication_slot/ruby.rb index cc49f7b4cd..31271cc51b 100644 --- a/lib/puppet/provider/postgresql_replication_slot/ruby.rb +++ b/lib/puppet/provider/postgresql_replication_slot/ruby.rb @@ -1,22 +1,21 @@ +# frozen_string_literal: true + Puppet::Type.type(:postgresql_replication_slot).provide(:ruby) do - # For confinement - commands :psql => 'psql' + desc 'For confinement' + commands psql: 'psql' def self.instances - run_sql_command('SELECT * FROM pg_replication_slots;')[0].split("\n").select { |l| l =~ /\|/ }.map do |l| - name, *others = l.strip.split(/\s+\|\s+/) - new({ - :name => name, - :ensure => :present, - }) + run_sql_command('SELECT * FROM pg_replication_slots;')[0].split("\n").select { |l| l.include?('|') }.map do |l| + name, *_others = l.strip.split(%r{\s+\|\s+}) + new(name: name, + ensure: :present) end end def self.prefetch(resources) instances.each do |i| - if slot = resources[i.name] - slot.provider = i - end + slot = resources[i.name] + slot.provider = i if slot end end @@ -26,20 +25,16 @@ def exists? def create output = self.class.run_sql_command("SELECT * FROM pg_create_physical_replication_slot('#{resource[:name]}');") - if output[1].success? - @property_hash[:ensure] = :present - else - raise Puppet::Error, "Failed to create replication slot #{resource[:name]}:\n#{output[0]}" - end + raise Puppet::Error, "Failed to create replication slot #{resource[:name]}:\n#{output[0]}" unless output[1].success? + + @property_hash[:ensure] = :present end def destroy output = self.class.run_sql_command("SELECT pg_drop_replication_slot('#{resource[:name]}');") - if output[1].success? - @property_hash[:ensure] = :absent - else - raise Puppet::Error, "Failed to destroy replication slot #{resource[:name]}:\n#{output[0]}" - end + raise Puppet::Error, "Failed to destroy replication slot #{resource[:name]}:\n#{output[0]}" unless output[1].success? + + @property_hash[:ensure] = :absent end private @@ -47,22 +42,16 @@ def destroy def self.run_sql_command(sql) command = ['psql', '-t', '-c', sql] - self.run_command(command, 'postgres', 'postgres') + run_command(command, 'postgres', 'postgres') end def self.run_command(command, user, group) - if Puppet::PUPPETVERSION.to_f < 3.4 - Puppet::Util::SUIDManager.run_and_capture(command, user, group) - else - output = Puppet::Util::Execution.execute(command, { - :uid => user, - :gid => group, - :failonfail => false, - :combine => true, - :override_locale => true, - :custom_environment => {} - }) - [output, $CHILD_STATUS.dup] - end + output = Puppet::Util::Execution.execute(command, uid: user, + gid: group, + failonfail: false, + combine: true, + override_locale: true, + custom_environment: {}) + [output, $CHILD_STATUS.dup] end end diff --git a/lib/puppet/type/postgresql_conf.rb b/lib/puppet/type/postgresql_conf.rb index 6dbaaee368..5cd753e20f 100644 --- a/lib/puppet/type/postgresql_conf.rb +++ b/lib/puppet/type/postgresql_conf.rb @@ -1,29 +1,41 @@ -Puppet::Type.newtype(:postgresql_conf) do - - @doc = "This type allows puppet to manage postgresql.conf parameters." +# frozen_string_literal: true +Puppet::Type.newtype(:postgresql_conf) do + @doc = 'This type allows puppet to manage postgresql.conf parameters.' ensurable newparam(:name) do - desc "The postgresql parameter name to manage." - isnamevar + desc 'A unique title for the resource.' + newvalues(%r{^[\w.]+$}) + end - newvalues(/^[\w\.]+$/) + newparam(:key) do + desc 'The Postgresql parameter to manage.' + newvalues(%r{^[\w.]+$}) end newproperty(:value) do - desc "The value to set for this parameter." - end + desc 'The value to set for this parameter.' + newvalues(%r{^(\S.*)?$}) - newproperty(:target) do - desc "The path to postgresql.conf" - defaultto { - if @resource.class.defaultprovider.ancestors.include?(Puppet::Provider::ParsedFile) - @resource.class.defaultprovider.default_target + munge do |value| + if value.to_i.to_s == value + value.to_i + elsif value.to_f.to_s == value + value.to_f else - nil + value end - } + end + end + + newproperty(:comment) do + desc 'The comment to set for this parameter.' + newvalues(%r{^[\w\W]+$}) end + newparam(:target) do + desc 'The path to the postgresql config file' + newvalues(%r{^/\S+[a-z0-9(/)-]*\w+.conf$}) + end end diff --git a/lib/puppet/type/postgresql_conn_validator.rb b/lib/puppet/type/postgresql_conn_validator.rb new file mode 100644 index 0000000000..8c8cd49e9e --- /dev/null +++ b/lib/puppet/type/postgresql_conn_validator.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +Puppet::Type.newtype(:postgresql_conn_validator) do + @doc = <<-EOS + @summary Verify if a connection can be successfully established + + Verify that a connection can be successfully established between a node + and the PostgreSQL server. Its primary use is as a precondition to + prevent configuration changes from being applied if the PostgreSQL + server cannot be reached, but it could potentially be used for other + purposes such as monitoring. + EOS + + ensurable do + desc 'Ensure connection validation' + defaultvalues + defaultto :present + end + + newparam(:name, namevar: true) do + desc 'An arbitrary name used as the identity of the resource.' + end + + newparam(:db_name) do + desc 'The name of the database you are trying to validate a connection with.' + end + + newparam(:db_username) do + desc 'A user that has access to the target PostgreSQL database.' + end + + newparam(:db_password) do + desc 'The password required to access the target PostgreSQL database.' + end + + newparam(:host) do + desc 'The DNS name or IP address of the server where PostgreSQL should be running.' + end + + newparam(:port) do + desc 'The port that the PostgreSQL server should be listening on.' + + validate do |value| + Integer(value) + end + munge do |value| + Integer(value) + end + end + + newparam(:connect_settings) do + desc 'Hash of environment variables for connection to a db.' + end + + newparam(:sleep) do + desc 'The length of sleep time between connection tries.' + + validate do |value| + Integer(value) + end + munge do |value| + Integer(value) + end + + defaultto 2 + end + + newparam(:tries) do + desc 'The number of tries to validate the connection to the target PostgreSQL database.' + + validate do |value| + Integer(value) + end + munge do |value| + Integer(value) + end + + defaultto 10 + end + + newparam(:psql_path) do + desc 'Path to the psql command.' + end + + newparam(:run_as) do + desc 'System user that will run the psql command.' + end + + newparam(:command) do + desc 'Command to run against target database.' + + defaultto 'SELECT 1' + end +end diff --git a/lib/puppet/type/postgresql_psql.rb b/lib/puppet/type/postgresql_psql.rb index 5b2702c2e8..d0101857c0 100644 --- a/lib/puppet/type/postgresql_psql.rb +++ b/lib/puppet/type/postgresql_psql.rb @@ -1,7 +1,8 @@ -Puppet::Type.newtype(:postgresql_psql) do +# frozen_string_literal: true +Puppet::Type.newtype(:postgresql_psql) do newparam(:name) do - desc "An arbitrary tag for your own reference; the name of the message." + desc 'An arbitrary tag for your own reference; the name of the message.' isnamevar end @@ -14,88 +15,92 @@ # a sync, else return the expected SQL command so no sync takes place def retrieve if @resource.should_run_sql - return :notrun + :notrun else - return self.should + should end end def sync output, status = provider.run_sql_command(value) - self.fail("Error executing SQL; psql returned #{status}: '#{output}'") unless status == 0 + raise("Error executing SQL; psql returned #{status}: '#{output}'") unless status.to_i.zero? end end newparam(:unless) do - desc "An optional SQL command to execute prior to the main :command; " + - "this is generally intended to be used for idempotency, to check " + - "for the existence of an object in the database to determine whether " + - "or not the main SQL command needs to be executed at all." + desc <<-DOC + An optional SQL command to execute prior to the main :command; + this is generally intended to be used for idempotency, to check + for the existence of an object in the database to determine whether + or not the main SQL command needs to be executed at all.' + DOC # Return true if a matching row is found def matches(value) output, status = provider.run_unless_sql_command(value) - self.fail("Error evaluating 'unless' clause, returned #{status}: '#{output}'") unless status == 0 + fail("Error evaluating 'unless' clause, returned #{status}: '#{output}'") unless status.to_i.zero? # rubocop:disable Style/SignalException result_count = output.strip.to_i - self.debug("Found #{result_count} row(s) executing 'unless' clause") - result_count > 0 + debug("Found #{result_count} row(s) executing 'unless' clause") + result_count.positive? end end newparam(:onlyif) do - desc "An optional SQL command to execute prior to the main :command; " + - "this is generally intended to be used for idempotency, to check " + - "for the existence of an object in the database to determine whether " + - "or not the main SQL command needs to be executed at all." + desc <<-DOC + An optional SQL command to execute prior to the main :command; + this is generally intended to be used for idempotency, to check + for the existence of an object in the database to determine whether + or not the main SQL command needs to be executed at all. + DOC # Return true if a matching row is found def matches(value) output, status = provider.run_unless_sql_command(value) status = output.exitcode if status.nil? - self.fail("Error evaluating 'onlyif' clause, returned #{status}: '#{output}'") unless status == 0 + raise("Error evaluating 'onlyif' clause, returned #{status}: '#{output}'") unless status.to_i.zero? result_count = output.strip.to_i - self.debug("Found #{result_count} row(s) executing 'onlyif' clause") - result_count > 0 + debug("Found #{result_count} row(s) executing 'onlyif' clause") + result_count.positive? end end newparam(:connect_settings) do - desc "Connection settings that will be used when connecting to postgres" + desc 'Connection settings that will be used when connecting to postgres' end newparam(:db) do - desc "The name of the database to execute the SQL command against, this overrides any PGDATABASE value in connect_settings" + desc 'The name of the database to execute the SQL command against, this overrides any PGDATABASE value in connect_settings' end newparam(:port) do - desc "The port of the database server to execute the SQL command against, this overrides any PGPORT value in connect_settings." + desc 'The port of the database server to execute the SQL command against, this overrides any PGPORT value in connect_settings.' end newparam(:search_path) do - desc "The schema search path to use when executing the SQL command" + desc 'The schema search path to use when executing the SQL command' end newparam(:psql_path) do - desc "The path to psql executable." - defaultto("psql") + desc 'The path to psql executable.' + defaultto('psql') end newparam(:psql_user) do - desc "The system user account under which the psql command should be executed." - defaultto("postgres") + desc 'The system user account under which the psql command should be executed.' + defaultto('postgres') end newparam(:psql_group) do - desc "The system user group account under which the psql command should be executed." - defaultto("postgres") + desc 'The system user group account under which the psql command should be executed.' + defaultto('postgres') end - newparam(:cwd, :parent => Puppet::Parameter::Path) do - desc "The working directory under which the psql command should be executed." - defaultto("/tmp") + newparam(:cwd, parent: Puppet::Parameter::Path) do + desc 'The working directory under which the psql command should be executed.' + defaultto('/tmp') end newparam(:environment) do @@ -105,31 +110,56 @@ def matches(value) validate do |values| Array(values).each do |value| - unless value =~ /\w+=/ - raise ArgumentError, "Invalid environment setting '#{value}'" - end + raise ArgumentError, "Invalid environment setting '#{value}'" unless %r{\w+=}.match?(value) end end end - newparam(:refreshonly, :boolean => true) do + newparam(:refreshonly, boolean: true) do desc "If 'true', then the SQL will only be executed via a notify/subscribe event." defaultto(:false) newvalues(:true, :false) end + newparam(:instance) do + desc 'The postgresql instance under which the psql command should be executed.' + defaultto('main') + end + + newparam(:sensitive, boolean: true) do + desc "If 'true', then the executed command will not be echoed into the log. Use this to protect sensitive information passing through." + + defaultto(:false) + newvalues(:true, :false) + end + + autorequire(:anchor) do + ["postgresql::server::service::end::#{self[:instance]}"] + end + def should_run_sql(refreshing = false) onlyif_param = @parameters[:onlyif] unless_param = @parameters[:unless] return false if !onlyif_param.nil? && !onlyif_param.value.nil? && !onlyif_param.matches(onlyif_param.value) return false if !unless_param.nil? && !unless_param.value.nil? && unless_param.matches(unless_param.value) return false if !refreshing && @parameters[:refreshonly].value == :true + true end def refresh - self.property(:command).sync if self.should_run_sql(true) + property(:command).sync if should_run_sql(true) end + private + + def set_sensitive_parameters(sensitive_parameters) + # Respect sensitive commands + if sensitive_parameters.include?(:unless) + sensitive_parameters.delete(:unless) + parameter(:unless).sensitive = true + end + super(sensitive_parameters) + end end diff --git a/lib/puppet/type/postgresql_replication_slot.rb b/lib/puppet/type/postgresql_replication_slot.rb index b5b317cd93..c60584f0d9 100644 --- a/lib/puppet/type/postgresql_replication_slot.rb +++ b/lib/puppet/type/postgresql_replication_slot.rb @@ -1,16 +1,19 @@ +# frozen_string_literal: true + Puppet::Type.newtype(:postgresql_replication_slot) do - @doc = "Manages Postgresql replication slots. + @doc = <<~EOS + @summary Manages Postgresql replication slots. -This type allows to create and destroy replication slots -to register warm standby replication on a Postgresql -master server. -" + This type allows to create and destroy replication slots + to register warm standby replication on a Postgresql + primary server. + EOS ensurable newparam(:name) do - desc "The name of the slot to create. Must be a valid replication slot name." + desc 'The name of the slot to create. Must be a valid replication slot name.' isnamevar - newvalues /^[a-z0-9_]+$/ + newvalues %r{^[a-z0-9_]+$} end end diff --git a/lib/puppet/util/postgresql_validator.rb b/lib/puppet/util/postgresql_validator.rb new file mode 100644 index 0000000000..6a3152b64f --- /dev/null +++ b/lib/puppet/util/postgresql_validator.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Puppet::Util + # postgresql_validator.rb + class PostgresqlValidator + attr_reader :resource + + def initialize(resource) + @resource = resource + end + + def build_psql_cmd + cmd = [@resource[:psql_path], '--tuples-only', '--quiet', '--no-psqlrc'] + + args = { + host: '--host', + port: '--port', + db_username: '--username', + db_name: '--dbname', + command: '--command' + } + + args.each do |k, v| + if @resource[k] + cmd.push v + cmd.push @resource[k] + end + end + + cmd + end + + def connect_settings + result = @resource[:connect_settings] || {} + result['PGPASSWORD'] = @resource[:db_password] if @resource[:db_password] + result + end + + def attempt_connection(sleep_length, tries) + (0..tries - 1).each do |_try| + Puppet.debug "PostgresqlValidator.attempt_connection: Attempting connection to #{@resource[:db_name]}" + cmd = build_psql_cmd + Puppet.debug "PostgresqlValidator.attempt_connection: #{cmd.inspect}" + result = Execution.execute(cmd, custom_environment: connect_settings, uid: @resource[:run_as]) + + if result && !result.empty? + Puppet.debug "PostgresqlValidator.attempt_connection: Connection to #{@resource[:db_name] || connect_settings.select { |elem| elem.include?('PGDATABASE') }} successful!" + return true + else + Puppet.warning "PostgresqlValidator.attempt_connection: Sleeping for #{sleep_length} seconds" + sleep sleep_length + end + end + false + end + end +end diff --git a/manifests/backup/pg_dump.pp b/manifests/backup/pg_dump.pp new file mode 100644 index 0000000000..64ac5cfb4f --- /dev/null +++ b/manifests/backup/pg_dump.pp @@ -0,0 +1,153 @@ +# @summary +# "Provider" for pg_dump backup +# +# @api private +# +# @param compress +# Whether or not to compress the backup. Support for compression also depends on other backup parameters. +# @param databases +# Databases to backup. By default `[]` will back up all databases. +# @param db_user +# PostgreSQL user to create with superuser privileges. +# @param db_password +# Password to create for `$db_user`. +# @param dir +# Directory to store backup. +# @param dir_mode +# Permissions applied to the backup directory. This parameter is passed directly to the file resource. +# @param dir_owner +# Owner for the backup directory. This parameter is passed directly to the file resource. +# @param dir_group +# Group owner for the backup directory. This parameter is passed directly to the file resource. +# @param format +# Backup format to use, must be supported by pg_dump or pg_dumpall. The choice will affect other options, i.e. compression. +# @param install_cron +# Manage installation of cron package. +# @param manage_user +# Manage creation of the backup user. +# @param optional_args +# Specifies an array of optional arguments which should be passed through to the backup tool. These options are not validated, +# unsupported options may break the backup. +# @param post_script +# One or more scripts that are executed when the backup is finished. This could be used to sync the backup to a central store. +# @param pre_script +# One or more scripts that are executed before the backup begins. +# @param rotate +# Backup rotation interval in 24 hour periods. +# @param success_file_path +# Specify a path where upon successful backup a file should be created for checking purposes. +# @param time +# An array of two elements to set the backup time. Allows `['23', '5']` (i.e., 23:05) or `['3', '45']` (i.e., 03:45) for HH:MM times. +# @param weekday +# Weekdays on which the backup job should run. Defaults to `*`. This parameter is passed directly to the cron resource. +class postgresql::backup::pg_dump ( + String[1] $dir, + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $ensure = 'present', + Boolean $compress = true, + Array $databases = [], + Boolean $delete_before_dump = false, + String[1] $dir_group = '0', + String[1] $dir_mode = '0700', + String[1] $dir_owner = 'root', + Enum['plain','custom','directory','tar'] $format = 'plain', + Boolean $install_cron = true, + Boolean $manage_user = false, + Array $optional_args = [], + Stdlib::Absolutepath $pgpass_path = '/root/.pgpass', + Integer $rotate = 30, + Stdlib::Absolutepath $script_path = '/usr/local/sbin/pg_dump.sh', + Stdlib::Absolutepath $success_file_path = '/tmp/pgbackup_success', + String[1] $template = 'postgresql/pg_dump.sh.epp', + Array $time = ['23', '5'], + String[1] $weekday = '*', + Optional[Variant[String, Sensitive[String]]] $db_password = undef, + Optional[String[1]] $db_user = undef, + Optional[String[1]] $package_name = undef, + Optional[String[1]] $post_script = undef, + Optional[String[1]] $pre_script = undef, +) { + # Install required packages + if $package_name { + stdlib::ensure_packages($package_name) + } + if $install_cron { + if $facts['os']['family'] == 'RedHat' { + stdlib::ensure_packages('cronie') + } elsif $facts['os']['family'] != 'FreeBSD' { + stdlib::ensure_packages('cron') + } + } + + # Setup db user with required permissions + if $manage_user and $db_user and $db_password { + # Create user with superuser privileges + postgresql::server::role { $db_user: + ensure => $ensure, + password_hash => postgresql::postgresql_password($db_user, $db_password, true, pick($postgresql::server::password_encryption, 'md5')), + superuser => true, + } + + # Allow authentication from localhost + postgresql::server::pg_hba_rule { 'local access as backup user': + type => 'local', + database => 'all', + user => $db_user, + auth_method => pick($postgresql::server::password_encryption, 'md5'), + order => 1, + } + } + + # Create backup directory + file { $dir: + ensure => 'directory', + mode => $dir_mode, + owner => $dir_owner, + group => $dir_group, + } + + # Create backup script + file { $script_path: + ensure => $ensure, + mode => '0700', + owner => 'root', + group => '0', # Use GID for compat with Linux and BSD. + content => epp($template, { + compress => $compress, + databases => $databases, + db_user => $db_user, + delete_before_dump => $delete_before_dump, + dir => $dir, + format => $format, + optional_args => $optional_args, + post_script => $post_script, + pre_script => $pre_script, + rotate => $rotate, + success_file_path => $success_file_path, + } + ), + } + + # Create password file for pg_dump + file { $pgpass_path: + ensure => $ensure, + mode => '0600', + owner => 'root', + group => '0', # Use GID for compat with Linux and BSD. + content => inline_epp ( '*:*:*:<%= $db_user %>:<%= $db_password %>', { + db_password => $db_password, + db_user => $db_user, + } + ), + show_diff => false, + } + + # Create cron job + cron { 'pg_dump backup job': + ensure => $ensure, + command => $script_path, + user => 'root', + hour => $time[0], + minute => $time[1], + weekday => $weekday, + } +} diff --git a/manifests/client.pp b/manifests/client.pp index 8cc6230ac1..7aa952fddf 100644 --- a/manifests/client.pp +++ b/manifests/client.pp @@ -1,25 +1,35 @@ -# Install client cli tool. See README.md for more details. +# @summary Installs PostgreSQL client software. Set the following parameters if you have a custom version you would like to install. +# +# @note +# Make sure to add any necessary yum or apt repositories if specifying a custom version. +# +# @param file_ensure +# Ensure the connection validation script is present +# @param validcon_script_path +# Optional. Absolute path for the postgresql connection validation script. +# @param package_name +# Sets the name of the PostgreSQL client package. +# @param package_ensure +# Ensure the client package is installed class postgresql::client ( - $file_ensure = 'file', - $validcon_script_path = $postgresql::params::validcon_script_path, - $package_name = $postgresql::params::client_package_name, - $package_ensure = 'present' + Enum['file', 'absent'] $file_ensure = 'file', + Stdlib::Absolutepath $validcon_script_path = $postgresql::params::validcon_script_path, + String[1] $package_name = $postgresql::params::client_package_name, + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', ) inherits postgresql::params { - validate_absolute_path($validcon_script_path) - validate_string($package_name) - - package { 'postgresql-client': - ensure => $package_ensure, - name => $package_name, - tag => 'postgresql', + if $package_name != 'UNSET' { + package { 'postgresql-client': + ensure => $package_ensure, + name => $package_name, + tag => 'puppetlabs-postgresql', + } } file { $validcon_script_path: - ensure => $file_ensure, - source => 'puppet:///modules/postgresql/validate_postgresql_connection.sh', - owner => 0, - group => 0, - mode => '0755', + ensure => $file_ensure, + content => file('postgresql/validate_postgresql_connection.sh'), + owner => 0, + group => 0, + mode => '0755', } - } diff --git a/manifests/dnfmodule.pp b/manifests/dnfmodule.pp new file mode 100644 index 0000000000..ef9316c4d5 --- /dev/null +++ b/manifests/dnfmodule.pp @@ -0,0 +1,20 @@ +# @summary Manage the DNF module +# +# On EL8 and newer and Fedora DNF can manage modules. This is a method of providing +# multiple versions on the same OS. Only one DNF module can be active at the +# same time. +# +# @api private +class postgresql::dnfmodule ( + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $ensure = 'installed', + String[1] $module = 'postgresql', +) { + package { 'postgresql dnf module': + ensure => $ensure, + name => $module, + enable_only => true, + provider => 'dnfmodule', + } + + Package['postgresql dnf module'] -> Package<|tag == 'puppetlabs-postgresql'|> +} diff --git a/manifests/globals.pp b/manifests/globals.pp index 8c2b918c88..f0eb07a9e8 100644 --- a/manifests/globals.pp +++ b/manifests/globals.pp @@ -1,118 +1,249 @@ -# Class for setting cross-class global overrides. See README.md for more -# details. +# @summary Class for setting cross-class global overrides. +# +# @note +# Most server-specific defaults should be overridden in the postgresql::server class. +# This class should be used only if you are using a non-standard OS, or if you are changing elements that can only be changed here, such +# as version or manage_package_repo. +# +# +# @param client_package_name Overrides the default PostgreSQL client package name. +# @param server_package_name Overrides the default PostgreSQL server package name. +# @param contrib_package_name Overrides the default PostgreSQL contrib package name. +# @param devel_package_name Overrides the default PostgreSQL devel package name. +# @param java_package_name Overrides the default PostgreSQL java package name. +# @param docs_package_name Overrides the default PostgreSQL docs package name. +# @param perl_package_name Overrides the default PostgreSQL Perl package name. +# @param plperl_package_name Overrides the default PostgreSQL PL/Perl package name. +# @param plpython_package_name Overrides the default PostgreSQL PL/Python package name. +# @param python_package_name Overrides the default PostgreSQL Python package name. +# @param postgis_package_name Overrides the default PostgreSQL PostGIS package name. +# +# @param service_name Overrides the default PostgreSQL service name. +# @param service_provider Overrides the default PostgreSQL service provider. +# @param service_status Overrides the default status check command for your PostgreSQL service. +# @param default_database Specifies the name of the default database to connect with. +# +# @param validcon_script_path Scipt path for the connection validation check. +# +# @param initdb_path Path to the initdb command. +# @param psql_path Sets the path to the psql command. +# @param pg_hba_conf_path Specifies the path to your pg_hba.conf file. +# @param pg_ident_conf_path Specifies the path to your pg_ident.conf file. +# @param postgresql_conf_path Sets the path to your postgresql.conf file. +# @param postgresql_conf_mode Sets the mode of your postgresql.conf file. Only relevant if manage_postgresql_conf_perms is true. +# @param recovery_conf_path Path to your recovery.conf file. +# @param default_connect_settings Default connection settings. +# +# @param pg_hba_conf_defaults Disables the defaults supplied with the module for pg_hba.conf if set to false. +# +# @param datadir +# Overrides the default PostgreSQL data directory for the target platform. +# Changing the datadir after installation causes the server to come to a full stop before making the change. +# For Red Hat systems, the data directory must be labeled appropriately for SELinux. +# On Ubuntu, you must explicitly set needs_initdb = true to allow Puppet to initialize the database in the new datadir (needs_initdb +# defaults to true on other systems). +# Warning! If datadir is changed from the default, Puppet does not manage purging of the original data directory, which causes it to fail +# if the data directory is changed back to the original +# +# @param confdir Overrides the default PostgreSQL configuration directory for the target platform. +# @param bindir Overrides the default PostgreSQL binaries directory for the target platform. +# @param xlogdir Overrides the default PostgreSQL xlog directory. +# @param logdir Overrides the default PostgreSQL log directory. +# @param log_line_prefix Overrides the default PostgreSQL log prefix. +# +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param group Overrides the default postgres user group to be used for related files in the file system. +# +# @param version The version of PostgreSQL to install and manage. +# @param postgis_version Defines the version of PostGIS to install, if you install PostGIS. +# @param repo_proxy Sets the proxy option for the official PostgreSQL yum-repositories only. +# +# @param repo_baseurl Sets the baseurl for the PostgreSQL repository. Useful if you host your own mirror of the repository. +# @param yum_repo_commonurl Sets the url for the PostgreSQL common Yum repository. Useful if you host your own mirror of the YUM repository. +# @param apt_source_release Overrides the default release for the apt source. +# +# @param needs_initdb +# Explicitly calls the initdb operation after the server package is installed and before the PostgreSQL service is started. +# +# @param encoding +# Sets the default encoding for all databases created with this module. +# On certain operating systems, this is also used during the template1 initialization, +# so it becomes a default outside of the module as well. +# @param locale +# Sets the default database locale for all databases created with this module. +# On certain operating systems, this is also used during the template1 initialization, +# so it becomes a default outside of the module as well. +# On Debian, you'll need to ensure that the 'locales-all' package is installed for full functionality of PostgreSQL. +# @param data_checksums +# Use checksums on data pages to help detect corruption by the I/O system that would otherwise be silent. +# Warning: This option is used during initialization by initdb, and cannot be changed later. +# +# @param timezone +# Sets the default timezone of the postgresql server. The postgresql built-in default is taking the systems timezone information. +# +# @param password_encryption +# Specify the type of encryption set for the password. +# Defaults to scram-sha-256 for PostgreSQL >= 14, otherwise md5. +# +# @param manage_pg_hba_conf Allow Puppet to manage the pg_hba.conf file. +# @param manage_pg_ident_conf Allow Puppet to manage the pg_ident.conf file. +# @param manage_recovery_conf Allow Puppet to manage the recovery.conf file. +# @param manage_postgresql_conf_perms +# Whether to manage the postgresql conf file permissions. This means owner, +# group and mode. Contents are not managed but should be managed through +# postgresql::server::config_entry. +# @param manage_selinux Allows Puppet to manage the appropriate configuration file for selinux. +# +# @param manage_datadir Set to false if you have file{ $datadir: } already defined +# @param manage_logdir Set to false if you have file{ $logdir: } already defined +# @param manage_xlogdir Set to false if you have file{ $xlogdir: } already defined +# +# @param manage_package_repo Sets up official PostgreSQL repositories on your host if set to true. +# @param manage_dnf_module +# Manage the DNF module. This only makes sense on distributions that use DNF +# package manager, such as EL8, EL9 or Fedora. +# @param module_workdir +# Specifies working directory under which the psql command should be executed. +# May need to specify if '/tmp' is on volume mounted with noexec option. +# class postgresql::globals ( - $client_package_name = undef, - $server_package_name = undef, - $contrib_package_name = undef, - $devel_package_name = undef, - $java_package_name = undef, - $docs_package_name = undef, - $perl_package_name = undef, - $plperl_package_name = undef, - $plpython_package_name = undef, - $python_package_name = undef, - $postgis_package_name = undef, + Optional[String[1]] $client_package_name = undef, + Optional[String[1]] $server_package_name = undef, + Optional[String[1]] $contrib_package_name = undef, + Optional[String[1]] $devel_package_name = undef, + Optional[String[1]] $java_package_name = undef, + Optional[String[1]] $docs_package_name = undef, + Optional[String[1]] $perl_package_name = undef, + Optional[String[1]] $plperl_package_name = undef, + Optional[String[1]] $plpython_package_name = undef, + Optional[String[1]] $python_package_name = undef, + Optional[String[1]] $postgis_package_name = undef, - $service_name = undef, - $service_provider = undef, - $service_status = undef, - $default_database = undef, + Optional[String[1]] $service_name = undef, + Optional[String[1]] $service_provider = undef, + Optional[String[1]] $service_status = undef, + Optional[String[1]] $default_database = undef, - $validcon_script_path = undef, + Optional[String[1]] $validcon_script_path = undef, - $initdb_path = undef, - $createdb_path = undef, - $psql_path = undef, - $pg_hba_conf_path = undef, - $pg_ident_conf_path = undef, - $postgresql_conf_path = undef, - $recovery_conf_path = undef, - $default_connect_settings = undef, + Optional[Stdlib::Absolutepath] $initdb_path = undef, + Optional[Stdlib::Absolutepath] $psql_path = undef, + Optional[Stdlib::Absolutepath] $pg_hba_conf_path = undef, + Optional[Stdlib::Absolutepath] $pg_ident_conf_path = undef, + Optional[Stdlib::Absolutepath] $postgresql_conf_path = undef, + Optional[Stdlib::Filemode] $postgresql_conf_mode = undef, + Optional[Stdlib::Absolutepath] $recovery_conf_path = undef, + Hash $default_connect_settings = {}, - $pg_hba_conf_defaults = undef, + Optional[Boolean] $pg_hba_conf_defaults = undef, - $datadir = undef, - $confdir = undef, - $bindir = undef, - $xlogdir = undef, - $logdir = undef, + Optional[Stdlib::Absolutepath] $datadir = undef, + Optional[Stdlib::Absolutepath] $confdir = undef, + Optional[Stdlib::Absolutepath] $bindir = undef, + Optional[Stdlib::Absolutepath] $xlogdir = undef, + Optional[Stdlib::Absolutepath] $logdir = undef, + Optional[String[1]] $log_line_prefix = undef, + Optional[Boolean] $manage_datadir = undef, + Optional[Boolean] $manage_logdir = undef, + Optional[Boolean] $manage_xlogdir = undef, - $user = undef, - $group = undef, + Optional[String[1]] $user = undef, + Optional[String[1]] $group = undef, - $version = undef, - $postgis_version = undef, - $repo_proxy = undef, + Optional[String[1]] $version = undef, + Optional[String[1]] $postgis_version = undef, + Optional[String[1]] $repo_proxy = undef, + Optional[String[1]] $repo_baseurl = undef, + Optional[String[1]] $yum_repo_commonurl = undef, + Optional[String[1]] $apt_source_release = undef, - $needs_initdb = undef, + Optional[Boolean] $needs_initdb = undef, - $encoding = undef, - $locale = undef, + Optional[String[1]] $encoding = undef, + Optional[String[1]] $locale = undef, + Optional[Boolean] $data_checksums = undef, + Optional[String[1]] $timezone = undef, + Optional[Postgresql::Pg_password_encryption] $password_encryption = undef, - $manage_pg_hba_conf = undef, - $manage_pg_ident_conf = undef, - $manage_recovery_conf = undef, + Optional[Boolean] $manage_pg_hba_conf = undef, + Optional[Boolean] $manage_pg_ident_conf = undef, + Optional[Boolean] $manage_recovery_conf = undef, + Optional[Boolean] $manage_postgresql_conf_perms = undef, + Optional[Boolean] $manage_selinux = undef, - $manage_package_repo = undef, + Optional[Boolean] $manage_package_repo = undef, + Boolean $manage_dnf_module = false, + Optional[Stdlib::Absolutepath] $module_workdir = undef, ) { # We are determining this here, because it is needed by the package repo # class. - $default_version = $::osfamily ? { - /^(RedHat|Linux)/ => $::operatingsystem ? { - 'Fedora' => $::operatingsystemrelease ? { - /^(22)$/ => '9.4', - /^(21)$/ => '9.3', + $default_version = $facts['os']['family'] ? { + /^(RedHat|Linux)/ => $facts['os']['name'] ? { + 'Fedora' => $facts['os']['release']['major'] ? { + /^(40|41)$/ => '16', + /^(38|39)$/ => '15', + /^(36|37)$/ => '14', + /^(34|35)$/ => '13', + /^(32|33)$/ => '12', + /^(31)$/ => '11.6', + /^(30)$/ => '11.2', + /^(29)$/ => '10.6', + /^(28)$/ => '10.4', + /^(26|27)$/ => '9.6', + /^(24|25)$/ => '9.5', + /^(22|23)$/ => '9.4', + /^(21)$/ => '9.3', /^(18|19|20)$/ => '9.2', - /^(17)$/ => '9.1', - default => undef, + /^(17)$/ => '9.1', + default => undef, }, 'Amazon' => '9.2', - default => $::operatingsystemrelease ? { - /^7\./ => '9.2', - /^6\./ => '8.4', - /^5\./ => '8.1', - default => undef, - }, - default => $::operatingsystemrelease ? { - /^7\./ => '9.2', - /^6\./ => '8.4', - /^5\./ => '8.1', + default => $facts['os']['release']['major'] ? { + '9' => '13', + '8' => '10', + '7' => '9.2', default => undef, }, }, - 'Debian' => $::operatingsystem ? { - 'Debian' => $::operatingsystemrelease ? { - /^6\./ => '8.4', - /^(wheezy|7\.)/ => '9.1', - /^(jessie|8\.)/ => '9.4', + 'Debian' => $facts['os']['name'] ? { + 'Debian' => $facts['os']['release']['major'] ? { + '10' => '11', + '11' => '13', + '12' => '15', + '13' => '17', default => undef, }, - 'Ubuntu' => $::operatingsystemrelease ? { - /^(15.04)$/ => '9.4', - /^(14.10)$/ => '9.4', - /^(14.04)$/ => '9.3', - /^(11.10|12.04|12.10|13.04|13.10)$/ => '9.1', - /^(10.04|10.10|11.04)$/ => '8.4', + 'Ubuntu' => $facts['os']['release']['major'] ? { + /^(18.04)$/ => '10', + /^(20.04)$/ => '12', + /^(21.04|21.10)$/ => '13', + /^(22.04)$/ => '14', + /^(24.04)$/ => '16', default => undef, }, default => undef, }, - 'Archlinux' => $::operatingsystem ? { - /Archlinux/ => '9.2', - default => '9.2', - }, - 'FreeBSD' => '93', - 'OpenBSD' => $::operatingsystemrelease ? { + 'Archlinux' => '9.2', + 'Gentoo' => '9.5', + 'FreeBSD' => '12', + 'OpenBSD' => $facts['os']['release']['full'] ? { /5\.6/ => '9.3', - /5\.[7-8]/ => '9.4', + /5\.[7-9]/ => '9.4', + /6\.[0-9]/ => '9.5', }, - 'Suse' => $::operatingsystem ? { - 'SLES' => $::operatingsystemrelease ? { - /11\.[0-4]/ => '91', - default => '93', + 'Suse' => $facts['os']['name'] ? { + 'SLES' => $facts['os']['release']['full'] ? { + /11\.[0-3]/ => '91', + /11\.4/ => '94', + /12\.0/ => '93', + /12\.[1-3]/ => '94', + /12\.[4-5]/ => '12', + /15\.[0-9]/ => '16', + default => '96', }, - 'OpenSuSE' => $::operatingsystemrelease ? { - '13.2' => '93', + 'OpenSuSE' => $facts['os']['release']['full'] ? { + /42\.[1-2]/ => '94', + default => '96', }, default => undef, }, @@ -124,15 +255,19 @@ } $default_postgis_version = $globals_version ? { - '8.1' => '1.3.6', - '8.4' => '1.5', - '9.0' => '1.5', - '9.1' => '1.5', - '91' => '1.5', - '9.2' => '2.0', - '9.3' => '2.1', - '9.4' => '2.1', - '93' => '2.1', + '9.0' => '2.1', + '9.1' => '2.1', + '91' => '2.1', + '9.2' => '2.3', + '9.3' => '2.3', + '93' => '2.3', + '9.4' => '2.3', + '9.5' => '2.3', + '9.6' => '2.3', + '10' => '2.4', + '11' => '3.0', + '12' => '3.0', + '16' => '3.4', default => undef, } $globals_postgis_version = $postgis_version ? { @@ -143,8 +278,17 @@ # Setup of the repo only makes sense globally, so we are doing this here. if($manage_package_repo) { class { 'postgresql::repo': - version => $globals_version, - proxy => $repo_proxy, + version => $globals_version, + proxy => $repo_proxy, + baseurl => $repo_baseurl, + commonurl => $yum_repo_commonurl, + release => $apt_source_release, + } + } + + if $manage_dnf_module { + class { 'postgresql::dnfmodule': + ensure => $globals_version, } } } diff --git a/manifests/lib/devel.pp b/manifests/lib/devel.pp index 5f1ad1ccbe..8b215b8b0f 100644 --- a/manifests/lib/devel.pp +++ b/manifests/lib/devel.pp @@ -1,17 +1,27 @@ -# This class installs postgresql development libraries. See README.md for more -# details. -class postgresql::lib::devel( - $package_name = $postgresql::params::devel_package_name, - $package_ensure = 'present', - $link_pg_config = $postgresql::params::link_pg_config +# @summary This class installs postgresql development libraries. +# +# @param package_name +# Override devel package name +# @param package_ensure +# Ensure the development libraries are installed +# @param link_pg_config +# If the bin directory used by the PostgreSQL page is not /usr/bin or /usr/local/bin, symlinks pg_config from the package's bin dir +# into usr/bin (not applicable to Debian systems). Set to false to disable this behavior. +# +# +class postgresql::lib::devel ( + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', + String $package_name = $postgresql::params::devel_package_name, + Boolean $link_pg_config = $postgresql::params::link_pg_config, ) inherits postgresql::params { - - validate_string($package_name) + if $facts['os']['family'] == 'Gentoo' { + fail('osfamily Gentoo does not have a separate "devel" package, postgresql::lib::devel is not supported') + } package { 'postgresql-devel': ensure => $package_ensure, name => $package_name, - tag => 'postgresql', + tag => 'puppetlabs-postgresql', } if $link_pg_config { @@ -22,5 +32,4 @@ } } } - } diff --git a/manifests/lib/docs.pp b/manifests/lib/docs.pp index 55825d1570..354c7c1b0d 100644 --- a/manifests/lib/docs.pp +++ b/manifests/lib/docs.pp @@ -1,16 +1,22 @@ -# This class installs the postgresql-docs See README.md for more -# details. +# @summary +# Installs PostgreSQL bindings for Postgres-Docs. Set the following parameters if you have a custom version you would like to install. +# +# @note +# Make sure to add any necessary yum or apt repositories if specifying a custom version. +# +# @param package_name +# Specifies the name of the PostgreSQL docs package. +# @param package_ensure +# Whether the PostgreSQL docs package resource should be present. +# +# class postgresql::lib::docs ( - $package_name = $postgresql::params::docs_package_name, - $package_ensure = 'present', + String $package_name = $postgresql::params::docs_package_name, + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', ) inherits postgresql::params { - - validate_string($package_name) - package { 'postgresql-docs': ensure => $package_ensure, name => $package_name, - tag => 'postgresql', + tag => 'puppetlabs-postgresql', } - } diff --git a/manifests/lib/java.pp b/manifests/lib/java.pp index 0a2d45f795..aa273c6bad 100644 --- a/manifests/lib/java.pp +++ b/manifests/lib/java.pp @@ -1,16 +1,20 @@ -# This class installs the postgresql jdbc connector. See README.md for more -# details. +# @summary This class installs the postgresql jdbc connector. +# +# @note +# Make sure to add any necessary yum or apt repositories if specifying a custom version. +# +# @param package_name +# Specifies the name of the PostgreSQL java package. +# @param package_ensure +# Specifies whether the package is present. +# class postgresql::lib::java ( - $package_name = $postgresql::params::java_package_name, - $package_ensure = 'present' + String $package_name = $postgresql::params::java_package_name, + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', ) inherits postgresql::params { - - validate_string($package_name) - package { 'postgresql-jdbc': ensure => $package_ensure, name => $package_name, - tag => 'postgresql', + tag => 'puppetlabs-postgresql', } - } diff --git a/manifests/lib/perl.pp b/manifests/lib/perl.pp index 6ed2853121..72ece8d15f 100644 --- a/manifests/lib/perl.pp +++ b/manifests/lib/perl.pp @@ -1,13 +1,17 @@ -# This class installs the perl libs for postgresql. See README.md for more -# details. -class postgresql::lib::perl( - $package_name = $postgresql::params::perl_package_name, - $package_ensure = 'present' +# @summary This class installs the perl libs for postgresql. +# +# @param package_name +# Specifies the name of the PostgreSQL perl package to install. +# @param package_ensure +# Ensure the perl libs for postgresql are installed. +# +class postgresql::lib::perl ( + String $package_name = $postgresql::params::perl_package_name, + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', ) inherits postgresql::params { - package { 'perl-DBD-Pg': ensure => $package_ensure, name => $package_name, + tag => 'puppetlabs-postgresql', } - } diff --git a/manifests/lib/python.pp b/manifests/lib/python.pp index bfe0585487..bbccdc3a50 100644 --- a/manifests/lib/python.pp +++ b/manifests/lib/python.pp @@ -1,13 +1,17 @@ -# This class installs the python libs for postgresql. See README.md for more -# details. -class postgresql::lib::python( - $package_name = $postgresql::params::python_package_name, - $package_ensure = 'present' +# @summary This class installs the python libs for postgresql. +# +# @param package_name +# The name of the PostgreSQL Python package. +# @param package_ensure +# Ensure the python libs for postgresql are installed. +# +class postgresql::lib::python ( + String[1] $package_name = $postgresql::params::python_package_name, + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', ) inherits postgresql::params { - package { 'python-psycopg2': ensure => $package_ensure, name => $package_name, + tag => 'puppetlabs-postgresql', } - } diff --git a/manifests/params.pp b/manifests/params.pp index 3885c07db2..55dcd24c0f 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -1,27 +1,41 @@ -# PRIVATE CLASS: do not use directly +# @api private class postgresql::params inherits postgresql::globals { - $version = $postgresql::globals::globals_version - $postgis_version = $postgresql::globals::globals_postgis_version - $listen_addresses = 'localhost' - $port = 5432 - $ip_mask_deny_postgres_user = '0.0.0.0/0' - $ip_mask_allow_all_users = '127.0.0.1/32' - $ipv4acls = [] - $ipv6acls = [] - $encoding = $postgresql::globals::encoding - $locale = $postgresql::globals::locale - $service_ensure = 'running' - $service_enable = true - $service_manage = true - $service_restart_on_change = true - $service_provider = $service_provider - $manage_pg_hba_conf = pick($manage_pg_hba_conf, true) - $manage_pg_ident_conf = pick($manage_pg_ident_conf, true) - $manage_recovery_conf = pick($manage_recovery_conf, false) - $package_ensure = 'present' + $version = $postgresql::globals::globals_version + $postgis_version = $postgresql::globals::globals_postgis_version + $listen_addresses = undef + $port = 5432 + $log_line_prefix = undef + $ip_mask_deny_postgres_user = '0.0.0.0/0' + $ip_mask_allow_all_users = '127.0.0.1/32' + $ipv4acls = [] + $ipv6acls = [] + $encoding = $postgresql::globals::encoding + $locale = $postgresql::globals::locale + $data_checksums = $postgresql::globals::data_checksums + $timezone = $postgresql::globals::timezone + $service_ensure = 'running' + $service_enable = true + $service_manage = true + $service_restart_on_change = true + $service_provider = $postgresql::globals::service_provider + $manage_pg_hba_conf = pick($manage_pg_hba_conf, true) + $manage_pg_ident_conf = pick($manage_pg_ident_conf, true) + $manage_recovery_conf = pick($manage_recovery_conf, false) + $manage_postgresql_conf_perms = pick($manage_postgresql_conf_perms, true) + $manage_selinux = pick($manage_selinux, false) + $package_ensure = 'present' + $module_workdir = pick($module_workdir,'/tmp') + $password_encryption = pick($password_encryption, versioncmp($version, '14') ? { -1 => 'md5', default => 'scram-sha-256' }) + $extra_systemd_config = undef + $manage_datadir = true + $manage_logdir = true + $manage_xlogdir = true + + $backup_enable = false + $backup_provider = 'pg_dump' # Amazon Linux's OS Family is 'Linux', operating system 'Amazon'. - case $::osfamily { + case $facts['os']['family'] { 'RedHat', 'Linux': { $link_pg_config = true $user = pick($user, 'postgres') @@ -30,7 +44,7 @@ $version_parts = split($version, '[.]') $package_version = "${version_parts[0]}${version_parts[1]}" - if $version == $postgresql::globals::default_version { + if $version == $postgresql::globals::default_version and $facts['os']['name'] != 'Amazon' or $postgresql::globals::manage_dnf_module { $client_package_name = pick($client_package_name, 'postgresql') $server_package_name = pick($server_package_name, 'postgresql-server') $contrib_package_name = pick($contrib_package_name,'postgresql-contrib') @@ -41,7 +55,7 @@ $plpython_package_name = pick($plpython_package_name, 'postgresql-plpython') $service_name = pick($service_name, 'postgresql') $bindir = pick($bindir, '/usr/bin') - $datadir = $::operatingsystem ? { + $datadir = $facts['os']['name'] ? { 'Amazon' => pick($datadir, "/var/lib/pgsql${package_version}/data"), default => pick($datadir, '/var/lib/pgsql/data'), } @@ -55,36 +69,43 @@ $docs_package_name = pick($docs_package_name, "postgresql${package_version}-docs") $plperl_package_name = pick($plperl_package_name, "postgresql${package_version}-plperl") $plpython_package_name = pick($plpython_package_name, "postgresql${package_version}-plpython") - $service_name = $::operatingsystem ? { - 'Amazon' => pick($service_name, "postgresql${version}"), + $service_name = $facts['os']['name'] ? { + 'Amazon' => pick($service_name, "postgresql${version_parts[0]}${version_parts[1]}"), default => pick($service_name, "postgresql-${version}"), } - $bindir = $::operatingsystem ? { + $bindir = $facts['os']['name'] ? { 'Amazon' => pick($bindir, '/usr/bin'), default => pick($bindir, "/usr/pgsql-${version}/bin"), } - $datadir = $::operatingsystem ? { + $datadir = $facts['os']['name'] ? { 'Amazon' => pick($datadir, "/var/lib/pgsql${package_version}/data"), default => pick($datadir, "/var/lib/pgsql/${version}/data"), } $confdir = pick($confdir, $datadir) + $postgresql_conf_mode = pick($postgresql_conf_mode, '0600') } + + $service_reload = "systemctl reload ${service_name}" + $service_status = pick($service_status, "systemctl status ${service_name}") + $psql_path = pick($psql_path, "${bindir}/psql") - $service_status = $service_status - $service_reload = "service ${service_name} reload" $perl_package_name = pick($perl_package_name, 'perl-DBD-Pg') - $python_package_name = pick($python_package_name, 'python-psycopg2') - - $postgis_package_name = pick( - $postgis_package_name, - $::operatingsystemrelease ? { - /^5\./ => 'postgis', - default => versioncmp($postgis_version, '2') ? { - '-1' => "postgis${package_version}", - default => "postgis2_${package_version}",} - } - ) + if $facts['os']['family'] == 'RedHat' and versioncmp($facts['os']['release']['major'], '8') >= 0 { + $python_package_name = pick($python_package_name, 'python3-psycopg2') + } else { + $python_package_name = pick($python_package_name, 'python-psycopg2') + } + + if $postgresql::globals::postgis_package_name { + $postgis_package_name = $postgresql::globals::postgis_package_name + } elsif $facts['os']['name'] == 'Fedora' { + $postgis_package_name = 'postgis' + } elsif $postgis_version and versioncmp($postgis_version, '2') < 0 { + $postgis_package_name = "postgis${package_version}" + } else { + $postgis_package_name = "postgis2_${package_version}" + } } 'Archlinux': { @@ -95,13 +116,11 @@ # Archlinux doesn't have a client-package but has a libs package which # pulls in postgresql server - $client_package_name = pick($client_package_name, 'postgresql') - $server_package_name = pick($server_package_name, 'postgresql-libs') + $client_package_name = pick($client_package_name, 'postgresql-libs') + $server_package_name = pick($server_package_name, 'postgresql') $java_package_name = pick($java_package_name, 'postgresql-jdbc') # Archlinux doesn't have develop packages $devel_package_name = pick($devel_package_name, 'postgresql-devel') - # Archlinux does have postgresql-contrib but it isn't maintained - $contrib_package_name = pick($contrib_package_name,'undef') # Archlinux postgresql package provides plperl $plperl_package_name = pick($plperl_package_name, 'undef') $plpython_package_name = pick($plpython_package_name, 'undef') @@ -111,8 +130,8 @@ $confdir = pick($confdir, $datadir) $psql_path = pick($psql_path, "${bindir}/psql") - $service_status = $service_status - $service_reload = "service ${service_name} reload" + $service_status = pick($service_status, "systemctl status ${service_name}") + $service_reload = "systemctl reload ${service_name}" $python_package_name = pick($python_package_name, 'python-psycopg2') # Archlinux does not have a perl::DBD::Pg package $perl_package_name = pick($perl_package_name, 'undef') @@ -123,26 +142,15 @@ $user = pick($user, 'postgres') $group = pick($group, 'postgres') - if $postgresql::globals::manage_package_repo == true { - $needs_initdb = pick($needs_initdb, true) - $service_name = pick($service_name, 'postgresql') - } else { - $needs_initdb = pick($needs_initdb, false) - $service_name = $::operatingsystem ? { - 'Debian' => pick($service_name, 'postgresql'), - 'Ubuntu' => $::lsbmajdistrelease ? { - /^10/ => pick($service_name, "postgresql-${version}"), - default => pick($service_name, 'postgresql'), - }, - default => undef - } - } + $needs_initdb = pick($needs_initdb, $postgresql::globals::manage_package_repo == true) + $service_name = pick($service_name, 'postgresql') $client_package_name = pick($client_package_name, "postgresql-client-${version}") $server_package_name = pick($server_package_name, "postgresql-${version}") - $contrib_package_name = pick($contrib_package_name, "postgresql-contrib-${version}") - if versioncmp($postgis_version, '2') < 0 { + if $postgis_version and versioncmp($postgis_version, '2') < 0 { $postgis_package_name = pick($postgis_package_name, "postgresql-${version}-postgis") + } elsif $postgis_version and versioncmp($postgis_version, '3') >= 0 { + $postgis_package_name = pick($postgis_package_name, "postgresql-${version}-postgis-3") } else { $postgis_package_name = pick($postgis_package_name, "postgresql-${version}-postgis-${postgis_version}") } @@ -151,26 +159,53 @@ $perl_package_name = pick($perl_package_name, 'libdbd-pg-perl') $plperl_package_name = pick($plperl_package_name, "postgresql-plperl-${version}") $plpython_package_name = pick($plpython_package_name, "postgresql-plpython-${version}") - $python_package_name = pick($python_package_name, 'python-psycopg2') + + $_ubuntu_2204 = ($facts['os']['name'] == 'Ubuntu' and versioncmp($facts['os']['release']['full'], '22.04') >= 0) + $_debian_11 = ($facts['os']['name'] == 'Debian' and versioncmp($facts['os']['release']['full'], '11') >= 0) + + if $_ubuntu_2204 or $_debian_11 { + $python_package_name = pick($python_package_name, 'python3-psycopg2') + } else { + $python_package_name = pick($python_package_name, 'python-psycopg2') + } $bindir = pick($bindir, "/usr/lib/postgresql/${version}/bin") $datadir = pick($datadir, "/var/lib/postgresql/${version}/main") $confdir = pick($confdir, "/etc/postgresql/${version}/main") - if $::operatingsystem == 'Debian' and versioncmp($::operatingsystemrelease, '8.0') >= 0 { - # Jessie uses systemd - $service_status = pick($service_status, "/usr/sbin/service ${service_name}@*-main status") - } else { - $service_status = pick($service_status, "/etc/init.d/${service_name} status | /bin/egrep -q 'Running clusters: .+|online'") - } - $service_reload = "service ${service_name} reload" + $service_reload = "systemctl reload ${service_name}" + $service_status = pick($service_status, "systemctl status ${service_name}") $psql_path = pick($psql_path, '/usr/bin/psql') + $postgresql_conf_mode = pick($postgresql_conf_mode, '0644') + } + + 'Gentoo': { + $user = pick($user, 'postgres') + $group = pick($group, 'postgres') + + $client_package_name = pick($client_package_name, 'UNSET') + $server_package_name = pick($server_package_name, 'postgresql') + $devel_package_name = pick_default($devel_package_name, undef) + $java_package_name = pick($java_package_name, 'jdbc-postgresql') + $perl_package_name = pick($perl_package_name, 'DBD-Pg') + $plperl_package_name = undef + $python_package_name = pick($python_package_name, 'psycopg') + + $service_name = pick($service_name, "postgresql-${version}") + $bindir = pick($bindir, "/usr/lib/postgresql-${version}/bin") + $datadir = pick($datadir, "/var/lib/postgresql/${version}_data") + $confdir = pick($confdir, "/etc/postgresql-${version}") + $service_status = pick($service_status, "systemctl status ${service_name}") + $service_reload = "systemctl reload ${service_name}" + $psql_path = pick($psql_path, "${bindir}/psql") + + $needs_initdb = pick($needs_initdb, true) } 'FreeBSD': { + $user = pick($user, 'postgres') + $group = pick($group, 'postgres') + $datadir = pick($datadir, "/var/db/postgres/data${version}") $link_pg_config = true - $user = pick($user, 'pgsql') - $group = pick($group, 'pgsql') - $client_package_name = pick($client_package_name, "databases/postgresql${version}-client") $server_package_name = pick($server_package_name, "databases/postgresql${version}-server") $contrib_package_name = pick($contrib_package_name, "databases/postgresql${version}-contrib") @@ -182,7 +217,6 @@ $service_name = pick($service_name, 'postgresql') $bindir = pick($bindir, '/usr/local/bin') - $datadir = pick($datadir, '/usr/local/pgsql/data') $confdir = pick($confdir, $datadir) $service_status = pick($service_status, "/usr/local/etc/rc.d/${service_name} onestatus") $service_reload = "service ${service_name} reload" @@ -233,8 +267,8 @@ $bindir = pick($bindir, "/usr/lib/postgresql${version}/bin") $datadir = pick($datadir, '/var/lib/pgsql/data') $confdir = pick($confdir, $datadir) - $service_status = pick($service_status, "/etc/init.d/${service_name} status") - $service_reload = "/etc/init.d/${service_name} reload" + $service_status = pick($service_status, "systemctl status ${service_name}") + $service_reload = "systemctl reload ${service_name}" $psql_path = pick($psql_path, "${bindir}/psql") $needs_initdb = pick($needs_initdb, true) @@ -247,7 +281,7 @@ # Since we can't determine defaults on our own, we rely on users setting # parameters with the postgresql::globals class. Here we are checking # that the mandatory minimum is set for the module to operate. - $err_prefix = "Module ${module_name} does not provide defaults for osfamily: ${::osfamily} operatingsystem: ${::operatingsystem}; please specify a value for ${module_name}::globals::" + $err_prefix = "Module ${module_name} does not provide defaults for osfamily: ${facts['os']['family']} operatingsystem: ${facts['os']['name']}; please specify a value for ${module_name}::globals::" # lint:ignore:140chars if ($needs_initdb == undef) { fail("${err_prefix}needs_initdb") } if ($service_name == undef) { fail("${err_prefix}service_name") } if ($client_package_name == undef) { fail("${err_prefix}client_package_name") } @@ -258,6 +292,10 @@ } } + if($data_checksums and versioncmp($version, '9.3') < 0) { + fail('data_checksums require version 9.3 or greater') + } + $validcon_script_path = pick($validcon_script_path, '/usr/local/bin/validate_postgresql_connection.sh') $initdb_path = pick($initdb_path, "${bindir}/initdb") $pg_hba_conf_path = pick($pg_hba_conf_path, "${confdir}/pg_hba.conf") diff --git a/manifests/repo.pp b/manifests/repo.pp index 58d859fc93..b33b699e76 100644 --- a/manifests/repo.pp +++ b/manifests/repo.pp @@ -1,9 +1,12 @@ -# PRIVATE CLASS: do not use directly +# @api private class postgresql::repo ( - $version = undef, - $proxy = undef, + Optional[String[1]] $version = undef, + Optional[String[1]] $release = undef, + Optional[String[1]] $proxy = undef, + Optional[String[1]] $baseurl = undef, + Optional[String[1]] $commonurl = undef, ) { - case $::osfamily { + case $facts['os']['family'] { 'RedHat', 'Linux': { if $version == undef { fail("The parameter 'version' for 'postgresql::repo' is undefined. You must always define it when osfamily == Redhat or Linux") @@ -16,7 +19,7 @@ } default: { - fail("Unsupported managed repository for osfamily: ${::osfamily}, operatingsystem: ${::operatingsystem}, module ${module_name} currently only supports managing repos for osfamily RedHat and Debian") + fail("Unsupported managed repository for osfamily: ${facts['os']['family']}, operatingsystem: ${facts['os']['name']}, module ${module_name} currently only supports managing repos for osfamily RedHat and Debian") # lint:ignore:140chars } } } diff --git a/manifests/repo/apt_postgresql_org.pp b/manifests/repo/apt_postgresql_org.pp index 1487e2cf85..8acd3d3941 100644 --- a/manifests/repo/apt_postgresql_org.pp +++ b/manifests/repo/apt_postgresql_org.pp @@ -1,22 +1,36 @@ -# PRIVATE CLASS: do not use directly +# @api private class postgresql::repo::apt_postgresql_org inherits postgresql::repo { -include ::apt + include apt + # Here we have tried to replicate the instructions on the PostgreSQL site: # # http://www.postgresql.org/download/linux/debian/ # + $default_baseurl = 'https://apt.postgresql.org/pub/repos/apt/' + $_baseurl = pick($postgresql::repo::baseurl, $default_baseurl) + + $default_release = "${facts['os']['distro']['codename']}-pgdg" + $_release = pick($postgresql::repo::release, $default_release) + apt::pin { 'apt_postgresql_org': originator => 'apt.postgresql.org', priority => 500, - }-> - apt::source { 'apt.postgresql.org': - location => 'http://apt.postgresql.org/pub/repos/apt/', - release => "${::lsbdistcodename}-pgdg", - repos => "main ${postgresql::repo::version}", - key => 'B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8', - key_source => 'https://www.postgresql.org/media/keys/ACCC4CF8.asc', - include_src => false, + } + -> apt::source { 'apt.postgresql.org': + location => $_baseurl, + release => $_release, + repos => 'main', + architecture => $facts['os']['architecture'], + key => { + name => 'apt.postgresql.org.asc', + # https://www.postgresql.org/media/keys/ACCC4CF8.asc + content => file("${module_name}/ACCC4CF8.asc"), + }, + include => { + src => false, + }, } - Apt::Source['apt.postgresql.org']->Package<|tag == 'postgresql'|> + Apt::Source['apt.postgresql.org'] -> Package<|tag == 'puppetlabs-postgresql'|> + Class['Apt::Update'] -> Package<|tag == 'puppetlabs-postgresql'|> } diff --git a/manifests/repo/yum_postgresql_org.pp b/manifests/repo/yum_postgresql_org.pp index 5cfaf4b159..faf9c2ace5 100644 --- a/manifests/repo/yum_postgresql_org.pp +++ b/manifests/repo/yum_postgresql_org.pp @@ -1,30 +1,52 @@ -# PRIVATE CLASS: do not use directly +# @api private class postgresql::repo::yum_postgresql_org inherits postgresql::repo { $version_parts = split($postgresql::repo::version, '[.]') $package_version = "${version_parts[0]}${version_parts[1]}" $gpg_key_path = "/etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-${package_version}" + $gpg_key_file = $facts['os']['release']['major'] ? { + '7' => 'postgresql/RPM-GPG-KEY-PGDG-7', + default => 'postgresql/RPM-GPG-KEY-PGDG', + } + file { $gpg_key_path: - source => 'puppet:///modules/postgresql/RPM-GPG-KEY-PGDG', - before => Yumrepo['yum.postgresql.org'] + content => file($gpg_key_file), + owner => 'root', + group => 'root', + mode => '0644', + before => Yumrepo['yum.postgresql.org'], } - if($::operatingsystem == 'Fedora') { + if($facts['os']['name'] == 'Fedora') { $label1 = 'fedora' $label2 = $label1 } else { $label1 = 'redhat' $label2 = 'rhel' } + $default_baseurl = "https://download.postgresql.org/pub/repos/yum/${postgresql::repo::version}/${label1}/${label2}-\$releasever-\$basearch" + $default_commonurl = "https://download.postgresql.org/pub/repos/yum/common/${label1}/${label2}-\$releasever-\$basearch" + + $_baseurl = pick($postgresql::repo::baseurl, $default_baseurl) + $_commonurl = pick($postgresql::repo::commonurl, $default_commonurl) yumrepo { 'yum.postgresql.org': descr => "PostgreSQL ${postgresql::repo::version} \$releasever - \$basearch", - baseurl => "http://yum.postgresql.org/${postgresql::repo::version}/${label1}/${label2}-\$releasever-\$basearch", + baseurl => $_baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => "file://${gpg_key_path}", + proxy => $postgresql::repo::proxy, + } + + yumrepo { 'pgdg-common': + descr => "PostgreSQL common RPMs \$releasever - \$basearch", + baseurl => $_commonurl, enabled => 1, gpgcheck => 1, - gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-${package_version}", + gpgkey => "file://${gpg_key_path}", proxy => $postgresql::repo::proxy, } - Yumrepo['yum.postgresql.org'] -> Package<|tag == 'postgresql'|> + Yumrepo['yum.postgresql.org'] -> Package<|tag == 'puppetlabs-postgresql'|> } diff --git a/manifests/server.pp b/manifests/server.pp index 5469f26797..2516e43611 100644 --- a/manifests/server.pp +++ b/manifests/server.pp @@ -1,81 +1,245 @@ -# This installs a PostgreSQL server. See README.md for more details. +# @summary This installs a PostgreSQL server +# +# @param postgres_password +# Sets the password for the postgres user to your specified value. By default, this setting uses the superuser account in the Postgres +# database, with a user called postgres and no password. +# @param package_name Specifies the name of the package to use for installing the server software. +# @param package_ensure Passes a value through to the package resource when creating the server instance. +# +# @param plperl_package_name Sets the default package name for the PL/Perl extension. +# @param plpython_package_name Sets the default package name for the PL/Python extension. +# +# @param service_ensure Ensure service is installed +# @param service_enable Enable the PostgreSQL service +# @param service_manage Defines whether or not Puppet should manage the service. +# @param service_name Overrides the default PostgreSQL service name. +# @param service_restart_on_change +# Overrides the default behavior to restart your PostgreSQL service when a config entry has been changed that requires a service restart +# to become active. +# @param service_provider Overrides the default PostgreSQL service provider. +# @param service_reload Overrides the default reload command for your PostgreSQL service. +# @param service_status Overrides the default status check command for your PostgreSQL service. +# @param default_database Specifies the name of the default database to connect with. On most systems this is 'postgres'. +# @param default_connect_settings +# Specifies a hash of environment variables used when connecting to a remote server. Becomes the default for other defined types, such as +# postgresql::server::role. +# +# @param listen_addresses Address list on which the PostgreSQL service will listen +# @param port +# Specifies the port for the PostgreSQL server to listen on. +# Note: The same port number is used for all IP addresses the server listens on. +# Also, for Red Hat systems and early Debian systems, changing the port causes the server to come to a full stop before being able to make +# the change. +# Default value: 5432. Meaning the Postgres server listens on TCP port 5432. +# +# @param ip_mask_deny_postgres_user Specifies the IP mask from which remote connections should be denied for the postgres superuser. +# Default value: '0.0.0.0/0', which denies any remote connection. +# +# @param ip_mask_allow_all_users +# Overrides PostgreSQL defaults for remote connections. By default, PostgreSQL does not allow database user accounts to connect via TCP +# from remote machines. If you'd like to allow this, you can override this setting. +# Set to '0.0.0.0/0' to allow database users to connect from any remote machine, or '192.168.0.0/1' to allow connections from any machine +# on your local '192.168' subnet. +# Default value: '127.0.0.1/32'. +# +# @param ipv4acls Lists strings for access control for connection method, users, databases, IPv4 addresses; +# @param ipv6acls Lists strings for access control for connection method, users, databases, IPv6 addresses. +# +# @param initdb_path Specifies the path to the initdb command. +# @param psql_path Specifies the path to the psql command. +# @param pg_hba_conf_path Specifies the path to your pg_hba.conf file. +# @param pg_ident_conf_path Specifies the path to your pg_ident.conf file. +# @param postgresql_conf_path Specifies the path to your postgresql.conf file. +# @param postgresql_conf_mode Sets the mode of your postgresql.conf file. Only relevant if manage_postgresql_conf_perms is true. +# @param recovery_conf_path Specifies the path to your recovery.conf file. +# +# @param datadir PostgreSQL data directory +# @param xlogdir PostgreSQL xlog directory +# @param logdir PostgreSQL log directory +# +# @param log_line_prefix PostgreSQL log line prefix +# +# @param pg_hba_conf_defaults +# If false, disables the defaults supplied with the module for pg_hba.conf. This is useful if you disagree with the defaults and wish to +# override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform +# basic psql operations for example. +# +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param group Overrides the default postgres user group to be used for related files in the file system. +# +# @param needs_initdb Explicitly calls the initdb operation after server package is installed, and before the PostgreSQL service is started. +# +# @param encoding +# Sets the default encoding for all databases created with this module. On certain operating systems this is also used during the +# template1 initialization, so it becomes a default outside of the module as well. +# @param locale +# Sets the default database locale for all databases created with this module. On certain operating systems this is used during the +# template1 initialization as well, so it becomes a default outside of the module. +# @param data_checksums +# Use checksums on data pages to help detect corruption by the I/O system that would otherwise be silent. +# Warning: This option is used during initialization by initdb, and cannot be changed later. +# If set, checksums are calculated for all objects, in all databases. +# +# @param timezone Set timezone for the PostgreSQL instance +# +# @param manage_pg_hba_conf Boolean. Whether to manage the pg_hba.conf. +# @param manage_pg_ident_conf Boolean. Overwrites the pg_ident.conf file. +# @param manage_recovery_conf Boolean. Specifies whether or not manage the recovery.conf. +# @param manage_postgresql_conf_perms +# Whether to manage the postgresql conf file permissions. This means owner, +# group and mode. Contents are not managed but should be managed through +# postgresql::server::config_entry. +# @param manage_selinux Specifies whether or not manage the conf file for selinux. +# @param module_workdir Working directory for the PostgreSQL module +# +# @param manage_datadir Set to false if you have file{ $datadir: } already defined +# @param manage_logdir Set to false if you have file{ $logdir: } already defined +# @param manage_xlogdir Set to false if you have file{ $xlogdir: } already defined +# @param password_encryption Specify the type of encryption set for the password. +# @param pg_hba_auth_password_encryption +# Specify the type of encryption set for the password in pg_hba_conf, +# this value is usefull if you want to start enforcing scram-sha-256, but give users transition time. +# @param roles Specifies a hash from which to generate postgresql::server::role resources. +# @param config_entries Specifies a hash from which to generate postgresql::server::config_entry resources. +# @param pg_hba_rules Specifies a hash from which to generate postgresql::server::pg_hba_rule resources. +# +# @param backup_enable Whether a backup job should be enabled. +# @param backup_options A hash of options that should be passed through to the backup provider. +# @param backup_provider Specifies the backup provider to use. +# +# @param extra_systemd_config +# Adds extra config to systemd config file, can for instance be used to add extra openfiles. This can be a multi line string +# @param auth_host auth method used by default for host authorization +# @param auth_local auth method used by default for local authorization +# @param lc_messages locale used for logging and system messages +# @param username username of user running the postgres instance +# class postgresql::server ( - $postgres_password = undef, - - $package_name = $postgresql::params::server_package_name, - $client_package_name = $postgresql::params::client_package_name, - $package_ensure = $postgresql::params::package_ensure, - - $plperl_package_name = $postgresql::params::plperl_package_name, - $plpython_package_name = $postgresql::params::plpython_package_name, - - $service_ensure = $postgresql::params::service_ensure, - $service_enable = $postgresql::params::service_enable, - $service_manage = $postgresql::params::service_manage, - $service_name = $postgresql::params::service_name, - $service_restart_on_change = $postgresql::params::service_restart_on_change, - $service_provider = $postgresql::params::service_provider, - $service_reload = $postgresql::params::service_reload, - $service_status = $postgresql::params::service_status, - $default_database = $postgresql::params::default_database, - - $listen_addresses = $postgresql::params::listen_addresses, - $port = $postgresql::params::port, - $ip_mask_deny_postgres_user = $postgresql::params::ip_mask_deny_postgres_user, - $ip_mask_allow_all_users = $postgresql::params::ip_mask_allow_all_users, - $ipv4acls = $postgresql::params::ipv4acls, - $ipv6acls = $postgresql::params::ipv6acls, - - $initdb_path = $postgresql::params::initdb_path, - $createdb_path = $postgresql::params::createdb_path, - $psql_path = $postgresql::params::psql_path, - $pg_hba_conf_path = $postgresql::params::pg_hba_conf_path, - $pg_ident_conf_path = $postgresql::params::pg_ident_conf_path, - $postgresql_conf_path = $postgresql::params::postgresql_conf_path, - $recovery_conf_path = $postgresql::params::recovery_conf_path, - - $datadir = $postgresql::params::datadir, - $xlogdir = $postgresql::params::xlogdir, - $logdir = $postgresql::params::logdir, - - $pg_hba_conf_defaults = $postgresql::params::pg_hba_conf_defaults, - - $user = $postgresql::params::user, - $group = $postgresql::params::group, - - $needs_initdb = $postgresql::params::needs_initdb, - - $encoding = $postgresql::params::encoding, - $locale = $postgresql::params::locale, - - $manage_pg_hba_conf = $postgresql::params::manage_pg_hba_conf, - $manage_pg_ident_conf = $postgresql::params::manage_pg_ident_conf, - $manage_recovery_conf = $postgresql::params::manage_recovery_conf, - - #Deprecated - $version = undef, + Optional[Variant[String[1], Sensitive[String[1]], Integer]] $postgres_password = undef, + + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = $postgresql::params::package_ensure, # lint:ignore:140chars + String[1] $package_name = $postgresql::params::server_package_name, + + Optional[String[1]] $plperl_package_name = $postgresql::params::plperl_package_name, + Optional[String[1]] $plpython_package_name = $postgresql::params::plpython_package_name, + + Variant[Enum['running', 'stopped'], Boolean] $service_ensure = $postgresql::params::service_ensure, + Boolean $service_enable = $postgresql::params::service_enable, + Boolean $service_manage = $postgresql::params::service_manage, + String[1] $service_name = $postgresql::params::service_name, + Boolean $service_restart_on_change = $postgresql::params::service_restart_on_change, + Optional[String[1]] $service_provider = $postgresql::params::service_provider, + String[1] $service_reload = $postgresql::params::service_reload, + Optional[String[1]] $service_status = $postgresql::params::service_status, + String[1] $default_database = $postgresql::params::default_database, + Hash $default_connect_settings = $postgresql::globals::default_connect_settings, + Optional[Variant[String[1], Array[String[1]]]] $listen_addresses = $postgresql::params::listen_addresses, + Stdlib::Port $port = $postgresql::params::port, + String[1] $ip_mask_deny_postgres_user = $postgresql::params::ip_mask_deny_postgres_user, + String[1] $ip_mask_allow_all_users = $postgresql::params::ip_mask_allow_all_users, + Array[String[1]] $ipv4acls = $postgresql::params::ipv4acls, + Array[String[1]] $ipv6acls = $postgresql::params::ipv6acls, + + Stdlib::Absolutepath $initdb_path = $postgresql::params::initdb_path, + Stdlib::Absolutepath $psql_path = $postgresql::params::psql_path, + Stdlib::Absolutepath $pg_hba_conf_path = $postgresql::params::pg_hba_conf_path, + Stdlib::Absolutepath $pg_ident_conf_path = $postgresql::params::pg_ident_conf_path, + Stdlib::Absolutepath $postgresql_conf_path = $postgresql::params::postgresql_conf_path, + Optional[Stdlib::Filemode] $postgresql_conf_mode = $postgresql::params::postgresql_conf_mode, + Stdlib::Absolutepath $recovery_conf_path = $postgresql::params::recovery_conf_path, + + Stdlib::Absolutepath $datadir = $postgresql::params::datadir, + Optional[Stdlib::Absolutepath] $xlogdir = $postgresql::params::xlogdir, + Optional[Stdlib::Absolutepath] $logdir = $postgresql::params::logdir, + + Optional[String[1]] $log_line_prefix = $postgresql::params::log_line_prefix, + + Boolean $pg_hba_conf_defaults = $postgresql::params::pg_hba_conf_defaults, + + String[1] $user = $postgresql::params::user, + String[1] $group = $postgresql::params::group, + + Boolean $needs_initdb = $postgresql::params::needs_initdb, + + Optional[String[1]] $auth_host = undef, + Optional[String[1]] $auth_local = undef, + Optional[String[1]] $encoding = $postgresql::params::encoding, + Optional[String[1]] $locale = $postgresql::params::locale, + Optional[String[1]] $lc_messages = undef, + Optional[Boolean] $data_checksums = $postgresql::params::data_checksums, + Optional[String[1]] $username = $user, + Optional[String[1]] $timezone = $postgresql::params::timezone, + + Boolean $manage_pg_hba_conf = $postgresql::params::manage_pg_hba_conf, + Boolean $manage_pg_ident_conf = $postgresql::params::manage_pg_ident_conf, + Boolean $manage_recovery_conf = $postgresql::params::manage_recovery_conf, + Boolean $manage_postgresql_conf_perms = $postgresql::params::manage_postgresql_conf_perms, + Boolean $manage_selinux = $postgresql::params::manage_selinux, + Stdlib::Absolutepath $module_workdir = $postgresql::params::module_workdir, + + Boolean $manage_datadir = $postgresql::params::manage_datadir, + Boolean $manage_logdir = $postgresql::params::manage_logdir, + Boolean $manage_xlogdir = $postgresql::params::manage_xlogdir, + Postgresql::Pg_password_encryption $password_encryption = $postgresql::params::password_encryption, + Optional[Postgresql::Pg_password_encryption] $pg_hba_auth_password_encryption = undef, + Optional[String] $extra_systemd_config = $postgresql::params::extra_systemd_config, + + Hash[String, Hash] $roles = {}, + Hash[String, Any] $config_entries = {}, + Postgresql::Pg_hba_rules $pg_hba_rules = {}, + + Boolean $backup_enable = $postgresql::params::backup_enable, + Hash $backup_options = {}, + Enum['pg_dump'] $backup_provider = $postgresql::params::backup_provider, ) inherits postgresql::params { - $pg = 'postgresql::server' + $_version = $postgresql::params::version - if $version != undef { - warning('Passing "version" to postgresql::server is deprecated; please use postgresql::globals instead.') - $_version = $version - } else { - $_version = $postgresql::params::version + # Reload has its own ordering, specified by other defines + class { 'postgresql::server::reload': + require => Class['postgresql::server::install'], } - if $createdb_path != undef{ - warning('Passing "createdb_path" to postgresql::server is deprecated, it can be removed safely for the same behaviour') + contain postgresql::server::install + contain postgresql::server::initdb + contain postgresql::server::config + contain postgresql::server::service + contain postgresql::server::passwd + + Class['postgresql::server::install'] + -> Class['postgresql::server::initdb'] + -> Class['postgresql::server::config'] + -> Class['postgresql::server::service'] + -> Class['postgresql::server::passwd'] + + $roles.each |$rolename, $role| { + postgresql::server::role { $rolename: + * => $role, + } } - # Reload has its own ordering, specified by other defines - class { "${pg}::reload": require => Class["${pg}::install"] } - - anchor { "${pg}::start": }-> - class { "${pg}::install": }-> - class { "${pg}::initdb": }-> - class { "${pg}::config": }-> - class { "${pg}::service": }-> - class { "${pg}::passwd": }-> - anchor { "${pg}::end": } + $config_entries.each |$entry, $value| { + postgresql::server::config_entry { $entry: + ensure => bool2str($value =~ Undef, 'absent', 'present'), + value => $value, + } + } + + $pg_hba_rules.each |String[1] $rule_name, Postgresql::Pg_hba_rule $rule| { + postgresql::server::pg_hba_rule { $rule_name: + * => $rule, + } + } + + if $backup_enable { + case $backup_provider { + 'pg_dump': { + class { 'postgresql::backup::pg_dump': + * => $backup_options, + } + } + default: { + fail("Unsupported backup provider '${backup_provider}'.") + } + } + } } diff --git a/manifests/server/config.pp b/manifests/server/config.pp index 592cd6a171..bd232e1bac 100644 --- a/manifests/server/config.pp +++ b/manifests/server/config.pp @@ -1,181 +1,32 @@ -# PRIVATE CLASS: do not call directly +# @api private class postgresql::server::config { - $ip_mask_deny_postgres_user = $postgresql::server::ip_mask_deny_postgres_user - $ip_mask_allow_all_users = $postgresql::server::ip_mask_allow_all_users - $listen_addresses = $postgresql::server::listen_addresses - $port = $postgresql::server::port - $ipv4acls = $postgresql::server::ipv4acls - $ipv6acls = $postgresql::server::ipv6acls - $pg_hba_conf_path = $postgresql::server::pg_hba_conf_path - $pg_ident_conf_path = $postgresql::server::pg_ident_conf_path - $postgresql_conf_path = $postgresql::server::postgresql_conf_path - $recovery_conf_path = $postgresql::server::recovery_conf_path - $pg_hba_conf_defaults = $postgresql::server::pg_hba_conf_defaults - $user = $postgresql::server::user - $group = $postgresql::server::group - $version = $postgresql::server::_version - $manage_package_repo = $postgresql::server::manage_package_repo - $manage_pg_hba_conf = $postgresql::server::manage_pg_hba_conf - $manage_pg_ident_conf = $postgresql::server::manage_pg_ident_conf - $manage_recovery_conf = $postgresql::server::manage_recovery_conf - $datadir = $postgresql::server::datadir - $logdir = $postgresql::server::logdir - $service_name = $postgresql::server::service_name - - if ($manage_pg_hba_conf == true) { - # Prepare the main pg_hba file - concat { $pg_hba_conf_path: - owner => $user, - group => $group, - mode => '0640', - warn => true, - notify => Class['postgresql::server::reload'], - } - - if $pg_hba_conf_defaults { - Postgresql::Server::Pg_hba_rule { - database => 'all', - user => 'all', - } - - # Lets setup the base rules - $local_auth_option = $version ? { - '8.1' => 'sameuser', - default => undef, - } - postgresql::server::pg_hba_rule { 'local access as postgres user': - type => 'local', - user => $user, - auth_method => 'ident', - auth_option => $local_auth_option, - order => '001', - } - postgresql::server::pg_hba_rule { 'local access to database with same name': - type => 'local', - auth_method => 'ident', - auth_option => $local_auth_option, - order => '002', - } - postgresql::server::pg_hba_rule { 'allow localhost TCP access to postgresql user': - type => 'host', - user => $user, - address => '127.0.0.1/32', - auth_method => 'md5', - order => '003', - } - postgresql::server::pg_hba_rule { 'deny access to postgresql user': - type => 'host', - user => $user, - address => $ip_mask_deny_postgres_user, - auth_method => 'reject', - order => '004', - } - - postgresql::server::pg_hba_rule { 'allow access to all users': - type => 'host', - address => $ip_mask_allow_all_users, - auth_method => 'md5', - order => '100', - } - postgresql::server::pg_hba_rule { 'allow access to ipv6 localhost': - type => 'host', - address => '::1/128', - auth_method => 'md5', - order => '101', - } - } - - # ipv4acls are passed as an array of rule strings, here we transform - # them into a resources hash, and pass the result to create_resources - $ipv4acl_resources = postgresql_acls_to_resources_hash($ipv4acls, - 'ipv4acls', 10) - create_resources('postgresql::server::pg_hba_rule', $ipv4acl_resources) - - - # ipv6acls are passed as an array of rule strings, here we transform - # them into a resources hash, and pass the result to create_resources - $ipv6acl_resources = postgresql_acls_to_resources_hash($ipv6acls, - 'ipv6acls', 102) - create_resources('postgresql::server::pg_hba_rule', $ipv6acl_resources) - } - - # We must set a "listen_addresses" line in the postgresql.conf if we - # want to allow any connections from remote hosts. - postgresql::server::config_entry { 'listen_addresses': - value => $listen_addresses, - } - postgresql::server::config_entry { 'port': - value => $port, - } - postgresql::server::config_entry { 'data_directory': - value => $datadir, - } - if $logdir { - postgresql::server::config_entry { 'log_directory': - value => $logdir, - } - - } - - # RedHat-based systems hardcode some PG* variables in the init script, and need to be overriden - # in /etc/sysconfig/pgsql/postgresql. Create a blank file so we can manage it with augeas later. - if ($::osfamily == 'RedHat') and ($::operatingsystemrelease !~ /^7/) and ($::operatingsystem != 'Fedora') { - file { '/etc/sysconfig/pgsql/postgresql': - ensure => present, - replace => false, - } - - # The init script from the packages of the postgresql.org repository - # sources an alternate sysconfig file. - # I. e. /etc/sysconfig/pgsql/postgresql-9.3 for PostgreSQL 9.3 - # Link to the sysconfig file set by this puppet module - file { "/etc/sysconfig/pgsql/postgresql-${version}": - ensure => link, - target => '/etc/sysconfig/pgsql/postgresql', - require => File[ '/etc/sysconfig/pgsql/postgresql' ], - } - - } - - - if ($manage_pg_ident_conf == true) { - concat { $pg_ident_conf_path: - owner => $user, - group => $group, - force => true, # do not crash if there is no pg_ident_rules - mode => '0640', - warn => true, - notify => Class['postgresql::server::reload'], - } - } - - if ($manage_recovery_conf == true) { - concat { $recovery_conf_path: - owner => $user, - group => $group, - force => true, # do not crash if there is no recovery conf file - mode => '0640', - warn => true, - notify => Class['postgresql::server::reload'], - } - } - - if $::osfamily == 'RedHat' { - if $::operatingsystemrelease =~ /^7/ or $::operatingsystem == 'Fedora' { - file { 'systemd-override': - ensure => present, - path => "/etc/systemd/system/${service_name}.service", - owner => root, - group => root, - content => template('postgresql/systemd-override.erb'), - notify => [ Exec['restart-systemd'], Class['postgresql::server::service'] ], - before => Class['postgresql::server::reload'], - } - exec { 'restart-systemd': - command => 'systemctl daemon-reload', - refreshonly => true, - path => '/bin:/usr/bin:/usr/local/bin' - } - } + postgresql::server::instance::config { 'main': + ip_mask_deny_postgres_user => $postgresql::server::ip_mask_deny_postgres_user, + ip_mask_allow_all_users => $postgresql::server::ip_mask_allow_all_users, + listen_addresses => $postgresql::server::listen_addresses, + port => $postgresql::server::port, + ipv4acls => $postgresql::server::ipv4acls, + ipv6acls => $postgresql::server::ipv6acls, + pg_hba_conf_path => $postgresql::server::pg_hba_conf_path, + pg_ident_conf_path => $postgresql::server::pg_ident_conf_path, + postgresql_conf_path => $postgresql::server::postgresql_conf_path, + postgresql_conf_mode => $postgresql::server::postgresql_conf_mode, + recovery_conf_path => $postgresql::server::recovery_conf_path, + pg_hba_conf_defaults => $postgresql::server::pg_hba_conf_defaults, + user => $postgresql::server::user, + group => $postgresql::server::group, + version => $postgresql::server::_version, + manage_pg_hba_conf => $postgresql::server::manage_pg_hba_conf, + manage_pg_ident_conf => $postgresql::server::manage_pg_ident_conf, + manage_recovery_conf => $postgresql::server::manage_recovery_conf, + manage_postgresql_conf_perms => $postgresql::server::manage_postgresql_conf_perms, + datadir => $postgresql::server::datadir, + logdir => $postgresql::server::logdir, + service_name => $postgresql::server::service_name, + service_enable => $postgresql::server::service_enable, + log_line_prefix => $postgresql::server::log_line_prefix, + timezone => $postgresql::server::timezone, + password_encryption => $postgresql::server::password_encryption, + extra_systemd_config => $postgresql::server::extra_systemd_config, } } diff --git a/manifests/server/config_entry.pp b/manifests/server/config_entry.pp index 50ec085e72..e6460659a2 100644 --- a/manifests/server/config_entry.pp +++ b/manifests/server/config_entry.pp @@ -1,126 +1,97 @@ -# Manage a postgresql.conf entry. See README.md for more details. +# @summary Manage a postgresql.conf entry. +# +# @param ensure Removes an entry if set to 'absent'. +# @param key Defines the key/name for the setting. Defaults to $name +# @param value Defines the value for the setting. +# @param path Path for postgresql.conf +# @param comment Defines the comment for the setting. The # is added by default. +# @param instance_name The name of the instance. +# define postgresql::server::config_entry ( - $ensure = 'present', - $value = undef, - $path = false + Enum['present', 'absent'] $ensure = 'present', + String[1] $key = $name, + Optional[Variant[String[1], Numeric, Array[String[1]]]] $value = undef, + Stdlib::Absolutepath $path = $postgresql::server::postgresql_conf_path, + Optional[String[1]] $comment = undef, + String[1] $instance_name = 'main', ) { - $postgresql_conf_path = $postgresql::server::postgresql_conf_path - - $target = $path ? { - false => $postgresql_conf_path, - default => $path, - } - - Exec { - logoutput => 'on_failure', - } - - case $name { - /data_directory|hba_file|ident_file|include|listen_addresses|port|max_connections|superuser_reserved_connections|unix_socket_directory|unix_socket_group|unix_socket_permissions|bonjour|bonjour_name|ssl|ssl_ciphers|shared_buffers|max_prepared_transactions|max_files_per_process|shared_preload_libraries|wal_level|wal_buffers|archive_mode|max_wal_senders|hot_standby|logging_collector|silent_mode|track_activity_query_size|autovacuum_max_workers|autovacuum_freeze_max_age|max_locks_per_transaction|max_pred_locks_per_transaction|restart_after_crash|lc_messages|lc_monetary|lc_numeric|lc_time/: { - if $postgresql::server::service_restart_on_change { - Postgresql_conf { - notify => Class['postgresql::server::service'], - before => Class['postgresql::server::reload'], - } - } else { - Postgresql_conf { - before => [ - Class['postgresql::server::service'], - Class['postgresql::server::reload'], - ], - } - } - } - - default: { - Postgresql_conf { - notify => Class['postgresql::server::reload'], - } - } + # Those are the variables that are marked as "(change requires restart)" + # on postgresql.conf. Items are ordered as on postgresql.conf. + # + # XXX: This resource supports setting other variables without knowing + # their names. Do not add them here. + $requires_restart_until = { + 'data_directory' => undef, + 'hba_file' => undef, + 'ident_file' => undef, + 'external_pid_file' => undef, + 'listen_addresses' => undef, + 'port' => undef, + 'max_connections' => undef, + 'superuser_reserved_connections' => undef, + 'unix_socket_directory' => '9.3', # Turned into "unix_socket_directories" + 'unix_socket_directories' => undef, + 'unix_socket_group' => undef, + 'unix_socket_permissions' => undef, + 'bonjour' => undef, + 'bonjour_name' => undef, + 'ssl' => '10', + 'ssl_ciphers' => '10', + 'ssl_prefer_server_ciphers' => '10', # New on 9.4 + 'ssl_ecdh_curve' => '10', # New on 9.4 + 'ssl_cert_file' => '10', # New on 9.2 + 'ssl_key_file' => '10', # New on 9.2 + 'ssl_ca_file' => '10', # New on 9.2 + 'ssl_crl_file' => '10', # New on 9.2 + 'shared_buffers' => undef, + 'huge_pages' => undef, # New on 9.4 + 'max_prepared_transactions' => undef, + 'max_files_per_process' => undef, + 'shared_preload_libraries' => undef, + 'max_worker_processes' => undef, # New on 9.4 + 'old_snapshot_threshold' => undef, # New on 9.6 + 'wal_level' => undef, + 'wal_log_hints' => undef, # New on 9.4 + 'wal_buffers' => undef, + 'archive_mode' => undef, + 'max_wal_senders' => undef, + 'max_replication_slots' => undef, # New on 9.4 + 'track_commit_timestamp' => undef, # New on 9.5 + 'hot_standby' => undef, + 'logging_collector' => undef, + 'cluster_name' => undef, # New on 9.5 + 'silent_mode' => '9.2', # Removed + 'track_activity_query_size' => undef, + 'autovacuum_max_workers' => undef, + 'autovacuum_freeze_max_age' => undef, + 'autovacuum_multixact_freeze_max_age' => undef, # New on 9.5 + 'max_locks_per_transaction' => undef, + 'max_pred_locks_per_transaction' => undef, } - # We have to handle ports and the data directory in a weird and - # special way. On early Debian and Ubuntu and RHEL we have to ensure - # we stop the service completely. On RHEL 7 we either have to create - # a systemd override for the port or update the sysconfig file, but this - # is managed for us in postgresql::server::config. - if $::operatingsystem == 'Debian' or $::operatingsystem == 'Ubuntu' { - if $name == 'port' and ( $::operatingsystemrelease =~ /^6/ or $::operatingsystemrelease =~ /^10\.04/ ) { - exec { "postgresql_stop_${name}": - command => "service ${::postgresql::server::service_name} stop", - onlyif => "service ${::postgresql::server::service_name} status", - unless => "grep 'port = ${value}' ${::postgresql::server::postgresql_conf_path}", - path => '/usr/sbin:/sbin:/bin:/usr/bin:/usr/local/bin', - before => Postgresql_conf[$name], - } + if ! ($key in $requires_restart_until and ( + ! $requires_restart_until[$key] or + versioncmp($postgresql::server::_version, $requires_restart_until[$key]) < 0 + )) { + Postgresql_conf { + notify => Postgresql::Server::Instance::Reload[$instance_name], } - elsif $name == 'data_directory' { - exec { "postgresql_stop_${name}": - command => "service ${::postgresql::server::service_name} stop", - onlyif => "service ${::postgresql::server::service_name} status", - unless => "grep \"data_directory = '${value}'\" ${::postgresql::server::postgresql_conf_path}", - path => '/usr/sbin:/sbin:/bin:/usr/bin:/usr/local/bin', - before => Postgresql_conf[$name], - } + } elsif $postgresql::server::service_restart_on_change { + Postgresql_conf { + notify => Postgresql::Server::Instance::Service[$instance_name], } - } - if $::osfamily == 'RedHat' { - if ! ($::operatingsystemrelease =~ /^7/ or $::operatingsystem == 'Fedora') { - if $name == 'port' { - # We need to force postgresql to stop before updating the port - # because puppet becomes confused and is unable to manage the - # service appropriately. - exec { "postgresql_stop_${name}": - command => "service ${::postgresql::server::service_name} stop", - onlyif => "service ${::postgresql::server::service_name} status", - unless => "grep 'PGPORT=${value}' /etc/sysconfig/pgsql/postgresql", - path => '/sbin:/bin:/usr/bin:/usr/local/bin', - require => File['/etc/sysconfig/pgsql/postgresql'], - } -> - augeas { 'override PGPORT in /etc/sysconfig/pgsql/postgresql': - lens => 'Shellvars.lns', - incl => '/etc/sysconfig/pgsql/*', - context => '/files/etc/sysconfig/pgsql/postgresql', - changes => "set PGPORT ${value}", - require => File['/etc/sysconfig/pgsql/postgresql'], - notify => Class['postgresql::server::service'], - before => Class['postgresql::server::reload'], - } - } elsif $name == 'data_directory' { - # We need to force postgresql to stop before updating the data directory - # otherwise init script breaks - exec { "postgresql_${name}": - command => "service ${::postgresql::server::service_name} stop", - onlyif => "service ${::postgresql::server::service_name} status", - unless => "grep 'PGDATA=${value}' /etc/sysconfig/pgsql/postgresql", - path => '/sbin:/bin:/usr/bin:/usr/local/bin', - require => File['/etc/sysconfig/pgsql/postgresql'], - } -> - augeas { 'override PGDATA in /etc/sysconfig/pgsql/postgresql': - lens => 'Shellvars.lns', - incl => '/etc/sysconfig/pgsql/*', - context => '/files/etc/sysconfig/pgsql/postgresql', - changes => "set PGDATA ${value}", - require => File['/etc/sysconfig/pgsql/postgresql'], - notify => Class['postgresql::server::service'], - before => Class['postgresql::server::reload'], - } - } + } else { + Postgresql_conf { + before => Postgresql::Server::Instance::Service[$instance_name], } } - case $ensure { - /present|absent/: { - postgresql_conf { $name: - ensure => $ensure, - target => $target, - value => $value, - require => Class['postgresql::server::initdb'], - } - } - - default: { - fail("Unknown value for ensure '${ensure}'.") - } + postgresql_conf { $name: + ensure => $ensure, + target => $path, + key => $key, + value => $value, + comment => $comment, + require => Postgresql::Server::Instance::Initdb[$instance_name], } } diff --git a/manifests/server/contrib.pp b/manifests/server/contrib.pp index e119d9c99a..e35eb511b3 100644 --- a/manifests/server/contrib.pp +++ b/manifests/server/contrib.pp @@ -1,19 +1,24 @@ -# Install the contrib postgresql packaging. See README.md for more details. +# @summary Install the contrib postgresql packaging. +# +# @param package_name +# The name of the PostgreSQL contrib package. +# @param package_ensure +# Ensure the contrib package is installed. class postgresql::server::contrib ( - $package_name = $postgresql::params::contrib_package_name, - $package_ensure = 'present' + Optional[String[1]] $package_name = $postgresql::params::contrib_package_name, + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', ) inherits postgresql::params { - validate_string($package_name) + if $package_name { + package { 'postgresql-contrib': + ensure => $package_ensure, + name => $package_name, + tag => 'puppetlabs-postgresql', + } - package { 'postgresql-contrib': - ensure => $package_ensure, - name => $package_name, - tag => 'postgresql', + anchor { 'postgresql::server::contrib::start': } + -> Class['postgresql::server::install'] + -> Package['postgresql-contrib'] + -> Class['postgresql::server::service'] + anchor { 'postgresql::server::contrib::end': } } - - anchor { 'postgresql::server::contrib::start': }-> - Class['postgresql::server::install']-> - Package['postgresql-contrib']-> - Class['postgresql::server::service']-> - anchor { 'postgresql::server::contrib::end': } } diff --git a/manifests/server/database.pp b/manifests/server/database.pp index f1adf646b7..48cd44103b 100644 --- a/manifests/server/database.pp +++ b/manifests/server/database.pp @@ -1,112 +1,119 @@ -# Define for creating a database. See README.md for more details. -define postgresql::server::database( - $comment = undef, - $dbname = $title, - $owner = $postgresql::server::user, - $tablespace = undef, - $template = 'template0', - $encoding = $postgresql::server::encoding, - $locale = $postgresql::server::locale, - $istemplate = false, - $connect_settings = $postgresql::server::default_connect_settings, +# @summary Define for creating a database. +# +# @param comment Sets a comment on the database. +# @param dbname Sets the name of the database. +# @param owner Sets name of the database owner. +# @param tablespace Sets tablespace for where to create this database. +# @param template Specifies the name of the template database from which to build this database. Default value: 'template0'. +# @param encoding Overrides the character set during creation of the database. +# @param locale Overrides the locale during creation of the database. +# @param istemplate Defines the database as a template if set to true. +# @param instance The name of the Postgresql database instance. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param psql_path Specifies the path to the psql command. +# @param default_db Specifies the name of the default database to connect with. On most systems this is 'postgres'. +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param group Overrides the default postgres user group to be used for related files in the file system. +# @param port Specifies the port for the PostgreSQL server to listen on. +define postgresql::server::database ( + Optional[String[1]] $comment = undef, + String[1] $dbname = $title, + Optional[String[1]] $owner = undef, + Optional[String[1]] $tablespace = undef, + String[1] $template = 'template0', + Optional[String[1]] $encoding = $postgresql::server::encoding, + Optional[String[1]] $locale = $postgresql::server::locale, + Boolean $istemplate = false, + String[1] $instance = 'main', + Hash $connect_settings = $postgresql::server::default_connect_settings, + String[1] $user = $postgresql::server::user, + String[1] $group = $postgresql::server::group, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + String[1] $default_db = $postgresql::server::default_database, + Stdlib::Port $port = $postgresql::server::port ) { - $createdb_path = $postgresql::server::createdb_path - $user = $postgresql::server::user - $group = $postgresql::server::group - $psql_path = $postgresql::server::psql_path - $default_db = $postgresql::server::default_database - - # If possible use the version of the remote database, otherwise - # fallback to our local DB version - if $connect_settings != undef and has_key( $connect_settings, 'DBVERSION') { - $version = $connect_settings['DBVERSION'] - } else { - $version = $postgresql::server::_version - } - - # If the connection settings do not contain a port, then use the local server port - if $connect_settings != undef and has_key( $connect_settings, 'PGPORT') { - $port = undef - } else { - $port = $postgresql::server::port - } + $version = pick($connect_settings['DBVERSION'], $postgresql::server::_version) + $port_override = pick($connect_settings['PGPORT'], $port) # Set the defaults for the postgresql_psql resource Postgresql_psql { + db => $default_db, psql_user => $user, psql_group => $group, psql_path => $psql_path, - port => $port, + port => $port_override, connect_settings => $connect_settings, + instance => $instance, } # Optionally set the locale switch. Older versions of createdb may not accept # --locale, so if the parameter is undefined its safer not to pass it. - if ($version != '8.1') { - $locale_option = $locale ? { - undef => '', - default => "LC_COLLATE='${locale}' LC_CTYPE='${locale}'", - } - $public_revoke_privilege = 'CONNECT' - } else { - $locale_option = '' - $public_revoke_privilege = 'ALL' + $locale_option = $locale ? { + undef => '', + default => "LC_COLLATE = '${locale}' LC_CTYPE = '${locale}'", } + $public_revoke_privilege = 'CONNECT' $template_option = $template ? { undef => '', - default => "TEMPLATE=${template}", + default => "TEMPLATE = \"${template}\"", } $encoding_option = $encoding ? { undef => '', - default => "ENCODING='${encoding}'", + default => "ENCODING = '${encoding}'", } $tablespace_option = $tablespace ? { undef => '', - default => "TABLESPACE=${tablespace}", + default => "TABLESPACE \"${tablespace}\"", } - if $createdb_path != undef{ - warning('Passing "createdb_path" to postgresql::database is deprecated, it can be removed safely for the same behaviour') + postgresql_psql { "CREATE DATABASE \"${dbname}\"": + command => "CREATE DATABASE \"${dbname}\" WITH ${template_option} ${encoding_option} ${locale_option} ${tablespace_option}", + unless => "SELECT 1 FROM pg_database WHERE datname = '${dbname}'", + require => Postgresql::Server::Instance::Service[$instance], } - postgresql_psql { "Create db '${dbname}'": - command => "CREATE DATABASE \"${dbname}\" WITH OWNER=${owner} ${template_option} ${encoding_option} ${locale_option} ${tablespace_option}", - unless => "SELECT datname FROM pg_database WHERE datname='${dbname}'", - db => $default_db, - require => Class['postgresql::server::service'] - }~> - # This will prevent users from connecting to the database unless they've been # granted privileges. - postgresql_psql {"REVOKE ${public_revoke_privilege} ON DATABASE \"${dbname}\" FROM public": - db => $default_db, + ~> postgresql_psql { "REVOKE ${public_revoke_privilege} ON DATABASE \"${dbname}\" FROM public": refreshonly => true, } - Postgresql_psql[ "Create db '${dbname}'" ]-> - postgresql_psql {"UPDATE pg_database SET datistemplate = ${istemplate} WHERE datname = '${dbname}'": - unless => "SELECT datname FROM pg_database WHERE datname = '${dbname}' AND datistemplate = ${istemplate}", - db => $default_db, + Postgresql_psql["CREATE DATABASE \"${dbname}\""] + -> postgresql_psql { "UPDATE pg_database SET datistemplate = ${istemplate} WHERE datname = '${dbname}'": + unless => "SELECT 1 FROM pg_database WHERE datname = '${dbname}' AND datistemplate = ${istemplate}", } if $comment { - # The shobj_description function was only introduced with 8.2 - $comment_information_function = $version ? { - '8.1' => 'obj_description', - default => 'shobj_description', - } - Postgresql_psql[ "Create db '${dbname}'" ]-> - postgresql_psql {"COMMENT ON DATABASE ${dbname} IS '${comment}'": - unless => "SELECT pg_catalog.${comment_information_function}(d.oid, 'pg_database') as \"Description\" FROM pg_catalog.pg_database d WHERE datname = '${dbname}' AND pg_catalog.${comment_information_function}(d.oid, 'pg_database') = '${comment}'", + Postgresql_psql["CREATE DATABASE \"${dbname}\""] + -> postgresql_psql { "COMMENT ON DATABASE \"${dbname}\" IS '${comment}'": + unless => "SELECT 1 FROM pg_catalog.pg_database d WHERE datname = '${dbname}' AND pg_catalog.shobj_description(d.oid, 'pg_database') = '${comment}'", # lint:ignore:140chars db => $dbname, } } - # Build up dependencies on tablespace - if($tablespace != undef and defined(Postgresql::Server::Tablespace[$tablespace])) { - Postgresql::Server::Tablespace[$tablespace]->Postgresql_psql[ "Create db '${dbname}'" ] + if $owner { + postgresql_psql { "ALTER DATABASE \"${dbname}\" OWNER TO \"${owner}\"": + unless => "SELECT 1 FROM pg_database JOIN pg_roles rol ON datdba = rol.oid WHERE datname = '${dbname}' AND rolname = '${owner}'", + require => Postgresql_psql["CREATE DATABASE \"${dbname}\""], + } + + if defined(Postgresql::Server::Role[$owner]) { + Postgresql::Server::Role[$owner] -> Postgresql_psql["ALTER DATABASE \"${dbname}\" OWNER TO \"${owner}\""] + } + } + + if $tablespace { + postgresql_psql { "ALTER DATABASE \"${dbname}\" SET ${tablespace_option}": + unless => "SELECT 1 FROM pg_database JOIN pg_tablespace spc ON dattablespace = spc.oid WHERE datname = '${dbname}' AND spcname = '${tablespace}'", # lint:ignore:140chars + require => Postgresql_psql["CREATE DATABASE \"${dbname}\""], + } + + if defined(Postgresql::Server::Tablespace[$tablespace]) { + # The tablespace must be there, before we create the database. + Postgresql::Server::Tablespace[$tablespace] -> Postgresql_psql["CREATE DATABASE \"${dbname}\""] + } } } diff --git a/manifests/server/database_grant.pp b/manifests/server/database_grant.pp index 6c29b57176..c4a7c67ca1 100644 --- a/manifests/server/database_grant.pp +++ b/manifests/server/database_grant.pp @@ -1,13 +1,29 @@ -# Manage a database grant. See README.md for more details. -define postgresql::server::database_grant( - $privilege, - $db, - $role, - $psql_db = undef, - $psql_user = undef, - $connect_settings = undef, +# @summary Manage a database grant. +# +# @param privilege Specifies comma-separated list of privileges to grant. Valid options: 'ALL', 'CREATE', 'CONNECT', 'TEMPORARY', 'TEMP'. +# @param db Specifies the database to which you are granting access. +# @param role Specifies the role or user whom you are granting access to. +# @param ensure Specifies whether to grant or revoke the privilege. Revoke or 'absent' works only in PostgreSQL version 9.1.24 or later. +# @param psql_db Defines the database to execute the grant against. This should not ordinarily be changed from the default +# @param psql_user Specifies the OS user for running psql. Default value: The default user for the module, usually 'postgres'. +# @param psql_group Overrides the default postgres user group to be used for related files in the file system. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param port Port to use when connecting. +# @param instance The name of the Postgresql database instance. +define postgresql::server::database_grant ( + Enum['ALL', 'CREATE', 'CONNECT', 'TEMPORARY', 'TEMP', 'all', 'create', 'connect', 'temporary', 'temp'] $privilege, + String[1] $db, + String[1] $role, + Optional[Enum['present', 'absent']] $ensure = undef, + Optional[String[1]] $psql_db = undef, + String[1] $psql_user = $postgresql::server::user, + Hash $connect_settings = $postgresql::server::default_connect_settings, + String[1] $psql_group = $postgresql::server::group, + Stdlib::Port $port = $postgresql::server::port, + String[1] $instance = 'main', ) { postgresql::server::grant { "database:${name}": + ensure => $ensure, role => $role, db => $db, privilege => $privilege, @@ -15,6 +31,9 @@ object_name => $db, psql_db => $psql_db, psql_user => $psql_user, + group => $psql_group, + port => $port, connect_settings => $connect_settings, + instance => $instance, } } diff --git a/manifests/server/db.pp b/manifests/server/db.pp index b4c1232cfa..9542dcc618 100644 --- a/manifests/server/db.pp +++ b/manifests/server/db.pp @@ -1,19 +1,37 @@ -# Define for conveniently creating a role, database and assigning the correct -# permissions. See README.md for more details. +# @summary Define for conveniently creating a role, database and assigning the correct permissions. +# +# @param user User to assign access to the database upon creation (will be created if not defined elsewhere). Mandatory. +# @param password Sets the password for the created user (if a user is created). +# @param comment Defines a comment to be stored about the database using the PostgreSQL COMMENT command. +# @param dbname Sets the name of the database to be created. +# @param encoding Overrides the character set during creation of the database. +# @param locale Overrides the locale during creation of the database. +# @param grant Specifies the permissions to grant during creation. Default value: 'ALL'. +# @param tablespace Defines the name of the tablespace to allocate the created database to. +# @param template Specifies the name of the template database from which to build this database. Defaults value: template0. +# @param istemplate Specifies that the database is a template, if set to true. +# @param owner Sets a user as the owner of the database. +# @param port Specifies the port where the PostgreSQL server is listening on. +# @param psql_user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param psql_group Overrides the default PostgreSQL user group to be used for related files in the file system. +# @param instance The name of the Postgresql database instance. define postgresql::server::db ( - $user, - $password, - $comment = undef, - $dbname = $title, - $encoding = $postgresql::server::encoding, - $locale = $postgresql::server::locale, - $grant = 'ALL', - $tablespace = undef, - $template = 'template0', - $istemplate = false, - $owner = undef + String[1] $user, + Optional[Variant[String, Sensitive[String]]] $password = undef, + Optional[String[1]] $comment = undef, + String[1] $dbname = $title, + Optional[String[1]] $encoding = $postgresql::server::encoding, + Optional[String[1]] $locale = $postgresql::server::locale, + Variant[String[1], Array[String[1]]] $grant = 'ALL', + Optional[String[1]] $tablespace = undef, + String[1] $template = 'template0', + Boolean $istemplate = false, + Optional[String[1]] $owner = undef, + Optional[Stdlib::Port] $port = undef, + String[1] $psql_user = $postgresql::server::user, + String[1] $psql_group = $postgresql::server::group, + String[1] $instance = 'main', ) { - if ! defined(Postgresql::Server::Database[$dbname]) { postgresql::server::database { $dbname: comment => $comment, @@ -23,25 +41,37 @@ locale => $locale, istemplate => $istemplate, owner => $owner, + port => $port, + user => $psql_user, + group => $psql_group, + instance => $instance, } } if ! defined(Postgresql::Server::Role[$user]) { postgresql::server::role { $user: password_hash => $password, + port => $port, + psql_user => $psql_user, + psql_group => $psql_group, before => Postgresql::Server::Database[$dbname], + instance => $instance, } } if ! defined(Postgresql::Server::Database_grant["GRANT ${user} - ${grant} - ${dbname}"]) { postgresql::server::database_grant { "GRANT ${user} - ${grant} - ${dbname}": - privilege => $grant, - db => $dbname, - role => $user, - } -> Postgresql::Validate_db_connection<| database_name == $dbname |> + privilege => $grant, + db => $dbname, + role => $user, + port => $port, + psql_user => $psql_user, + psql_group => $psql_group, + instance => $instance, + } -> Postgresql_conn_validator<| db_name == $dbname |> } - if($tablespace != undef and defined(Postgresql::Server::Tablespace[$tablespace])) { - Postgresql::Server::Tablespace[$tablespace]->Postgresql::Server::Database[$name] + if ($tablespace != undef and defined(Postgresql::Server::Tablespace[$tablespace])) { + Postgresql::Server::Tablespace[$tablespace] -> Postgresql::Server::Database[$name] } } diff --git a/manifests/server/default_privileges.pp b/manifests/server/default_privileges.pp new file mode 100644 index 0000000000..815abaebbd --- /dev/null +++ b/manifests/server/default_privileges.pp @@ -0,0 +1,175 @@ +# @summary Manage a database defaults privileges. Only works with PostgreSQL version 9.6 and above. +# +# @param target_role Target role whose created objects will receive the default privileges. Defaults to the current user. +# @param ensure Specifies whether to grant or revoke the privilege. +# @param role Specifies the role or user whom you are granting access to. +# @param db Specifies the database to which you are granting access. +# @param object_type Specify target object type: 'FUNCTIONS', 'ROUTINES', 'SEQUENCES', 'TABLES', 'TYPES'. +# @param privilege Specifies comma-separated list of privileges to grant. Valid options: depends on object type. +# @param schema Target schema. Defaults to 'public'. Can be set to '' to apply to all schemas. +# @param psql_db Defines the database to execute the grant against. This should not ordinarily be changed from the default. +# @param psql_user Specifies the OS user for running psql. Default value: The default user for the module, usually 'postgres'. +# @param psql_path Specifies the OS user for running psql. Default value: The default user for the module, usually 'postgres'. +# @param port Specifies the port to access the server. Default value: The default user for the module, usually '5432'. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param instance The name of the Postgresql database instance. +# @param group Specifies the user group to which the privileges will be granted. +define postgresql::server::default_privileges ( + String $role, + String $db, + String $privilege, + Pattern[ + /(?i:^FUNCTIONS$)/, + /(?i:^ROUTINES$)/, + /(?i:^SEQUENCES$)/, + /(?i:^TABLES$)/, + /(?i:^TYPES$)/, + /(?i:^SCHEMAS$)/ + ] $object_type, + String $schema = 'public', + String $psql_db = $postgresql::server::default_database, + String $psql_user = $postgresql::server::user, + Stdlib::Port $port = $postgresql::server::port, + Hash $connect_settings = $postgresql::server::default_connect_settings, + Enum['present', 'absent'] $ensure = 'present', + String $group = $postgresql::server::group, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + Optional[String] $target_role = undef, + String[1] $instance = 'main', +) { + $version = pick($connect_settings['DBVERSION'],postgresql::default('version')) + $port_override = pick($connect_settings['PGPORT'], $port) + + if (versioncmp($version, '9.6') == -1) { + fail 'Default_privileges is only useable with PostgreSQL >= 9.6' + } + + case $ensure { + default: { + # default is 'present' + $sql_command = 'ALTER DEFAULT PRIVILEGES%s%s GRANT %s ON %s TO "%s"' + $unless_is = true + } + 'absent': { + $sql_command = 'ALTER DEFAULT PRIVILEGES%s%s REVOKE %s ON %s FROM "%s"' + $unless_is = false + } + } + + if $target_role { + $_target_role = " FOR ROLE ${target_role}" + $_check_target_role = "/${target_role}" + } else { + $_target_role = '' + $_check_target_role = '' + } + + if $schema != '' { + $_schema = " IN SCHEMA ${schema}" + $_check_schema = " AND nspname = '${schema}'" + } else { + $_schema = '' + $_check_schema = ' AND nspname IS NULL' + } + + ## Munge the input values + $_object_type = upcase($object_type) + $_privilege = upcase($privilege) + + case $_object_type { + # Routines and functions ends up with the same definition + Pattern[ + /^ROUTINES$/, + /^FUNCTIONS$/, + ]: { + case $_privilege { + Pattern[ + /^ALL$/, + /^EXECUTE$/, + ]: { + $_check_privilege = 'X' + } + default: { fail('Illegal value for $privilege parameter') } + } + $_check_type = 'f' + } + 'SEQUENCES': { + case $_privilege { + /^(ALL)$/: { $_check_privilege = 'rwU' } + /^SELECT$/: { $_check_privilege = 'r' } + /^UPDATE$/: { $_check_privilege = 'w' } + /^USAGE$/: { $_check_privilege = 'U' } + default: { fail('Illegal value for $privilege parameter') } + } + $_check_type = 'S' + } + 'TABLES': { + case $_privilege { + /^ALL$/: { $_check_privilege = 'arwdDxt' } + /^DELETE$/: { $_check_privilege = 'd' } + /^INSERT$/: { $_check_privilege = 'a' } + /^REFERENCES$/: { $_check_privilege = 'x' } + /^SELECT$/: { $_check_privilege = 'r' } + /^TRIGGER$/: { $_check_privilege = 'd' } + /^TRUNCATE$/: { $_check_privilege = 'D' } + /^UPDATE$/: { $_check_privilege = 'w' } + default: { fail('Illegal value for $privilege parameter') } + } + $_check_type = 'r' + } + 'TYPES': { + case $_privilege { + /^(ALL|USAGE)$/: { $_check_privilege = 'U' } + default: { fail('Illegal value for $privilege parameter') } + } + $_check_type = 'T' + } + 'SCHEMAS': { + if (versioncmp($version, '10') == -1) { + fail 'Default_privileges on schemas is only supported on PostgreSQL >= 10.0' + } + if $schema != '' { + fail('Cannot alter default schema permissions within a schema') + } + case $_privilege { + /^ALL$/: { $_check_privilege = 'UC' } + /^USAGE$/: { $_check_privilege = 'U' } + /^CREATE$/: { $_check_privilege = 'C' } + default: { fail('Illegal value for $privilege parameter') } + } + $_check_type = 'n' + } + default: { + fail("Missing privilege validation for object type ${_object_type}") + } + } + + $_unless = $ensure ? { + 'absent' => "SELECT 1 WHERE NOT EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '%s=%s%s' = ANY (defaclacl)%s and defaclobjtype = '%s')", # lint:ignore:140chars + default => "SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '%s=%s%s' = ANY (defaclacl)%s and defaclobjtype = '%s')", # lint:ignore:140chars + } + + $unless_cmd = sprintf($_unless, $role, $_check_privilege, $_check_target_role, $_check_schema, $_check_type) + $grant_cmd = sprintf($sql_command, $_target_role, $_schema, $_privilege, $_object_type, $role) + + postgresql_psql { "default_privileges:${name}": + command => $grant_cmd, + db => $db, + port => $port_override, + connect_settings => $connect_settings, + psql_user => $psql_user, + psql_group => $group, + psql_path => $psql_path, + unless => $unless_cmd, + environment => 'PGOPTIONS=--client-min-messages=error', + instance => $instance, + } + + if defined(Postgresql::Server::Role[$role]) { + Postgresql::Server::Role[$role] -> Postgresql_psql["default_privileges:${name}"] + } + + if defined(Postgresql::Server::Database[$db]) { + Postgresql::Server::Database[$db] -> Postgresql_psql["default_privileges:${name}"] + } +} diff --git a/manifests/server/extension.pp b/manifests/server/extension.pp index 14b51f2c78..196c077c0b 100644 --- a/manifests/server/extension.pp +++ b/manifests/server/extension.pp @@ -1,29 +1,76 @@ -# Activate an extension on a postgresql database +# @summary Activate an extension on a postgresql database. +# +# @param database Specifies the database on which to activate the extension. +# @param extension Specifies the extension to activate. If left blank, uses the name of the resource. +# @param schema Specifies the schema on which to activate the extension. +# @param version +# Specifies the version of the extension which the database uses. When an extension package is updated, this does not automatically +# change the effective version in each database. +# This needs be updated using the PostgreSQL-specific SQL ALTER EXTENSION... +# version may be set to latest, in which case the SQL ALTER EXTENSION "extension" UPDATE is applied to this database (only). +# version may be set to a specific version, in which case the extension is updated using ALTER EXTENSION "extension" UPDATE TO 'version' +# eg. If extension is set to postgis and version is set to 2.3.3, this will apply the SQL ALTER EXTENSION "postgis" UPDATE TO '2.3.3' to +# this database only. +# version may be omitted, in which case no ALTER EXTENSION... SQL is applied, and the version will be left unchanged. +# +# @param ensure Specifies whether to activate or deactivate the extension. Valid options: 'present' or 'absent'. +# @param package_name Specifies a package to install prior to activating the extension. +# @param package_ensure +# Overrides default package deletion behavior. By default, the package specified with package_name is installed when the extension is +# activated and removed when the extension is deactivated. To override this behavior, set the ensure value for the package. +# @param port Port to use when connecting. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param database_resource_name Specifies the resource name of the DB being managed. Defaults to the parameter $database, if left blank. +# @param instance The name of the Postgresql database instance. +# @param psql_path Specifies the path to the psql command. +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param group Overrides the default postgres user group to be used for related files in the file system. define postgresql::server::extension ( - $database, - $extension = $name, - $ensure = 'present', - $package_name = undef, - $package_ensure = undef, - $connect_settings = $postgresql::server::default_connect_settings, + String[1] $database, + Optional[Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]]] $package_ensure = undef, + String[1] $extension = $name, + Optional[String[1]] $schema = undef, + Optional[String[1]] $version = undef, + Enum['present', 'absent'] $ensure = 'present', + Optional[String[1]] $package_name = undef, + Stdlib::Port $port = postgresql::default('port'), + Hash $connect_settings = postgresql::default('default_connect_settings'), + String[1] $database_resource_name = $database, + String[1] $instance = 'main', + String[1] $user = postgresql::default('user'), + String[1] $group = postgresql::default('group'), + Stdlib::Absolutepath $psql_path = postgresql::default('psql_path'), ) { - $user = $postgresql::server::user - $group = $postgresql::server::group - $psql_path = $postgresql::server::psql_path + if( $database != 'postgres' ) { + # The database postgres cannot managed by this module, so it is exempt from this dependency + $default_psql_require = Postgresql::Server::Database[$database_resource_name] + + Postgresql_psql { + require => $default_psql_require, + } + } else { + $default_psql_require = undef + } case $ensure { 'present': { $command = "CREATE EXTENSION \"${extension}\"" - $unless_comp = '=' - $package_require = undef - $package_before = Postgresql_psql["Add ${extension} extension to ${database}"] + $unless_mod = undef + $psql_cmd_require = $package_name ? { + undef => $default_psql_require, + default => [$default_psql_require, Package[$package_name]], + } + $psql_cmd_before = [] } 'absent': { $command = "DROP EXTENSION \"${extension}\"" - $unless_comp = '!=' - $package_require = Postgresql_psql["Add ${extension} extension to ${database}"] - $package_before = undef + $unless_mod = 'NOT ' + $psql_cmd_require = $default_psql_require + $psql_cmd_before = $package_name ? { + undef => [], + default => Package[$package_name], + } } default: { @@ -31,18 +78,49 @@ } } + $port_override = pick($connect_settings['PGPORT'], $port) - postgresql_psql {"Add ${extension} extension to ${database}": - + postgresql_psql { "${database}: ${command}": psql_user => $user, psql_group => $group, psql_path => $psql_path, connect_settings => $connect_settings, - db => $database, + port => $port_override, command => $command, - unless => "SELECT t.count FROM (SELECT count(extname) FROM pg_extension WHERE extname = '${extension}') as t WHERE t.count ${unless_comp} 1", - require => Postgresql::Server::Database[$database], + instance => $instance, + unless => "SELECT 1 WHERE ${unless_mod}EXISTS (SELECT 1 FROM pg_extension WHERE extname = '${extension}')", + require => $psql_cmd_require, + before => $psql_cmd_before, + } + + if $ensure == 'present' and $schema { + $set_schema_command = "ALTER EXTENSION \"${extension}\" SET SCHEMA \"${schema}\"" + + postgresql_psql { "${database}: ${set_schema_command}": + command => $set_schema_command, + unless => @("END") + SELECT 1 + WHERE EXISTS ( + SELECT 1 + FROM pg_extension e + JOIN pg_namespace n ON e.extnamespace = n.oid + WHERE e.extname = '${extension}' AND + n.nspname = '${schema}' + ) + |-END + , + psql_user => $user, + psql_group => $group, + psql_path => $psql_path, + connect_settings => $connect_settings, + db => $database, + port => $port_override, + instance => $instance, + require => Postgresql_psql["${database}: ${command}"], + } + + Postgresql::Server::Schema <| db == $database and schema == $schema |> -> Postgresql_psql["${database}: ${set_schema_command}"] } if $package_name { @@ -51,11 +129,29 @@ default => $package_ensure, } - ensure_packages($package_name, { - ensure => $_package_ensure, - tag => 'postgresql', - require => $package_require, - before => $package_before, + stdlib::ensure_packages($package_name, { + ensure => $_package_ensure, + tag => 'puppetlabs-postgresql', }) } + if $version { + if $version == 'latest' { + $alter_extension_sql = "ALTER EXTENSION \"${extension}\" UPDATE" + $update_unless = "SELECT 1 FROM pg_available_extensions WHERE name = '${extension}' AND default_version = installed_version" + } else { + $alter_extension_sql = "ALTER EXTENSION \"${extension}\" UPDATE TO '${version}'" + $update_unless = "SELECT 1 FROM pg_extension WHERE extname='${extension}' AND extversion='${version}'" + } + postgresql_psql { "${database}: ${alter_extension_sql}": + db => $database, + port => $port_override, + psql_user => $user, + psql_group => $group, + psql_path => $psql_path, + connect_settings => $connect_settings, + command => $alter_extension_sql, + instance => $instance, + unless => $update_unless, + } + } } diff --git a/manifests/server/grant.pp b/manifests/server/grant.pp index 447ba186df..e9c0894003 100644 --- a/manifests/server/grant.pp +++ b/manifests/server/grant.pp @@ -1,18 +1,74 @@ -# Define for granting permissions to roles. See README.md for more details. +# @summary Define for granting permissions to roles. +# +# @param role Specifies the role or user whom you are granting access to. +# @param db Specifies the database to which you are granting access. +# @param privilege Specifies the privilege to grant. Valid options: 'ALL', 'ALL PRIVILEGES' or 'object_type' dependent string. +# @param object_type +# Specifies the type of object to which you are granting privileges. +# Valid options: 'DATABASE', 'SCHEMA', 'SEQUENCE', 'ALL SEQUENCES IN SCHEMA', 'TABLE' or 'ALL TABLES IN SCHEMA'. +# @param object_name +# Specifies name of object_type to which to grant access, can be either a string or a two element array. +# String: 'object_name' Array: ['schema_name', 'object_name'] +# @param object_arguments Specifies any arguments to be passed alongisde the access grant. +# @param psql_db Specifies the database to execute the grant against. This should not ordinarily be changed from the default +# @param psql_user Sets the OS user to run psql. +# @param port Port to use when connecting. +# @param onlyif_exists Create grant only if doesn't exist +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param ensure Specifies whether to grant or revoke the privilege. Default is to grant the privilege. Valid values: 'present', 'absent'. +# @param group Sets the OS group to run psql +# @param psql_path Sets the path to psql command +# @param instance The name of the Postgresql database instance. define postgresql::server::grant ( - $role, - $db, - $privilege = undef, - $object_type = 'database', - $object_name = undef, - $psql_db = $postgresql::server::default_database, - $psql_user = $postgresql::server::user, - $port = $postgresql::server::port, - $onlyif_exists = false, - $connect_settings = $postgresql::server::default_connect_settings, + String $role, + String $db, + String $privilege = '', # lint:ignore:params_empty_string_assignment + Pattern[#/(?i:^COLUMN$)/, + /(?i:^ALL SEQUENCES IN SCHEMA$)/, + /(?i:^ALL TABLES IN SCHEMA$)/, + /(?i:^DATABASE$)/, + #/(?i:^FOREIGN DATA WRAPPER$)/, + #/(?i:^FOREIGN SERVER$)/, + /(?i:^FUNCTION$)/, + /(?i:^LANGUAGE$)/, + #/(?i:^PROCEDURAL LANGUAGE$)/, + /(?i:^TABLE$)/, + #/(?i:^TABLESPACE$)/, + /(?i:^SCHEMA$)/, + /(?i:^SEQUENCE$)/ + #/(?i:^VIEW$)/ + ] $object_type = 'database', + Optional[Variant[Array[String,2,2],String[1]]] $object_name = undef, + Array[String[1],0] $object_arguments = [], + String $psql_db = $postgresql::server::default_database, + String $psql_user = $postgresql::server::user, + Stdlib::Port $port = $postgresql::server::port, + Boolean $onlyif_exists = false, + Hash $connect_settings = $postgresql::server::default_connect_settings, + Enum['present', 'absent'] $ensure = 'present', + String $group = $postgresql::server::group, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + String[1] $instance = 'main', ) { - $group = $postgresql::server::group - $psql_path = $postgresql::server::psql_path + case $ensure { + default: { + # default is 'present' + $sql_command = 'GRANT %s ON %s "%s%s" TO %s' + $sql_command_unquoted = 'GRANT %s ON %s %s%s TO %s' + $unless_is = true + } + 'absent': { + $sql_command = 'REVOKE %s ON %s "%s%s" FROM %s' + $sql_command_unquoted = 'REVOKE %s ON %s %s%s FROM %s' + $unless_is = false + } + } + + # Quote the role if not PUBLIC + $_query_role = $role ? { + 'PUBLIC' => 'PUBLIC', + default => "\"${role}\"" + } if ! $object_name { $_object_name = $db @@ -20,38 +76,12 @@ $_object_name = $object_name } - validate_bool($onlyif_exists) - # - # Port, order of precedence: $port parameter, $connect_settings[PGPORT], $postgresql::server::port - # - if $port != undef { - $port_override = $port - } elsif $connect_settings != undef and has_key( $connect_settings, 'PGPORT') { - $port_override = undef - } else { - $port_override = $postgresql::server::port - } + $port_override = pick($connect_settings['PGPORT'], $port) ## Munge the input values $_object_type = upcase($object_type) $_privilege = upcase($privilege) - ## Validate that the object type is known - validate_string($_object_type, - #'COLUMN', - 'DATABASE', - #'FOREIGN SERVER', - #'FOREIGN DATA WRAPPER', - #'FUNCTION', - #'PROCEDURAL LANGUAGE', - 'SCHEMA', - 'SEQUENCE', - 'ALL SEQUENCES IN SCHEMA', - 'TABLE', - 'ALL TABLES IN SCHEMA', - #'TABLESPACE', - #'VIEW', - ) # You can use ALL TABLES IN SCHEMA by passing schema_name to object_name # You can use ALL SEQUENCES IN SCHEMA by passing schema_name to object_name @@ -69,38 +99,76 @@ $unless_privilege = $_privilege ? { 'ALL' => 'CREATE', 'ALL PRIVILEGES' => 'CREATE', - default => $_privilege, + Pattern[ + /^$/, + /^CONNECT$/, + /^CREATE$/, + /^TEMP$/, + /^TEMPORARY$/, + ] => $_privilege, + default => fail('Illegal value for $privilege parameter'), } - validate_string($unless_privilege,'CREATE','CONNECT','TEMPORARY','TEMP', - 'ALL','ALL PRIVILEGES') $unless_function = 'has_database_privilege' $on_db = $psql_db - $onlyif_function = undef + $onlyif_function = $ensure ? { + default => undef, + 'absent' => 'role_exists', + } + $arguments = '' + $_enquote_object = true } 'SCHEMA': { $unless_privilege = $_privilege ? { 'ALL' => 'CREATE', 'ALL PRIVILEGES' => 'CREATE', - default => $_privilege, + Pattern[ + /^$/, + /^CREATE$/, + /^USAGE$/, + ] => $_privilege, + default => fail('Illegal value for $privilege parameter'), } - validate_string($_privilege, 'CREATE', 'USAGE', 'ALL', 'ALL PRIVILEGES') $unless_function = 'has_schema_privilege' $on_db = $db $onlyif_function = undef + $arguments = '' + $_enquote_object = true } 'SEQUENCE': { $unless_privilege = $_privilege ? { 'ALL' => 'USAGE', - default => $_privilege, + Pattern[ + /^$/, + /^ALL PRIVILEGES$/, + /^SELECT$/, + /^UPDATE$/, + /^USAGE$/, + ] => $_privilege, + default => fail('Illegal value for $privilege parameter'), } - validate_string($unless_privilege,'USAGE','ALL','ALL PRIVILEGES') $unless_function = 'has_sequence_privilege' $on_db = $db + $onlyif_function = undef + $arguments = '' + $_enquote_object = true } 'ALL SEQUENCES IN SCHEMA': { - validate_string($_privilege,'USAGE','ALL','ALL PRIVILEGES') + case $_privilege { + Pattern[ + /^$/, + /^ALL$/, + /^ALL PRIVILEGES$/, + /^SELECT$/, + /^UPDATE$/, + /^USAGE$/, + ]: {} + default: { fail('Illegal value for $privilege parameter') } + } $unless_function = 'custom' $on_db = $db + $onlyif_function = undef + $arguments = '' + $_enquote_object = true $schema = $object_name @@ -109,7 +177,7 @@ 'ALL PRIVILEGES' => 'USAGE', default => $_privilege, } - + # This checks if there is a difference between the sequences in the # specified schema and the sequences for which the role has the specified # privilege. It uses the EXCEPT clause which computes the set of rows @@ -121,76 +189,223 @@ # If this number is not zero then there is at least one sequence for which # the role does not have the specified privilege, making it necessary to # execute the GRANT statement. - $custom_unless = "SELECT 1 FROM ( - SELECT sequence_name - FROM information_schema.sequences - WHERE sequence_schema='${schema}' - EXCEPT DISTINCT - SELECT object_name as sequence_name - FROM information_schema.role_usage_grants - WHERE object_type='SEQUENCE' - AND grantee='${role}' - AND object_schema='${schema}' - AND privilege_type='${custom_privilege}' - ) P - HAVING count(P.sequence_name) = 0" + if $ensure == 'present' { + $custom_unless = "SELECT 1 WHERE NOT EXISTS ( + SELECT sequence_name + FROM information_schema.sequences + WHERE sequence_schema='${schema}' + EXCEPT DISTINCT + SELECT object_name as sequence_name + FROM ( + SELECT object_schema, + object_name, + grantee, + CASE privs_split + WHEN 'r' THEN 'SELECT' + WHEN 'w' THEN 'UPDATE' + WHEN 'U' THEN 'USAGE' + END AS privilege_type + FROM ( + SELECT DISTINCT + object_schema, + object_name, + regexp_replace((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[1],'\"','','g') AS grantee, + regexp_split_to_table((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[2],E'\\s*') AS privs_split + FROM ( + SELECT n.nspname as object_schema, + c.relname as object_name, + regexp_split_to_table(array_to_string(c.relacl,','),',') AS privs + FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid + WHERE c.relkind = 'S' + AND n.nspname NOT IN ( 'pg_catalog', 'information_schema' ) + ) P1 + ) P2 + ) P3 + WHERE grantee='${role}' + AND object_schema='${schema}' + AND privilege_type='${custom_privilege}' + )" + } else { + # ensure == absent + $custom_unless = "SELECT 1 WHERE NOT EXISTS ( + SELECT object_name as sequence_name + FROM ( + SELECT object_schema, + object_name, + grantee, + CASE privs_split + WHEN 'r' THEN 'SELECT' + WHEN 'w' THEN 'UPDATE' + WHEN 'U' THEN 'USAGE' + END AS privilege_type + FROM ( + SELECT DISTINCT + object_schema, + object_name, + regexp_replace((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[1],'\"','','g') AS grantee, + regexp_split_to_table((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[2],E'\\s*') AS privs_split + FROM ( + SELECT n.nspname as object_schema, + c.relname as object_name, + regexp_split_to_table(array_to_string(c.relacl,','),',') AS privs + FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid + WHERE c.relkind = 'S' + AND n.nspname NOT IN ( 'pg_catalog', 'information_schema' ) + ) P1 + ) P2 + ) P3 + WHERE grantee='${role}' + AND object_schema='${schema}' + AND privilege_type='${custom_privilege}' + )" + } } 'TABLE': { $unless_privilege = $_privilege ? { 'ALL' => 'INSERT', - default => $_privilege, + Pattern[ + /^$/, + /^ALL$/, + /^ALL PRIVILEGES$/, + /^DELETE$/, + /^INSERT$/, + /^REFERENCES$/, + /^SELECT$/, + /^TRIGGER$/, + /^TRUNCATE$/, + /^UPDATE$/, + ] => $_privilege, + default => fail('Illegal value for $privilege parameter'), } - validate_string($unless_privilege,'SELECT','INSERT','UPDATE','DELETE', - 'TRUNCATE','REFERENCES','TRIGGER','ALL','ALL PRIVILEGES') $unless_function = 'has_table_privilege' $on_db = $db $onlyif_function = $onlyif_exists ? { true => 'table_exists', default => undef, } + $arguments = '' + $_enquote_object = true } 'ALL TABLES IN SCHEMA': { - validate_string($_privilege,'SELECT','INSERT','UPDATE','DELETE', - 'TRUNCATE','REFERENCES','TRIGGER','ALL','ALL PRIVILEGES') + case $_privilege { + Pattern[ + /^$/, + /^ALL$/, + /^ALL PRIVILEGES$/, + /^DELETE$/, + /^INSERT$/, + /^REFERENCES$/, + /^SELECT$/, + /^TRIGGER$/, + /^TRUNCATE$/, + /^UPDATE$/, + ]: {} + default: { fail('Illegal value for $privilege parameter') } + } $unless_function = 'custom' $on_db = $db $onlyif_function = undef + $arguments = '' + $_enquote_object = true $schema = $object_name # Again there seems to be no easy way in plain SQL to check if ALL - # PRIVILEGES are granted on a table. By convention we use INSERT - # here to represent ALL PRIVILEGES (truly terrible). - $custom_privilege = $_privilege ? { - 'ALL' => 'INSERT', - 'ALL PRIVILEGES' => 'INSERT', - default => $_privilege, - } + # PRIVILEGES are granted on a table. + # There are currently 7 possible priviliges: + # ('SELECT','UPDATE','INSERT','DELETE','TRIGGER','REFERENCES','TRUNCATE') + # This list is consistant from Postgresql 8.0 + # + # There are 4 cases to cover, each with it's own distinct unless clause: + # grant ALL + # grant SELECT (or INSERT or DELETE ...) + # revoke ALL + # revoke SELECT (or INSERT or DELETE ...) - # This checks if there is a difference between the tables in the - # specified schema and the tables for which the role has the specified - # privilege. It uses the EXCEPT clause which computes the set of rows - # that are in the result of the first SELECT statement but not in the - # result of the second one. It then counts the number of rows from this - # operation. If this number is zero then the role has the specified - # privilege for all tables in the schema and the whole query returns a - # single row, which satisfies the `unless` parameter of Postgresql_psql. - # If this number is not zero then there is at least one table for which - # the role does not have the specified privilege, making it necessary to - # execute the GRANT statement. - $custom_unless = "SELECT 1 FROM ( - SELECT table_name - FROM information_schema.tables - WHERE table_schema='${schema}' - EXCEPT DISTINCT - SELECT table_name - FROM information_schema.role_table_grants - WHERE grantee='${role}' - AND table_schema='${schema}' - AND privilege_type='${custom_privilege}' - ) P - HAVING count(P.table_name) = 0" + if $ensure == 'present' { + if $_privilege == 'ALL' or $_privilege == 'ALL PRIVILEGES' { + # GRANT ALL + # lint:ignore:140chars + $custom_unless = "SELECT 1 WHERE NOT EXISTS + ( SELECT 1 FROM + ( SELECT t.tablename,count(privilege_type) AS priv_count FROM pg_catalog.pg_tables AS t + LEFT JOIN information_schema.role_table_grants AS g ON t.tablename = g.table_name AND g.grantee = '${role}' AND g.table_schema = '${schema}' + WHERE t.schemaname = '${schema}' AND + ( g.grantee = '${role}' AND privilege_type IN ('SELECT','UPDATE','INSERT','DELETE','TRIGGER','REFERENCES','TRUNCATE') OR privilege_type IS NULL ) + GROUP BY t.tablename + ) AS j WHERE j.priv_count < 7 + )" + # lint:endignore:140chars + } else { + # GRANT $_privilege + # lint:ignore:140chars + $custom_unless = "SELECT 1 WHERE NOT EXISTS + ( SELECT 1 FROM pg_catalog.pg_tables AS t + LEFT JOIN information_schema.role_table_grants AS g ON t.tablename = g.table_name AND g.grantee = '${role}' AND g.table_schema = '${schema}' AND g.privilege_type = '${_privilege}' + WHERE t.schemaname = '${schema}' AND g.table_name IS NULL + )" + # lint:endignore:140chars + } + } else { + if $_privilege == 'ALL' or $_privilege == 'ALL PRIVILEGES' { + # REVOKE ALL + $custom_unless = "SELECT 1 WHERE NOT EXISTS + ( SELECT table_name FROM information_schema.role_table_grants + WHERE grantee = '${role}' AND table_schema ='${schema}' + )" + } else { + # REVOKE $_privilege + $custom_unless = "SELECT 1 WHERE NOT EXISTS + ( SELECT table_name FROM information_schema.role_table_grants + WHERE grantee = '${role}' AND table_schema ='${schema}' + AND privilege_type = '${_privilege}' + )" + } + } + } + 'LANGUAGE': { + $unless_privilege = $_privilege ? { + 'ALL' => 'USAGE', + 'ALL PRIVILEGES' => 'USAGE', + Pattern[ + /^$/, + /^CREATE$/, + /^USAGE$/, + ] => $_privilege, + default => fail('Illegal value for $privilege parameter'), + } + $unless_function = 'has_language_privilege' + $on_db = $db + $onlyif_function = $onlyif_exists ? { + true => 'language_exists', + default => undef, + } + $arguments = '' + $_enquote_object = false } + 'FUNCTION': { + $unless_privilege = $_privilege ? { + 'ALL' => 'EXECUTE', + 'ALL PRIVILEGES' => 'EXECUTE', + Pattern[ + /^$/, + /^EXECUTE$/, + ] => $_privilege, + default => fail('Illegal value for $privilege parameter'), + } + $unless_function = 'has_function_privilege' + $on_db = $db + $onlyif_function = $onlyif_exists ? { + true => 'function_exists', + default => undef, + } + $_joined_args = join($object_arguments, ',') + $arguments = "(${_joined_args})" + $_enquote_object = false + } + default: { fail("Missing privilege validation for object type ${_object_type}") } @@ -204,29 +419,51 @@ # object_type => 'TABLE', # object_name => [$schema, $table], # } - if is_array($_object_name) { - $_togrant_object = join($_object_name, '"."') - # Never put double quotes into has_*_privilege function - $_granted_object = join($_object_name, '.') - } else { - $_granted_object = $_object_name - $_togrant_object = $_object_name + case $_object_name { + Array: { + $_togrant_object = $_enquote_object ? { + false => join($_object_name, '.'), + default => join($_object_name, '"."'), + } + # Never put double quotes into has_*_privilege function + $_granted_object = join($_object_name, '.') + # pg_* views does not contain schema name as part of the object name + $_togrant_object_only = $_object_name[1] + } + default: { + $_granted_object = $_object_name + $_togrant_object = $_object_name + # if $_togrant_object_only not set, set it to a default value $_togrant_object + # allows an Array or String to be passed as $_object_name i.e. [$schema, $table] or $table + $_togrant_object_only = $_togrant_object + } } + # Function like has_database_privilege() refer the PUBLIC pseudo role as 'public' + # So we need to replace 'PUBLIC' by 'public'. + $_unless = $unless_function ? { - false => undef, - 'custom' => $custom_unless, - default => "SELECT 1 WHERE ${unless_function}('${role}', - '${_granted_object}', '${unless_privilege}')", + false => undef, + 'custom' => $custom_unless, + default => $role ? { + 'PUBLIC' => "SELECT 1 WHERE ${unless_function}('public', '${_granted_object}${arguments}', '${unless_privilege}') = ${unless_is}", + default => "SELECT 1 WHERE ${unless_function}('${role}', '${_granted_object}${arguments}', '${unless_privilege}') = ${unless_is}", + } } $_onlyif = $onlyif_function ? { - 'table_exists' => "SELECT true FROM pg_tables WHERE tablename = '${_togrant_object}'", - default => undef, + 'table_exists' => "SELECT true FROM pg_tables WHERE tablename = '${_togrant_object_only}'", + 'language_exists' => "SELECT true from pg_language WHERE lanname = '${_togrant_object_only}'", + 'role_exists' => "SELECT 1 FROM pg_roles WHERE rolname = '${role}' or '${role}' = 'PUBLIC'", + 'function_exists' => "SELECT true FROM pg_proc WHERE (oid::regprocedure)::text = '${_togrant_object_only}${arguments}'", + default => undef, + } + + $grant_cmd = $_enquote_object ? { + false => sprintf($sql_command_unquoted, $_privilege, $_object_type, $_togrant_object, $arguments, $_query_role), + default => sprintf($sql_command, $_privilege, $_object_type, $_togrant_object, $arguments, $_query_role), } - $grant_cmd = "GRANT ${_privilege} ON ${_object_type} \"${_togrant_object}\" TO - \"${role}\"" postgresql_psql { "grant:${name}": command => $grant_cmd, db => $on_db, @@ -235,16 +472,16 @@ psql_user => $psql_user, psql_group => $group, psql_path => $psql_path, + instance => $instance, unless => $_unless, onlyif => $_onlyif, - require => Class['postgresql::server'] } - if($role != undef and defined(Postgresql::Server::Role[$role])) { - Postgresql::Server::Role[$role]->Postgresql_psql["grant:${name}"] + if defined(Postgresql::Server::Role[$role]) { + Postgresql::Server::Role[$role] -> Postgresql_psql["grant:${name}"] } - if($db != undef and defined(Postgresql::Server::Database[$db])) { - Postgresql::Server::Database[$db]->Postgresql_psql["grant:${name}"] + if defined(Postgresql::Server::Database[$db]) { + Postgresql::Server::Database[$db] -> Postgresql_psql["grant:${name}"] } -} \ No newline at end of file +} diff --git a/manifests/server/grant_role.pp b/manifests/server/grant_role.pp new file mode 100644 index 0000000000..11ef6a70de --- /dev/null +++ b/manifests/server/grant_role.pp @@ -0,0 +1,54 @@ +# @summary Define for granting membership to a role. +# +# @param group Specifies the group role to which you are assigning a role. +# @param role Specifies the role you want to assign to a group. If left blank, uses the name of the resource. +# @param ensure Specifies whether to grant or revoke the membership. Valid options: 'present' or 'absent'. +# @param psql_db Specifies the database to execute the grant against. This should not ordinarily be changed from the default +# @param psql_user Sets the OS user to run psql. +# @param port Port to use when connecting. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param instance The name of the Postgresql database instance. +define postgresql::server::grant_role ( + String[1] $group, + String[1] $role = $name, + Enum['present', 'absent'] $ensure = 'present', + String[1] $instance = 'main', + String[1] $psql_db = $postgresql::server::default_database, + String[1] $psql_user = $postgresql::server::user, + Stdlib::Port $port = $postgresql::server::port, + Hash $connect_settings = $postgresql::server::default_connect_settings, +) { + case $ensure { + 'present': { + $command = "GRANT \"${group}\" TO \"${role}\"" + $unless_comp = '=' + } + 'absent': { + $command = "REVOKE \"${group}\" FROM \"${role}\"" + $unless_comp = '!=' + } + default: { + fail("Unknown value for ensure '${ensure}'.") + } + } + + postgresql_psql { "grant_role:${name}": + command => $command, + unless => "SELECT 1 WHERE EXISTS (SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = '${group}' AND r_role.rolname = '${role}') ${unless_comp} true", # lint:ignore:140chars + db => $psql_db, + psql_user => $psql_user, + port => $port, + instance => $instance, + connect_settings => $connect_settings, + } + + if empty($connect_settings) { + Class['postgresql::server'] -> Postgresql_psql["grant_role:${name}"] + } + if defined(Postgresql::Server::Role[$role]) { + Postgresql::Server::Role[$role] -> Postgresql_psql["grant_role:${name}"] + } + if defined(Postgresql::Server::Role[$group]) { + Postgresql::Server::Role[$group] -> Postgresql_psql["grant_role:${name}"] + } +} diff --git a/manifests/server/initdb.pp b/manifests/server/initdb.pp index b0df326319..605e9ea79e 100644 --- a/manifests/server/initdb.pp +++ b/manifests/server/initdb.pp @@ -1,126 +1,23 @@ -# PRIVATE CLASS: do not call directly +# @api private class postgresql::server::initdb { - $needs_initdb = $postgresql::server::needs_initdb - $initdb_path = $postgresql::server::initdb_path - $datadir = $postgresql::server::datadir - $xlogdir = $postgresql::server::xlogdir - $logdir = $postgresql::server::logdir - $encoding = $postgresql::server::encoding - $locale = $postgresql::server::locale - $group = $postgresql::server::group - $user = $postgresql::server::user - $psql_path = $postgresql::server::psql_path - $port = $postgresql::server::port - - # Set the defaults for the postgresql_psql resource - Postgresql_psql { - psql_user => $user, - psql_group => $group, - psql_path => $psql_path, - port => $port, - } - - # Make sure the data directory exists, and has the correct permissions. - file { $datadir: - ensure => directory, - owner => $user, - group => $group, - mode => '0700', - } - - if($xlogdir) { - # Make sure the xlog directory exists, and has the correct permissions. - file { $xlogdir: - ensure => directory, - owner => $user, - group => $group, - mode => '0700', - } - } - - if($logdir) { - # Make sure the log directory exists, and has the correct permissions. - file { $logdir: - ensure => directory, - owner => $user, - group => $group, - } - } - - if($needs_initdb) { - # Build up the initdb command. - # - # We optionally add the locale switch if specified. Older versions of the - # initdb command don't accept this switch. So if the user didn't pass the - # parameter, lets not pass the switch at all. - $ic_base = "${initdb_path} --encoding '${encoding}' --pgdata '${datadir}'" - $ic_xlog = $xlogdir ? { - undef => $ic_base, - default => "${ic_base} --xlogdir '${xlogdir}'" - } - - # The xlogdir need to be present before initdb runs. - # If xlogdir is default it's created by package installer - if($xlogdir) { - $require_before_initdb = [$datadir, $xlogdir] - } else { - $require_before_initdb = [$datadir] - } - - $initdb_command = $locale ? { - undef => $ic_xlog, - default => "${ic_xlog} --locale '${locale}'" - } - - # This runs the initdb command, we use the existance of the PG_VERSION - # file to ensure we don't keep running this command. - exec { 'postgresql_initdb': - command => $initdb_command, - creates => "${datadir}/PG_VERSION", - user => $user, - group => $group, - logoutput => on_failure, - require => File[$require_before_initdb], - } - # The package will take care of this for us the first time, but if we - # ever need to init a new db we need to copy these files explicitly - if $::operatingsystem == 'Debian' or $::operatingsystem == 'Ubuntu' { - if $::operatingsystemrelease =~ /^6/ or $::operatingsystemrelease =~ /^7/ or $::operatingsystemrelease =~ /^10\.04/ or $::operatingsystemrelease =~ /^12\.04/ { - file { 'server.crt': - ensure => file, - path => "${datadir}/server.crt", - source => 'file:///etc/ssl/certs/ssl-cert-snakeoil.pem', - owner => $::postgresql::server::user, - group => $::postgresql::server::group, - mode => '0644', - require => Exec['postgresql_initdb'], - } - file { 'server.key': - ensure => file, - path => "${datadir}/server.key", - source => 'file:///etc/ssl/private/ssl-cert-snakeoil.key', - owner => $::postgresql::server::user, - group => $::postgresql::server::group, - mode => '0600', - require => Exec['postgresql_initdb'], - } - } - } - } elsif $encoding != undef { - # [workaround] - # by default pg_createcluster encoding derived from locale - # but it do does not work by installing postgresql via puppet because puppet - # always override LANG to 'C' - postgresql_psql { "Set template1 encoding to ${encoding}": - command => "UPDATE pg_database - SET datistemplate = FALSE - WHERE datname = 'template1' - ; - UPDATE pg_database - SET encoding = pg_char_to_encoding('${encoding}'), datistemplate = TRUE - WHERE datname = 'template1'", - unless => "SELECT datname FROM pg_database WHERE - datname = 'template1' AND encoding = pg_char_to_encoding('${encoding}')", - } + postgresql::server::instance::initdb { 'main': + auth_host => $postgresql::server::auth_host, + auth_local => $postgresql::server::auth_local, + data_checksums => $postgresql::server::data_checksums, + datadir => $postgresql::server::datadir, + encoding => $postgresql::server::encoding, + group => $postgresql::server::group, + initdb_path => $postgresql::server::initdb_path, + lc_messages => $postgresql::server::lc_messages, + locale => $postgresql::server::locale, + logdir => $postgresql::server::logdir, + manage_datadir => $postgresql::server::manage_datadir, + manage_logdir => $postgresql::server::manage_logdir, + manage_xlogdir => $postgresql::server::manage_xlogdir, + module_workdir => $postgresql::server::module_workdir, + needs_initdb => $postgresql::server::needs_initdb, + user => $postgresql::server::user, + username => $postgresql::server::username, + xlogdir => $postgresql::server::xlogdir, } } diff --git a/manifests/server/install.pp b/manifests/server/install.pp index 8724f9f379..afd579b3d5 100644 --- a/manifests/server/install.pp +++ b/manifests/server/install.pp @@ -1,8 +1,7 @@ -# PRIVATE CLASS: do not call directly +# @api private class postgresql::server::install { $package_ensure = $postgresql::server::package_ensure $package_name = $postgresql::server::package_name - $client_package_name = $postgresql::server::client_package_name $_package_ensure = $package_ensure ? { true => 'present', @@ -17,7 +16,6 @@ # This is searched for to create relationships with the package repos, be # careful about its removal - tag => 'postgresql', + tag => 'puppetlabs-postgresql', } - } diff --git a/manifests/server/instance/config.pp b/manifests/server/instance/config.pp new file mode 100644 index 0000000000..342d8fdba3 --- /dev/null +++ b/manifests/server/instance/config.pp @@ -0,0 +1,262 @@ +# @summary Manages the config for a postgresql::server instance +# +# @param ip_mask_deny_postgres_user Specifies the IP mask from which remote connections should be denied for the postgres superuser. +# Default value: '0.0.0.0/0', which denies any remote connection. +# @param ip_mask_allow_all_users +# Overrides PostgreSQL defaults for remote connections. By default, PostgreSQL does not allow database user accounts to connect via TCP +# from remote machines. If you'd like to allow this, you can override this setting. +# Set to '0.0.0.0/0' to allow database users to connect from any remote machine, or '192.168.0.0/1' to allow connections from any machine +# on your local '192.168' subnet. +# Default value: '127.0.0.1/32'. +# @param listen_addresses Address list on which the PostgreSQL service will listen +# @param port +# Specifies the port for the PostgreSQL server to listen on. +# Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +# changing the port causes the server to come to a full stop before being able to make the change. +# Default value: 5432. Meaning the Postgres server listens on TCP port 5432. +# @param ipv4acls Lists strings for access control for connection method, users, databases, IPv4 addresses. +# @param ipv6acls Lists strings for access control for connection method, users, databases, IPv6 addresses. +# @param pg_hba_conf_path Specifies the path to your pg_hba.conf file. +# @param pg_ident_conf_path Specifies the path to your pg_ident.conf file. +# @param postgresql_conf_path Specifies the path to your postgresql.conf file. +# @param postgresql_conf_mode Sets the mode of your postgresql.conf file. Only relevant if manage_postgresql_conf_perms is true. +# @param recovery_conf_path Specifies the path to your recovery.conf file. +# @param pg_hba_conf_defaults +# If false, disables the defaults supplied with the module for pg_hba.conf. This is useful if you disagree with the defaults and wish to +# override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform +# basic psql operations for example. +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param group Overrides the default postgres user group to be used for related files in the file system. +# @param version Sets PostgreSQL version +# @param manage_pg_hba_conf Boolean. Whether to manage the pg_hba.conf. +# @param manage_pg_ident_conf Boolean. Overwrites the pg_ident.conf file. +# @param manage_recovery_conf Boolean. Specifies whether or not manage the recovery.conf. +# @param manage_postgresql_conf_perms +# Whether to manage the postgresql conf file permissions. This means owner, +# group and mode. Contents are not managed but should be managed through +# postgresql::server::config_entry. +# @param datadir PostgreSQL data directory +# @param logdir PostgreSQL log directory +# @param service_name Overrides the default PostgreSQL service name. +# @param service_enable Enable the PostgreSQL service +# @param log_line_prefix PostgreSQL log line prefix +# @param timezone Set timezone for the PostgreSQL instance +# @param password_encryption Specify the type of encryption set for the password. +# @param pg_hba_auth_password_encryption +# Specify the type of encryption set for the password in pg_hba_conf, +# this value is usefull if you want to start enforcing scram-sha-256, but give users transition time. +# @param extra_systemd_config +# Adds extra config to systemd config file, can for instance be used to add extra openfiles. This can be a multi line string +# @param manage_selinux Specifies whether or not manage the conf file for selinux. +define postgresql::server::instance::config ( + String[1] $ip_mask_deny_postgres_user = $postgresql::server::ip_mask_deny_postgres_user, + String[1] $ip_mask_allow_all_users = $postgresql::server::ip_mask_allow_all_users, + Optional[Variant[String[1], Array[String[1]]]] $listen_addresses = $postgresql::server::listen_addresses, + Stdlib::Port $port = $postgresql::server::port, + Array[String[1]] $ipv4acls = $postgresql::server::ipv4acls, + Array[String[1]] $ipv6acls = $postgresql::server::ipv6acls, + Stdlib::Absolutepath $pg_hba_conf_path = $postgresql::server::pg_hba_conf_path, + Stdlib::Absolutepath $pg_ident_conf_path = $postgresql::server::pg_ident_conf_path, + Stdlib::Absolutepath $postgresql_conf_path = $postgresql::server::postgresql_conf_path, + Optional[Stdlib::Filemode] $postgresql_conf_mode = $postgresql::server::postgresql_conf_mode, + Stdlib::Absolutepath $recovery_conf_path = $postgresql::server::recovery_conf_path, + Boolean $pg_hba_conf_defaults = $postgresql::server::pg_hba_conf_defaults, + String[1] $user = $postgresql::server::user, + String[1] $group = $postgresql::server::group, + Optional[String[1]] $version = $postgresql::server::_version, + Boolean $manage_pg_hba_conf = $postgresql::server::manage_pg_hba_conf, + Boolean $manage_pg_ident_conf = $postgresql::server::manage_pg_ident_conf, + Boolean $manage_recovery_conf = $postgresql::server::manage_recovery_conf, + Boolean $manage_postgresql_conf_perms = $postgresql::server::manage_postgresql_conf_perms, + Stdlib::Absolutepath $datadir = $postgresql::server::datadir, + Optional[Stdlib::Absolutepath] $logdir = $postgresql::server::logdir, + String[1] $service_name = $postgresql::server::service_name, + Boolean $service_enable = $postgresql::server::service_enable, + Optional[String[1]] $log_line_prefix = $postgresql::server::log_line_prefix, + Optional[String[1]] $timezone = $postgresql::server::timezone, + Postgresql::Pg_password_encryption $password_encryption = $postgresql::server::password_encryption, + Optional[Postgresql::Pg_password_encryption] $pg_hba_auth_password_encryption = $postgresql::server::pg_hba_auth_password_encryption, + Optional[String] $extra_systemd_config = $postgresql::server::extra_systemd_config, + Boolean $manage_selinux = $postgresql::server::manage_selinux, +) { + $_pg_hba_auth_password_encryption = pick($pg_hba_auth_password_encryption,$password_encryption) + + if ($manage_pg_hba_conf == true) { + # Prepare the main pg_hba file + concat { $pg_hba_conf_path: + owner => $user, + group => $group, + mode => '0640', + warn => true, + notify => Postgresql::Server::Instance::Reload[$name], + } + + if $pg_hba_conf_defaults { + Postgresql::Server::Pg_hba_rule { + database => 'all', + target => $pg_hba_conf_path, + user => 'all', + } + + postgresql::server::pg_hba_rule { + "local access as postgres user for instance ${name}": + type => 'local', + user => $user, + auth_method => 'ident', + order => 1; + + "local access to database with same name for instance ${name}": + type => 'local', + auth_method => 'ident', + order => 2; + + "allow localhost TCP access to postgresql user for instance ${name}": + type => 'host', + user => $user, + address => '127.0.0.1/32', + auth_method => $_pg_hba_auth_password_encryption, + order => 3; + + "deny access to postgresql user for instance ${name}": + type => 'host', + user => $user, + address => $ip_mask_deny_postgres_user, + auth_method => 'reject', + order => 4; + + "allow access to all users for instance ${name}": + type => 'host', + address => $ip_mask_allow_all_users, + auth_method => $_pg_hba_auth_password_encryption, + order => 100; + + "allow access to ipv6 localhost for instance ${name}": + type => 'host', + address => '::1/128', + auth_method => $_pg_hba_auth_password_encryption, + order => 101; + } + } else { + Postgresql::Server::Pg_hba_rule { + target => $pg_hba_conf_path, + } + } + + # $ipv4acls and $ipv6acls are arrays of rule strings + # They are converted into hashes we can iterate over to create postgresql::server::pg_hba_rule resources. + ( + postgresql::postgresql_acls_to_resources_hash($ipv4acls, 'ipv4acls', 10) + + postgresql::postgresql_acls_to_resources_hash($ipv6acls, 'ipv6acls', 102) + ).each | String $key, Hash $attrs| { + postgresql::server::pg_hba_rule { $key: + * => $attrs, + } + } + } + # set default postgresql_conf_path here so the path is configurable in instances for + # default values like port or listen_address + Postgresql::Server::Config_entry { + path => $postgresql_conf_path, + } + + if $manage_postgresql_conf_perms { + file { $postgresql_conf_path: + ensure => file, + owner => $user, + group => $group, + mode => $postgresql_conf_mode, + } + } + + if $listen_addresses { + postgresql::server::config_entry { "listen_addresses_for_instance_${name}": + key => 'listen_addresses', + value => $listen_addresses, + } + } + + # ensure that SELinux has a proper label for the port defined + if $manage_selinux and $facts['os']['selinux']['enabled'] { + case $facts['os']['family'] { + 'RedHat', 'Linux': { + if $facts['os']['name'] == 'Amazon' { + $package_name = 'policycoreutils' + } + else { + $package_name = $facts['os']['release']['major'] ? { + '6' => 'policycoreutils-python', + '7' => 'policycoreutils-python', + default => 'policycoreutils-python-utils', + } + } + } + default: { + $package_name = 'policycoreutils' + } + } + + stdlib::ensure_packages([$package_name]) + + $exec_command = ['/usr/sbin/semanage', 'port', '-a', '-t', 'postgresql_port_t', '-p', 'tcp', $port] + $exec_unless = "/usr/sbin/semanage port -l | grep -qw ${port}" + exec { "/usr/sbin/semanage port -a -t postgresql_port_t -p tcp ${port}": + command => $exec_command, + unless => $exec_unless, + before => Postgresql::Server::Config_entry["port_for_instance_${name}"], + require => Package[$package_name], + } + } + + postgresql::server::config_entry { "port_for_instance_${name}": + key => 'port', + value => $port, + } + + if ($password_encryption) and (versioncmp($version, '10') >= 0) { + postgresql::server::config_entry { "password_encryption_for_instance_${name}": + key => 'password_encryption', + value => $password_encryption, + } + } + + postgresql::server::config_entry { "data_directory_for_instance_${name}": + key => 'data_directory', + value => $datadir, + } + if $timezone { + postgresql::server::config_entry { "timezone_for_instance_${name}": + key => 'timezone', + value => $timezone, + } + } + if $logdir { + postgresql::server::config_entry { "log_directory_for_instance_${name}": + key => 'log_directory', + value => $logdir, + } + } + # Allow timestamps in log by default + if $log_line_prefix { + postgresql::server::config_entry { "log_line_prefix_for_instance_${name}": + key => 'log_line_prefix', + value => $log_line_prefix, + } + } + + if ($manage_pg_ident_conf == true) { + concat { $pg_ident_conf_path: + owner => $user, + group => $group, + mode => '0640', + warn => true, + notify => Postgresql::Server::Instance::Reload[$name], + } + } + + postgresql::server::instance::systemd { $name: + port => $port, + datadir => $datadir, + extra_systemd_config => $extra_systemd_config, + service_name => $service_name, + } +} diff --git a/manifests/server/instance/initdb.pp b/manifests/server/instance/initdb.pp new file mode 100644 index 0000000000..0cfdc4382a --- /dev/null +++ b/manifests/server/instance/initdb.pp @@ -0,0 +1,204 @@ +# @summary Manages initdb feature for a postgresql::server instance +# +# @param auth_host auth method used by default for host authorization +# @param auth_local auth method used by default for local authorization +# @param data_checksums Boolean. Use checksums on data pages to help detect corruption by the I/O system that would otherwise be silent. +# @param datadir PostgreSQL data directory +# @param encoding +# Sets the default encoding for all databases created with this module. +# On certain operating systems this is also used during the template1 initialization, +# so it becomes a default outside of the module as well. +# @param group Overrides the default postgres user group to be used for related files in the file system. +# @param initdb_path Specifies the path to the initdb command. +# @param lc_messages locale used for logging and system messages +# @param locale Sets the default database locale for all databases created with this module. +# On certain operating systems this is used during the template1 initialization as well, so it becomes a default outside of the module. +# Warning: This option is used during initialization by initdb, and cannot be changed later. +# If set, checksums are calculated for all objects, in all databases. +# @param logdir PostgreSQL log directory +# @param manage_datadir Set to false if you have file{ $datadir: } already defined +# @param manage_logdir Set to false if you have file{ $logdir: } already defined +# @param manage_xlogdir Set to false if you have file{ $xlogdir: } already defined +# @param module_workdir Working directory for the PostgreSQL module +# @param needs_initdb Explicitly calls the initdb operation after server package is installed +# and before the PostgreSQL service is started. +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param username username of user running the postgres instance +# @param xlogdir PostgreSQL xlog/WAL directory +# @param port +# Specifies the port for the PostgreSQL server to listen on. +# Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +# changing the port causes the server to come to a full stop before being able to make the change. +# @param psql_path Specifies the path to the psql command. +define postgresql::server::instance::initdb ( + Optional[String[1]] $auth_host = $postgresql::server::auth_host, + Optional[String[1]] $auth_local = $postgresql::server::auth_local, + Optional[Boolean] $data_checksums = $postgresql::server::data_checksums, + Stdlib::Absolutepath $datadir = $postgresql::server::datadir, + Optional[String[1]] $encoding = $postgresql::server::encoding, + String[1] $group = $postgresql::server::group, + Stdlib::Absolutepath $initdb_path = $postgresql::server::initdb_path, + Optional[String[1]] $lc_messages = $postgresql::server::lc_messages, + Optional[String[1]] $locale = $postgresql::server::locale, + Optional[Stdlib::Absolutepath] $logdir = $postgresql::server::logdir, + Boolean $manage_datadir = $postgresql::server::manage_datadir, + Boolean $manage_logdir = $postgresql::server::manage_logdir, + Boolean $manage_xlogdir = $postgresql::server::manage_xlogdir, + Stdlib::Absolutepath $module_workdir = $postgresql::server::module_workdir, + Boolean $needs_initdb = $postgresql::server::needs_initdb, + String[1] $user = $postgresql::server::user, + Optional[String[1]] $username = $postgresql::server::username, + Optional[Stdlib::Absolutepath] $xlogdir = $postgresql::server::xlogdir, + Stdlib::Port $port = $postgresql::server::port, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, +) { + if $facts['os']['family'] == 'RedHat' and $facts['os']['selinux']['enabled'] == true { + $seltype = 'postgresql_db_t' + $logdir_type = 'postgresql_log_t' + } else { + $seltype = undef + $logdir_type = undef + } + + if $manage_datadir { + # Make sure the data directory exists, and has the correct permissions. + file { $datadir: + ensure => directory, + owner => $user, + group => $group, + mode => '0700', + seltype => $seltype, + } + } else { + # changes an already defined datadir + File <| title == $datadir |> { + ensure => directory, + owner => $user, + group => $group, + mode => '0700', + seltype => $seltype, + } + } + + if $xlogdir { + # The xlogdir need to be present before initdb runs. + # If xlogdir is default it's created by package installer + $require_before_initdb = [$datadir, $xlogdir] + if$manage_xlogdir { + # Make sure the xlog directory exists, and has the correct permissions. + file { $xlogdir: + ensure => directory, + owner => $user, + group => $group, + mode => '0700', + seltype => $seltype, + } + } else { + # changes an already defined xlogdir + File <| title == $xlogdir |> { + ensure => directory, + owner => $user, + group => $group, + mode => '0700', + seltype => $seltype, + } + } + } else { + $require_before_initdb = [$datadir] + } + + if $logdir { + if $manage_logdir { + # Make sure the log directory exists, and has the correct permissions. + file { $logdir: + ensure => directory, + owner => $user, + group => $group, + seltype => $logdir_type, + } + } else { + # changes an already defined logdir + File <| title == $logdir |> { + ensure => directory, + owner => $user, + group => $group, + seltype => $logdir_type, + } + } + } + + if $needs_initdb { + # Build up the initdb command. + # + # We optionally add the locale switch if specified. Older versions of the + # initdb command don't accept this switch. So if the user didn't pass the + # parameter, lets not pass the switch at all. + + $auth_host_parameter = $auth_host ? { + undef => undef, + default => "--auth-host '${auth_host}'" + } + + $auth_local_parameter = $auth_local ? { + undef => undef, + default => "--auth-local '${auth_local}'" + } + + $data_checksums_parameter = $data_checksums ? { + undef => undef, + false => undef, + default => '--data-checksums' + } + + $datadir_parameter = "--pgdata '${datadir}'" + + # PostgreSQL 11 no longer allows empty encoding + $encoding_parameter = $encoding ? { + undef => undef, + default => "--encoding '${encoding}'" + } + + $lc_messages_parameter = $locale ? { + undef => undef, + default => "--lc-messages '${lc_messages}'" + } + + $locale_parameter = $locale ? { + undef => undef, + default => "--locale '${locale}'" + } + + $username_parameter = $username ? { + undef => undef, + default => "--username '${username}'" + } + + $xlogdir_parameter = $xlogdir ? { + undef => undef, + default => "-X '${xlogdir}'" + } + + $initdb_command = squeeze("${initdb_path} ${auth_host_parameter} ${auth_local_parameter} ${data_checksums_parameter} ${datadir_parameter} ${encoding_parameter} ${lc_messages_parameter} ${locale_parameter} ${username_parameter} ${xlogdir_parameter}", ' ') # lint:ignore:140chars + + # This runs the initdb command, we use the existance of the PG_VERSION + # file to ensure we don't keep running this command. + exec { "postgresql_initdb_instance_${name}": + command => $initdb_command, + creates => "${datadir}/PG_VERSION", + user => $user, + group => $group, + logoutput => on_failure, + require => File[$require_before_initdb], + cwd => $module_workdir, + } + } elsif $encoding { + postgresql::server::instance::late_initdb { $name: + encoding => $encoding, + user => $user, + group => $group, + module_workdir => $module_workdir, + psql_path => $psql_path, + port => $port, + } + } +} diff --git a/manifests/server/instance/late_initdb.pp b/manifests/server/instance/late_initdb.pp new file mode 100644 index 0000000000..bc011b9a01 --- /dev/null +++ b/manifests/server/instance/late_initdb.pp @@ -0,0 +1,48 @@ +# @summary Manage the default encoding when database initialization is managed by the package +# +# @param encoding +# Sets the default encoding for all databases created with this module. On certain operating systems this is also used during the +# template1 initialization, so it becomes a default outside of the module as well. +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param group Overrides the default postgres user group to be used for related files in the file system. +# @param psql_path Specifies the path to the psql command. +# @param port +# Specifies the port for the PostgreSQL server to listen on. +# Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +# changing the port causes the server to come to a full stop before being able to make the change. +# @param module_workdir Working directory for the PostgreSQL module +define postgresql::server::instance::late_initdb ( + Optional[String[1]] $encoding = $postgresql::server::encoding, + String[1] $user = $postgresql::server::user, + String[1] $group = $postgresql::server::group, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + Stdlib::Port $port = $postgresql::server::port, + Stdlib::Absolutepath $module_workdir = $postgresql::server::module_workdir, +) { + # Set the defaults for the postgresql_psql resource + Postgresql_psql { + psql_user => $user, + psql_group => $group, + psql_path => $psql_path, + port => $port, + instance => $name, + cwd => $module_workdir, + } + + # [workaround] + # by default pg_createcluster encoding derived from locale + # but it do does not work by installing postgresql via puppet because puppet + # always override LANG to 'C' + postgresql_psql { "Set template1 encoding to ${encoding}": + command => "UPDATE pg_database + SET datistemplate = FALSE + WHERE datname = 'template1' + ; + UPDATE pg_database + SET encoding = pg_char_to_encoding('${encoding}'), datistemplate = TRUE + WHERE datname = 'template1'", + unless => "SELECT datname FROM pg_database WHERE + datname = 'template1' AND encoding = pg_char_to_encoding('${encoding}')", + before => Anchor["postgresql::server::service::end::${name}"], + } +} diff --git a/manifests/server/instance/passwd.pp b/manifests/server/instance/passwd.pp new file mode 100644 index 0000000000..a4bc20f467 --- /dev/null +++ b/manifests/server/instance/passwd.pp @@ -0,0 +1,67 @@ +# @summary Overrides the default PostgreSQL superuser +# +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param group Overrides the default postgres user group to be used for related files in the file system. +# Default value: 5432. Meaning the Postgres server listens on TCP port 5432. +# @param psql_path Specifies the path to the psql command. +# @param port +# Specifies the port for the PostgreSQL server to listen on. +# Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +# changing the port causes the server to come to a full stop before being able to make the change. +# @param database Specifies the name of the database to connect with. On most systems this is 'postgres'. +# @param module_workdir Working directory for the PostgreSQL module +# @param postgres_password +# Sets the password for the postgres user to your specified value. By default, this setting uses the superuser account in the Postgres +# database, with a user called postgres and no password. +define postgresql::server::instance::passwd ( + String[1] $user = $postgresql::server::user, + String[1] $group = $postgresql::server::group, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + Stdlib::Port $port = $postgresql::server::port, + String[1] $database = $postgresql::server::default_database, + Stdlib::Absolutepath $module_workdir = $postgresql::server::module_workdir, + Optional[Variant[String[1], Sensitive[String[1]], Integer]] $postgres_password = $postgresql::server::postgres_password, +) { + $real_postgres_password = if $postgres_password =~ Sensitive { + $postgres_password.unwrap + } else { + $postgres_password + } + + # psql will default to connecting as $user if you don't specify name + $_datbase_user_same = $database == $user + $_dboption = $_datbase_user_same ? { + false => " --dbname ${stdlib::shell_escape($database)}", + default => '' + } + + if $real_postgres_password { + # NOTE: this password-setting logic relies on the pg_hba.conf being + # configured to allow the postgres system user to connect via psql + # without specifying a password ('ident' or 'trust' security). This is + # the default for pg_hba.conf. + $escaped = postgresql::postgresql_escape($real_postgres_password) + $exec_command = "${stdlib::shell_escape($psql_path)}${_dboption} -c \"ALTER ROLE \\\"${stdlib::shell_escape($user)}\\\" PASSWORD \${NEWPASSWD_ESCAPED}\"" # lint:ignore:140chars + exec { "set_postgres_postgrespw_${name}": + # This command works w/no password because we run it as postgres system + # user + command => $exec_command, + user => $user, + group => $group, + logoutput => true, + cwd => $module_workdir, + environment => [ + "PGPASSWORD=${real_postgres_password}", + "PGPORT=${port}", + "NEWPASSWD_ESCAPED=${escaped}", + ], + # With this command we're passing -h to force TCP authentication, which + # does require a password. We specify the password via the PGPASSWORD + # environment variable. If the password is correct (current), this + # command will exit with an exit code of 0, which will prevent the main + # command from running. + unless => "${psql_path} -h localhost -p ${port} -c 'select 1' > /dev/null", + path => '/usr/bin:/usr/local/bin:/bin', + } + } +} diff --git a/manifests/server/instance/reload.pp b/manifests/server/instance/reload.pp new file mode 100644 index 0000000000..fd0c750ab2 --- /dev/null +++ b/manifests/server/instance/reload.pp @@ -0,0 +1,16 @@ +# @summary Overrides the default reload or status command for your PostgreSQL service +# +# @param service_reload Overrides the default reload command for your PostgreSQL service. +# @param service_status Overrides the default status check command for your PostgreSQL service. +define postgresql::server::instance::reload ( + String[1] $service_status = $postgresql::server::service_status, + String[1] $service_reload = $postgresql::server::service_reload, +) { + exec { "postgresql_reload_${name}": + path => '/usr/bin:/usr/sbin:/bin:/sbin', + command => $service_reload, + onlyif => $service_status, + refreshonly => true, + require => Postgresql::Server::Instance::Service[$name], + } +} diff --git a/manifests/server/instance/service.pp b/manifests/server/instance/service.pp new file mode 100644 index 0000000000..47e7ecda25 --- /dev/null +++ b/manifests/server/instance/service.pp @@ -0,0 +1,74 @@ +# @summary Manages the service for the postgres main instance (default) or additional instances +# +# @param service_ensure Ensure service is installed +# @param service_enable Enable the PostgreSQL service +# @param service_manage Defines whether or not Puppet should manage the service. +# @param service_name Overrides the default PostgreSQL service name. +# @param service_provider Overrides the default PostgreSQL service provider. +# @param service_status Overrides the default status check command for your PostgreSQL service. +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param port +# Specifies the port for the PostgreSQL server to listen on. +# Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, +# changing the port causes the server to come to a full stop before being able to make the change. +# Default value: 5432. Meaning the Postgres server listens on TCP port 5432. +# @param default_database Specifies the name of the default database to connect with. On most systems this is 'postgres'. +# @param psql_path Specifies the path to the psql command. +# @param connect_settings +# Specifies a hash of environment variables used when connecting to a remote server. Becomes the default for other defined types, +# such as postgresql::server::role. +define postgresql::server::instance::service ( + Variant[Enum['running', 'stopped'], Boolean] $service_ensure = $postgresql::server::service_ensure, + Boolean $service_enable = $postgresql::server::service_enable, + Boolean $service_manage = $postgresql::server::service_manage, + String[1] $service_name = $postgresql::server::service_name, + Optional[String[1]] $service_provider = $postgresql::server::service_provider, + String[1] $service_status = $postgresql::server::service_status, + String[1] $user = $postgresql::server::user, + Stdlib::Port $port = $postgresql::server::port, + String[1] $default_database = $postgresql::server::default_database, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + Hash $connect_settings = $postgresql::server::default_connect_settings, +) { + anchor { "postgresql::server::service::begin::${name}": } + + if $service_manage { + service { "postgresqld_instance_${name}": + ensure => $service_ensure, + enable => $service_enable, + name => $service_name, + provider => $service_provider, + hasstatus => true, + status => $service_status, + } + + Anchor["postgresql::server::service::begin::${name}"] + -> Service["postgresqld_instance_${name}"] + -> Anchor["postgresql::server::service::end::${name}"] + + if $service_ensure in ['running', true] { + # This blocks the class before continuing if chained correctly, making + # sure the service really is 'up' before continuing. + # + # Without it, we may continue doing more work before the database is + # prepared leading to a nasty race condition. + postgresql_conn_validator { "validate_service_is_running_instance_${name}": + run_as => $user, + db_name => $default_database, + port => $port, + connect_settings => $connect_settings, + sleep => 1, + tries => 60, + psql_path => $psql_path, + } + + Anchor["postgresql::server::service::begin::${name}"] + -> Service["postgresqld_instance_${name}"] + -> Postgresql::Server::Database <| title == $default_database |> + -> Postgresql_conn_validator["validate_service_is_running_instance_${name}"] + -> Anchor["postgresql::server::service::end::${name}"] + } + } + + anchor { "postgresql::server::service::end::${name}": } +} diff --git a/manifests/server/instance/systemd.pp b/manifests/server/instance/systemd.pp new file mode 100644 index 0000000000..9214f2a22a --- /dev/null +++ b/manifests/server/instance/systemd.pp @@ -0,0 +1,40 @@ +# @summary This define handles systemd drop-in files for the postgres main instance (default) or additional instances +# @param service_name Overrides the default PostgreSQL service name. +# @param drop_in_ensure sets the Systemd drop-in file to present or absent +# @api private +define postgresql::server::instance::systemd ( + Stdlib::Port $port, + Stdlib::Absolutepath $datadir, + String[1] $instance_name = $name, + Optional[String[1]] $extra_systemd_config = undef, + String[1] $service_name = $name, + Enum[present, absent] $drop_in_ensure = 'present', +) { + if $facts['service_provider'] == 'systemd' { + if $facts['os']['family'] in ['RedHat', 'Gentoo'] { + # RHEL 7 and 8 both support drop-in files for systemd units. + # Gentoo also supports drop-in files. + # RHEL based Systems need Variables set for $PGPORT, $DATA_DIR or $PGDATA, thats what the drop-in file is for. + # For additional instances (!= 'main') we need a new systemd service anyhow and use one systemd-file. no dropin needed. + # + # Template uses: + # - $port + # - $datadir + # - $extra_systemd_config + systemd::dropin_file { "${service_name}.conf": + ensure => $drop_in_ensure, + unit => "${service_name}.service", + owner => 'root', + group => 'root', + content => epp('postgresql/systemd-override.conf.epp', { + port => $port, + datadir => $datadir, + extra_systemd_config => $extra_systemd_config, + } + ), + notify => Postgresql::Server::Instance::Service[$name], + before => Postgresql::Server::Instance::Reload[$name], + } + } + } +} diff --git a/manifests/server/late_initdb.pp b/manifests/server/late_initdb.pp new file mode 100644 index 0000000000..d0fa68c0a7 --- /dev/null +++ b/manifests/server/late_initdb.pp @@ -0,0 +1,15 @@ +# @summary Manage the default encoding when database initialization is managed by the package +# +# @api private +class postgresql::server::late_initdb { + assert_private() + + postgresql::server::instance::late_initdb { 'main': + encoding => $postgresql::server::encoding, + user => $postgresql::server::user, + group => $postgresql::server::group, + psql_path => $postgresql::server::psql_path, + port => $postgresql::server::port, + module_workdir => $postgresql::server::module_workdir, + } +} diff --git a/manifests/server/passwd.pp b/manifests/server/passwd.pp index 358a044ea4..e30beef032 100644 --- a/manifests/server/passwd.pp +++ b/manifests/server/passwd.pp @@ -1,36 +1,12 @@ -# PRIVATE CLASS: do not call directly +# @api private class postgresql::server::passwd { - $postgres_password = $postgresql::server::postgres_password - $user = $postgresql::server::user - $group = $postgresql::server::group - $psql_path = $postgresql::server::psql_path - $port = $postgresql::server::port - - if ($postgres_password != undef) { - # NOTE: this password-setting logic relies on the pg_hba.conf being - # configured to allow the postgres system user to connect via psql - # without specifying a password ('ident' or 'trust' security). This is - # the default for pg_hba.conf. - $escaped = postgresql_escape($postgres_password) - exec { 'set_postgres_postgrespw': - # This command works w/no password because we run it as postgres system - # user - command => "${psql_path} -c \"ALTER ROLE \\\"${user}\\\" PASSWORD \${NEWPASSWD_ESCAPED}\"", - user => $user, - group => $group, - logoutput => true, - cwd => '/tmp', - environment => [ - "PGPASSWORD=${postgres_password}", - "NEWPASSWD_ESCAPED=${escaped}", - ], - # With this command we're passing -h to force TCP authentication, which - # does require a password. We specify the password via the PGPASSWORD - # environment variable. If the password is correct (current), this - # command will exit with an exit code of 0, which will prevent the main - # command from running. - unless => "${psql_path} -h localhost -p ${port} -c 'select 1' > /dev/null", - path => '/usr/bin:/usr/local/bin:/bin', - } + postgresql::server::instance::passwd { 'main': + user => $postgresql::server::user, + group => $postgresql::server::group, + psql_path => $postgresql::server::psql_path, + port => $postgresql::server::port, + database => $postgresql::server::default_database, + module_workdir => $postgresql::server::module_workdir, + postgres_password => $postgresql::server::postgres_password, } } diff --git a/manifests/server/pg_hba_rule.pp b/manifests/server/pg_hba_rule.pp index 406568fbca..e7945669e0 100644 --- a/manifests/server/pg_hba_rule.pp +++ b/manifests/server/pg_hba_rule.pp @@ -1,21 +1,40 @@ -# This resource manages an individual rule that applies to the file defined in -# $target. See README.md for more details. -define postgresql::server::pg_hba_rule( - $type, - $database, - $user, - $auth_method, - $address = undef, - $description = 'none', - $auth_option = undef, - $order = '150', - - # Needed for testing primarily, support for multiple files is not really - # working. - $target = $postgresql::server::pg_hba_conf_path, - $postgresql_version = $postgresql::server::_version +# @summary This resource manages an individual rule that applies to the file defined in target. +# +# @param type Sets the type of rule. +# @param database Sets a comma-separated list of databases that this rule matches. +# @param user Sets a comma-separated list of users that this rule matches. +# @param auth_method +# Provides the method that is used for authentication for the connection that this rule matches. +# Described further in the PostgreSQL pg_hba.conf documentation. +# @param address +# Sets a address for this rule matching when the type is not 'local'. +# Value can either be IPv4 CIDR, IPv6 CIDR, a FQDN, the strings 'all', 'samehost' or 'samenet' or a domain either with or without starting +# dot (.) https://www.postgresql.org/docs/current/auth-pg-hba-conf.html +# @param description +# Defines a longer description for this rule, if required. This description is placed in the comments above the rule in pg_hba.conf. +# Default value: 'none'. +# @param auth_option +# For certain auth_method settings there are extra options that can be passed. Consult the PostgreSQL pg_hba.conf documentation for +# further details. +# @param order +# Sets an order for placing the rule in pg_hba.conf. This can be either a string or an integer. If it is an integer, it will be converted +# to a string by zero-padding it to three digits. E.g. 42 will be zero-padded to the string '042'. The pg_hba_rule fragments are sorted +# using the alpha sorting order. +# Default value: 150. +# @param target Provides the target for the rule, and is generally an internal only property. Use with caution. +# @param postgresql_version Manages pg_hba.conf without managing the entire PostgreSQL instance. +define postgresql::server::pg_hba_rule ( + Postgresql::Pg_hba_rule_type $type, + String[1] $database, + String[1] $user, + String[1] $auth_method, + Optional[Postgresql::Pg_hba_rule_address] $address = undef, + String[1] $description = 'none', + Optional[String] $auth_option = undef, + Variant[String, Integer] $order = 150, + Stdlib::Absolutepath $target = $postgresql::server::pg_hba_conf_path, + String $postgresql_version = $postgresql::server::_version ) { - #Allow users to manage pg_hba.conf even if they are not managing the whole PostgreSQL instance if !defined( 'postgresql::server' ) { $manage_pg_hba_conf = true @@ -25,38 +44,50 @@ } if $manage_pg_hba_conf == false { - fail('postgresql::server::manage_pg_hba_conf has been disabled, so this resource is now unused and redundant, either enable that option or remove this resource from your manifests') + fail('postgresql::server::manage_pg_hba_conf has been disabled, so this resource is now unused and redundant, either enable that option or remove this resource from your manifests') # lint:ignore:140chars } else { - validate_re($type, '^(local|host|hostssl|hostnossl)$', - "The type you specified [${type}] must be one of: local, host, hostssl, hostnosssl") - if($type =~ /^host/ and $address == undef) { fail('You must specify an address property when type is host based') } + if $order =~ Integer { + $_order = sprintf('%03d', $order) + } + else { + $_order = $order + } + $allowed_auth_methods = $postgresql_version ? { + '10' => ['trust', 'reject', 'scram-sha-256', 'md5', 'password', 'gss', 'sspi', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam', 'bsd'], # lint:ignore:140chars + '9.6' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam', 'bsd'], + '9.5' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.4' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.3' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.2' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.1' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.0' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'radius', 'cert', 'pam'], - '8.4' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'cert', 'pam'], - '8.3' => ['trust', 'reject', 'md5', 'crypt', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'pam'], - '8.2' => ['trust', 'reject', 'md5', 'crypt', 'password', 'krb5', 'ident', 'ldap', 'pam'], - '8.1' => ['trust', 'reject', 'md5', 'crypt', 'password', 'krb5', 'ident', 'pam'], - default => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam', 'crypt'] + default => ['trust', 'reject', 'scram-sha-256', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam', 'crypt', 'bsd'] # lint:ignore:140chars } - $auth_method_regex = join(['^(', join($allowed_auth_methods, '|'), ')$'],'') - validate_re($auth_method, $auth_method_regex, - join(["The auth_method you specified [${auth_method}] must be one of: ", join($allowed_auth_methods, ', ')],'')) + assert_type(Enum[$allowed_auth_methods], $auth_method) # Create a rule fragment $fragname = "pg_hba_rule_${name}" concat::fragment { $fragname: target => $target, - content => template('postgresql/pg_hba_rule.conf'), - order => $order, + content => epp('postgresql/pg_hba_rule.conf.epp', { + name => $name, + description => $description, + order => $order, + type => $type, + database => $database, + user => $user, + address => $address, + auth_method => $auth_method, + auth_option => $auth_option, + } + ), + order => $_order, } } } diff --git a/manifests/server/pg_ident_rule.pp b/manifests/server/pg_ident_rule.pp index 3e9cdcd351..088bce6c98 100644 --- a/manifests/server/pg_ident_rule.pp +++ b/manifests/server/pg_ident_rule.pp @@ -1,26 +1,42 @@ -# This resource manages an individual rule that applies to the file defined in -# $target. See README.md for more details. -define postgresql::server::pg_ident_rule( - $map_name, - $system_username, - $database_username, - $description = 'none', - $order = '150', +# @summary This resource manages an individual rule that applies to the file defined in target. +# +# @param map_name Sets the name of the user map that is used to refer to this mapping in pg_hba.conf. +# @param system_username Specifies the operating system user name (the user name used to connect to the database). +# @param database_username +# Specifies the user name of the database user. +# The system_username is mapped to this user name. +# @param description +# Sets a longer description for this rule if required. +# This description is placed in the comments above the rule in pg_ident.conf. +# @param order Defines an order for placing the mapping in pg_ident.conf. Default value: 150. +# @param target Provides the target for the rule and is generally an internal only property. Use with caution. +define postgresql::server::pg_ident_rule ( + String[1] $map_name, + String[1] $system_username, + String[1] $database_username, + String[1] $description = 'none', + String[1] $order = '150', # Needed for testing primarily, support for multiple files is not really # working. - $target = $postgresql::server::pg_ident_conf_path + Stdlib::Absolutepath $target = $postgresql::server::pg_ident_conf_path ) { - if $postgresql::server::manage_pg_ident_conf == false { - fail('postgresql::server::manage_pg_ident_conf has been disabled, so this resource is now unused and redundant, either enable that option or remove this resource from your manifests') + fail('postgresql::server::manage_pg_ident_conf has been disabled, so this resource is now unused and redundant, either enable that option or remove this resource from your manifests') # lint:ignore:140chars } else { - # Create a rule fragment $fragname = "pg_ident_rule_${name}" concat::fragment { $fragname: target => $target, - content => template('postgresql/pg_ident_rule.conf'), + content => epp('postgresql/pg_ident_rule.conf.epp', { + name => $name, + description => $description, + order => $order, + map_name => $map_name, + system_username => $system_username, + database_username => $database_username, + } + ), order => $order, } } diff --git a/manifests/server/plperl.pp b/manifests/server/plperl.pp index 6ad5cf9b2a..08c5298fc3 100644 --- a/manifests/server/plperl.pp +++ b/manifests/server/plperl.pp @@ -1,19 +1,20 @@ -# This class installs the PL/Perl procedural language for postgresql. See -# README.md for more details. -class postgresql::server::plperl( - $package_ensure = 'present', - $package_name = $postgresql::server::plperl_package_name +# @summary This class installs the PL/Perl procedural language for postgresql. +# +# @param package_ensure The ensure parameter passed on to PostgreSQL PL/Perl package resource. +# @param package_name The name of the PostgreSQL PL/Perl package. +class postgresql::server::plperl ( + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', + Optional[String[1]] $package_name = $postgresql::server::plperl_package_name, ) { package { 'postgresql-plperl': ensure => $package_ensure, name => $package_name, - tag => 'postgresql', + tag => 'puppetlabs-postgresql', } - anchor { 'postgresql::server::plperl::start': }-> - Class['postgresql::server::install']-> - Package['postgresql-plperl']-> - Class['postgresql::server::service']-> - anchor { 'postgresql::server::plperl::end': } - + anchor { 'postgresql::server::plperl::start': } + -> Class['postgresql::server::install'] + -> Package['postgresql-plperl'] + -> Class['postgresql::server::service'] + -> anchor { 'postgresql::server::plperl::end': } } diff --git a/manifests/server/plpython.pp b/manifests/server/plpython.pp index 962dbad621..8577bd34e5 100644 --- a/manifests/server/plpython.pp +++ b/manifests/server/plpython.pp @@ -1,19 +1,22 @@ -# This class installs the PL/Python procedural language for postgresql. See -# README.md for more details. -class postgresql::server::plpython( - $package_ensure = 'present', - $package_name = $postgresql::server::plpython_package_name, +# @summary This class installs the PL/Python procedural language for postgresql. +# +# @param package_ensure +# Specifies whether the package is present. +# @param package_name +# Specifies the name of the postgresql PL/Python package. +class postgresql::server::plpython ( + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', + Optional[String[1]] $package_name = $postgresql::server::plpython_package_name, ) { package { 'postgresql-plpython': ensure => $package_ensure, name => $package_name, - tag => 'postgresql', + tag => 'puppetlabs-postgresql', } - anchor { 'postgresql::server::plpython::start': }-> - Class['postgresql::server::install']-> - Package['postgresql-plpython']-> - Class['postgresql::server::service']-> - anchor { 'postgresql::server::plpython::end': } - + anchor { 'postgresql::server::plpython::start': } + -> Class['postgresql::server::install'] + -> Package['postgresql-plpython'] + -> Class['postgresql::server::service'] + -> anchor { 'postgresql::server::plpython::end': } } diff --git a/manifests/server/postgis.pp b/manifests/server/postgis.pp index ac4c641054..c259e030ff 100644 --- a/manifests/server/postgis.pp +++ b/manifests/server/postgis.pp @@ -1,24 +1,25 @@ -# Install the postgis postgresql packaging. See README.md for more details. +# @summary Install the postgis postgresql packaging. +# +# @param package_name Sets the package name. +# @param package_ensure Specifies if the package is present or not. class postgresql::server::postgis ( - $package_name = $postgresql::params::postgis_package_name, - $package_ensure = 'present' + String $package_name = $postgresql::params::postgis_package_name, + Variant[Enum['present', 'absent', 'purged', 'disabled', 'installed', 'latest'], String[1]] $package_ensure = 'present', ) inherits postgresql::params { - validate_string($package_name) - package { 'postgresql-postgis': ensure => $package_ensure, name => $package_name, - tag => 'postgresql', + tag => 'puppetlabs-postgresql', } - anchor { 'postgresql::server::postgis::start': }-> - Class['postgresql::server::install']-> - Package['postgresql-postgis']-> - Class['postgresql::server::service']-> - anchor { 'postgresql::server::postgis::end': } + anchor { 'postgresql::server::postgis::start': } + -> Class['postgresql::server::install'] + -> Package['postgresql-postgis'] + -> Class['postgresql::server::service'] + -> anchor { 'postgresql::server::postgis::end': } if $postgresql::globals::manage_package_repo { - Class['postgresql::repo'] -> - Package['postgresql-postgis'] + Class['postgresql::repo'] + -> Package['postgresql-postgis'] } } diff --git a/manifests/server/reassign_owned_by.pp b/manifests/server/reassign_owned_by.pp new file mode 100644 index 0000000000..ce98f2601b --- /dev/null +++ b/manifests/server/reassign_owned_by.pp @@ -0,0 +1,62 @@ +# @summary Define for reassigning the ownership of objects within a database. +# +# @note This enables us to force the a particular ownership for objects within a database +# +# @param old_role Specifies the role or user who is the current owner of the objects in the specified db +# @param new_role Specifies the role or user who will be the new owner of these objects +# @param db Specifies the database to which the 'REASSIGN OWNED' will be applied +# @param psql_user Specifies the OS user for running psql. +# @param port Port to use when connecting. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param group Sets the OS group to run psql +# @param psql_path Sets the path to psql command +# @param instance The name of the Postgresql database instance. +define postgresql::server::reassign_owned_by ( + String $old_role, + String $new_role, + String $db, + String $psql_user = $postgresql::server::user, + Stdlib::Port $port = $postgresql::server::port, + Hash $connect_settings = $postgresql::server::default_connect_settings, + String[1] $group = $postgresql::server::group, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + String[1] $instance = 'main', +) { + $sql_command = "REASSIGN OWNED BY \"${old_role}\" TO \"${new_role}\"" + + $port_override = pick($connect_settings['PGPORT'], $port) + + $onlyif = "SELECT tablename FROM pg_catalog.pg_tables WHERE + schemaname NOT IN ('pg_catalog', 'information_schema') AND + tableowner = '${old_role}' + UNION ALL SELECT proname FROM pg_catalog.pg_proc WHERE + pg_get_userbyid(proowner) = '${old_role}' + UNION ALL SELECT viewname FROM pg_catalog.pg_views WHERE + pg_views.schemaname NOT IN ('pg_catalog', 'information_schema') AND + viewowner = '${old_role}' + UNION ALL SELECT relname FROM pg_catalog.pg_class WHERE + relkind='S' AND pg_get_userbyid(relowner) = '${old_role}'" + + postgresql_psql { "reassign_owned_by:${db}:${sql_command}": + command => $sql_command, + db => $db, + port => $port_override, + connect_settings => $connect_settings, + psql_user => $psql_user, + psql_group => $group, + psql_path => $psql_path, + instance => $instance, + onlyif => $onlyif, + } + + if defined(Postgresql::Server::Role[$old_role]) { + Postgresql::Server::Role[$old_role] -> Postgresql_psql["reassign_owned_by:${db}:${sql_command}"] + } + if($new_role != undef and defined(Postgresql::Server::Role[$new_role])) { + Postgresql::Server::Role[$new_role] -> Postgresql_psql["reassign_owned_by:${db}:${sql_command}"] + } + + if defined(Postgresql::Server::Database[$db]) { + Postgresql::Server::Database[$db] -> Postgresql_psql["reassign_owned_by:${db}:${sql_command}"] + } +} diff --git a/manifests/server/recovery.pp b/manifests/server/recovery.pp index 924866e965..e28976e7f5 100644 --- a/manifests/server/recovery.pp +++ b/manifests/server/recovery.pp @@ -1,38 +1,94 @@ -# This resource manages the parameters that applies to the recovery.conf template. See README.md for more details. -define postgresql::server::recovery( - $restore_command = undef, - $archive_cleanup_command = undef, - $recovery_end_command = undef, - $recovery_target_name = undef, - $recovery_target_time = undef, - $recovery_target_xid = undef, - $recovery_target_inclusive = undef, - $recovery_target = undef, - $recovery_target_timeline = undef, - $pause_at_recovery_target = undef, - $standby_mode = undef, - $primary_conninfo = undef, - $primary_slot_name = undef, - $trigger_file = undef, - $recovery_min_apply_delay = undef, - $target = $postgresql::server::recovery_conf_path +# @summary This resource manages the parameters that applies to the recovery.conf template. +# +# @note +# Allows you to create the content for recovery.conf. For more details see the usage example and the PostgreSQL documentation. +# Every parameter value is a string set in the template except recovery_target_inclusive, pause_at_recovery_target, standby_mode and +# recovery_min_apply_delay. +# A detailed description of all listed parameters can be found in the PostgreSQL documentation. +# Only the specified parameters are recognized in the template. The recovery.conf is only created if at least one parameter is set and +# manage_recovery_conf is set to true. +# +# @param restore_command The shell command to execute to retrieve an archived segment of the WAL file series. +# @param archive_cleanup_command This optional parameter specifies a shell command that will be executed at every restartpoint. +# @param recovery_end_command This parameter specifies a shell command that will be executed once only at the end of recovery. +# @param recovery_target_name +# This parameter specifies the named restore point (created with pg_create_restore_point()) to which recovery will proceed. +# @param recovery_target_time This parameter specifies the time stamp up to which recovery will proceed. +# @param recovery_target_xid This parameter specifies the transaction ID up to which recovery will proceed. +# @param recovery_target_inclusive +# Specifies whether to stop just after the specified recovery target (true), or just before the recovery target (false). +# @param recovery_target +# This parameter specifies that recovery should end as soon as a consistent state is reached, i.e. as early as possible. +# @param recovery_target_timeline Specifies recovering into a particular timeline. +# @param pause_at_recovery_target Specifies whether recovery should pause when the recovery target is reached. +# @param standby_mode Specifies whether to start the PostgreSQL server as a standby. +# @param primary_conninfo Specifies a connection string to be used for the standby server to connect with the primary. +# @param primary_slot_name +# Optionally specifies an existing replication slot to be used when connecting to the primary via streaming replication to control +# resource removal on the upstream node. +# @param trigger_file Specifies a trigger file whose presence ends recovery in the standby. +# @param recovery_min_apply_delay +# This parameter allows you to delay recovery by a fixed period of time, measured in milliseconds if no unit is specified. +# @param target Provides the target for the rule, and is generally an internal only property. Use with caution. +define postgresql::server::recovery ( + Optional[String] $restore_command = undef, + Optional[String[1]] $archive_cleanup_command = undef, + Optional[String[1]] $recovery_end_command = undef, + Optional[String[1]] $recovery_target_name = undef, + Optional[String[1]] $recovery_target_time = undef, + Optional[String[1]] $recovery_target_xid = undef, + Optional[Boolean] $recovery_target_inclusive = undef, + Optional[String[1]] $recovery_target = undef, + Optional[String[1]] $recovery_target_timeline = undef, + Optional[Boolean] $pause_at_recovery_target = undef, + Optional[String[1]] $standby_mode = undef, + Optional[String[1]] $primary_conninfo = undef, + Optional[String[1]] $primary_slot_name = undef, + Optional[String[1]] $trigger_file = undef, + Optional[Integer] $recovery_min_apply_delay = undef, + Stdlib::Absolutepath $target = $postgresql::server::recovery_conf_path ) { - if $postgresql::server::manage_recovery_conf == false { - fail('postgresql::server::manage_recovery_conf has been disabled, so this resource is now unused and redundant, either enable that option or remove this resource from your manifests') + fail('postgresql::server::manage_recovery_conf has been disabled, so this resource is now unused and redundant, either enable that option or remove this resource from your manifests') # lint:ignore:140chars } else { if($restore_command == undef and $archive_cleanup_command == undef and $recovery_end_command == undef and $recovery_target_name == undef and $recovery_target_time == undef and $recovery_target_xid == undef and $recovery_target_inclusive == undef and $recovery_target == undef and $recovery_target_timeline == undef and $pause_at_recovery_target == undef and $standby_mode == undef and $primary_conninfo == undef - and $primary_slot_name == undef and $trigger_file == undef and $recovery_min_apply_delay == undef) { - fail('postgresql::server::recovery use this resource but do not pass a parameter will avoid creating the recovery.conf, because it makes no sense.') + and $primary_slot_name == undef and $trigger_file == undef and $recovery_min_apply_delay == undef) { + fail('postgresql::server::recovery use this resource but do not pass a parameter will avoid creating the recovery.conf, because it makes no sense.') # lint:ignore:140chars + } + + concat { $target: + owner => $postgresql::server::user, + group => $postgresql::server::group, + force => true, # do not crash if there is no recovery conf file + mode => '0640', + warn => true, + notify => Class['postgresql::server::reload'], } # Create the recovery.conf content - concat::fragment { 'recovery.conf': + concat::fragment { "${name}-recovery.conf": target => $target, - content => template('postgresql/recovery.conf'), + content => epp('postgresql/recovery.conf.epp', { + restore_command => $restore_command, + archive_cleanup_command => $archive_cleanup_command, + recovery_end_command => $recovery_end_command, + recovery_target_name => $recovery_target_name, + recovery_target_time => $recovery_target_time, + recovery_target_xid => $recovery_target_xid, + recovery_target_inclusive => $recovery_target_inclusive, + recovery_target => $recovery_target, + recovery_target_timeline => $recovery_target_timeline, + pause_at_recovery_target => $pause_at_recovery_target, + standby_mode => $standby_mode, + primary_conninfo => $primary_conninfo, + primary_slot_name => $primary_slot_name, + trigger_file => $trigger_file, + recovery_min_apply_delay => $recovery_min_apply_delay, + } + ), } } } diff --git a/manifests/server/reload.pp b/manifests/server/reload.pp index 47f270452e..be5e7576d3 100644 --- a/manifests/server/reload.pp +++ b/manifests/server/reload.pp @@ -1,14 +1,7 @@ -# PRIVATE CLASS: do not use directly +# @api private class postgresql::server::reload { - $service_name = $postgresql::server::service_name - $service_status = $postgresql::server::service_status - $service_reload = $postgresql::server::service_reload - - exec { 'postgresql_reload': - path => '/usr/bin:/usr/sbin:/bin:/sbin', - command => $service_reload, - onlyif => $service_status, - refreshonly => true, - require => Class['postgresql::server::service'], + postgresql::server::instance::reload { 'main': + service_status => $postgresql::server::service_status, + service_reload => $postgresql::server::service_reload, } } diff --git a/manifests/server/role.pp b/manifests/server/role.pp index 3637b6908a..f71ecf599c 100644 --- a/manifests/server/role.pp +++ b/manifests/server/role.pp @@ -1,122 +1,203 @@ -# Define for creating a database role. See README.md for more information -define postgresql::server::role( - $password_hash = false, - $createdb = false, - $createrole = false, - $db = $postgresql::server::default_database, - $port = undef, - $login = true, - $inherit = true, - $superuser = false, - $replication = false, - $connection_limit = '-1', - $username = $title, - $connect_settings = $postgresql::server::default_connect_settings, +# @summary Define for creating a database role. +# +# @param update_password +# If set to true, updates the password on changes. Set this to false to not modify the role's password after creation. +# @param password_hash Sets the hash to use during password creation. +# @param createdb Specifies whether to grant the ability to create new databases with this role. +# @param createrole Specifies whether to grant the ability to create new roles with this role. +# @param db Database used to connect to. +# @param port Port to use when connecting. +# @param login Specifies whether to grant login capability for the new role. +# @param inherit Specifies whether to grant inherit capability for the new role. +# @param superuser Specifies whether to grant super user capability for the new role. +# @param replication Provides provides replication capabilities for this role if set to true. +# @param valid_until Specifies whether to set a valid until date for the role. +# @param connection_limit Specifies how many concurrent connections the role can make. Default value: '-1', meaning no limit. +# @param username Defines the username of the role to create. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param ensure Specify whether to create or drop the role. Specifying 'present' creates the role. Specifying 'absent' drops the role. +# @param psql_user Sets the OS user to run psql +# @param psql_group Sets the OS group to run psql +# @param psql_path Sets path to psql command +# @param module_workdir +# Specifies working directory under which the psql command should be executed. +# May need to specify if '/tmp' is on volume mounted with noexec option. +# @param hash Specify the hash method for pg password +# @param salt Specify the salt use for the scram-sha-256 encoding password (default username) +# @param instance The name of the Postgresql database instance. +define postgresql::server::role ( + Boolean $update_password = true, + Variant[Boolean, String, Sensitive[String]] $password_hash = false, + Boolean $createdb = false, + Boolean $createrole = false, + String[1] $db = $postgresql::server::default_database, + Stdlib::Port $port = postgresql::default('port'), + Boolean $login = true, + Boolean $inherit = true, + Boolean $superuser = false, + Boolean $replication = false, + Optional[String[1]] $valid_until = undef, + String[1] $connection_limit = '-1', + String[1] $username = $title, + Hash $connect_settings = $postgresql::server::default_connect_settings, + String[1] $psql_user = $postgresql::server::user, + String[1] $psql_group = $postgresql::server::group, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + String[1] $module_workdir = $postgresql::server::module_workdir, + Enum['present', 'absent'] $ensure = 'present', + Optional[Enum['md5', 'scram-sha-256']] $hash = undef, + Optional[Variant[String[1], Integer]] $salt = undef, + String[1] $instance = 'main', ) { - $psql_user = $postgresql::server::user - $psql_group = $postgresql::server::group - $psql_path = $postgresql::server::psql_path - - # - # Port, order of precedence: $port parameter, $connect_settings[PGPORT], $postgresql::server::port - # - if $port != undef { - $port_override = $port - } elsif $connect_settings != undef and has_key( $connect_settings, 'PGPORT') { - $port_override = undef - } else { - $port_override = $postgresql::server::port - } - - # If possible use the version of the remote database, otherwise - # fallback to our local DB version - if $connect_settings != undef and has_key( $connect_settings, 'DBVERSION') { - $version = $connect_settings['DBVERSION'] - } else { - $version = $postgresql::server::_version - } - - $login_sql = $login ? { true => 'LOGIN', default => 'NOLOGIN' } - $inherit_sql = $inherit ? { true => 'INHERIT', default => 'NOINHERIT' } - $createrole_sql = $createrole ? { true => 'CREATEROLE', default => 'NOCREATEROLE' } - $createdb_sql = $createdb ? { true => 'CREATEDB', default => 'NOCREATEDB' } - $superuser_sql = $superuser ? { true => 'SUPERUSER', default => 'NOSUPERUSER' } - $replication_sql = $replication ? { true => 'REPLICATION', default => '' } - if ($password_hash != false) { - $environment = "NEWPGPASSWD=${password_hash}" - $password_sql = "ENCRYPTED PASSWORD '\$NEWPGPASSWD'" + $password_hash_unsensitive = if $password_hash =~ Sensitive[String] { + $password_hash.unwrap } else { - $password_sql = '' - $environment = [] + $password_hash } + $port_override = pick($connect_settings['PGPORT'], $port) + $version = pick($connect_settings['DBVERSION'], postgresql::default('version')) Postgresql_psql { - db => $db, - port => $port_override, - psql_user => $psql_user, - psql_group => $psql_group, - psql_path => $psql_path, + db => $db, + port => $port_override, + psql_user => $psql_user, + psql_group => $psql_group, + psql_path => $psql_path, connect_settings => $connect_settings, - require => [ - Postgresql_psql["CREATE ROLE ${username} ENCRYPTED PASSWORD ****"], - Class['postgresql::server'], - ], + instance => $instance, + cwd => $module_workdir, + require => Postgresql_psql["CREATE ROLE ${username} ENCRYPTED PASSWORD ****"], } - postgresql_psql { "CREATE ROLE ${username} ENCRYPTED PASSWORD ****": - command => "CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}", - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}'", - environment => $environment, - require => Class['Postgresql::Server'], - } + if $ensure == 'present' { + $login_sql = $login ? { true => 'LOGIN', default => 'NOLOGIN' } + $inherit_sql = $inherit ? { true => 'INHERIT', default => 'NOINHERIT' } + $createrole_sql = $createrole ? { true => 'CREATEROLE', default => 'NOCREATEROLE' } + $createdb_sql = $createdb ? { true => 'CREATEDB', default => 'NOCREATEDB' } + $superuser_sql = $superuser ? { true => 'SUPERUSER', default => 'NOSUPERUSER' } + $replication_sql = $replication ? { true => 'REPLICATION', default => '' } - postgresql_psql {"ALTER ROLE \"${username}\" ${superuser_sql}": - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolsuper=${superuser}", - } + if $password_hash_unsensitive =~ Deferred { + $password_sql = Deferred('postgresql::prepend_sql_password', [$password_hash_unsensitive]) + } elsif ($password_hash_unsensitive != false) { + $password_sql = postgresql::prepend_sql_password($password_hash_unsensitive) + } else { + $password_sql = '' + } - postgresql_psql {"ALTER ROLE \"${username}\" ${createdb_sql}": - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolcreatedb=${createdb}", - } + if $password_sql =~ Deferred { + $create_role_command = Deferred('sprintf', ["CREATE ROLE \"%s\" %s %s %s %s %s %s CONNECTION LIMIT %s", + $username, + $password_sql, + $login_sql, + $createrole_sql, + $createdb_sql, + $superuser_sql, + $replication_sql, + $connection_limit, + ] + ) + } else { + $create_role_command = "CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}" # lint:ignore:140chars + } - postgresql_psql {"ALTER ROLE \"${username}\" ${createrole_sql}": - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolcreaterole=${createrole}", - } + postgresql_psql { "CREATE ROLE ${username} ENCRYPTED PASSWORD ****": + command => Sensitive($create_role_command), + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}'", + require => undef, + sensitive => true, + } - postgresql_psql {"ALTER ROLE \"${username}\" ${login_sql}": - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolcanlogin=${login}", - } + postgresql_psql { "ALTER ROLE \"${username}\" ${superuser_sql}": + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolsuper = ${superuser}", + } - postgresql_psql {"ALTER ROLE \"${username}\" ${inherit_sql}": - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolinherit=${inherit}", - } + postgresql_psql { "ALTER ROLE \"${username}\" ${createdb_sql}": + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolcreatedb = ${createdb}", + } + + postgresql_psql { "ALTER ROLE \"${username}\" ${createrole_sql}": + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolcreaterole = ${createrole}", + } + + postgresql_psql { "ALTER ROLE \"${username}\" ${login_sql}": + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolcanlogin = ${login}", + } - if(versioncmp($version, '9.1') >= 0) { - if $replication_sql == '' { - postgresql_psql {"ALTER ROLE \"${username}\" NOREPLICATION": - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolreplication=${replication}", + postgresql_psql { "ALTER ROLE \"${username}\" ${inherit_sql}": + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolinherit = ${inherit}", + } + + if $valid_until { + postgresql_psql { "ALTER ROLE \"${username}\" VALID UNTIL '${valid_until}'": + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolvaliduntil = '${valid_until}'", } - } else { - postgresql_psql {"ALTER ROLE \"${username}\" ${replication_sql}": - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolreplication=${replication}", + } + + if(versioncmp($version, '9.1') >= 0) { + if $replication_sql == '' { + postgresql_psql { "ALTER ROLE \"${username}\" NOREPLICATION": + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolreplication = ${replication}", + } + } else { + postgresql_psql { "ALTER ROLE \"${username}\" ${replication_sql}": + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolreplication = ${replication}", + } } } - } - postgresql_psql {"ALTER ROLE \"${username}\" CONNECTION LIMIT ${connection_limit}": - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolconnlimit=${connection_limit}", - } + postgresql_psql { "ALTER ROLE \"${username}\" CONNECTION LIMIT ${connection_limit}": + unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolconnlimit = ${connection_limit}", + } - if $password_hash { - if($password_hash =~ /^md5.+/) { - $pwd_hash_sql = $password_hash + $_hash = if $hash { + $hash + } elsif $connect_settings != undef and 'DBVERSION' in $connect_settings { + versioncmp($version, '14') ? { -1 => 'md5', default => 'scram-sha-256' } } else { - $pwd_md5 = md5("${password_hash}${username}") - $pwd_hash_sql = "md5${pwd_md5}" + $postgresql::server::password_encryption } - postgresql_psql { "ALTER ROLE ${username} ENCRYPTED PASSWORD ****": - command => "ALTER ROLE \"${username}\" ${password_sql}", - unless => "SELECT usename FROM pg_shadow WHERE usename='${username}' and passwd='${pwd_hash_sql}'", - environment => $environment, + if $password_hash_unsensitive and $update_password { + if $password_hash_unsensitive =~ Deferred { + $pwd_hash_sql = Deferred ( 'postgresql::postgresql_password', [ + $username, + $password_hash_unsensitive, + false, + $_hash, + $salt, + ] + ) + } else { + $pwd_hash_sql = postgresql::postgresql_password( + $username, + $password_hash_unsensitive, + false, + $_hash, + $salt, + ) + } + if $pwd_hash_sql =~ Deferred { + $pw_command = Deferred('sprintf', ["ALTER ROLE \"%s\" ENCRYPTED PASSWORD '%s'", $username, $pwd_hash_sql]) + $unless_pw_command = Deferred('sprintf', ["SELECT 1 FROM pg_shadow WHERE usename = '%s' AND passwd = '%s'", + $username, + $pwd_hash_sql, + ] + ) + } else { + $pw_command = "ALTER ROLE \"${username}\" ENCRYPTED PASSWORD '${pwd_hash_sql}'" + $unless_pw_command = "SELECT 1 FROM pg_shadow WHERE usename = '${username}' AND passwd = '${pwd_hash_sql}'" + } + postgresql_psql { "ALTER ROLE ${username} ENCRYPTED PASSWORD ****": + command => Sensitive($pw_command), + unless => Sensitive($unless_pw_command), + sensitive => true, + } + } + } else { + # ensure == absent + postgresql_psql { "DROP ROLE \"${username}\"": + onlyif => "SELECT 1 FROM pg_roles WHERE rolname = '${username}'", + require => undef, } } } diff --git a/manifests/server/schema.pp b/manifests/server/schema.pp index 74a00dedb7..e8405792f7 100644 --- a/manifests/server/schema.pp +++ b/manifests/server/schema.pp @@ -1,60 +1,68 @@ -# = Type: postgresql::server::schema +# @summary +# Create a new schema. # -# Create a new schema. See README.md for more details. +# @note +# The database must exist and the PostgreSQL user should have enough privileges # -# == Requires: -# -# The database must exist and the PostgreSQL user should have enough privileges -# -# == Sample Usage: -# -# postgresql::server::schema {'private': -# db => 'template1', -# } -# -define postgresql::server::schema( - $db = $postgresql::server::default_database, - $owner = undef, - $schema = $title, - $connect_settings = $postgresql::server::default_connect_settings, +# @param db Required. Sets the name of the database in which to create this schema. +# @param owner Sets the default owner of the schema. +# @param schema Sets the name of the schema. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param port the post the postgresql instance is listening on. +# @param user Sets the OS user to run psql +# @param group Sets the OS group to run psql +# @param psql_path Sets path to psql command +# @param module_workdir +# Specifies working directory under which the psql command should be executed. +# May need to specify if '/tmp' is on volume mounted with noexec option. +# @param instance The name of the Postgresql database instance. +# @example +# postgresql::server::schema {'private': +# db => 'template1', +# } +define postgresql::server::schema ( + String[1] $db = $postgresql::server::default_database, + Optional[String[1]] $owner = undef, + String[1] $schema = $title, + Hash $connect_settings = $postgresql::server::default_connect_settings, + Stdlib::Port $port = $postgresql::server::port, + String[1] $user = $postgresql::server::user, + String[1] $group = $postgresql::server::group, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + Stdlib::Absolutepath $module_workdir = $postgresql::server::module_workdir, + String[1] $instance = 'main', ) { - $user = $postgresql::server::user - $group = $postgresql::server::group - $psql_path = $postgresql::server::psql_path - $version = $postgresql::server::_version + Postgresql::Server::Db <| dbname == $db |> -> Postgresql::Server::Schema[$name] # If the connection settings do not contain a port, then use the local server port - if $connect_settings != undef and has_key( $connect_settings, 'PGPORT') { - $port = undef - } else { - $port = $postgresql::server::port - } + $port_override = pick($connect_settings['PGPORT'], $port) Postgresql_psql { - db => $db, - psql_user => $user, - psql_group => $group, - psql_path => $psql_path, - port => $port, + db => $db, + psql_user => $user, + psql_group => $group, + psql_path => $psql_path, + port => $port_override, + cwd => $module_workdir, connect_settings => $connect_settings, + instance => $instance, } - $schema_title = "Create Schema '${title}'" - $authorization = $owner? { - undef => '', - default => "AUTHORIZATION \"${owner}\"", - } - - $schema_command = "CREATE SCHEMA \"${schema}\" ${authorization}" - $unless = "SELECT nspname FROM pg_namespace WHERE nspname='${schema}'" - - postgresql_psql { $schema_title: - command => $schema_command, - unless => $unless, + postgresql_psql { "${db}: CREATE SCHEMA \"${schema}\"": + command => "CREATE SCHEMA \"${schema}\"", + unless => "SELECT 1 FROM pg_namespace WHERE nspname = '${schema}'", require => Class['postgresql::server'], } - if($owner != undef and defined(Postgresql::Server::Role[$owner])) { - Postgresql::Server::Role[$owner]->Postgresql_psql[$schema_title] + if $owner { + postgresql_psql { "${db}: ALTER SCHEMA \"${schema}\" OWNER TO \"${owner}\"": + command => "ALTER SCHEMA \"${schema}\" OWNER TO \"${owner}\"", + unless => "SELECT 1 FROM pg_namespace JOIN pg_roles rol ON nspowner = rol.oid WHERE nspname = '${schema}' AND rolname = '${owner}'", + require => Postgresql_psql["${db}: CREATE SCHEMA \"${schema}\""], + } + + if defined(Postgresql::Server::Role[$owner]) { + Postgresql::Server::Role[$owner] -> Postgresql_psql["${db}: ALTER SCHEMA \"${schema}\" OWNER TO \"${owner}\""] + } } } diff --git a/manifests/server/service.pp b/manifests/server/service.pp index de06818be9..174e550790 100644 --- a/manifests/server/service.pp +++ b/manifests/server/service.pp @@ -1,46 +1,16 @@ -# PRIVATE CLASS: do not call directly +# @api private class postgresql::server::service { - $service_ensure = $postgresql::server::service_ensure - $service_enable = $postgresql::server::service_enable - $service_manage = $postgresql::server::service_manage - $service_name = $postgresql::server::service_name - $service_provider = $postgresql::server::service_provider - $service_status = $postgresql::server::service_status - $user = $postgresql::server::user - $port = $postgresql::server::port - $default_database = $postgresql::server::default_database - - anchor { 'postgresql::server::service::begin': } - - if $service_manage { - - service { 'postgresqld': - ensure => $service_ensure, - enable => $service_enable, - name => $service_name, - provider => $service_provider, - hasstatus => true, - status => $service_status, - } - - if $service_ensure == 'running' { - # This blocks the class before continuing if chained correctly, making - # sure the service really is 'up' before continuing. - # - # Without it, we may continue doing more work before the database is - # prepared leading to a nasty race condition. - postgresql::validate_db_connection { 'validate_service_is_running': - run_as => $user, - database_name => $default_database, - database_port => $port, - sleep => 1, - tries => 60, - create_db_first => false, - require => Service['postgresqld'], - before => Anchor['postgresql::server::service::end'] - } - } + postgresql::server::instance::service { 'main': + service_ensure => $postgresql::server::service_ensure, + service_enable => $postgresql::server::service_enable, + service_manage => $postgresql::server::service_manage, + service_name => $postgresql::server::service_name, + service_provider => $postgresql::server::service_provider, + service_status => $postgresql::server::service_status, + user => $postgresql::server::user, + port => $postgresql::server::port, + default_database => $postgresql::server::default_database, + psql_path => $postgresql::server::psql_path, + connect_settings => $postgresql::server::default_connect_settings, } - - anchor { 'postgresql::server::service::end': } } diff --git a/manifests/server/table_grant.pp b/manifests/server/table_grant.pp index 452f13d9de..719460fd22 100644 --- a/manifests/server/table_grant.pp +++ b/manifests/server/table_grant.pp @@ -1,17 +1,34 @@ -# This resource wraps the grant resource to manage table grants specifically. -# See README.md for more details. -define postgresql::server::table_grant( - $privilege, - $table, - $db, - $role, - $port = undef, - $psql_db = undef, - $psql_user = undef, - $connect_settings = undef, - $onlyif_exists = false, +# @summary This resource wraps the grant resource to manage table grants specifically. +# +# @param privilege +# Specifies comma-separated list of privileges to grant. +# Valid options: 'ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER'. +# @param table Specifies the table to which you are granting access. +# @param db Specifies which database the table is in. +# @param role Specifies the role or user to whom you are granting access. +# @param ensure Specifies whether to grant or revoke the privilege. Default is to grant the privilege. +# @param port Port to use when connecting. +# @param psql_db Specifies the database to execute the grant against. This should not ordinarily be changed from the default. +# @param psql_user Specifies the OS user for running psql. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param onlyif_exists Create grant only if it doesn't exist. +# @param instance The name of the Postgresql database instance. +define postgresql::server::table_grant ( + Enum['ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER', 'all', 'select', 'insert', 'update', 'delete', + 'truncate', 'references', 'trigger'] $privilege, + String[1] $table, + String[1] $db, + String[1] $role, + Optional[Enum['present', 'absent']] $ensure = undef, + Optional[Stdlib::Port] $port = undef, + Optional[String[1]] $psql_db = undef, + Optional[String[1]] $psql_user = undef, + Optional[Hash] $connect_settings = undef, + Boolean $onlyif_exists = false, + String[1] $instance = 'main', ) { postgresql::server::grant { "table:${name}": + ensure => $ensure, role => $role, db => $db, port => $port, @@ -22,5 +39,6 @@ psql_user => $psql_user, onlyif_exists => $onlyif_exists, connect_settings => $connect_settings, + instance => $instance, } -} \ No newline at end of file +} diff --git a/manifests/server/tablespace.pp b/manifests/server/tablespace.pp index 8fb22b571f..2774732780 100644 --- a/manifests/server/tablespace.pp +++ b/manifests/server/tablespace.pp @@ -1,56 +1,82 @@ -# This module creates tablespace. See README.md for more details. -define postgresql::server::tablespace( - $location, - $owner = undef, - $spcname = $title, - $connect_settings = $postgresql::server::default_connect_settings, +# @summary This module creates tablespace. +# +# @param location Specifies the path to locate this tablespace. +# @param manage_location Set to false if you have file{ $location: } already defined +# @param owner Specifies the default owner of the tablespace. +# @param spcname Specifies the name of the tablespace. +# @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. +# @param port the port of the postgresql instance that sould be used. +# @param user Sets the OS user to run psql +# @param group Sets the OS group to run psql +# @param psql_path Sets path to psql command +# @param module_workdir +# Specifies working directory under which the psql command should be executed. +# May need to specify if '/tmp' is on volume mounted with noexec option. +# @param instance The name of the Postgresql database instance. +define postgresql::server::tablespace ( + String[1] $location, + Boolean $manage_location = true, + Optional[String[1]] $owner = undef, + String[1] $spcname = $title, + Hash $connect_settings = $postgresql::server::default_connect_settings, + Stdlib::Port $port = $postgresql::server::port, + String[1] $user = $postgresql::server::user, + String[1] $group = $postgresql::server::group, + Stdlib::Absolutepath $psql_path = $postgresql::server::psql_path, + String[1] $module_workdir = $postgresql::server::module_workdir, + String[1] $instance = 'main', ) { - $user = $postgresql::server::user - $group = $postgresql::server::group - $psql_path = $postgresql::server::psql_path - # If the connection settings do not contain a port, then use the local server port - if $connect_settings != undef and has_key( $connect_settings, 'PGPORT') { - $port = undef - } else { - $port = $postgresql::server::port - } + $port_override = pick($connect_settings['PGPORT'], $port) Postgresql_psql { psql_user => $user, psql_group => $group, psql_path => $psql_path, - port => $port, + port => $port_override, connect_settings => $connect_settings, + cwd => $module_workdir, + instance => $instance, } - if ($owner == undef) { - $owner_section = '' + if($manage_location) { + file { $location: + ensure => directory, + owner => $user, + group => $group, + mode => '0700', + seluser => 'system_u', + selrole => 'object_r', + seltype => 'postgresql_db_t', + require => Class['postgresql::server'], + } } else { - $owner_section = "OWNER \"${owner}\"" + File <| title == $location |> { + ensure => directory, + owner => $user, + group => $group, + mode => '0700', + seluser => 'system_u', + selrole => 'object_r', + seltype => 'postgresql_db_t', + require => Class['postgresql::server'], + } } - $create_tablespace_command = "CREATE TABLESPACE \"${spcname}\" ${owner_section} LOCATION '${location}'" - - file { $location: - ensure => directory, - owner => $user, - group => $group, - mode => '0700', - seluser => 'system_u', - selrole => 'object_r', - seltype => 'postgresql_db_t', - require => Class['postgresql::server'], + postgresql_psql { "CREATE TABLESPACE \"${spcname}\"": + command => "CREATE TABLESPACE \"${spcname}\" LOCATION '${location}'", + unless => "SELECT 1 FROM pg_tablespace WHERE spcname = '${spcname}'", + require => File[$location], } - $create_ts = "Create tablespace '${spcname}'" - postgresql_psql { "Create tablespace '${spcname}'": - command => $create_tablespace_command, - unless => "SELECT spcname FROM pg_tablespace WHERE spcname='${spcname}'", - require => [Class['postgresql::server'], File[$location]], - } + if $owner { + postgresql_psql { "ALTER TABLESPACE \"${spcname}\" OWNER TO \"${owner}\"": + unless => "SELECT 1 FROM pg_tablespace JOIN pg_roles rol ON spcowner = rol.oid WHERE spcname = '${spcname}' AND rolname = '${owner}'", # lint:ignore:140chars + require => Postgresql_psql["CREATE TABLESPACE \"${spcname}\""], + } - if($owner != undef and defined(Postgresql::Server::Role[$owner])) { - Postgresql::Server::Role[$owner]->Postgresql_psql[$create_ts] + if defined(Postgresql::Server::Role[$owner]) { + Postgresql::Server::Role[$owner] -> Postgresql_psql["ALTER TABLESPACE \"${spcname}\" OWNER TO \"${owner}\""] + } } } diff --git a/manifests/server_instance.pp b/manifests/server_instance.pp new file mode 100644 index 0000000000..5ef8dec527 --- /dev/null +++ b/manifests/server_instance.pp @@ -0,0 +1,140 @@ +# @summary define to install and manage additional postgresql instances +# @param instance_name The name of the instance. +# @param instance_user The user to run the instance as. +# @param instance_group The group to run the instance as. +# @param instance_user_homedirectory The home directory of the instance user. +# @param manage_instance_user_and_group Should Puppet manage the instance user and it's primary group?. +# @param instance_directories directories needed for the instance. Option to manage the directory properties for each directory. +# @param initdb_settings Specifies a hash witn parameters for postgresql::server::instance::initdb +# @param config_settings Specifies a hash with parameters for postgresql::server::instance::config +# @param service_settings Specifies a hash with parameters for postgresql::server:::instance::service +# @param passwd_settings Specifies a hash with parameters for postgresql::server::instance::passwd +# @param roles Specifies a hash from which to generate postgresql::server::role resources. +# @param config_entries Specifies a hash from which to generate postgresql::server::config_entry resources. +# @param pg_hba_rules Specifies a hash from which to generate postgresql::server::pg_hba_rule resources. +# @param databases Specifies a hash from which to generate postgresql::server::database resources. +# @param databases_and_users Specifies a hash from which to generate postgresql::server::db resources. +# @param database_grants Specifies a hash from which to generate postgresql::server::database_grant resources. +# @param table_grants Specifies a hash from which to generate postgresql::server::table_grant resources. +define postgresql::server_instance ( + String[1] $instance_name = $name, + Boolean $manage_instance_user_and_group = true, + Hash $instance_directories = {}, + String[1] $instance_user = $instance_name, + String[1] $instance_group = $instance_name, + Stdlib::Absolutepath $instance_user_homedirectory = "/opt/pgsql/data/home/${instance_user}", + Hash $initdb_settings = {}, + Hash $config_settings = {}, + Hash $service_settings = {}, + Hash $passwd_settings = {}, + Hash $roles = {}, + Hash $config_entries = {}, + Hash $pg_hba_rules = {}, + Hash $databases_and_users = {}, + Hash $databases = {}, + Hash $database_grants = {}, + Hash $table_grants = {}, +) { + unless($facts['os']['family'] == 'RedHat' and $facts['os']['release']['major'] == '8') { + warning('This define postgresql::server_instance is only tested on RHEL8') + } + $instance_directories.each |Stdlib::Absolutepath $directory, Hash $directory_settings| { + file { $directory: + * => $directory_settings, + } + } + + if $manage_instance_user_and_group { + user { $instance_user: + managehome => true, + system => true, + home => $instance_user_homedirectory, + gid => $instance_group, + } + group { $instance_group: + system => true, + } + } + postgresql::server::instance::initdb { $instance_name: + * => $initdb_settings, + } + postgresql::server::instance::config { $instance_name: + * => $config_settings, + } + postgresql::server::instance::service { $instance_name: + * => $service_settings, + port => $config_settings['port'], + user => $instance_user, + } + postgresql::server::instance::reload { $instance_name: + service_status => $service_settings['service_status'], + service_reload => "systemctl reload ${service_settings['service_name']}.service", + } + postgresql::server::instance::passwd { $instance_name: + * => $passwd_settings, + } + + $roles.each |$rolename, $role| { + postgresql::server::role { $rolename: + * => $role, + psql_user => $instance_user, + psql_group => $instance_group, + port => $config_settings['port'], + instance => $instance_name, + } + } + + $config_entries.each |$entry, $settings| { + $value = $settings['value'] + $comment = $settings['comment'] + postgresql::server::config_entry { "${entry}_${$instance_name}": + ensure => bool2str($value =~ Undef, 'absent', 'present'), + key => $entry, + value => $value, + comment => $comment, + path => $config_settings['postgresql_conf_path'], + instance_name => $instance_name, + } + } + $pg_hba_rules.each |String[1] $rule_name, Postgresql::Pg_hba_rule $rule| { + $rule_title = "${rule_name} for instance ${name}" + postgresql::server::pg_hba_rule { $rule_title: + * => $rule, + target => $config_settings['pg_hba_conf_path'], # TODO: breaks if removed + } + } + $databases_and_users.each |$database, $database_details| { + postgresql::server::db { $database: + * => $database_details, + psql_user => $instance_user, + psql_group => $instance_group, + port => $config_settings['port'], + } + } + $databases.each |$database, $database_details| { + postgresql::server::database { $database: + * => $database_details, + user => $instance_user, + group => $instance_group, + port => $config_settings['port'], + instance => $instance_name, + } + } + $database_grants.each |$db_grant_title, $dbgrants| { + postgresql::server::database_grant { $db_grant_title: + * => $dbgrants, + psql_user => $instance_user, + psql_group => $instance_group, + port => $config_settings['port'], + instance => $instance_name, + } + } + $table_grants.each |$table_grant_title, $tgrants| { + postgresql::server::table_grant { $table_grant_title: + * => $tgrants, + psql_user => $instance_user, + port => $config_settings['port'], + instance => $instance_name, + } + } +} diff --git a/manifests/validate_db_connection.pp b/manifests/validate_db_connection.pp deleted file mode 100644 index bbdc94424d..0000000000 --- a/manifests/validate_db_connection.pp +++ /dev/null @@ -1,91 +0,0 @@ -# This type validates that a successful postgres connection can be established -# between the node on which this resource is run and a specified postgres -# instance (host/port/user/password/database name). -# -# See README.md for more details. -define postgresql::validate_db_connection( - $database_host = undef, - $database_name = undef, - $database_password = undef, - $database_username = undef, - $database_port = undef, - $connect_settings = undef, - $run_as = undef, - $sleep = 2, - $tries = 10, - $create_db_first = true -) { - include postgresql::client - include postgresql::params - - $psql_path = $postgresql::params::psql_path - $validcon_script_path = $postgresql::client::validcon_script_path - - $cmd_init = "${psql_path} --tuples-only --quiet " - $cmd_host = $database_host ? { - undef => '', - default => "-h ${database_host} ", - } - $cmd_user = $database_username ? { - undef => '', - default => "-U ${database_username} ", - } - $cmd_port = $database_port ? { - undef => '', - default => "-p ${database_port} ", - } - $cmd_dbname = $database_name ? { - undef => "--dbname ${postgresql::params::default_database} ", - default => "--dbname ${database_name} ", - } - $pass_env = $database_password ? { - undef => undef, - default => "PGPASSWORD=${database_password}", - } - $cmd = join([$cmd_init, $cmd_host, $cmd_user, $cmd_port, $cmd_dbname], ' ') - $validate_cmd = "${validcon_script_path} ${sleep} ${tries} '${cmd}'" - - # This is more of a safety valve, we add a little extra to compensate for the - # time it takes to run each psql command. - $timeout = (($sleep + 2) * $tries) - - # Combine $database_password and $connect_settings into an array of environment - # variables, ensure $database_password is last, allowing it to override a password - # from the $connect_settings hash - if $connect_settings != undef { - if $pass_env != undef { - $env = concat(join_keys_to_values( $connect_settings, '='), $pass_env) - } else { - $env = join_keys_to_values( $connect_settings, '=') - } - } else { - $env = $pass_env - } - - $exec_name = "validate postgres connection for ${database_username}@${database_host}:${database_port}/${database_name}" - - exec { $exec_name: - command => "echo 'Unable to connect to defined database using: ${cmd}' && false", - unless => $validate_cmd, - cwd => '/tmp', - environment => $env, - logoutput => 'on_failure', - user => $run_as, - path => '/bin:/usr/bin:/usr/local/bin', - timeout => $timeout, - require => Class['postgresql::client'], - } - - # This is a little bit of puppet magic. What we want to do here is make - # sure that if the validation and the database instance creation are being - # applied on the same machine, then the database resource is applied *before* - # the validation resource. Otherwise, the validation is guaranteed to fail - # on the first run. - # - # We accomplish this by using Puppet's resource collection syntax to search - # for the Database resource in our current catalog; if it exists, the - # appropriate relationship is created here. - if($create_db_first) { - Postgresql::Server::Database<|title == $database_name|> -> Exec[$exec_name] - } -} diff --git a/metadata.json b/metadata.json index f822f06664..82cb5fa869 100644 --- a/metadata.json +++ b/metadata.json @@ -1,74 +1,107 @@ { "name": "puppetlabs-postgresql", - "version": "4.6.0", - "author": "Inkling/Puppet Labs", + "version": "10.6.0", + "author": "puppetlabs", "summary": "Offers support for basic management of PostgreSQL databases.", "license": "Apache-2.0", - "source": "git://github.com/puppetlabs/puppetlabs-postgresql.git", + "source": "https://github.com/puppetlabs/puppetlabs-postgresql", "project_page": "https://github.com/puppetlabs/puppetlabs-postgresql", - "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", + "issues_url": "https://github.com/puppetlabs/puppetlabs-postgresql/issues", "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":"4.x"}, - {"name":"puppetlabs/apt","version_requirement":">=1.8.0 <3.0.0"}, - {"name":"puppetlabs/concat","version_requirement":">= 1.1.0 <2.0.0"} + { + "name": "puppetlabs/stdlib", + "version_requirement": ">= 9.0.0 < 10.0.0" + }, + { + "name": "puppetlabs/apt", + "version_requirement": ">= 9.2.0 < 12.0.0" + }, + { + "name": "puppet/systemd", + "version_requirement": ">= 4.0.1 < 10.0.0" + }, + { + "name": "puppetlabs/concat", + "version_requirement": ">= 4.1.0 < 10.0.0" + } ], "operatingsystem_support": [ { "operatingsystem": "RedHat", "operatingsystemrelease": [ - "5", - "6", - "7" + "7", + "8", + "9" ] }, { "operatingsystem": "CentOS", "operatingsystemrelease": [ - "5", - "6", - "7" + "7", + "8", + "9" ] }, { "operatingsystem": "OracleLinux", "operatingsystemrelease": [ - "5", - "6", - "7" + "7", + "9" ] }, { "operatingsystem": "Scientific", "operatingsystemrelease": [ - "5", - "6", "7" ] }, { "operatingsystem": "Debian", "operatingsystemrelease": [ - "6", - "7" + "10", + "11", + "12", + "13" + ] + }, + { + "operatingsystem": "SLES", + "operatingsystemrelease": [ + "12", + "15" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ - "10.04", - "12.04", - "14.04" + "18.04", + "20.04", + "22.04", + "24.04" + ] + }, + { + "operatingsystem": "Rocky", + "operatingsystemrelease": [ + "8", + "9" + ] + }, + { + "operatingsystem": "AlmaLinux", + "operatingsystemrelease": [ + "8", + "9" ] } ], "requirements": [ - { - "name": "pe", - "version_requirement": ">= 3.0.0 < 2015.3.0" - }, { "name": "puppet", - "version_requirement": ">= 3.0.0 < 5.0.0" + "version_requirement": ">= 7.0.0 < 9.0.0" } - ] + ], + "pdk-version": "3.2.0", + "template-url": "https://github.com/puppetlabs/pdk-templates#main", + "template-ref": "tags/3.2.0.4-0-g5d17ec1" } diff --git a/pdk.yaml b/pdk.yaml new file mode 100644 index 0000000000..4bef4bd0f9 --- /dev/null +++ b/pdk.yaml @@ -0,0 +1,2 @@ +--- +ignore: [] diff --git a/provision.yaml b/provision.yaml new file mode 100644 index 0000000000..51e4abc91d --- /dev/null +++ b/provision.yaml @@ -0,0 +1,72 @@ +--- +default: + provisioner: docker + images: + - litmusimage/centos:7 +vagrant: + provisioner: vagrant + images: + - centos/7 + - generic/ubuntu1804 +docker_deb: + provisioner: docker + images: + - litmusimage/debian:8 + - litmusimage/debian:9 + - litmusimage/debian:10 +docker_ub_6: + provisioner: docker + images: + - litmusimage/ubuntu:14.04 + - litmusimage/ubuntu:16.04 + - litmusimage/ubuntu:18.04 + - litmusimage/ubuntu:20.04 +docker_el7: + provisioner: docker + images: + - litmusimage/centos:7 + - litmusimage/oraclelinux:7 + - litmusimage/scientificlinux:7 +docker_el8: + provisioner: docker + images: + - litmusimage/centos:8 +release_checks_6: + provisioner: abs + images: + - redhat-6-x86_64 + - redhat-7-x86_64 + - redhat-8-x86_64 + - redhat-9-x86_64 + - centos-6-x86_64 + - centos-7-x86_64 + - centos-8-x86_64 + - oracle-5-x86_64 + - oracle-6-x86_64 + - oracle-7-x86_64 + - scientific-6-x86_64 + - scientific-7-x86_64 + - debian-8-x86_64 + - debian-9-x86_64 + - debian-10-x86_64 + - sles-12-x86_64 + - ubuntu-1404-x86_64 + - ubuntu-1604-x86_64 + - ubuntu-1804-x86_64 + - ubuntu-2004-x86_64 +release_checks_7: + provisioner: abs + images: + - redhat-7-x86_64 + - redhat-8-x86_64 + - redhat-9-x86_64 + - centos-7-x86_64 + - centos-8-x86_64 + - oracle-7-x86_64 + - scientific-7-x86_64 + - debian-9-x86_64 + - debian-10-x86_64 + - sles-12-x86_64 + - sles-15-x86_64 + - ubuntu-1804-x86_64 + - ubuntu-2004-x86_64 diff --git a/spec/acceptance/00-utf8_encoding_spec.rb b/spec/acceptance/00-utf8_encoding_spec.rb deleted file mode 100644 index c0a00b4403..0000000000 --- a/spec/acceptance/00-utf8_encoding_spec.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'spec_helper_acceptance' - -# These tests are designed to ensure that the module, when ran with defaults, -# sets up everything correctly and allows us to connect to Postgres. -describe 'postgres::server', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do - it 'with defaults' do - pp = <<-EOS - class { 'postgresql::globals': - encoding => 'UTF8', - locale => 'en_NG', - } -> - class { 'postgresql::server': } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end - - describe port(5432) do - it { is_expected.to be_listening } - end - - it 'can connect with psql' do - psql('--command="\l" postgres', 'postgres') do |r| - expect(r.stdout).to match(/List of databases/) - end - end - - it 'must set UTF8 as template1 encoding' do - psql('--command="SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname=\'template1\'"') do |r| - expect(r.stdout).to match(/UTF8/) - end - end -end - - - diff --git a/spec/acceptance/aaa_spec.rb b/spec/acceptance/aaa_spec.rb new file mode 100644 index 0000000000..a7c9b52497 --- /dev/null +++ b/spec/acceptance/aaa_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql::server' do + let(:pp) do + <<-MANIFEST + class { 'postgresql::globals': + encoding => 'UTF8', + locale => 'en_NG', + } -> + class { 'postgresql::server': } + MANIFEST + end + + it 'with defaults' do + export_locales('en_NG.UTF8') + idempotent_apply(pp) + expect(port(5432)).to be_listening + expect(psql('--command="\l" postgres', 'postgres').stdout).to match(%r{List of databases}) + expect(psql('--command="SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname=\'template1\'"').stdout).to match(%r{UTF8}) + end +end diff --git a/spec/acceptance/alternative_port_spec.rb b/spec/acceptance/alternative_port_spec.rb index fbfad16fba..57ac64cf70 100644 --- a/spec/acceptance/alternative_port_spec.rb +++ b/spec/acceptance/alternative_port_spec.rb @@ -1,28 +1,30 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' # These tests ensure that postgres can change itself to an alternative port # properly. -describe 'postgres::server', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do +describe 'postgresql::server' do it 'on an alternative port' do - pp = <<-EOS - class { 'postgresql::server': port => '55433' } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) + pp = <<-MANIFEST + class { 'postgresql::server': port => 55433, manage_selinux => true } + MANIFEST + if os[:family] == 'redhat' && os[:release].start_with?('8') + apply_manifest(pp, expect_failures: false) + # GCP failures on redhat8 IAC-1286 - idempotency failing + # apply_manifest(pp, catch_changes: true) + else + idempotent_apply(pp) + end end - describe port(55433) do + describe port(55_433) do it { is_expected.to be_listening } end it 'can connect with psql' do psql('-p 55433 --command="\l" postgres', 'postgres') do |r| - expect(r.stdout).to match(/List of databases/) + expect(r.stdout).to match(%r{List of databases}) end end - end - - - diff --git a/spec/acceptance/db_deferred_spec.rb b/spec/acceptance/db_deferred_spec.rb new file mode 100644 index 0000000000..731e0742b8 --- /dev/null +++ b/spec/acceptance/db_deferred_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql::server::db:' do + let(:user) { 'user_test' } + let(:password) { 'deferred_password_test' } + let(:database) { 'test_database' } + + let(:pp_one) do + <<~MANIFEST + $user = '#{user}' + $password = '#{password}' + $database = '#{database}' + + include postgresql::server + postgresql::server::db { $database: + user => $user, + password => Deferred('unwrap', [$password]), + } + MANIFEST + end + + it 'creates a database with with the password in the deferred function' do + apply_manifest(pp_one) + psql_cmd = "PGPASSWORD=#{password} PGUSER=#{user} PGDATABASE=#{database} psql -h 127.0.0.1 -d postgres -c '\\q'" + run_shell("cd /tmp; su #{shellescape('postgres')} -c #{shellescape(psql_cmd)}", + acceptable_exit_codes: [0]) + end +end diff --git a/spec/acceptance/db_spec.rb b/spec/acceptance/db_spec.rb index 643511967e..2564aaedf5 100644 --- a/spec/acceptance/db_spec.rb +++ b/spec/acceptance/db_spec.rb @@ -1,54 +1,46 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' -describe 'postgresql::server::db', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do +describe 'postgresql::server::db' do + before(:all) do + LitmusHelper.instance.run_shell("cd /tmp; su 'postgres' -c 'pg_ctl stop -D /var/lib/pgsql/data/ -m fast'", acceptable_exit_codes: [0, 1]) unless os[:family].match?(%r{debian|ubuntu}) + end + it 'creates a database' do - begin - tmpdir = default.tmpdir('postgresql') - pp = <<-EOS - class { 'postgresql::server': - postgres_password => 'space password', - } - postgresql::server::tablespace { 'postgresql_test_db': - location => '#{tmpdir}', - } -> - postgresql::server::db { 'postgresql_test_db': - comment => 'testcomment', - user => 'test', - password => 'test1', - tablespace => 'postgresql_test_db', - } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - - # Verify that the postgres password works - shell("echo 'localhost:*:*:postgres:space password' > /root/.pgpass") - shell("chmod 600 /root/.pgpass") - shell("psql -U postgres -h localhost --command='\\l'") - - psql('--command="select datname from pg_database" postgresql_test_db') do |r| - expect(r.stdout).to match(/postgresql_test_db/) - expect(r.stderr).to eq('') - end - - psql('--command="SELECT 1 FROM pg_roles WHERE rolname=\'test\'"') do |r| - expect(r.stdout).to match(/\(1 row\)/) - end - - result = shell('psql --version') - version = result.stdout.match(%r{\s(\d\.\d)})[1] - if version > "8.1" - comment_information_function = "shobj_description" - else - comment_information_function = "obj_description" - end - psql("--dbname postgresql_test_db --command=\"SELECT pg_catalog.#{comment_information_function}(d.oid, 'pg_database') FROM pg_catalog.pg_database d WHERE datname = 'postgresql_test_db' AND pg_catalog.#{comment_information_function}(d.oid, 'pg_database') = 'testcomment'\"") do |r| - expect(r.stdout).to match(/\(1 row\)/) - end - ensure - psql('--command="drop database postgresql_test_db" postgres') - psql('--command="DROP USER test"') - end + tmpdir = run_shell('mktemp').stdout + pp = <<-MANIFEST + class { 'postgresql::server': + postgres_password => 'space password', + } + postgresql::server::tablespace { 'postgresql-test-db': + location => '#{tmpdir}', + } -> + postgresql::server::db { 'postgresql-test-db': + comment => 'testcomment', + user => 'test-user', + password => 'test1', + tablespace => 'postgresql-test-db', + } + MANIFEST + + idempotent_apply(pp) + + # Verify that the postgres password works + run_shell("echo 'localhost:*:*:postgres:'space password'' > /root/.pgpass") + run_shell('chmod 600 /root/.pgpass') + run_shell("psql -U postgres -h localhost --command='\\l'") + + result = psql('--command="select datname from pg_database" "postgresql-test-db"') + expect(result.stdout).to match(%r{postgresql-test-db}) + expect(result.stderr).to eq('') + + result = psql('--command="SELECT 1 FROM pg_roles WHERE rolname=\'test-user\'"') + expect(result.stdout).to match(%r{\(1 row\)}) + + result = psql("--dbname postgresql-test-db --command=\"SELECT pg_catalog.shobj_description(d.oid, 'pg_database') FROM pg_catalog.pg_database d WHERE datname = 'postgresql-test-db' AND pg_catalog.shobj_description(d.oid, 'pg_database') = 'testcomment'\"") # rubocop:disable Layout/LineLength + expect(result.stdout).to match(%r{\(1 row\)}) + ensure + psql('--command=\'drop database "postgresql-test-db"\'') end end diff --git a/spec/acceptance/default_parameters_spec.rb b/spec/acceptance/default_parameters_spec.rb index 81163ca91d..41eb6c9774 100644 --- a/spec/acceptance/default_parameters_spec.rb +++ b/spec/acceptance/default_parameters_spec.rb @@ -1,15 +1,20 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' # These tests are designed to ensure that the module, when ran with defaults, # sets up everything correctly and allows us to connect to Postgres. -describe 'postgres::server', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do +describe 'postgresql::server' do + before(:all) do + LitmusHelper.instance.run_shell("cd /tmp; su 'postgres' -c 'pg_ctl stop -D /var/lib/pgsql/data/ -m fast'", acceptable_exit_codes: [0, 1]) unless os[:family].match?(%r{debian|ubuntu}) + end + it 'with defaults' do - pp = <<-EOS + pp = <<-MANIFEST class { 'postgresql::server': } - EOS + MANIFEST - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) + idempotent_apply(pp) end describe port(5432) do @@ -18,11 +23,7 @@ class { 'postgresql::server': } it 'can connect with psql' do psql('--command="\l" postgres', 'postgres') do |r| - expect(r.stdout).to match(/List of databases/) + expect(r.stdout).to match(%r{List of databases}) end end - end - - - diff --git a/spec/acceptance/nodesets/centos-510-x64.yml b/spec/acceptance/nodesets/centos-510-x64.yml deleted file mode 100644 index 12c9e7893a..0000000000 --- a/spec/acceptance/nodesets/centos-510-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-510-x64: - roles: - - master - platform: el-5-x86_64 - box : centos-510-x64-virtualbox-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-510-x64-virtualbox-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/spec/acceptance/nodesets/centos-59-x64.yml b/spec/acceptance/nodesets/centos-59-x64.yml deleted file mode 100644 index 2ad90b86aa..0000000000 --- a/spec/acceptance/nodesets/centos-59-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-59-x64: - roles: - - master - platform: el-5-x86_64 - box : centos-59-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/spec/acceptance/nodesets/centos-64-x64-2-hosts.yml b/spec/acceptance/nodesets/centos-64-x64-2-hosts.yml deleted file mode 100644 index 574b238208..0000000000 --- a/spec/acceptance/nodesets/centos-64-x64-2-hosts.yml +++ /dev/null @@ -1,18 +0,0 @@ -HOSTS: - database: - roles: - - default - - database - platform: el-6-x86_64 - box : centos-64-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box - hypervisor : vagrant - client: - roles: - - client - platform: el-6-x86_64 - box : centos-64-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: foss \ No newline at end of file diff --git a/spec/acceptance/nodesets/centos-64-x64-pe.yml b/spec/acceptance/nodesets/centos-64-x64-pe.yml deleted file mode 100644 index 7d9242f1b9..0000000000 --- a/spec/acceptance/nodesets/centos-64-x64-pe.yml +++ /dev/null @@ -1,12 +0,0 @@ -HOSTS: - centos-64-x64: - roles: - - master - - database - - dashboard - platform: el-6-x86_64 - box : centos-64-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: pe diff --git a/spec/acceptance/nodesets/centos-64-x64.yml b/spec/acceptance/nodesets/centos-64-x64.yml deleted file mode 100644 index 0639835490..0000000000 --- a/spec/acceptance/nodesets/centos-64-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-64-x64: - roles: - - master - platform: el-6-x86_64 - box : centos-64-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/spec/acceptance/nodesets/centos-65-x64.yml b/spec/acceptance/nodesets/centos-65-x64.yml deleted file mode 100644 index 4e2cb809e8..0000000000 --- a/spec/acceptance/nodesets/centos-65-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-65-x64: - roles: - - master - platform: el-6-x86_64 - box : centos-65-x64-vbox436-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/spec/acceptance/nodesets/debian-607-x64.yml b/spec/acceptance/nodesets/debian-607-x64.yml deleted file mode 100644 index 4c8be42d03..0000000000 --- a/spec/acceptance/nodesets/debian-607-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - debian-607-x64: - roles: - - master - platform: debian-6-amd64 - box : debian-607-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/spec/acceptance/nodesets/debian-73-x64.yml b/spec/acceptance/nodesets/debian-73-x64.yml deleted file mode 100644 index 3e31a82760..0000000000 --- a/spec/acceptance/nodesets/debian-73-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - debian-73-x64: - roles: - - master - platform: debian-7-amd64 - box : debian-73-x64-virtualbox-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-x64-virtualbox-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml deleted file mode 100644 index 0639835490..0000000000 --- a/spec/acceptance/nodesets/default.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-64-x64: - roles: - - master - platform: el-6-x86_64 - box : centos-64-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml b/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml deleted file mode 100644 index 5ca1514e40..0000000000 --- a/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - ubuntu-server-10044-x64: - roles: - - master - platform: ubuntu-10.04-amd64 - box : ubuntu-server-10044-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml b/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml deleted file mode 100644 index d065b304f8..0000000000 --- a/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - ubuntu-server-12042-x64: - roles: - - master - platform: ubuntu-12.04-amd64 - box : ubuntu-server-12042-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml deleted file mode 100644 index cba1cd04c2..0000000000 --- a/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - ubuntu-server-1404-x64: - roles: - - master - platform: ubuntu-14.04-amd64 - box : puppetlabs/ubuntu-14.04-64-nocm - box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm - hypervisor : vagrant -CONFIG: - log_level : debug - type: git diff --git a/spec/acceptance/overridden_settings_spec.rb b/spec/acceptance/overridden_settings_spec.rb new file mode 100644 index 0000000000..225f5c7a78 --- /dev/null +++ b/spec/acceptance/overridden_settings_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +# These tests are designed to ensure that the module, when ran overrides, +# sets up everything correctly and allows us to connect to Postgres. +describe 'postgresql::server' do + before(:all) do + LitmusHelper.instance.run_shell("cd /tmp; su 'postgres' -c 'pg_ctl stop -D /var/lib/pgsql/data/ -m fast'", acceptable_exit_codes: [0, 1]) unless os[:family].match?(%r{debian|ubuntu}) + end + + let(:pp) do + <<-MANIFEST + class { 'postgresql::server': + roles => { + 'testusername' => { + password_hash => postgresql::postgresql_password('testusername', 'supersecret'), + createdb => true, + }, + }, + config_entries => { + max_connections => 21, + }, + pg_hba_rules => { + 'from_remote_host' => { + type => 'host', + database => 'mydb', + user => 'myuser', + auth_method => postgresql::default('password_encryption'), + address => '192.0.2.100/32', + }, + }, + } + + postgresql::server::database { 'testusername': + owner => 'testusername', + } + MANIFEST + end + + it 'with additional hiera entries' do + idempotent_apply(pp) + expect(port(5432)).to be_listening + expect(psql('--command="\l" postgres', 'postgres').stdout).to match(%r{List of databases}) + expect(run_shell('PGPASSWORD=supersecret psql -U testusername -h localhost --command="\l"').stdout).to match 'List of databases' + end +end diff --git a/spec/acceptance/postgresql_conn_validator_spec.rb b/spec/acceptance/postgresql_conn_validator_spec.rb new file mode 100644 index 0000000000..81eab7a8da --- /dev/null +++ b/spec/acceptance/postgresql_conn_validator_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql_conn_validator' do + let(:install_pp) do + <<-MANIFEST + class { 'postgresql::server': + postgres_password => 'space password', + }-> + postgresql::server::role { 'testuser': + password_hash => postgresql::postgresql_password('testuser','test1'), + }-> + postgresql::server::database { 'testdb': + owner => 'testuser', + require => Postgresql::Server::Role['testuser'] + }-> + postgresql::server::database_grant { 'allow connect for testuser': + privilege => 'ALL', + db => 'testdb', + role => 'testuser', + } + MANIFEST + end + + context 'local connection' do + it 'validates successfully with defaults' do + pp = <<-MANIFEST + #{install_pp}-> + postgresql_conn_validator { 'validate this': + db_name => 'testdb', + db_username => 'testuser', + db_password => 'test1', + host => 'localhost', + psql_path => '/usr/bin/psql', + } + MANIFEST + + idempotent_apply(pp) + end + + it 'works with connect settings hash' do + pp = <<-MANIFEST + #{install_pp}-> + postgresql_conn_validator { 'validate this': + connect_settings => { + 'PGDATABASE' => 'testdb', + 'PGPORT' => '5432', + 'PGUSER' => 'testuser', + 'PGPASSWORD' => 'test1', + 'PGHOST' => 'localhost' + }, + psql_path => '/usr/bin/psql' + } + MANIFEST + + idempotent_apply(pp) + end + + it 'fails gracefully' do + pp = <<-MANIFEST + #{install_pp}-> + postgresql_conn_validator { 'validate this': + psql_path => '/usr/bin/psql', + tries => 3 + } + MANIFEST + + result = apply_manifest(pp) + expect(result.stderr).to match %r{Unable to connect to PostgreSQL server} + end + end +end diff --git a/spec/acceptance/postgresql_psql_spec.rb b/spec/acceptance/postgresql_psql_spec.rb index 34a258c5f2..571d111d51 100644 --- a/spec/acceptance/postgresql_psql_spec.rb +++ b/spec/acceptance/postgresql_psql_spec.rb @@ -1,183 +1,158 @@ -require 'spec_helper_acceptance' +# frozen_string_literal: true -describe 'postgresql_psql', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do +require 'spec_helper_acceptance' - it 'should always run SQL' do - pp = <<-EOS - class { 'postgresql::server': } -> - postgresql_psql { 'foobar': - db => 'postgres', - psql_user => 'postgres', - command => 'select 1', - } - EOS +describe 'postgresql_psql' do + pp_one = <<-MANIFEST + class { 'postgresql::server': } -> + postgresql_psql { 'foobar': + db => 'postgres', + psql_user => 'postgres', + command => 'select 1', + } + MANIFEST + it 'alwayses run SQL' do + apply_manifest(pp_one, catch_failures: true) + apply_manifest(pp_one, expect_changes: true) + end - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :expect_changes => true) + pp_two = <<-MANIFEST + class { 'postgresql::server': } -> + postgresql_psql { 'foobar': + db => 'postgres', + psql_user => 'postgres', + command => 'select 1', + unless => 'select 1 where 1=2', + } + MANIFEST + it 'runs some SQL when the unless query returns no rows' do + apply_manifest(pp_two, catch_failures: true) + apply_manifest(pp_two, expect_changes: true) end - it 'should run some SQL when the unless query returns no rows' do - pp = <<-EOS - class { 'postgresql::server': } -> - postgresql_psql { 'foobar': - db => 'postgres', - psql_user => 'postgres', - command => 'select 1', - unless => 'select 1 where 1=2', - } - EOS + pp_three = <<-MANIFEST + class { 'postgresql::server': } -> + postgresql_psql { 'foobar': + db => 'postgres', + psql_user => 'postgres', + command => 'select * from pg_database limit 1', + unless => 'select 1 where 1=1', + } + MANIFEST + it 'does not run SQL when the unless query returns rows' do + idempotent_apply(pp_three) + end - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :expect_changes => true) + pp_four = <<-MANIFEST + class { 'postgresql::server': } -> + notify { 'trigger': } ~> + postgresql_psql { 'foobar': + db => 'postgres', + psql_user => 'postgres', + command => 'invalid sql statement', + unless => 'select 1 where 1=1', + } + MANIFEST + it 'does not run SQL when refreshed and the unless query returns rows' do + apply_manifest(pp_four, catch_failures: true) + apply_manifest(pp_four, expect_changes: true) end - it 'should not run SQL when the unless query returns rows' do - pp = <<-EOS + context 'with refreshonly' do + pp_five = <<-MANIFEST class { 'postgresql::server': } -> postgresql_psql { 'foobar': - db => 'postgres', - psql_user => 'postgres', - command => 'select * from pg_database limit 1', - unless => 'select 1 where 1=1', + db => 'postgres', + psql_user => 'postgres', + command => 'select 1', + unless => 'select 1 where 1=2', + refreshonly => true, } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end + MANIFEST + it 'does not run SQL when the unless query returns no rows' do + idempotent_apply(pp_five) + end - it 'should not run SQL when refreshed and the unless query returns rows' do - pp = <<-EOS + pp_six = <<-MANIFEST.unindent class { 'postgresql::server': } -> notify { 'trigger': } ~> postgresql_psql { 'foobar': - db => 'postgres', - psql_user => 'postgres', - command => 'invalid sql statement', - unless => 'select 1 where 1=1', + db => 'postgres', + psql_user => 'postgres', + command => 'select 1', + unless => 'select 1 where 1=2', + refreshonly => true, } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :expect_changes => true) - end - - context 'with refreshonly' do - it 'should not run SQL when the unless query returns no rows' do - pp = <<-EOS - class { 'postgresql::server': } -> - postgresql_psql { 'foobar': - db => 'postgres', - psql_user => 'postgres', - command => 'select 1', - unless => 'select 1 where 1=2', - refreshonly => true, - } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) + MANIFEST + it 'runs SQL when refreshed and the unless query returns no rows' do + apply_manifest(pp_six, catch_failures: true) + apply_manifest(pp_six, expect_changes: true) end - it 'should run SQL when refreshed and the unless query returns no rows' do - pp = <<-EOS.unindent - class { 'postgresql::server': } -> - notify { 'trigger': } ~> - postgresql_psql { 'foobar': - db => 'postgres', - psql_user => 'postgres', - command => 'select 1', - unless => 'select 1 where 1=2', - refreshonly => true, - } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :expect_changes => true) - end - - it 'should not run SQL when refreshed and the unless query returns rows' do - pp = <<-EOS.unindent - class { 'postgresql::server': } -> - notify { 'trigger': } ~> - postgresql_psql { 'foobar': - db => 'postgres', - psql_user => 'postgres', - command => 'invalid sql query', - unless => 'select 1 where 1=1', - refreshonly => true, - } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :expect_changes => true) - end - end - - it 'should not run some SQL when the onlyif query returns no rows' do - pp = <<-EOS + pp_seven = <<-MANIFEST.unindent class { 'postgresql::server': } -> + notify { 'trigger': } ~> postgresql_psql { 'foobar': - db => 'postgres', - psql_user => 'postgres', - command => 'select 1', - onlyif => 'select 1 where 1=2', + db => 'postgres', + psql_user => 'postgres', + command => 'invalid sql query', + unless => 'select 1 where 1=1', + refreshonly => true, } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) + MANIFEST + it 'does not run SQL when refreshed and the unless query returns rows' do + apply_manifest(pp_seven, catch_failures: true) + apply_manifest(pp_seven, expect_changes: true) + end end - it 'should run SQL when the onlyif query returns rows' do - pp = <<-EOS - class { 'postgresql::server': } -> - postgresql_psql { 'foobar': - db => 'postgres', - psql_user => 'postgres', - command => 'select * from pg_database limit 1', - onlyif => 'select 1 where 1=1', - } - EOS + pp_eight = <<-MANIFEST + class { 'postgresql::server': } -> + postgresql_psql { 'foobar': + db => 'postgres', + psql_user => 'postgres', + command => 'select 1', + onlyif => 'select 1 where 1=2', + } + MANIFEST + it 'does not run some SQL when the onlyif query returns no rows' do + apply_manifest(pp_eight, catch_failures: true) + apply_manifest(pp_eight, catch_changes: true) + end - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :expect_changes => true) + pp_nine = <<-MANIFEST + class { 'postgresql::server': } -> + postgresql_psql { 'foobar': + db => 'postgres', + psql_user => 'postgres', + command => 'select * from pg_database limit 1', + onlyif => 'select 1 where 1=1', + } + MANIFEST + it 'runs SQL when the onlyif query returns rows' do + apply_manifest(pp_nine, catch_failures: true) + apply_manifest(pp_nine, expect_changes: true) end - context 'with secure password passing by environment' do - it 'should run SQL that contanins password passed by environment' do - select = "select \\'$PASS_TO_EMBED\\'" - pp = <<-EOS.unindent + context 'when setting sensitive => true' do + it 'runs queries without leaking to the log' do + select = "select \\'pa$swD\\'" + pp = <<~MANIFEST class { 'postgresql::server': } -> - postgresql_psql { 'password embedded by environment: #{select}': + postgresql_psql { 'password protected by sensitive: #{select}': db => 'postgres', psql_user => 'postgres', + sensitive => true, command => '#{select}', - environment => [ - 'PASS_TO_EMBED=pa$swD', - ], } - EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :expect_changes => false) - end - it 'should run SQL that contanins password passed by environment in check' do - select = "select 1 where \\'$PASS_TO_EMBED\\'=\\'passwD\\'" - pp = <<-EOS.unindent - class { 'postgresql::server': } -> - postgresql_psql { 'password embedded by environment in check: #{select}': - db => 'postgres', - psql_user => 'postgres', - command => 'invalid sql query', - unless => '#{select}', - environment => [ - 'PASS_TO_EMBED=passwD', - ], - } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :expect_changes => false) + MANIFEST + result = apply_manifest(pp, catch_failures: true, debug: true) + expect(result.stdout).not_to contain('pa$swD') + expect(result.stderr).not_to contain('pa$swD') + + result = apply_manifest(pp, expect_changes: false, debug: true) + expect(result.stdout).not_to contain('pa$swD') + expect(result.stderr).not_to contain('pa$swD') end end end diff --git a/spec/acceptance/remote_access_spec.rb b/spec/acceptance/remote_access_spec.rb deleted file mode 100644 index 9dd31de1b6..0000000000 --- a/spec/acceptance/remote_access_spec.rb +++ /dev/null @@ -1,72 +0,0 @@ -require 'spec_helper_acceptance' - -describe 'remote-access', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do - before do - skip "These tests require the spec/acceptance/nodesets/centos-64-x64-2-hosts nodeset" - end - - describe "configuring multi-node postgresql" do - - # Get the database's IP to connect to from the database - let(:database_ip_address) do - hosts_as('database').inject({}) do |memo,host| - fact_on host, "ipaddress_eth1" - end - end - - hosts_as('database').each do |host| - it "should be able to configure a host as database on #{host}" do - pp = <<-EOS - # Stop firewall so we can easily connect - service {'iptables': - ensure => 'stopped', - } - - class { 'postgresql::server': - ip_mask_allow_all_users => '0.0.0.0/0', - listen_addresses => '*', - } - - postgresql::server::db { 'puppet': - user => 'puppet', - password => postgresql_password('puppet', 'puppet'), - } - - postgresql::server::pg_hba_rule { 'allow full yolo access password': - type => 'host', - database => 'all', - user => 'all', - address => '0.0.0.0/0', - auth_method => 'password', - order => '002', - } - EOS - apply_manifest_on(host, pp, :catch_failures => true) - end - end - - hosts_as('client').each do |host| - it "should be able to configure a host as client on #{host} and then access database" do - pp = <<-EOS - class { 'postgresql::client':} - - $connection_settings = { - 'PGUSER' => "puppet", - 'PGPASSWORD' => "puppet", - 'PGHOST' => "#{database_ip_address}", - 'PGPORT' => "5432", - 'PGDATABASE' => "puppet", - } - - postgresql_psql { 'run using connection_settings': - command => 'select 1', - psql_user => 'root', - psql_group => 'root', - connect_settings => $connection_settings, - } - EOS - apply_manifest_on(host, pp, :catch_failures => true) - end - end - end -end diff --git a/spec/acceptance/server/config_entry_spec.rb b/spec/acceptance/server/config_entry_spec.rb new file mode 100644 index 0000000000..de034c01a2 --- /dev/null +++ b/spec/acceptance/server/config_entry_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql::server::config_entry' do + before(:all) do + LitmusHelper.instance.run_shell("cd /tmp; su 'postgres' -c 'pg_ctl stop -D /var/lib/pgsql/data/ -m fast'", acceptable_exit_codes: [0, 1]) unless os[:family].match?(%r{debian|ubuntu}) + end + + context 'unix_socket_directories' do + let(:pp_test) do + <<-MANIFEST + class { 'postgresql::server': + postgresql_conf_path => '/etc/postgresql-puppet.conf', + } + + postgresql::server::config_entry { 'unix_socket_directories': + value => '/var/socket/, /root/' + } + MANIFEST + end + + it 'is expected to run idempotently' do + idempotent_apply(pp_test) + expect(run_shell('cat /etc/postgresql-puppet.conf').stdout).to match "unix_socket_directories = '/var/socket/, /root/'" + end + end +end diff --git a/spec/acceptance/server/default_privileges_spec.rb b/spec/acceptance/server/default_privileges_spec.rb new file mode 100644 index 0000000000..c3eac9cee9 --- /dev/null +++ b/spec/acceptance/server/default_privileges_spec.rb @@ -0,0 +1,383 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql::server::default_privileges:' do + let(:db) { 'grant_role_test' } + let(:user) { 'psql_grant_role_tester' } + let(:group) { 'test_group' } + let(:password) { 'psql_grant_role_pw' } + + # Check that the default privileges were revoked + let(:check_command) do + "SELECT * FROM pg_default_acl a LEFT JOIN pg_namespace b ON a.defaclnamespace = b.oid WHERE '#{user}=arwdDxt' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r';" + end + + let(:pp_one) do + <<-MANIFEST.unindent + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Set default privileges on tables + postgresql::server::default_privileges { "alter default privileges grant all on tables to ${user}": + db => $db, + role => $user, + privilege => 'ALL', + object_type => 'TABLES', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + let(:pp_two) do + <<-MANIFEST + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Removes default privileges on tables + postgresql::server::default_privileges { "alter default privileges revoke all on tables for ${user}": + db => $db, + role => $user, + privilege => 'ALL', + object_type => 'TABLES', + ensure => 'absent', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + + let(:target_user) { 'target_role_user' } + let(:target_password) { 'target_role_password' } + + let(:target_check_command) do + "SELECT 1 FROM pg_default_acl a LEFT JOIN pg_namespace AS b ON a.defaclnamespace = b.oid WHERE '#{user}=arwdDxt/#{target_user}' = ANY (defaclacl) AND nspname = 'public' AND defaclobjtype = 'r';" + end + + let(:pp_target_role) do + <<-MANIFEST.unindent + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + $target_user = #{target_user} + $target_password = #{target_password} + + user {$user: + ensure => present, + } + postgresql::server::database_grant { "allow connect for ${user}": + privilege => 'CONNECT', + db => $db, + role => $user, + } + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + + postgresql::server::role { $target_user: + password_hash => postgresql::postgresql_password($target_user, $target_password), + } + + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Set default privileges on tables + postgresql::server::default_privileges { "alter default privileges grant all on tables to ${user}": + db => $db, + role => $user, + target_role => $target_user, + psql_user => 'postgres', + privilege => 'ALL', + object_type => 'TABLES', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + + let(:pp_target_role_revoke) do + <<-MANIFEST.unindent + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + $target_user = #{target_user} + $target_password = #{target_password} + + user {$user: + ensure => present, + } + postgresql::server::database_grant { "allow connect for ${user}": + privilege => 'CONNECT', + db => $db, + role => $user, + } + + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + + postgresql::server::role { $target_user: + password_hash => postgresql::postgresql_password($target_user, $target_password), + } + + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Set default privileges on tables + postgresql::server::default_privileges { "alter default privileges grant all on tables to ${user}": + db => $db, + role => $user, + target_role => $target_user, + psql_user => 'postgres', + privilege => 'ALL', + object_type => 'TABLES', + ensure => 'absent', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + + let(:schema_check_command) do + "SELECT * FROM pg_default_acl WHERE '#{user}=UC' = ANY (defaclacl) AND defaclnamespace = 0 and defaclobjtype = 'n';" + end + + let(:pp_schema) do + <<-MANIFEST.unindent + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Set default privileges on tables + postgresql::server::default_privileges { "alter default privileges grant all on tables to ${user}": + db => $db, + role => $user, + privilege => 'ALL', + object_type => 'SCHEMAS', + schema => '', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + let(:pp_schema_revoke) do + <<-MANIFEST + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Removes default privileges on tables + postgresql::server::default_privileges { "alter default privileges revoke all on tables for ${user}": + db => $db, + role => $user, + privilege => 'ALL', + object_type => 'SCHEMAS', + schema => '', + ensure => 'absent', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + + let(:all_schemas_check_command) do + "SELECT * FROM pg_default_acl a WHERE '#{user}=arwdDxt' = ANY (defaclacl) AND defaclnamespace = 0 and defaclobjtype = 'r';" + end + + let(:pp_unset_schema) do + <<-MANIFEST.unindent + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Set default privileges on tables + postgresql::server::default_privileges { "alter default privileges grant all on tables to ${user}": + db => $db, + role => $user, + privilege => 'ALL', + object_type => 'TABLES', + schema => '', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + let(:pp_unset_schema_revoke) do + <<-MANIFEST + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Removes default privileges on tables + postgresql::server::default_privileges { "alter default privileges revoke all on tables for ${user}": + db => $db, + role => $user, + privilege => 'ALL', + object_type => 'TABLES', + schema => '', + ensure => 'absent', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + + it 'grants default privileges to an user' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6') + idempotent_apply(pp_one) + + psql("--command=\"SET client_min_messages = 'error';#{check_command}\" --db=#{db}") do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end + + it 'revokes default privileges for an user' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6') + apply_manifest(pp_one, catch_failures: true) + apply_manifest(pp_two, expect_changes: true) + + psql("--command=\"SET client_min_messages = 'error';#{check_command}\" --db=#{db}") do |r| + expect(r.stdout).to match(%r{\(0 rows\)}) + expect(r.stderr).to eq('') + end + end + end + + it 'grants default privileges to a user on a specific target role' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6') + idempotent_apply(pp_target_role) + + psql("--command=\"SET client_min_messages = 'error'; #{target_check_command}\" --db=#{db}", user) do |r| + expect(r.stdout).to match(%r{^\(1 row\)$}) + expect(r.stderr).to eq('') + end + end + end + + it 'revokes default privileges from a user on a specific target role' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6') + idempotent_apply(pp_target_role) + idempotent_apply(pp_target_role_revoke) + + psql("--command=\"SET client_min_messages = 'error'; #{target_check_command}\" --db=#{db}", user) do |r| + expect(r.stdout).to match(%r{^\(0 rows\)$}) + expect(r.stderr).to eq('') + end + end + end + + it 'grants default privileges to an user on schemas' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('10.0') + idempotent_apply(pp_schema) + + psql("--command=\"SET client_min_messages = 'error';#{schema_check_command}\" --db=#{db}") do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end + + it 'revokes default privileges for an user on schemas' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('10.0') + apply_manifest(pp_schema, catch_failures: true) + apply_manifest(pp_schema_revoke, expect_changes: true) + + psql("--command=\"SET client_min_messages = 'error';#{schema_check_command}\" --db=#{db}") do |r| + expect(r.stdout).to match(%r{\(0 rows\)}) + expect(r.stderr).to eq('') + end + end + end + + it 'grants default privileges on all schemas to a user' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6') + idempotent_apply(pp_unset_schema) + + psql("--command=\"SET client_min_messages = 'error';#{all_schemas_check_command}\" --db=#{db}") do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end + + it 'revokes default privileges on all schemas for a user' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6') + apply_manifest(pp_unset_schema, catch_failures: true) + apply_manifest(pp_unset_schema_revoke, expect_changes: true) + + psql("--command=\"SET client_min_messages = 'error';#{all_schemas_check_command}\" --db=#{db}") do |r| + expect(r.stdout).to match(%r{\(0 rows\)}) + expect(r.stderr).to eq('') + end + end + end +end diff --git a/spec/acceptance/server/deferred_pw_role_spec.rb b/spec/acceptance/server/deferred_pw_role_spec.rb new file mode 100644 index 0000000000..70cd6d031c --- /dev/null +++ b/spec/acceptance/server/deferred_pw_role_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql::server::role:' do + let(:user) { 'deferred_user_test' } + let(:password) { 'test_password' } + + let(:pp_one) do + <<-MANIFEST.unindent + $user = #{user} + $password = #{password} + + class { 'postgresql::server': } + $deferred_func = Deferred('new', [String, $password]) + + postgresql::server::role { $user: + password_hash => $deferred_func, + } + MANIFEST + end + + it 'creates a role with the password in the deferred function' do + if run_shell('puppet --version').stdout[0].to_i < 7 + skip # Deferred function fixes only in puppet 7, see https://tickets.puppetlabs.com/browse/PUP-11518 + end + apply_manifest(pp_one) + psql_cmd = "PGPASSWORD=#{password} PGUSER=#{user} psql -h 127.0.0.1 -d postgres -c '\\q'" + run_shell("cd /tmp; su #{shellescape('postgres')} -c #{shellescape(psql_cmd)}", + acceptable_exit_codes: [0]) + end +end diff --git a/spec/acceptance/server/grant_role_spec.rb b/spec/acceptance/server/grant_role_spec.rb new file mode 100644 index 0000000000..246328e23f --- /dev/null +++ b/spec/acceptance/server/grant_role_spec.rb @@ -0,0 +1,173 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql::server::grant_role:' do + let(:db) { 'grant_role_test' } + let(:user) { 'psql_grant_role_tester' } + let(:group) { 'test_group' } + let(:password) { 'psql_grant_role_pw' } + let(:pp_one) do + <<-MANIFEST.unindent + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + + class { 'postgresql::server': } + + # Since we are not testing pg_hba or any of that, make a local user for ident auth + user { $user: + ensure => present, + } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + + postgresql::server::database { $db: + owner => $user, + require => Postgresql::Server::Role[$user], + } + + # Create a rule for the user + postgresql::server::pg_hba_rule { "allow ${user}": + type => 'local', + database => $db, + user => $user, + auth_method => 'ident', + order => 1, + } + + # Create a role to grant to the user + postgresql::server::role { $group: + db => $db, + login => false, + require => Postgresql::Server::Database[$db], + } + + # Grant the role to the user + postgresql::server::grant_role { "grant_role ${group} to ${user}": + role => $user, + group => $group, + } + MANIFEST + end + let(:pp_two) do + <<-MANIFEST + $db = "#{db}" + $user = "#{user}" + $group = "#{group}" + $password = #{password} + + class { 'postgresql::server': } + + # Since we are not testing pg_hba or any of that, make a local user for ident auth + user { $user: + ensure => present, + } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + + postgresql::server::database { $db: + owner => $user, + require => Postgresql::Server::Role[$user], + } + + # Create a rule for the user + postgresql::server::pg_hba_rule { "allow ${user}": + type => 'local', + database => $db, + user => $user, + auth_method => 'ident', + order => 1, + } + + # Create a role to grant to the user + postgresql::server::role { $group: + db => $db, + login => false, + require => Postgresql::Server::Database[$db], + } + + # Grant the role to the user + postgresql::server::grant_role { "grant_role ${group} to ${user}": + role => $user, + group => $group, + } + + postgresql::server::grant_role {"revoke ${group} from ${user}": + ensure => absent, + role => $user, + group => $group, + } + MANIFEST + end + let(:pp_three) do + <<-MANIFEST + $db = "#{db}" + $user = "#{user}" + $group = "#{group}" + $password = #{password} + + class { 'postgresql::server': } + + # Since we are not testing pg_hba or any of that, make a local user for ident auth + user { $user: + ensure => absent, + } + + postgresql::server::database { $db: + } + + # Create a role to grant to the nonexistent user + postgresql::server::role { $group: + db => $db, + login => false, + require => Postgresql::Server::Database[$db], + } + + # Grant the role to the nonexistent user + postgresql::server::grant_role { "grant_role ${group} to ${user}": + role => $user + group => $group, + } + MANIFEST + end + + it 'grants a role to a user/superuser' do + idempotent_apply(pp_one) + + ## Check that the role was granted to the user + psql('--command="SELECT 1 WHERE pg_has_role(\'psql_grant_role_tester\', \'test_group\', \'MEMBER\') = true" grant_role_test', 'psql_grant_role_tester') do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + ## Check that the role was granted to the user + psql('--command="SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = \'test_group\' AND r_role.rolname = \'psql_grant_role_tester\'" grant_role_test', 'psql_grant_role_tester') do |r| # rubocop:disable Layout/LineLength + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + + it 'revokes a role from a user' do + apply_manifest(pp_two, catch_failures: true) + apply_manifest(pp_two, expect_changes: true) + + psql('--command="SELECT 1 WHERE pg_has_role(\'psql_grant_role_tester\', \'test_group\', \'MEMBER\') = true" grant_role_test', 'psql_grant_role_tester') do |r| + expect(r.stdout).to match(%r{\(0 rows\)}) + expect(r.stderr).to eq('') + end + end + + it 'does not grant permission to a nonexistent user' do + apply_manifest(pp_three, expect_failures: true) + + psql('--command="SELECT 1 WHERE pg_has_role(\'psql_grant_role_tester\', \'test_group\', \'MEMBER\') = true" grant_role_test', 'psql_grant_role_tester') do |r| + expect(r.stdout).to match(%r{\(0 rows\)}) + expect(r.stderr).to eq('') + end + end +end diff --git a/spec/acceptance/server/grant_spec.rb b/spec/acceptance/server/grant_spec.rb new file mode 100644 index 0000000000..51a4ac1416 --- /dev/null +++ b/spec/acceptance/server/grant_spec.rb @@ -0,0 +1,494 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql::server::grant:' do + let(:db) { 'grant_priv_test' } + let(:owner) { 'psql_grant_priv_owner' } + let(:user) { 'psql_grant_priv_tester' } + let(:password) { 'psql_grant_role_pw' } + let(:pp_setup) do + <<-MANIFEST.unindent + $db = #{db} + $owner = #{owner} + $user = #{user} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $owner: + password_hash => postgresql::postgresql_password($owner, $password), + } + + # Since we are not testing pg_hba or any of that, make a local user for ident auth + user { $owner: + ensure => present, + } + + postgresql::server::database { $db: + owner => $owner, + require => Postgresql::Server::Role[$owner], + } + + # Create a user to grant privileges to + postgresql::server::role { $user: + db => $db, + require => Postgresql::Server::Database[$db], + } + + # Make a local user for ident auth + user { $user: + ensure => present, + } + + # Grant them connect to the database + postgresql::server::database_grant { "allow connect for ${user}": + privilege => 'CONNECT', + db => $db, + role => $user, + } + MANIFEST + end + + context 'LANGUAGE' do + describe 'GRANT * ON LANGUAGE' do + # testing grants on language requires a superuser + let(:superuser) { 'postgres' } + let(:pp) do + pp_setup + <<-MANIFEST.unindent + postgresql_psql { 'make sure plpgsql exists': + command => 'CREATE LANGUAGE plpgsql', + db => $db, + psql_user => '#{superuser}', + unless => "SELECT 1 from pg_language where lanname = 'plpgsql'", + require => Postgresql::Server::Database[$db], + } + + postgresql::server::grant { 'grant usage on plpgsql': + psql_user => '#{superuser}', + privilege => 'USAGE', + object_type => 'LANGUAGE', + object_name => 'plpgsql', + role => $user, + db => $db, + require => [ Postgresql_psql['make sure plpgsql exists'], + Postgresql::Server::Role[$user], ], + onlyif_exists => true, + } + MANIFEST + end + + it 'is expected to run idempotently' do + idempotent_apply(pp) + end + + it 'is expected to GRANT USAGE ON LANGUAGE plpgsql to ROLE' do + ## Check that the privilege was granted to the user + psql("-d #{db} --command=\"SELECT 1 WHERE has_language_privilege('#{user}', 'plpgsql', 'USAGE')\"", superuser) do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end + end + + ### SEQUENCE grants + context 'sequence' do + let(:pp) do + pp_setup + <<-MANIFEST.unindent + postgresql_psql { 'create test sequence': + command => 'CREATE SEQUENCE test_seq', + db => $db, + psql_user => $owner, + unless => "SELECT 1 FROM information_schema.sequences WHERE sequence_name = 'test_seq'", + require => Postgresql::Server::Database[$db], + } + + postgresql::server::grant { 'grant usage on test_seq': + privilege => 'USAGE', + object_type => 'SEQUENCE', + object_name => 'test_seq', + db => $db, + role => $user, + require => [ Postgresql_psql['create test sequence'], + Postgresql::Server::Role[$user], ] + } + + postgresql::server::grant { 'grant update on test_seq': + privilege => 'UPDATE', + object_type => 'SEQUENCE', + object_name => 'test_seq', + db => $db, + role => $user, + require => [ Postgresql_psql['create test sequence'], + Postgresql::Server::Role[$user], ] + } + MANIFEST + end + + it 'grants usage/update on a sequence to a user' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.0') + idempotent_apply(pp) + + ## Check that the privilege was granted to the user + psql("-d #{db} --command=\"SELECT 1 WHERE has_sequence_privilege('#{user}', 'test_seq', 'USAGE')\"", user) do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + + ## Check that the privilege was granted to the user + psql("-d #{db} --command=\"SELECT 1 WHERE has_sequence_privilege('#{user}', 'test_seq', 'UPDATE')\"", user) do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end + end + + context 'all sequences' do + let(:pp) do + pp_setup + <<-MANIFEST.unindent + + postgresql_psql { 'create test sequences': + command => 'CREATE SEQUENCE test_seq2; CREATE SEQUENCE test_seq3;', + db => $db, + psql_user => $owner, + unless => "SELECT 1 FROM information_schema.sequences WHERE sequence_name = 'test_seq2'", + require => Postgresql::Server::Database[$db], + } + + postgresql::server::grant { 'grant usage on all sequences': + privilege => 'USAGE', + object_type => 'ALL SEQUENCES IN SCHEMA', + object_name => 'public', + db => $db, + role => $user, + require => [ Postgresql_psql['create test sequences'], + Postgresql::Server::Role[$user], ] + } + + postgresql::server::grant { 'grant update on all sequences': + privilege => 'UPDATE', + object_type => 'ALL SEQUENCES IN SCHEMA', + object_name => 'public', + db => $db, + role => $user, + require => [ Postgresql_psql['create test sequences'], + Postgresql::Server::Role[$user], ] + } + MANIFEST + end + + it 'grants usage on all sequences to a user' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.0') + idempotent_apply(pp) + + ## Check that the privileges were granted to the user, this check is not available on postgresql_version < 9.0 + psql("-d #{db} --command=\"SELECT 1 WHERE has_sequence_privilege('#{user}', 'test_seq2', 'USAGE') AND has_sequence_privilege('#{user}', 'test_seq3', 'USAGE')\"", user) do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + + ## Check that the privileges were granted to the user + psql("-d #{db} --command=\"SELECT 1 WHERE has_sequence_privilege('#{user}', 'test_seq2', 'UPDATE') AND has_sequence_privilege('#{user}', 'test_seq3', 'UPDATE')\"", user) do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end + end + + ### FUNCTION grants + context 'sequence' do + let(:pp) do + pp_setup + <<-MANIFEST.unindent + postgresql_psql { 'create test function': + command => "CREATE FUNCTION test_func() RETURNS boolean AS 'SELECT true' LANGUAGE 'sql'", + db => $db, + psql_user => $owner, + unless => "SELECT 1 FROM information_schema.routines WHERE routine_name = 'test_func'", + require => Postgresql::Server::Database[$db], + } + + postgresql::server::grant { 'grant execute on test_func': + privilege => 'EXECUTE', + object_type => 'FUNCTION', + object_name => 'test_func', + db => $db, + role => $user, + require => [ Postgresql_psql['create test function'], + Postgresql::Server::Role[$user], ] + } + + postgresql_psql { 'create test function with argument': + command => "CREATE FUNCTION test_func_with_arg(val integer) RETURNS integer AS 'SELECT val + 1' LANGUAGE 'sql'", + db => $db, + psql_user => $owner, + unless => "SELECT 1 FROM (SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes)) as func_with_args FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid) WHERE ns.nspname not in ('pg_catalog', 'information_schema')) as funclist WHERE func_with_args='public.test_func_with_arg(integer)'", + require => Postgresql::Server::Database[$db], + } + + postgresql::server::grant { 'grant execute on test_func_with_arg': + privilege => 'EXECUTE', + object_type => 'FUNCTION', + object_name => 'test_func_with_arg', + object_arguments => ['integer'], + db => $db, + role => $user, + require => [ Postgresql_psql['create test function with argument'], + Postgresql::Server::Role[$user], ] + } + MANIFEST + end + + it 'grants execute on a function to a user' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.0') + idempotent_apply(pp) + + ## Check that the privilege was granted to the user + psql("-d #{db} --command=\"SELECT 1 WHERE has_function_privilege('#{user}', 'test_func()', 'EXECUTE')\"", user) do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end + + it 'grants execute on a function with argument to a user' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.0') + idempotent_apply(pp) + + ## Check that the privilege was granted to the user + psql("-d #{db} --command=\"SELECT 1 WHERE has_function_privilege('#{user}', 'test_func_with_arg(integer)', 'EXECUTE')\"", user) do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end + end + + ### TABLE grants + context 'table' do + describe 'GRANT ... ON TABLE' do + let(:pp_create_table) do + pp_setup + <<-EOS.unindent + postgresql_psql { 'create test table': + command => 'CREATE TABLE test_tbl (col1 integer)', + db => $db, + psql_user => $owner, + unless => "SELECT table_name FROM information_schema.tables WHERE table_name = 'test_tbl'", + require => Postgresql::Server::Database[$db], + } + postgresql_psql { 'create test table 2': + command => 'CREATE TABLE test_tbl2 (col1 integer)', + db => $db, + psql_user => $owner, + unless => "SELECT table_name FROM information_schema.tables WHERE table_name = 'test_tbl2'", + require => Postgresql::Server::Database[$db], + } + postgresql_psql { "grant all on table test_tbl2 to ${user}": + command => "GRANT ALL ON TABLE test_tbl2 TO ${user}", + db => $db, + psql_user => $owner, + unless => "SELECT 1 FROM information_schema.role_table_grants WHERE table_name = 'test_tbl2' AND grantee = '${user}' HAVING count(*)>=7", + require => [ Postgresql::Server::Database[$db], Postgresql_psql['create test table 2'], Postgresql::Server::Role[$user] ], + } + EOS + end + + it 'grant select on a table to a user' do + pp_grant = pp_setup + <<-EOS.unindent + + postgresql::server::grant { 'grant select on test_tbl': + privilege => 'SELECT', + object_type => 'TABLE', + object_name => 'test_tbl', + db => $db, + role => $user, + require => [ Postgresql::Server::Role[$user] ], + } + + postgresql::server::table_grant { 'INSERT priviledge to table': + privilege => 'INSERT', + table => 'test_tbl', + db => $db, + role => $user, + require => [ Postgresql::Server::Role[$user] ], + } + EOS + + pp_revoke = pp_setup + <<-EOS.unindent + + postgresql::server::grant { 'revoke select on test_tbl': + ensure => absent, + privilege => 'SELECT', + object_type => 'TABLE', + object_name => 'test_tbl', + db => $db, + role => $user, + require => [ Postgresql::Server::Role[$user] ], + } + + postgresql::server::table_grant { 'INSERT priviledge to table': + ensure => absent, + privilege => 'INSERT', + table => 'test_tbl', + db => $db, + role => $user, + require => [ Postgresql::Server::Role[$user] ], + } + EOS + + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.0') + idempotent_apply(pp_create_table) + idempotent_apply(pp_grant) + + ## Check that the SELECT privilege was granted to the user + psql("-d #{db} --tuples-only --command=\"SELECT * FROM has_table_privilege('#{user}', 'test_tbl', 'SELECT')\"", user) do |r| + expect(r.stdout).to match(%r{t}) + expect(r.stderr).to eq('') + end + + ## Check that the INSERT privilege was granted to the user + psql("-d #{db} --tuples-only --command=\"SELECT * FROM has_table_privilege('#{user}', 'test_tbl', 'INSERT')\"", user) do |r| + expect(r.stdout).to match(%r{t}) + end + + idempotent_apply(pp_create_table) + idempotent_apply(pp_revoke) + + ## Check that the SELECT privilege was revoked from the user + psql("-d #{db} --tuples-only --command=\"SELECT * FROM has_table_privilege('#{user}', 'test_tbl', 'SELECT')\"", user) do |r| + expect(r.stdout).to match(%r{f}) + expect(r.stderr).to eq('') + end + end + end + + it 'grant update on all tables to a user' do + pp_grant = pp_setup + <<-EOS.unindent + + postgresql::server::grant { 'grant update on all tables': + privilege => 'UPDATE', + object_type => 'ALL TABLES IN SCHEMA', + object_name => 'public', + db => $db, + role => $user, + require => [ Postgresql::Server::Role[$user] ], + } + EOS + + pp_revoke = pp_setup + <<-EOS.unindent + + postgresql::server::grant { 'revoke update on all tables': + ensure => absent, + privilege => 'UPDATE', + object_type => 'ALL TABLES IN SCHEMA', + object_name => 'public', + db => $db, + role => $user, + require => [ Postgresql::Server::Role[$user] ], + } + EOS + + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.0') + ## pp_create_table sets up the permissions that pp_grant 'fixes', so these to steps cannot be rolled into one + idempotent_apply(pp_create_table) + idempotent_apply(pp_grant) + + ## Check that all privileges were granted to the user + psql("-d #{db} --command=\"SELECT table_name,privilege_type FROM information_schema.role_table_grants + WHERE grantee = '#{user}' AND table_schema = 'public' AND privilege_type='UPDATE'\"", user) do |r| + expect(r.stdout).to match(%r{test_tbl[ |]*UPDATE}) + expect(r.stdout).to match(%r{test_tbl2[ |]*UPDATE}) + expect(r.stdout).to match(%r{\(2 rows\)}) + expect(r.stderr).to eq('') + end + + ## idempotent_apply(pp_create_table) + idempotent_apply(pp_revoke) + + ## Check that all privileges were revoked from the user + psql("-d #{db} --command=\"SELECT table_name,privilege_type FROM information_schema.role_table_grants + WHERE grantee = '#{user}' AND table_schema = 'public' AND privilege_type='UPDATE'\"", user) do |r| + expect(r.stdout).to match(%r{\(0 rows\)}) + expect(r.stderr).to eq('') + end + end + end + + it 'grant all on all tables to a user' do + pp_grant = pp_setup + <<-EOS.unindent + + postgresql::server::grant { 'grant all on all tables': + privilege => 'ALL', + object_type => 'ALL TABLES IN SCHEMA', + object_name => 'public', + db => $db, + role => $user, + require => [ Postgresql::Server::Role[$user] ], + } + EOS + + pp_revoke = pp_setup + <<-EOS.unindent + + postgresql::server::grant { 'revoke all on all tables': + ensure => absent, + privilege => 'ALL', + object_type => 'ALL TABLES IN SCHEMA', + object_name => 'public', + db => $db, + role => $user, + require => [ Postgresql::Server::Role[$user] ], + } + EOS + + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.0') + ## pp_create_table sets up the permissions that pp_grant 'fixes', so these to steps cannot be rolled into one + idempotent_apply(pp_create_table) + idempotent_apply(pp_grant) + + ## Check that all privileges were granted to the user + psql("-d #{db} --tuples-only --command=\"SELECT table_name,count(privilege_type) FROM information_schema.role_table_grants + WHERE grantee = '#{user}' AND table_schema = 'public' + AND privilege_type IN ('SELECT','UPDATE','INSERT','DELETE','TRIGGER','REFERENCES','TRUNCATE') + GROUP BY table_name\"", user) do |r| + expect(r.stdout).to match(%r{test_tbl[ |]*7$}) + expect(r.stdout).to match(%r{test_tbl2[ |]*7$}) + expect(r.stderr).to eq('') + end + + ## idempotent_apply(pp_create_table) + idempotent_apply(pp_revoke) + + ## Check that all privileges were revoked from the user + psql("-d #{db} --command=\"SELECT table_name FROM information_schema.role_table_grants + WHERE grantee = '#{user}' AND table_schema = 'public'\"", user) do |r| + expect(r.stdout).to match(%r{\(0 rows\)}) + expect(r.stderr).to eq('') + end + end + end + end + end + + context 'database' do + describe 'REVOKE ... ON DATABASE...' do + it 'do not fail on revoke connect from non-existant user' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.1.24') + apply_manifest(pp_setup, catch_failures: true) + pp = pp_setup + <<-EOS.unindent + postgresql::server::grant { 'revoke connect on db from norole': + ensure => absent, + privilege => 'CONNECT', + object_type => 'DATABASE', + db => '#{db}', + role => '#{user}_does_not_exist', + } + EOS + idempotent_apply(pp) + end + end + end + end + ##################### +end diff --git a/spec/acceptance/server/reassign_owned_by_spec.rb b/spec/acceptance/server/reassign_owned_by_spec.rb new file mode 100644 index 0000000000..4cbd3a49c1 --- /dev/null +++ b/spec/acceptance/server/reassign_owned_by_spec.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql::server::reassign_owned_by:' do + let(:db) { 'reassign_test' } + let(:old_owner) { 'psql_reassign_old_owner' } + let(:new_owner) { 'psql_reassign_new_owner' } + let(:password) { 'psql_reassign_pw' } + let(:superuser) { 'postgres' } + + let(:pp_setup) do + <<-MANIFEST.unindent + $db = #{db} + $old_owner = #{old_owner} + $new_owner = #{new_owner} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $old_owner: + password_hash => postgresql::postgresql_password($old_owner, $password), + } + + # Since we are not testing pg_hba or any of that, make a local user for ident auth + user { $old_owner: + ensure => present, + } + + # Create a user to reassign ownership to + postgresql::server::role { $new_owner: + db => $db, + require => Postgresql::Server::Database[$db], + } + + # Make a local user for ident auth + user { $new_owner: + ensure => present, + } + + # Grant the new owner membership of the old owner (must have both for REASSIGN OWNED BY to work) + postgresql::server::grant_role { "grant_role to ${new_owner}": + role => $new_owner, + group => $old_owner, + } + + # Grant them connect to the database + postgresql::server::database_grant { "allow connect for ${old_owner}": + privilege => 'CONNECT', + db => $db, + role => $old_owner, + } + MANIFEST + end + + let(:pp_db_old_owner) do + <<-MANIFEST.unindent + postgresql::server::database { $db: + owner => $old_owner, + require => Postgresql::Server::Role[$old_owner], + } + MANIFEST + end + + let(:pp_db_no_owner) do + <<-MANIFEST.unindent + postgresql::server::database { $db: + } + MANIFEST + end + + context 'reassign_owned_by' do + describe 'REASSIGN OWNED BY tests' do + let(:db) { 'reassign_test' } + let(:old_owner) { 'psql_reassign_old_owner' } + let(:new_owner) { 'psql_reassign_new_owner' } + + let(:pp_setup_objects) do + <<-MANIFEST.unindent + postgresql_psql { 'create test table': + command => 'CREATE TABLE test_tbl (col1 integer)', + db => '#{db}', + psql_user => '#{old_owner}', + unless => "SELECT tablename FROM pg_catalog.pg_tables WHERE tablename = 'test_tbl'", + require => Postgresql::Server::Database['#{db}'], + } + postgresql_psql { 'create test sequence': + command => 'CREATE SEQUENCE test_seq', + db => '#{db}', + psql_user => '#{old_owner}', + unless => "SELECT relname FROM pg_catalog.pg_class WHERE relkind='S' AND relname = 'test_seq'", + require => [ Postgresql_psql['create test table'], Postgresql::Server::Database['#{db}'] ], + } + MANIFEST + end + let(:pp_reassign_owned_by) do + <<-MANIFEST.unindent + postgresql::server::reassign_owned_by { 'test reassign to new_owner': + db => '#{db}', + old_role => '#{old_owner}', + new_role => '#{new_owner}', + psql_user => '#{new_owner}', + } + MANIFEST + end + + it 'reassigns all objects to new_owner' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.0') + apply_manifest(pp_setup + pp_db_old_owner + pp_setup_objects, catch_failures: true) + + idempotent_apply(pp_setup + pp_db_no_owner + pp_reassign_owned_by) + + ## Check that the ownership was transferred + psql("-d #{db} --tuples-only --no-align --command=\"SELECT tablename,tableowner FROM pg_catalog.pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema')\"", superuser) do |r| + expect(r.stdout).to match(%r{test_tbl.#{new_owner}}) + expect(r.stderr).to eq('') + end + psql("-d #{db} --tuples-only --no-align --command=\"SELECT relname,pg_get_userbyid(relowner) FROM pg_catalog.pg_class c WHERE relkind='S'\"", superuser) do |r| + expect(r.stdout).to match(%r{test_seq.#{new_owner}}) + expect(r.stderr).to eq('') + end + if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.3') + psql("-d #{db} --tuples-only --no-align --command=\"SELECT pg_get_userbyid(datdba) FROM pg_database WHERE datname = current_database()\"", superuser) do |r| + expect(r.stdout).to match(%r{#{new_owner}}) + expect(r.stderr).to eq('') + end + end + end + end + end + end + ##################### +end diff --git a/spec/acceptance/server/recovery_spec.rb b/spec/acceptance/server/recovery_spec.rb index b27a5c5afb..1c68332a5a 100644 --- a/spec/acceptance/server/recovery_spec.rb +++ b/spec/acceptance/server/recovery_spec.rb @@ -1,56 +1,60 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' -describe 'postgresql::server::recovery', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do +describe 'postgresql::server::recovery', skip: 'IAC-1286' do describe 'should manage recovery' do + before(:all) do + pre_run + end + after(:all) do - pp = <<-EOS.unindent + pp = <<-MANIFEST.unindent file { '/tmp/recovery.conf': ensure => absent, } - EOS + MANIFEST - apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, catch_failures: true) end - it 'adds conf file' do - pp = <<-EOS.unindent - class { 'postgresql::globals': - recovery_conf_path => '/tmp/recovery.conf', - manage_recovery_conf => true, - } - - class { 'postgresql::server': } + pp = <<-MANIFEST.unindent + class { 'postgresql::globals': + recovery_conf_path => '/tmp/recovery.conf', + manage_recovery_conf => true, + } - # Create a recovery.conf file - postgresql::server::recovery { "recovery.conf": - restore_command => 'restore_command', - recovery_target_timeline => 'recovery_target_timeline', - } - EOS + class { 'postgresql::server': } - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) + # Create a recovery.conf file + postgresql::server::recovery { "recovery.conf": + restore_command => 'restore_command', + recovery_target_timeline => 'recovery_target_timeline', + } + MANIFEST + it 'adds conf file' do + idempotent_apply(pp) end describe file('/tmp/recovery.conf') do it { is_expected.to be_file } - it { is_expected.to contain /restore_command = 'restore_command'/ } - it { is_expected.to contain /recovery_target_timeline = 'recovery_target_timeline'/ } + it { is_expected.to contain %r{restore_command = 'restore_command'} } + it { is_expected.to contain %r{recovery_target_timeline = 'recovery_target_timeline'} } end end - describe 'should not manage recovery' do + describe 'should not create recovery if recovery config not specified' do it 'does not add conf file' do pp = <<-EOS.unindent class { 'postgresql::globals': - manage_recovery_conf => false, + recovery_conf_path => '/tmp/recovery.conf', + manage_recovery_conf => true, } class { 'postgresql::server': } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) + idempotent_apply(pp) end describe file('/tmp/recovery.conf') do @@ -58,4 +62,3 @@ class { 'postgresql::server': } end end end - diff --git a/spec/acceptance/server/role_spec.rb b/spec/acceptance/server/role_spec.rb new file mode 100644 index 0000000000..8050653951 --- /dev/null +++ b/spec/acceptance/server/role_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'postgresql::server::role' do + let(:user) { 'foo' } + let(:password) { 'bar' } + + it 'with different DBVERSION in connect_settings' do + pp_role = <<-MANIFEST + $user = '#{user}' + $password = '#{password}' + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => $password, + connect_settings => { + 'DBVERSION' => '13', + }, + } + MANIFEST + + if Gem::Version.new(postgresql_version) >= Gem::Version.new('14') + idempotent_apply(pp_role) + + # verify that password_encryption selectio is based on 'DBVERSION' and not on postgresql::serverglobals::version + psql("--command=\"SELECT 1 FROM pg_shadow WHERE usename = '#{user}' AND passwd = 'md596948aad3fcae80c08a35c9b5958cd89'\"") do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end +end diff --git a/spec/acceptance/server/schema_spec.rb b/spec/acceptance/server/schema_spec.rb index 065ec63607..250ffeca81 100644 --- a/spec/acceptance/server/schema_spec.rb +++ b/spec/acceptance/server/schema_spec.rb @@ -1,56 +1,56 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' -describe 'postgresql::server::schema:', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do - it 'should create a schema for a user' do - begin - pp = <<-EOS.unindent - $db = 'schema_test' - $user = 'psql_schema_tester' - $password = 'psql_schema_pw' - - class { 'postgresql::server': } - - # Since we are not testing pg_hba or any of that, make a local user for ident auth - user { $user: - ensure => present, - } - - postgresql::server::role { $user: - password_hash => postgresql_password($user, $password), - } - - postgresql::server::database { $db: - owner => $user, - require => Postgresql::Server::Role[$user], - } - - # Create a rule for the user - postgresql::server::pg_hba_rule { "allow ${user}": - type => 'local', - database => $db, - user => $user, - auth_method => 'ident', - order => 1, - } - - postgresql::server::schema { $user: - db => $db, - owner => $user, - require => Postgresql::Server::Database[$db], - } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - - ## Check that the user can create a table in the database - psql('--command="create table psql_schema_tester.foo (foo int)" schema_test', 'psql_schema_tester') do |r| - expect(r.stdout).to match(/CREATE TABLE/) - expect(r.stderr).to eq('') - end - ensure - psql('--command="drop table psql_schema_tester.foo" schema_test', 'psql_schema_tester') - end +describe 'postgresql::server::schema:' do + let(:pp) do + <<-MANIFEST.unindent + $db = 'schema_test' + $user = 'psql_schema_tester' + $password = 'psql_schema_pw' + + class { 'postgresql::server': } + + # Since we are not testing pg_hba or any of that, make a local user for ident auth + user { $user: + ensure => present, + } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + + postgresql::server::database { $db: + owner => $user, + require => Postgresql::Server::Role[$user], + } + + # Create a rule for the user + postgresql::server::pg_hba_rule { "allow ${user}": + type => 'local', + database => $db, + user => $user, + auth_method => 'ident', + order => 1, + } + + postgresql::server::schema { $user: + db => $db, + owner => $user, + require => Postgresql::Server::Database[$db], + } + MANIFEST end + it 'creates a schema for a user' do + idempotent_apply(pp) + + ## Check that the user can create a table in the database + psql('--command="create table psql_schema_tester.foo (foo int)" schema_test', 'psql_schema_tester') do |r| + expect(r.stdout).to match(%r{CREATE TABLE}) + expect(r.stderr).to eq('') + end + ensure + psql('--command="drop table psql_schema_tester.foo" schema_test', 'psql_schema_tester') + end end diff --git a/spec/acceptance/server_instance_spec.rb b/spec/acceptance/server_instance_spec.rb new file mode 100644 index 0000000000..4b8d6a4bb8 --- /dev/null +++ b/spec/acceptance/server_instance_spec.rb @@ -0,0 +1,161 @@ +# frozen_string_literal: true + +# run a test task +require 'spec_helper_acceptance' + +describe 'postgresql instance test1', if: os[:family] == 'redhat' && !os[:release].start_with?('7') do + pp = <<-MANIFEST + # set global defaults + class { 'postgresql::globals': + encoding => 'UTF-8', + locale => 'en_US.UTF-8', + manage_package_repo => false, + manage_dnf_module => true, + needs_initdb => true, + version => '16', + } + # stop default main instance + class { 'postgresql::server': + service_ensure => 'stopped', + service_enable => false, + } + # define instance test1 + postgresql::server_instance { 'test1': + instance_user => 'ins_test1', + instance_group => 'ins_test1', + instance_directories => { + '/opt/pgsql' => { 'ensure' => 'directory' }, + '/opt/pgsql/backup' => { 'ensure' => 'directory' }, + '/opt/pgsql/data' => { 'ensure' => 'directory' }, + '/opt/pgsql/data/13' => { 'ensure' => 'directory' }, + '/opt/pgsql/data/home' => { 'ensure' => 'directory' }, + '/opt/pgsql/wal' => { 'ensure' => 'directory' }, + '/opt/pgsql/log' => { 'ensure' => 'directory' }, + '/opt/pgsql/log/13' => { 'ensure' => 'directory' }, + '/opt/pgsql/log/13/test1' => { 'ensure' => 'directory' }, + }, + config_settings => { + 'pg_hba_conf_path' => '/opt/pgsql/data/13/test1/pg_hba.conf', + 'postgresql_conf_path' => '/opt/pgsql/data/13/test1/postgresql.conf', + 'pg_ident_conf_path' => '/opt/pgsql/data/13/test1/pg_ident.conf', + 'datadir' => '/opt/pgsql/data/13/test1', + 'service_name' => 'postgresql@13-test1', + 'port' => 5433, + 'pg_hba_conf_defaults' => false, + 'manage_selinux' => true, + }, + service_settings => { + 'service_name' => 'postgresql@13-test1', + 'service_status' => 'systemctl status postgresql@13-test1.service', + 'service_ensure' => 'running', + 'service_enable' => true, + }, + initdb_settings => { + 'auth_local' => 'peer', + 'auth_host' => 'md5', + 'needs_initdb' => true, + 'datadir' => '/opt/pgsql/data/13/test1', + 'encoding' => 'UTF-8', + 'lc_messages' => 'en_US.UTF8', + 'locale' => 'en_US.UTF8', + 'data_checksums' => false, + 'group' => 'postgres', + 'user' => 'postgres', + 'username' => 'ins_test1', + }, + config_entries => { + 'authentication_timeout' => { + 'value' => '1min', + 'comment' => 'a test', + }, + 'log_statement_stats' => { 'value' => 'off' }, + 'autovacuum_vacuum_scale_factor' => { 'value' => 0.3 }, + }, + databases => { + 'testdb1' => { + 'encoding' => 'UTF8', + 'locale' => 'en_US.UTF8', + 'owner' => 'dba_test1', + }, + 'testdb2' => { + 'encoding' => 'UTF8', + 'locale' => 'en_US.UTF8', + 'owner' => 'dba_test1', + }, + }, + roles => { + 'ins_test1' => { + 'superuser' => true, + 'login' => true, + }, + 'dba_test1' => { + 'createdb' => true, + 'login' => true, + }, + 'app_test1' => { 'login' => true }, + 'rep_test1' => { + 'replication' => true, + 'login' => true, + }, + 'rou_test1' => { 'login' => true }, + }, + pg_hba_rules => { + 'local all INSTANCE user' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'ins_test1', + 'auth_method' => 'peer', + 'order' => 1, + }, + 'local all DB user' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'dba_test1', + 'auth_method' => 'peer', + 'order' => 2, + }, + 'local all APP user' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'app_test1', + 'auth_method' => 'peer', + 'order' => 3, + }, + 'local all READONLY user' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'rou_test1', + 'auth_method' => 'peer', + 'order' => 4, + }, + 'remote all INSTANCE user PGADMIN server' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'ins_test1', + 'address' => '192.168.22.131/32', + 'auth_method' => 'md5', + 'order' => 5, + }, + 'local replication INSTANCE user' => { + 'type' => 'local', + 'database' => 'replication', + 'user' => 'ins_test1', + 'auth_method' => 'peer', + 'order' => 6, + }, + 'local replication REPLICATION user' => { + 'type' => 'local', + 'database' => 'replication', + 'user' => 'rep_test1', + 'auth_method' => 'peer', + 'order' => 7, + }, + }, + } + MANIFEST + + it 'installs postgres instance test1' do + export_locales('en_US.UTF-8 ') + idempotent_apply(pp) + end +end diff --git a/spec/acceptance/sql_task_spec.rb b/spec/acceptance/sql_task_spec.rb new file mode 100644 index 0000000000..571ec35768 --- /dev/null +++ b/spec/acceptance/sql_task_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# run a test task +require 'spec_helper_acceptance' + +describe 'postgresql task' do + describe 'sql task' do + pp = <<-MANIFEST + class { 'postgresql::server': } -> + postgresql::server::db { 'spec1': + user => 'root1', + password => postgresql::postgresql_password('root1', 'password'), + } + MANIFEST + + it 'sets up a postgres db' do + export_locales('en_US.UTF-8 ') + apply_manifest(pp, catch_failures: true) + end + + it 'execute some sql' do + # equates to 'psql -c "SELECT table_name FROM information_schema.tables WHERE table_schema = 'information_schema';" --password --host localhost --dbname=spec1 --username root1' + result = run_bolt_task('postgresql::sql', 'sql' => 'SELECT count(table_name) FROM information_schema.tables;', 'host' => 'localhost', + 'user' => 'root1', 'password' => 'password', 'database' => 'spec1') + expect(result.stdout).to contain(%r{(1 row)}) + end + end +end diff --git a/spec/acceptance/z_alternative_pgdata_spec.rb b/spec/acceptance/z_alternative_pgdata_spec.rb index 29f09a0898..7c717c4344 100644 --- a/spec/acceptance/z_alternative_pgdata_spec.rb +++ b/spec/acceptance/z_alternative_pgdata_spec.rb @@ -1,34 +1,33 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' # These tests ensure that postgres can change itself to an alternative pgdata # location properly. -# Allow postgresql to use /tmp/* as a datadir -if fact('osfamily') == 'RedHat' and fact('selinux') == 'true' - shell 'setenforce 0' -end +describe 'postgresql::server', skip: 'IAC-1286' do + before(:each) do + skip "These test's currently do not work on SLES/Suse modules" if os[:family] == 'sles' + end -describe 'postgres::server', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do it 'on an alternative pgdata location' do - pp = <<-EOS + pp = <<-MAIFEST #file { '/var/lib/pgsql': ensure => directory, } -> # needs_initdb will be true by default for all OS's except Debian # in order to change the datadir we need to tell it explicitly to call initdb class { 'postgresql::server': datadir => '/tmp/data', needs_initdb => true } - EOS + MAIFEST - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) + idempotent_apply(pp) end describe file('/tmp/data') do - it { should be_directory } + it { is_expected.to be_directory } end it 'can connect with psql' do psql('--command="\l" postgres', 'postgres') do |r| - expect(r.stdout).to match(/List of databases/) + expect(r.stdout).to match(%r{List of databases}) end end - end diff --git a/spec/classes/client_spec.rb b/spec/classes/client_spec.rb new file mode 100644 index 0000000000..55fee3ed54 --- /dev/null +++ b/spec/classes/client_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::client' do + include_examples 'Debian 11' + + describe 'with parameters' do + let :params do + { + validcon_script_path: '/opt/bin/my-validate-con.sh', + package_ensure: 'absent', + package_name: 'mypackage', + file_ensure: 'file' + } + end + + it 'modifies package' do + expect(subject).to contain_package('postgresql-client').with(ensure: 'absent', + name: 'mypackage', + tag: 'puppetlabs-postgresql') + end + + it 'has specified validate connexion' do + expect(subject).to contain_file('/opt/bin/my-validate-con.sh').with(ensure: 'file', + owner: 0, + group: 0, + mode: '0755') + end + end + + describe 'with no parameters' do + it 'creates package with postgresql tag' do + expect(subject).to contain_package('postgresql-client').with(tag: 'puppetlabs-postgresql') + end + end + + describe 'with manage_dnf_module true' do + let(:pre_condition) do + <<-PUPPET + class { 'postgresql::globals': + manage_dnf_module => true, + } + PUPPET + end + + it { is_expected.to contain_package('postgresql dnf module').that_comes_before('Package[postgresql-client]') } + end + + describe 'with client package name explicitly set undef' do + let :params do + { + package_name: 'UNSET' + } + end + + it 'does not manage postgresql-client package' do + expect(subject).not_to contain_package('postgresql-client') + end + end +end diff --git a/spec/classes/globals_spec.rb b/spec/classes/globals_spec.rb new file mode 100644 index 0000000000..3a6f021ba3 --- /dev/null +++ b/spec/classes/globals_spec.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::globals' do + context 'on a debian 11' do + include_examples 'Debian 11' + + describe 'with no parameters' do + it 'executes successfully' do + expect(subject).to contain_class('postgresql::globals') + end + end + + describe 'manage_package_repo => true' do + let(:params) do + { + manage_package_repo: true + } + end + + it 'pulls in class postgresql::repo' do + expect(subject).to contain_class('postgresql::repo') + end + end + end + + context 'on redhat 7' do + include_examples 'RedHat 7' + + describe 'with no parameters' do + it 'executes successfully' do + expect(subject).to contain_class('postgresql::globals') + end + end + + describe 'manage_package_repo on RHEL => true' do + let(:params) do + { + manage_package_repo: true, + repo_proxy: 'http://proxy-server:8080' + } + end + + it 'pulls in class postgresql::repo' do + expect(subject).to contain_class('postgresql::repo') + end + + it do + expect(subject).to contain_yumrepo('yum.postgresql.org').with( + 'enabled' => '1', + 'proxy' => 'http://proxy-server:8080', + ) + expect(subject).to contain_yumrepo('pgdg-common').with( + 'enabled' => '1', + 'proxy' => 'http://proxy-server:8080', + ) + end + end + + describe 'repo_baseurl on RHEL => mirror.localrepo.com' do + let(:params) do + { + manage_package_repo: true, + repo_baseurl: 'http://mirror.localrepo.com/pgdg-postgresql', + yum_repo_commonurl: 'http://mirror.localrepo.com/pgdg-common' + } + end + + it 'pulls in class postgresql::repo' do + expect(subject).to contain_class('postgresql::repo') + end + + it do + expect(subject).to contain_yumrepo('yum.postgresql.org').with( + 'enabled' => '1', + 'baseurl' => 'http://mirror.localrepo.com/pgdg-postgresql', + ) + expect(subject).to contain_yumrepo('pgdg-common').with( + 'enabled' => '1', + 'baseurl' => 'http://mirror.localrepo.com/pgdg-common', + ) + end + end + end +end diff --git a/spec/classes/lib/devel_spec.rb b/spec/classes/lib/devel_spec.rb new file mode 100644 index 0000000000..bbc4098dac --- /dev/null +++ b/spec/classes/lib/devel_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::lib::devel' do + include_examples 'Debian 11' + + it { is_expected.to contain_class('postgresql::lib::devel') } + + describe 'link pg_config to /usr/bin' do + it { + expect(subject).not_to contain_file('/usr/bin/pg_config') \ + .with_ensure('link') \ + .with_target('/usr/lib/postgresql/13/bin/pg_config') + } + end + + describe 'disable link_pg_config' do + let(:params) do + { + link_pg_config: false + } + end + + it { is_expected.not_to contain_file('/usr/bin/pg_config') } + end + + describe 'should not link pg_config on RedHat with default version' do + include_examples 'RedHat 8' + + it { is_expected.not_to contain_file('/usr/bin/pg_config') } + end + + describe 'link pg_config on RedHat with non-default version' do + include_examples 'RedHat 8' + let :pre_condition do + "class { '::postgresql::globals': version => '9.3' }" + end + + it { + expect(subject).to contain_file('/usr/bin/pg_config') \ + .with_ensure('link') \ + .with_target('/usr/pgsql-9.3/bin/pg_config') + } + end + + describe 'on Gentoo' do + include_examples 'Gentoo' + let :params do + { + link_pg_config: false + } + end + + it 'fails to compile' do + expect(subject).to compile.and_raise_error(%r{is not supported}) + end + end +end diff --git a/spec/classes/lib/java_spec.rb b/spec/classes/lib/java_spec.rb new file mode 100644 index 0000000000..dff666d4ad --- /dev/null +++ b/spec/classes/lib/java_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::lib::java' do + describe 'on a debian based os' do + include_examples 'Debian 11' + + it { + expect(subject).to contain_package('postgresql-jdbc').with( + name: 'libpostgresql-jdbc-java', + ensure: 'present', + tag: 'puppetlabs-postgresql', + ) + } + end + + describe 'on a redhat based os' do + include_examples 'RedHat 8' + + it { + expect(subject).to contain_package('postgresql-jdbc').with( + name: 'postgresql-jdbc', + ensure: 'present', + tag: 'puppetlabs-postgresql', + ) + } + + describe 'when parameters are supplied' do + let :params do + { package_ensure: 'latest', package_name: 'somepackage' } + end + + it { + expect(subject).to contain_package('postgresql-jdbc').with( + name: 'somepackage', + ensure: 'latest', + tag: 'puppetlabs-postgresql', + ) + } + end + end +end diff --git a/spec/classes/lib/perl_spec.rb b/spec/classes/lib/perl_spec.rb new file mode 100644 index 0000000000..1dab09759f --- /dev/null +++ b/spec/classes/lib/perl_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::lib::perl' do + describe 'on redhat 8' do + include_examples 'RedHat 8' + + it { + expect(subject).to contain_package('perl-DBD-Pg').with( + name: 'perl-DBD-Pg', + ensure: 'present', + ) + } + end + + describe 'on debian 11' do + include_examples 'Debian 11' + + it { + expect(subject).to contain_package('perl-DBD-Pg').with( + name: 'libdbd-pg-perl', + ensure: 'present', + ) + } + end +end diff --git a/spec/classes/lib/pgdocs_spec.rb b/spec/classes/lib/pgdocs_spec.rb new file mode 100644 index 0000000000..733322d0e9 --- /dev/null +++ b/spec/classes/lib/pgdocs_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::lib::docs' do + describe 'on a redhat based os' do + include_examples 'RedHat 8' + + it { + expect(subject).to contain_package('postgresql-docs').with( + name: 'postgresql-docs', + ensure: 'present', + tag: 'puppetlabs-postgresql', + ) + } + + describe 'when parameters are supplied' do + let :params do + { package_ensure: 'latest', package_name: 'somepackage' } + end + + it { + expect(subject).to contain_package('postgresql-docs').with( + name: 'somepackage', + ensure: 'latest', + tag: 'puppetlabs-postgresql', + ) + } + end + end +end diff --git a/spec/classes/lib/python_spec.rb b/spec/classes/lib/python_spec.rb new file mode 100644 index 0000000000..64e426ca39 --- /dev/null +++ b/spec/classes/lib/python_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::lib::python' do + describe 'on redhat 7' do + include_examples 'RedHat 7' + + it { + expect(subject).to contain_package('python-psycopg2').with( + name: 'python-psycopg2', + ensure: 'present', + ) + } + end + + describe 'on redhat 8' do + include_examples 'RedHat 8' + + it { + expect(subject).to contain_package('python-psycopg2').with( + name: 'python3-psycopg2', + ensure: 'present', + ) + } + end + + describe 'on debian 11' do + include_examples 'Debian 11' + + it { + expect(subject).to contain_package('python-psycopg2').with( + name: 'python3-psycopg2', + ensure: 'present', + ) + } + end + + describe 'on debian 12' do + include_examples 'Debian 12' + + it { + expect(subject).to contain_package('python-psycopg2').with( + name: 'python3-psycopg2', + ensure: 'present', + ) + } + end +end diff --git a/spec/classes/params_spec.rb b/spec/classes/params_spec.rb new file mode 100644 index 0000000000..8fc61e3e34 --- /dev/null +++ b/spec/classes/params_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::params' do + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) { os_facts } + + it { is_expected.to contain_class('postgresql::params') } + end + end +end diff --git a/spec/classes/repo_spec.rb b/spec/classes/repo_spec.rb new file mode 100644 index 0000000000..0414501a72 --- /dev/null +++ b/spec/classes/repo_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::repo' do + include_examples 'Debian 11' + + describe 'with no parameters' do + it 'instantiates apt_postgresql_org class' do + expect(subject).to contain_class('postgresql::repo::apt_postgresql_org') + end + + it { + is_expected.to contain_apt__source('apt.postgresql.org') + .with_location('https://apt.postgresql.org/pub/repos/apt/') + .with_release("#{facts[:os]['distro']['codename']}-pgdg") + } + + it { is_expected.to contain_apt__pin('apt_postgresql_org') } + end + + describe 'with custom baseurl and release' do + let(:params) do + { + baseurl: 'https://apt-archive.postgresql.org/pub/repos/apt/', + release: 'bionic-pgdg-archive', + } + end + + it { + is_expected.to contain_apt__source('apt.postgresql.org') + .with_location(params[:baseurl]) + .with_release(params[:release]) + } + end +end diff --git a/spec/classes/server/config_spec.rb b/spec/classes/server/config_spec.rb new file mode 100644 index 0000000000..a44e4f107e --- /dev/null +++ b/spec/classes/server/config_spec.rb @@ -0,0 +1,209 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::config' do + let(:pre_condition) do + 'class { postgresql::server: manage_selinux => true }' + end + + describe 'on RedHat 7' do + include_examples 'RedHat 7' + + it 'has SELinux port defined' do + expect(subject).to contain_package('policycoreutils-python').with(ensure: 'installed') + + expect(subject).to contain_exec('/usr/sbin/semanage port -a -t postgresql_port_t -p tcp 5432') + .with(unless: '/usr/sbin/semanage port -l | grep -qw 5432') + .that_comes_before('Postgresql::Server::Config_entry[port_for_instance_main]') + .that_requires('Package[policycoreutils-python]') + end + + it 'has the correct systemd-override drop file' do + expect(subject).to contain_file('/etc/systemd/system/postgresql.service.d/postgresql.conf').with( + ensure: 'file', owner: 'root', group: 'root', + ).that_requires('File[/etc/systemd/system/postgresql.service.d]') + end + + it 'has the correct systemd-override file #regex' do + expect(subject).to contain_file('/etc/systemd/system/postgresql.service.d/postgresql.conf') + end + + describe 'with manage_package_repo => true and a version' do + let(:pre_condition) do + <<-EOS + class { 'postgresql::globals': + manage_package_repo => true, + version => '10', + }-> + class { 'postgresql::server': } + EOS + end + + it 'has the correct systemd-override file' do + expect(subject).to contain_file('/etc/systemd/system/postgresql-10.service.d/postgresql-10.conf').with( + ensure: 'file', owner: 'root', group: 'root', + ) + end + + it 'has the correct systemd-override file #regex' do + expect(subject).to contain_file('/etc/systemd/system/postgresql-10.service.d/postgresql-10.conf').without_content(%r{\.include}) + end + end + end + + describe 'on Redhat 8' do + include_examples 'RedHat 8' + + it 'has SELinux port defined' do + expect(subject).to contain_package('policycoreutils-python-utils').with(ensure: 'installed') + + expect(subject).to contain_exec('/usr/sbin/semanage port -a -t postgresql_port_t -p tcp 5432') + .with(unless: '/usr/sbin/semanage port -l | grep -qw 5432') + .that_comes_before('Postgresql::Server::Config_entry[port_for_instance_main]') + .that_requires('Package[policycoreutils-python-utils]') + end + + it 'has the correct systemd-override drop file' do + expect(subject).to contain_file('/etc/systemd/system/postgresql.service.d/postgresql.conf').with( + ensure: 'file', owner: 'root', group: 'root', + ).that_requires('File[/etc/systemd/system/postgresql.service.d]') + end + + it 'has the correct systemd-override file #regex' do + expect(subject).to contain_file('/etc/systemd/system/postgresql.service.d/postgresql.conf').without_content(%r{\.include}) + end + + describe 'with manage_package_repo => true and a version' do + let(:pre_condition) do + <<-EOS + class { 'postgresql::globals': + manage_package_repo => true, + version => '14', + }-> + class { 'postgresql::server': } + EOS + end + + it 'has the correct systemd-override file' do + expect(subject).to contain_file('/etc/systemd/system/postgresql-14.service.d/postgresql-14.conf').with( + ensure: 'file', owner: 'root', group: 'root', + ) + end + + it 'has the correct systemd-override file #regex' do + expect(subject).to contain_file('/etc/systemd/system/postgresql-14.service.d/postgresql-14.conf').without_content(%r{\.include}) + end + end + end + + describe 'on Fedora 33' do + include_examples 'Fedora 33' + + it 'has SELinux port defined' do + expect(subject).to contain_package('policycoreutils-python-utils').with(ensure: 'installed') + + expect(subject).to contain_exec('/usr/sbin/semanage port -a -t postgresql_port_t -p tcp 5432') + .with(unless: '/usr/sbin/semanage port -l | grep -qw 5432') + .that_comes_before('Postgresql::Server::Config_entry[port_for_instance_main]') + .that_requires('Package[policycoreutils-python-utils]') + end + + it 'has the correct systemd-override drop file' do + expect(subject).to contain_file('/etc/systemd/system/postgresql.service.d/postgresql.conf').with( + ensure: 'file', owner: 'root', group: 'root', + ).that_requires('File[/etc/systemd/system/postgresql.service.d]') + end + + it 'has the correct systemd-override file #regex' do + expect(subject).to contain_file('/etc/systemd/system/postgresql.service.d/postgresql.conf').without_content(%r{\.include}) + end + + describe 'with manage_package_repo => true and a version' do + let(:pre_condition) do + <<-EOS + class { 'postgresql::globals': + manage_package_repo => true, + version => '13', + }-> + class { 'postgresql::server': } + EOS + end + + it 'has the correct systemd-override file' do + expect(subject).to contain_file('/etc/systemd/system/postgresql-13.service.d/postgresql-13.conf').with( + ensure: 'file', owner: 'root', group: 'root', + ) + end + + it 'has the correct systemd-override file #regex' do + expect(subject).to contain_file('/etc/systemd/system/postgresql-13.service.d/postgresql-13.conf').without_content(%r{\.include}) + end + end + end + + describe 'on Amazon' do + include_examples 'Amazon 1' + + it 'has SELinux port defined' do + expect(subject).to contain_package('policycoreutils').with(ensure: 'installed') + + expect(subject).to contain_exec('/usr/sbin/semanage port -a -t postgresql_port_t -p tcp 5432') + .with(unless: '/usr/sbin/semanage port -l | grep -qw 5432') + .that_comes_before('Postgresql::Server::Config_entry[port_for_instance_main]') + .that_requires('Package[policycoreutils]') + end + end + + describe 'with managed pg_hba_conf and ipv4acls' do + include_examples 'RedHat 7' + let(:pre_condition) do + <<-EOS + class { 'postgresql::globals': + version => '14', + }-> + class { 'postgresql::server': + manage_pg_hba_conf => true, + ipv4acls => [ + 'hostnossl all all 0.0.0.0/0 reject', + 'hostssl all all 0.0.0.0/0 md5' + ] + } + EOS + end + + it 'has hba rule default' do + expect(subject).to contain_postgresql__server__pg_hba_rule('local access as postgres user for instance main') + end + + it 'has hba rule ipv4acls' do + expect(subject).to contain_postgresql__server__pg_hba_rule('postgresql class generated rule ipv4acls 0') + end + end + + describe 'on Gentoo' do + include_examples 'Gentoo' + + describe 'with systemd' do + let(:facts) { super().merge(service_provider: 'systemd') } + let(:pre_condition) do + <<-EOS + class { 'postgresql::globals': + version => '14', + }-> + class { 'postgresql::server': } + EOS + end + + it 'does not have SELinux port defined' do + expect(subject).not_to contain_exec('/usr/sbin/semanage port -a -t postgresql_port_t -p tcp 5432') + end + + it 'has the correct systemd-override drop file' do + expect(subject).to contain_file('/etc/systemd/system/postgresql-14.service.d/postgresql-14.conf').with( + ensure: 'file', owner: 'root', group: 'root', + ) + end + end + end +end diff --git a/spec/classes/server/contrib_spec.rb b/spec/classes/server/contrib_spec.rb new file mode 100644 index 0000000000..16e3139aa2 --- /dev/null +++ b/spec/classes/server/contrib_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::contrib' do + include_examples 'RedHat 8' + + let :pre_condition do + "class { 'postgresql::server': }" + end + + describe 'with parameters' do + let(:params) do + { + package_name: 'mypackage', + package_ensure: 'absent' + } + end + + it 'creates package with correct params' do + expect(subject).to contain_package('postgresql-contrib').with(ensure: 'absent', + name: 'mypackage', + tag: 'puppetlabs-postgresql') + end + end + + describe 'with no parameters' do + it 'creates package with postgresql tag' do + expect(subject).to contain_package('postgresql-contrib').with(tag: 'puppetlabs-postgresql') + end + end + + describe 'on Gentoo' do + include_examples 'Gentoo' + + it 'postgresql-contrib should not be installed' do + expect(subject).to compile + expect(subject).not_to contain_package('postgresql-contrib') + end + end + + describe 'on Debian 11' do + include_examples 'Debian 11' + + it 'postgresql-contrib should not be installed' do + expect(subject).to compile + expect(subject).not_to contain_package('postgresql-contrib') + end + end +end diff --git a/spec/classes/server/initdb_spec.rb b/spec/classes/server/initdb_spec.rb new file mode 100644 index 0000000000..c18c7f92f8 --- /dev/null +++ b/spec/classes/server/initdb_spec.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::initdb' do + let(:pre_condition) do + 'include postgresql::server' + end + + describe 'on RedHat' do + include_examples 'RedHat 8' + + it { is_expected.to contain_file('/var/lib/pgsql/data').with_ensure('directory') } + + context 'with (log,manage,xlog)_datadir set to false' do + let :pre_condition do + " + class {'postgresql::server': + manage_logdir => false, + manage_datadir => false, + manage_xlogdir => false, + logdir => '/var/lib/pgsql/data/log', + xlogdir => '/var/lib/pgsql/data/xlog', + } + file {'/var/lib/pgsql/data': ensure => 'directory'} + file {'/var/lib/pgsql/data/log': ensure => 'directory'} + file {'/var/lib/pgsql/data/xlog': ensure => 'directory'} + " + end + + it { is_expected.to contain_file('/var/lib/pgsql/data').with_ensure('directory') } + it { is_expected.to contain_file('/var/lib/pgsql/data/log').with_ensure('directory') } + it { is_expected.to contain_file('/var/lib/pgsql/data/xlog').with_ensure('directory') } + end + end + + describe 'on Amazon' do + include_examples 'Amazon 1' + + it { is_expected.to contain_file('/var/lib/pgsql92/data').with_ensure('directory') } + + context 'with manage_datadir set to false' do + let :pre_condition do + " + class {'postgresql::server': + manage_datadir => false, + } + file {'/var/lib/pgsql92/data': ensure => 'directory'} + " + end + + it { is_expected.to contain_file('/var/lib/pgsql92/data').with_ensure('directory') } + end + end + + describe 'exec with module_workdir => /var/tmp' do + include_examples 'RedHat 8' + let(:pre_condition) do + <<-EOS + class { 'postgresql::globals': + module_workdir => '/var/tmp', + }-> + class { 'postgresql::server': } + EOS + end + + it 'contains exec with specified working directory' do + expect(subject).to contain_exec('postgresql_initdb_instance_main').with( + cwd: '/var/tmp', + ) + end + end + + describe 'exec with module_workdir => undef' do + include_examples 'RedHat 8' + let(:pre_condition) do + <<-EOS + class { 'postgresql::globals': + }-> + class { 'postgresql::server': } + EOS + end + + it 'contains exec with default working directory' do + expect(subject).to contain_exec('postgresql_initdb_instance_main').with( + cwd: '/tmp', + ) + end + end + + describe 'postgresql_psql with module_workdir => /var/tmp' do + include_examples 'RedHat 8' + let(:pre_condition) do + <<-EOS + class { 'postgresql::globals': + module_workdir => '/var/tmp', + encoding => 'test', + needs_initdb => false, + }-> + class { 'postgresql::server': } + EOS + end + + it 'contains postgresql_psql with specified working directory' do + expect(subject).to contain_postgresql_psql('Set template1 encoding to test').with(cwd: '/var/tmp') + end + end +end diff --git a/spec/classes/server/plperl_spec.rb b/spec/classes/server/plperl_spec.rb new file mode 100644 index 0000000000..a749d758eb --- /dev/null +++ b/spec/classes/server/plperl_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::plperl' do + include_examples 'Debian 11' + + let :pre_condition do + "class { 'postgresql::server': }" + end + + describe 'with no parameters' do + it { is_expected.to contain_class('postgresql::server::plperl') } + + it 'creates package' do + expect(subject).to contain_package('postgresql-plperl').with(ensure: 'present', + tag: 'puppetlabs-postgresql') + end + end + + describe 'with parameters' do + let :params do + { + package_ensure: 'absent', + package_name: 'mypackage' + } + end + + it { is_expected.to contain_class('postgresql::server::plperl') } + + it 'creates package with correct params' do + expect(subject).to contain_package('postgresql-plperl').with(ensure: 'absent', + name: 'mypackage', + tag: 'puppetlabs-postgresql') + end + end +end diff --git a/spec/classes/server/plpython_spec.rb b/spec/classes/server/plpython_spec.rb new file mode 100644 index 0000000000..d657b67e36 --- /dev/null +++ b/spec/classes/server/plpython_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::plpython' do + include_examples 'RedHat 8' + + let :pre_condition do + "class { 'postgresql::server': }" + end + + describe 'on RedHat with no parameters' do + it { is_expected.to contain_class('postgresql::server::plpython') } + + it 'creates package' do + expect(subject).to contain_package('postgresql-plpython').with(ensure: 'present', + tag: 'puppetlabs-postgresql') + end + end + + describe 'with parameters' do + let :params do + { + package_ensure: 'absent', + package_name: 'mypackage' + } + end + + it { is_expected.to contain_class('postgresql::server::plpython') } + + it 'creates package with correct params' do + expect(subject).to contain_package('postgresql-plpython').with(ensure: 'absent', + name: 'mypackage', + tag: 'puppetlabs-postgresql') + end + end +end diff --git a/spec/classes/server/postgis_spec.rb b/spec/classes/server/postgis_spec.rb new file mode 100644 index 0000000000..eb149e7073 --- /dev/null +++ b/spec/classes/server/postgis_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::postgis' do + include_examples 'Debian 11' + let :pre_condition do + "class { 'postgresql::server': }" + end + + describe 'with parameters' do + let(:params) do + { + package_name: 'mypackage', + package_ensure: 'absent' + } + end + + it 'creates package with correct params' do + expect(subject).to contain_package('postgresql-postgis').with(ensure: 'absent', + name: 'mypackage', + tag: 'puppetlabs-postgresql') + end + end + + describe 'with no parameters' do + it 'creates package with postgresql tag' do + expect(subject).to contain_package('postgresql-postgis').with(tag: 'puppetlabs-postgresql') + end + end +end diff --git a/spec/classes/server/service_spec.rb b/spec/classes/server/service_spec.rb new file mode 100644 index 0000000000..1018fbc688 --- /dev/null +++ b/spec/classes/server/service_spec.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::service' do + include_examples 'Ubuntu 18.04' + + let :pre_condition do + 'include postgresql::server' + end + + it { is_expected.to contain_class('postgresql::server::service') } + it { is_expected.to contain_service('postgresqld_instance_main').with_name('postgresql').with_status('systemctl status postgresql') } +end diff --git a/spec/classes/server_spec.rb b/spec/classes/server_spec.rb new file mode 100644 index 0000000000..513c3d1760 --- /dev/null +++ b/spec/classes/server_spec.rb @@ -0,0 +1,339 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server' do + include_examples 'Debian 11' + + describe 'with no parameters' do + it { is_expected.to contain_class('postgresql::params') } + it { is_expected.to contain_class('postgresql::server') } + it { is_expected.to contain_file('/var/lib/postgresql/13/main') } + + it { + expect(subject).to contain_exec('postgresql_reload_main').with('command' => 'systemctl reload postgresql') + } + + it 'validates connection' do + expect(subject).to contain_postgresql_conn_validator('validate_service_is_running_instance_main') + end + end + + describe 'with manage_dnf_module true' do + include_examples 'RedHat 8' + + let(:pre_condition) do + <<-PUPPET + class { 'postgresql::globals': + manage_dnf_module => true, + } + PUPPET + end + + it { is_expected.to contain_package('postgresql dnf module').with_ensure('10').that_comes_before('Package[postgresql-server]') } + it { is_expected.to contain_package('postgresql-server').with_name('postgresql-server') } + + describe 'with version set' do + let(:pre_condition) do + <<-PUPPET + class { 'postgresql::globals': + manage_dnf_module => true, + version => '12', + } + PUPPET + end + + it { is_expected.to contain_package('postgresql dnf module').with_ensure('12').that_comes_before('Package[postgresql-server]') } + it { is_expected.to contain_package('postgresql-server').with_name('postgresql-server') } + end + end + + describe 'service_ensure => running' do + let(:params) do + { + service_ensure: 'running', + postgres_password: 'new-p@s$word-to-set' + } + end + + it { is_expected.to contain_class('postgresql::params') } + it { is_expected.to contain_class('postgresql::server') } + it { is_expected.to contain_class('postgresql::server::passwd') } + + it 'validates connection' do + expect(subject).to contain_postgresql_conn_validator('validate_service_is_running_instance_main') + end + + it 'sets postgres password' do + expect(subject).to contain_exec('set_postgres_postgrespw_main').with('command' => '/usr/bin/psql -c "ALTER ROLE \"postgres\" PASSWORD ${NEWPASSWD_ESCAPED}"', + 'user' => 'postgres', + 'environment' => ['PGPASSWORD=new-p@s$word-to-set', 'PGPORT=5432', 'NEWPASSWD_ESCAPED=$$new-p@s$word-to-set$$'], + 'unless' => "/usr/bin/psql -h localhost -p 5432 -c 'select 1' > /dev/null") + end + end + + describe 'service_ensure => true' do + let(:params) do + { + service_ensure: true, + postgres_password: 'new-p@s$word-to-set' + } + end + + it { is_expected.to contain_class('postgresql::params') } + it { is_expected.to contain_class('postgresql::server') } + it { is_expected.to contain_class('postgresql::server::passwd') } + + it 'validates connection' do + expect(subject).to contain_postgresql_conn_validator('validate_service_is_running_instance_main') + end + + it 'sets postgres password' do + expect(subject).to contain_exec('set_postgres_postgrespw_main').with('command' => ['/usr/bin/psql -c "ALTER ROLE \"postgres\" PASSWORD ${NEWPASSWD_ESCAPED}"'], + 'user' => 'postgres', + 'environment' => ['PGPASSWORD=new-p@s$word-to-set', 'PGPORT=5432', 'NEWPASSWD_ESCAPED=$$new-p@s$word-to-set$$'], + 'unless' => "/usr/bin/psql -h localhost -p 5432 -c 'select 1' > /dev/null") + end + end + + describe 'service_ensure => stopped' do + let(:params) { { service_ensure: 'stopped' } } + + it { is_expected.to contain_class('postgresql::params') } + it { is_expected.to contain_class('postgresql::server') } + + it 'shouldnt validate connection' do + expect(subject).not_to contain_postgresql_conn_validator('validate_service_is_running_instance_main') + end + end + + describe 'service_restart_on_change => false' do + let(:params) { { service_restart_on_change: false } } + + it { is_expected.to contain_class('postgresql::params') } + it { is_expected.to contain_class('postgresql::server') } + + it { + expect(subject).not_to contain_Postgresql_conf('data_directory_for_instance_main').that_notifies('Class[postgresql::server::service]') + } + + it 'validates connection' do + expect(subject).to contain_postgresql_conn_validator('validate_service_is_running_instance_main') + end + end + + describe 'service_restart_on_change => true' do + let(:params) { { service_restart_on_change: true } } + + it { is_expected.to contain_class('postgresql::params') } + it { is_expected.to contain_class('postgresql::server') } + + it { + expect(subject).to contain_Postgresql_conf('data_directory_for_instance_main').that_notifies('Postgresql::Server::Instance::Service[main]') + } + + it { is_expected.to contain_postgresql__server__config_entry('data_directory_for_instance_main') } + + it 'validates connection' do + expect(subject).to contain_postgresql_conn_validator('validate_service_is_running_instance_main') + end + end + + describe 'service_reload => /bin/true' do + let(:params) { { service_reload: '/bin/true' } } + + it { is_expected.to contain_class('postgresql::params') } + it { is_expected.to contain_class('postgresql::server') } + + it { + expect(subject).to contain_exec('postgresql_reload_main').with('command' => '/bin/true') + } + + it 'validates connection' do + expect(subject).to contain_postgresql_conn_validator('validate_service_is_running_instance_main') + end + end + + describe 'service_manage => true' do + let(:params) { { service_manage: true } } + + it { is_expected.to contain_service('postgresqld_instance_main') } + end + + describe 'service_manage => false' do + let(:params) { { service_manage: false } } + + it { is_expected.not_to contain_service('postgresqld_instance_main') } + + it 'shouldnt validate connection' do + expect(subject).not_to contain_postgresql_conn_validator('validate_service_is_running_instance_main') + end + end + + describe 'package_ensure => absent' do + let(:params) do + { + package_ensure: 'absent' + } + end + + it 'removes the package' do + expect(subject).to contain_package('postgresql-server').with(ensure: 'purged') + end + + it 'stills enable the service' do + expect(subject).to contain_service('postgresqld_instance_main').with(ensure: 'running') + end + end + + describe 'needs_initdb => true' do + let(:params) do + { + needs_initdb: true + } + end + + it 'contains proper initdb exec' do + expect(subject).to contain_exec('postgresql_initdb_instance_main') + end + end + + describe 'postgresql_version' do + let(:pre_condition) do + <<-EOS + class { 'postgresql::globals': + manage_package_repo => true, + version => '14', + before => Class['postgresql::server'], + } + EOS + end + + it 'contains the correct package version' do + expect(subject).to contain_class('postgresql::repo').with_version('14') + expect(subject).to contain_file('/var/lib/postgresql/14/main') # FIXME: be more precise + expect(subject).to contain_concat('/etc/postgresql/14/main/pg_hba.conf') # FIXME: be more precise + expect(subject).to contain_concat('/etc/postgresql/14/main/pg_ident.conf') # FIXME: be more precise + end + end + + describe 'additional roles' do + let(:params) do + { + roles: { + username: { createdb: true } + } + } + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__role('username').with_createdb(true) } + end + + describe 'additional config_entries' do + let(:params) do + { + config_entries: { + fsync: 'off', + checkpoint_segments: '20', + remove_me: :undef + } + } + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__config_entry('fsync').with_value('off').with_ensure('present') } + it { is_expected.to contain_postgresql__server__config_entry('checkpoint_segments').with_value('20').with_ensure('present') } + it { is_expected.to contain_postgresql__server__config_entry('remove_me').with_value(nil).with_ensure('absent') } + end + + describe 'additional pg_hba_rules' do + let(:params) do + { + pg_hba_rules: { + from_remote_host: { + type: 'host', + database: 'mydb', + user: 'myuser', + auth_method: 'md5', + address: '192.0.2.100' + } + } + } + end + + it { is_expected.to compile.with_all_deps } + + it do + expect(subject).to contain_postgresql__server__pg_hba_rule('from_remote_host') + .with_type('host') + .with_database('mydb') + .with_user('myuser') + .with_auth_method('md5') + .with_address('192.0.2.100') + end + end + + describe 'backup_enable => false' do + let(:params) { { backup_enable: false } } + + it { is_expected.to contain_class('postgresql::server') } + it { is_expected.not_to contain_class('postgresql::backup::pg_dump') } + it { is_expected.not_to contain_file('/root/.pgpass') } + it { is_expected.not_to contain_file('/usr/local/sbin/pg_dump.sh') } + it { is_expected.not_to contain_cron('pg_dump backup job') } + end + + describe 'backup_enable => true' do + let(:params) do + { + backup_enable: true, + backup_provider: 'pg_dump', + backup_options: { + db_user: 'backupuser', + db_password: 'backuppass', + dir: '/tmp/backuptest', + manage_user: true + } + } + end + + it { is_expected.to contain_class('postgresql::server') } + it { is_expected.to contain_class('postgresql::backup::pg_dump') } + + it { + expect(subject).to contain_postgresql__server__role('backupuser') + .with_superuser(true) + } + + it { + expect(subject).to contain_postgresql__server__pg_hba_rule('local access as backup user') + .with_type('local') + .with_database('all') + .with_user('backupuser') + .with_auth_method('md5') + } + + it { + expect(subject).to contain_file('/root/.pgpass') + .with_content(%r{.*:backupuser:.*}) + } + + it { + expect(subject).to contain_file('/usr/local/sbin/pg_dump.sh') + .with_content(%r{.*pg_dumpall \$_pg_args --file=\$\{FILE\} \$@.*}) + } + + it { + expect(subject).to contain_cron('pg_dump backup job') + .with( + ensure: 'present', + command: '/usr/local/sbin/pg_dump.sh', + user: 'root', + hour: '23', + minute: '5', + weekday: '*', + ) + } + end +end diff --git a/spec/default_facts.yml b/spec/default_facts.yml new file mode 100644 index 0000000000..3346c394df --- /dev/null +++ b/spec/default_facts.yml @@ -0,0 +1,9 @@ +# Use default_module_facts.yml for module specific facts. +# +# Facts specified here will override the values provided by rspec-puppet-facts. +--- +networking: + ip: "172.16.254.254" + ip6: "FE80:0000:0000:0000:AAAA:AAAA:AAAA" + mac: "AA:AA:AA:AA:AA:AA" +is_pe: false diff --git a/spec/defines/server/config_entry_spec.rb b/spec/defines/server/config_entry_spec.rb new file mode 100644 index 0000000000..243e2ea5e9 --- /dev/null +++ b/spec/defines/server/config_entry_spec.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::config_entry' do + include_examples 'Debian 11' + + let(:title) { 'config_entry' } + + let :target do + tmpfilename('postgresql_conf') + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'syntax check' do + let(:params) { { ensure: 'present' } } + + it { is_expected.to contain_postgresql__server__config_entry('config_entry') } + end + + context 'ports' do + let(:params) { { ensure: 'present', name: 'port_spec', value: '5432' } } + + context 'redhat 7' do + include_examples 'RedHat 7' + + it 'stops postgresql and changes the port #file' do + expect(subject).to contain_file('/etc/systemd/system/postgresql.service.d/postgresql.conf') + end + end + end + + context 'passes values through appropriately' do + let(:params) { { ensure: 'present', name: 'check_function_bodies', value: 'off' } } + + it 'with no quotes' do + expect(subject).to contain_postgresql_conf('check_function_bodies').with(name: 'check_function_bodies', + value: 'off') + end + end + + context 'passes a string value through appropriately' do + let(:params) { { ensure: 'present', name: 'string_value', value: 'entry_test' } } + + it 'and adds string value to config' do + expect(subject).to contain_postgresql_conf('string_value').with(name: 'string_value', + value: 'entry_test') + end + end + + context 'passes an integer value through appropriately' do + let(:params) { { ensure: 'present', name: 'integer_value', value: 40 } } + + it 'and adds integer value to config' do + expect(subject).to contain_postgresql_conf('integer_value').with(name: 'integer_value', + value: 40) + end + end + + context 'passes a float value through appropriately' do + let(:params) { { ensure: 'present', name: 'floating_point_value', value: 4.0 } } + + it 'and adds float value to config' do + expect(subject).to contain_postgresql_conf('floating_point_value').with(name: 'floating_point_value', + value: 4.0) + end + end + + context 'unix_socket_directories' do + let(:params) { { ensure: 'present', name: 'unix_socket_directories', value: '/var/pgsql, /opt/postgresql, /root/' } } + + it 'restarts the server and change unix_socket_directories to the provided list' do + expect(subject).to contain_postgresql_conf('unix_socket_directories') + .with(name: 'unix_socket_directories', + value: '/var/pgsql, /opt/postgresql, /root/') + .that_notifies('Postgresql::Server::Instance::Service[main]') + end + end +end diff --git a/spec/defines/server/database_grant_spec.rb b/spec/defines/server/database_grant_spec.rb new file mode 100644 index 0000000000..61fe77ded8 --- /dev/null +++ b/spec/defines/server/database_grant_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::database_grant' do + include_examples 'Debian 11' + + let :title do + 'test' + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'with minimal settings' do + let :params do + { + privilege: 'ALL', + db: 'test', + role: 'test' + } + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__database_grant('test') } + it { is_expected.to contain_postgresql__server__grant('database:test').with_psql_user('postgres').with_port(5432).with_group('postgres') } + end + + context 'with different user/group/port' do + let :params do + { + privilege: 'ALL', + db: 'test', + role: 'test', + psql_user: 'foo', + psql_group: 'bar', + port: 1337 + } + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('database:test').with_psql_user('foo').with_port(1337).with_group('bar') } + end +end diff --git a/spec/defines/server/database_spec.rb b/spec/defines/server/database_spec.rb new file mode 100644 index 0000000000..d9df85e40a --- /dev/null +++ b/spec/defines/server/database_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::database' do + include_examples 'Debian 11' + let :title do + 'test' + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql__server__database('test') } + it { is_expected.to contain_postgresql_psql('CREATE DATABASE "test"').that_requires('Service[postgresqld_instance_main]') } + + context "with comment set to 'test comment'" do + let(:params) { { comment: 'test comment' } } + + it { is_expected.to contain_postgresql_psql("COMMENT ON DATABASE \"test\" IS 'test comment'").with_connect_settings({}) } + end + + context 'with specific db connection settings - default port' do + let :pre_condition do + "class {'postgresql::server':}" + end + + let(:params) do + { connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1' } } + end + + it { is_expected.to contain_postgresql_psql('CREATE DATABASE "test"').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1').with_port(5432) } + end + + context 'with specific db connection settings - including port' do + let :pre_condition do + "class {'postgresql::globals':} + + class {'postgresql::server':}" + end + + let(:params) do + { connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234' } } + end + + it { is_expected.to contain_postgresql_psql('CREATE DATABASE "test"').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234').with_port(1234) } + end + + context 'with global db connection settings - including port' do + let :pre_condition do + "class {'postgresql::globals': + default_connect_settings => { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.2', + 'PGPORT' => '1234' } + } + + class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql_psql('CREATE DATABASE "test"').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.2', 'PGPORT' => '1234').with_port(1234) } + end + + context 'with different owner' do + let(:params) { { owner: 'test_owner' } } + + it { is_expected.to contain_postgresql_psql('ALTER DATABASE "test" OWNER TO "test_owner"') } + end +end diff --git a/spec/defines/server/db_spec.rb b/spec/defines/server/db_spec.rb new file mode 100644 index 0000000000..4056f0f4ce --- /dev/null +++ b/spec/defines/server/db_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::db' do + include_examples 'Debian 11' + + let :title do + 'testdb' + end + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'with minimal params' do + let :params do + { + user: 'foo' + } + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__db('testdb').without_port.with_user('foo').with_psql_user('postgres').with_psql_group('postgres') } + it { is_expected.to contain_postgresql__server__database('testdb').without_owner.with_user('postgres').with_group('postgres') } + it { is_expected.to contain_postgresql__server__role('foo').that_comes_before('Postgresql::Server::Database[testdb]').with_port(5432).with_psql_user('postgres').with_psql_group('postgres') } + it { is_expected.to contain_postgresql__server__database_grant('GRANT foo - ALL - testdb').with_port(5432).with_psql_user('postgres').with_psql_group('postgres') } + end + + context 'without dbname param' do + let :params do + { + user: 'test', + password: 'test', + owner: 'tester' + } + end + + it { is_expected.to contain_postgresql__server__db('testdb') } + it { is_expected.to contain_postgresql__server__database('testdb').with_owner('tester') } + it { is_expected.to contain_postgresql__server__role('test').that_comes_before('Postgresql::Server::Database[testdb]') } + it { is_expected.to contain_postgresql__server__database_grant('GRANT test - ALL - testdb') } + end + + context 'dbname' do + let :params do + { + dbname: 'testtest', + user: 'test', + password: 'test', + owner: 'tester' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql__server__database('testtest') } + end +end diff --git a/spec/defines/server/default_privileges_spec.rb b/spec/defines/server/default_privileges_spec.rb new file mode 100644 index 0000000000..c5917b08fc --- /dev/null +++ b/spec/defines/server/default_privileges_spec.rb @@ -0,0 +1,394 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::default_privileges' do + include_examples 'Debian 11' + + let :title do + 'test' + end + + context 'with unsupported PostgreSQL version' do + include_examples 'RedHat 7' + + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'tables' + } + end + + let :pre_condition do + "class {'postgresql::server': }" + end + + it { is_expected.to compile.and_raise_error(%r{Default_privileges is only useable with PostgreSQL >= 9.6}m) } + end + + context 'case insensitive object_type and privilege match' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'aLl', + object_type: 'TaBlEs' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + + it do + expect(subject).to contain_postgresql_psql('default_privileges:test') + .with_command('ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO "test"') + end + end + + context 'invalid object_type' do + context 'tables' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'wrong_type' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.and_raise_error(%r{parameter 'object_type' expects a match for Pattern}) } + end + end + + context 'valid object_type' do + context 'supported privilege' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'tables' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + + it do + # rubocop:disable Layout/LineLength + expect(subject).to contain_postgresql_psql('default_privileges:test') + .with_command('ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO "test"') + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r')") + # rubocop:enable Layout/LineLength + end + end + + context 'unsupported privilege' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'wrong_privilege', + object_type: 'tables' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.and_raise_error(%r{Illegal value for \$privilege parameter}) } + end + + context 'schemas on postgres < 9.6' do + include_examples 'RedHat 7' + + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'schemas', + schema: '' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.and_raise_error(%r{Default_privileges is only useable with PostgreSQL >= 9.6}m) } + end + + context 'schemas on postgres >= 10.0' do + include_examples 'Debian 11' + + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'schemas', + schema: '' + } + end + + let :pre_condition do + <<-MANIFEST + class { 'postgresql::globals': + version => '10.0', + } + class { 'postgresql::server': } + MANIFEST + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + + it do + # rubocop:disable Layout/LineLength + expect(subject).to contain_postgresql_psql('default_privileges:test') + .with_command('ALTER DEFAULT PRIVILEGES GRANT ALL ON SCHEMAS TO "test"') + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=UC' = ANY (defaclacl) AND nspname IS NULL and defaclobjtype = 'n')") + # rubocop:enable Layout/LineLength + end + end + + context 'nested schemas are invalid' do + include_examples 'Debian 11' + + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'schemas', + schema: 'public' + } + end + + let :pre_condition do + <<-MANIFEST + class { 'postgresql::globals': + version => '10.0', + } + class { 'postgresql::server': } + MANIFEST + end + + it { is_expected.to compile.and_raise_error(%r{Cannot alter default schema permissions within a schema}) } + end + end + + context 'with specific db connection settings - default port' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'tables', + connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.6' } + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + it { is_expected.to contain_postgresql_psql('default_privileges:test').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.6').with_port(5432) } + end + + context 'with specific db connection settings - including port' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'tables', + connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.6', + 'PGPORT' => '1234' } + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + it { is_expected.to contain_postgresql_psql('default_privileges:test').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.6', 'PGPORT' => '1234') } + end + + context 'with specific db connection settings - port overriden by explicit parameter' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'tables', + connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.6', + 'PGPORT' => '1234' }, + port: 5678 + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + it { is_expected.to contain_postgresql_psql('default_privileges:test').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.6', 'PGPORT' => '1234').with_port('1234') } + end + + context 'with specific schema name' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'tables', + schema: 'my_schema' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + + it do + # rubocop:disable Layout/LineLength + expect(subject).to contain_postgresql_psql('default_privileges:test') + .with_command('ALTER DEFAULT PRIVILEGES IN SCHEMA my_schema GRANT ALL ON TABLES TO "test"') + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt' = ANY (defaclacl) AND nspname = 'my_schema' and defaclobjtype = 'r')") + # rubocop:enable Layout/LineLength + end + end + + context 'with unset schema name' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'tables', + schema: '' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + + it do + # rubocop:disable Layout/LineLength + expect(subject).to contain_postgresql_psql('default_privileges:test') + .with_command('ALTER DEFAULT PRIVILEGES GRANT ALL ON TABLES TO "test"') + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt' = ANY (defaclacl) AND nspname IS NULL and defaclobjtype = 'r')") + # rubocop:enable Layout/LineLength + end + end + + context 'with a role defined' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'tables' + } + end + + let :pre_condition do + <<-EOS + class {'postgresql::server':} + postgresql::server::role { 'test': } + EOS + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + it { is_expected.to contain_postgresql__server__role('test') } + + it do + expect(subject).to contain_postgresql_psql('default_privileges:test') \ + .that_requires(['Service[postgresqld_instance_main]', 'Postgresql::Server::Role[test]']) + end + end + + context 'with a target role' do + let :params do + { + target_role: 'target', + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'tables' + } + end + + let :pre_condition do + <<-EOS + class {'postgresql::server':} + postgresql::server::role { 'target': } + EOS + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + it { is_expected.to contain_postgresql__server__role('target') } + + it do + # rubocop:disable Layout/LineLength + expect(subject).to contain_postgresql_psql('default_privileges:test') + .with_command('ALTER DEFAULT PRIVILEGES FOR ROLE target IN SCHEMA public GRANT ALL ON TABLES TO "test"') + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt/target' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r')") + # rubocop:enable Layout/LineLength + end + end + + context 'standalone not managing server' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'execute', + object_type: 'functions', + group: 'postgresql', + psql_path: '/usr/bin', + psql_user: 'postgres', + psql_db: 'db', + port: 1542, + connect_settings: { 'DBVERSION' => '9.6' } + } + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.not_to contain_class('postgresql::server') } + end +end diff --git a/spec/defines/server/extension_spec.rb b/spec/defines/server/extension_spec.rb new file mode 100644 index 0000000000..fd2f6ffa8f --- /dev/null +++ b/spec/defines/server/extension_spec.rb @@ -0,0 +1,242 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::extension' do # rubocop:disable RSpec/MultipleDescribes + include_examples 'Debian 11' + + let :pre_condition do + "class { 'postgresql::server': } + postgresql::server::database { 'template_postgis': + template => 'template1', + }" + end + let(:title) { 'postgis' } + let(:params) do + { + database: 'template_postgis' + } + end + + context 'with mandatory arguments only' do + it { + expect(subject).to contain_postgresql_psql('template_postgis: CREATE EXTENSION "postgis"') + .with(db: 'template_postgis', command: 'CREATE EXTENSION "postgis"').that_requires('Postgresql::Server::Database[template_postgis]') + } + end + + context 'when schema is specified' do + let(:params) do + super().merge(schema: 'pg_catalog') + end + + it { + expect(subject).to contain_postgresql_psql('template_postgis: ALTER EXTENSION "postgis" SET SCHEMA "pg_catalog"') + } + end + + context 'when setting package name' do + let(:params) do + super().merge(package_name: 'postgis') + end + + it { + expect(subject).to contain_package('postgis') + .with(ensure: 'installed', name: 'postgis').that_comes_before('Postgresql_psql[template_postgis: CREATE EXTENSION "postgis"]') + } + end + + context 'when ensuring absence' do + let(:params) do + super().merge(ensure: 'absent', + package_name: 'postgis') + end + + it { + expect(subject).to contain_postgresql_psql('template_postgis: DROP EXTENSION "postgis"') + .with(db: 'template_postgis', command: 'DROP EXTENSION "postgis"').that_requires('Postgresql::Server::Database[template_postgis]') + } + + it { + expect(subject).to contain_package('postgis').with(ensure: 'absent', + name: 'postgis') + } + + context 'when keeping package installed' do + let(:params) do + super().merge(package_ensure: 'present') + end + + it { + expect(subject).to contain_postgresql_psql('template_postgis: DROP EXTENSION "postgis"') + .with(db: 'template_postgis', command: 'DROP EXTENSION "postgis"').that_requires('Postgresql::Server::Database[template_postgis]') + } + + it { + expect(subject).to contain_package('postgis') + .with(ensure: 'installed', name: 'postgis').that_requires('Postgresql_psql[template_postgis: DROP EXTENSION "postgis"]') + } + end + end + + context 'when extension version is specified' do + let(:params) do + super().merge(ensure: 'absent', + package_name: 'postgis', + version: '99.99.99') + end + + it { + expect(subject).to contain_postgresql_psql('template_postgis: ALTER EXTENSION "postgis" UPDATE TO \'99.99.99\'') + .with(db: 'template_postgis', unless: "SELECT 1 FROM pg_extension WHERE extname='postgis' AND extversion='99.99.99'").that_requires('Postgresql::Server::Database[template_postgis]') + } + end + + context 'when extension version is latest' do + let(:params) do + super().merge(ensure: 'absent', + package_name: 'postgis', + version: 'latest') + end + + it { + expect(subject).to contain_postgresql_psql('template_postgis: ALTER EXTENSION "postgis" UPDATE') + .with(db: 'template_postgis', + unless: "SELECT 1 FROM pg_available_extensions WHERE name = 'postgis' AND default_version = installed_version").that_requires('Postgresql::Server::Database[template_postgis]') + } + end +end + +describe 'postgresql::server::extension' do + include_examples 'Debian 10' + + let :pre_condition do + "class { 'postgresql::server': } + postgresql::server::database { 'template_postgis2': + template => 'template1', + }" + end + let(:title) { 'postgis_db2' } + let(:params) do + { + database: 'template_postgis2', + extension: 'postgis' + } + end + + it { is_expected.to contain_file('/var/lib/postgresql/11/main') } # FIXME: be more precise + it { is_expected.to contain_concat('/etc/postgresql/11/main/pg_hba.conf') } # FIXME: be more precise + it { is_expected.to contain_concat('/etc/postgresql/11/main/pg_ident.conf') } # FIXME: be more precise + + context 'with mandatory arguments only' do + it { + expect(subject).to contain_postgresql_psql('template_postgis2: CREATE EXTENSION "postgis"') + .with(db: 'template_postgis2', command: 'CREATE EXTENSION "postgis"').that_requires('Postgresql::Server::Database[template_postgis2]') + } + end +end + +describe 'postgresql::server::extension' do + include_examples 'Debian 10' + + let(:title) { 'pg_repack' } + let(:params) do + { + database: 'postgres', + extension: 'pg_repack' + } + end + + context 'without including postgresql::server' do + let :pre_condition do + "class {'postgresql::server':}" + end + + it { + expect(subject).to contain_postgresql_psql('postgres: CREATE EXTENSION "pg_repack"') + .with(db: 'postgres', command: 'CREATE EXTENSION "pg_repack"') + } + end + + context 'default port' do + let :params do + { + database: 'postgres', + extension: 'pg_repack' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql_psql('postgres: CREATE EXTENSION "pg_repack"').with_port('5432') } + end + + context 'port overriden by explicit parameter' do + let :params do + { + database: 'postgres', + extension: 'pg_repack', + port: 1234 + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql_psql('postgres: CREATE EXTENSION "pg_repack"').with_port('1234') } + end + + context 'with specific db connection settings' do + let :params do + { + database: 'postgres', + extension: 'pg_repack', + connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => 1234 } + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + + it { + expect(subject).to contain_postgresql_psql('postgres: CREATE EXTENSION "pg_repack"') + .with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234') + .with_port(1234) + } + end + + context 'with specific db connection settings - port overriden by explicit parameter' do + let :params do + { + database: 'postgres', + extension: 'pg_repack', + connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => 1234 }, + port: 5678 + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + + it { + expect(subject).to contain_postgresql_psql('postgres: CREATE EXTENSION "pg_repack"') + .with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234') + .with_port('1234') + } + end +end diff --git a/spec/defines/server/grant_role_spec.rb b/spec/defines/server/grant_role_spec.rb new file mode 100644 index 0000000000..016255aa70 --- /dev/null +++ b/spec/defines/server/grant_role_spec.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::grant_role' do + include_examples 'Debian 11' + + let :pre_condition do + "class { 'postgresql::server': }" + end + + let(:title) { 'test' } + + let(:params) do + { + group: 'my_group', + role: 'my_role' + } + end + + context 'with mandatory arguments only' do + it { + expect(subject).to contain_postgresql_psql("grant_role:#{title}") + .with(command: "GRANT \"#{params[:group]}\" TO \"#{params[:role]}\"", + unless: "SELECT 1 WHERE EXISTS (SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = '#{params[:group]}' AND r_role.rolname = '#{params[:role]}') = true") # rubocop:disable Layout/LineLength + .that_requires('Class[postgresql::server]') + } + end + + context 'with db arguments' do + let(:params) do + super().merge(psql_db: 'postgres', + psql_user: 'postgres', + port: 5432) + end + + it { + expect(subject).to contain_postgresql_psql("grant_role:#{title}") + .with(command: "GRANT \"#{params[:group]}\" TO \"#{params[:role]}\"", + unless: "SELECT 1 WHERE EXISTS (SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = '#{params[:group]}' AND r_role.rolname = '#{params[:role]}') = true", # rubocop:disable Layout/LineLength + db: params[:psql_db], psql_user: params[:psql_user], + port: params[:port]).that_requires('Class[postgresql::server]') + } + end + + context 'with ensure => absent' do + let(:params) do + super().merge(ensure: 'absent') + end + + it { + expect(subject).to contain_postgresql_psql("grant_role:#{title}") + .with(command: "REVOKE \"#{params[:group]}\" FROM \"#{params[:role]}\"", + unless: "SELECT 1 WHERE EXISTS (SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = '#{params[:group]}' AND r_role.rolname = '#{params[:role]}') != true") # rubocop:disable Layout/LineLength + .that_requires('Class[postgresql::server]') + } + end + + context 'with user defined' do + let(:pre_condition) do + "class { 'postgresql::server': } +postgresql::server::role { '#{params[:role]}': }" + end + + it { + expect(subject).to contain_postgresql_psql("grant_role:#{title}").that_requires("Postgresql::Server::Role[#{params[:role]}]") + } + + it { + expect(subject).not_to contain_postgresql_psql("grant_role:#{title}").that_requires("Postgresql::Server::Role[#{params[:group]}]") + } + end + + context 'with group defined' do + let(:pre_condition) do + "class { 'postgresql::server': } +postgresql::server::role { '#{params[:group]}': }" + end + + it { + expect(subject).to contain_postgresql_psql("grant_role:#{title}").that_requires("Postgresql::Server::Role[#{params[:group]}]") + } + + it { + expect(subject).not_to contain_postgresql_psql("grant_role:#{title}").that_requires("Postgresql::Server::Role[#{params[:role]}]") + } + end + + context 'with connect_settings' do + let(:params) do + super().merge(connect_settings: { 'PGHOST' => 'postgres-db-server' }) + end + + it { + expect(subject).to contain_postgresql_psql("grant_role:#{title}").with_connect_settings('PGHOST' => 'postgres-db-server') + } + + it { + expect(subject).not_to contain_postgresql_psql("grant_role:#{title}").that_requires('Class[postgresql::server]') + } + end +end diff --git a/spec/defines/server/grant_spec.rb b/spec/defines/server/grant_spec.rb new file mode 100644 index 0000000000..1b730174dc --- /dev/null +++ b/spec/defines/server/grant_spec.rb @@ -0,0 +1,422 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::grant' do + include_examples 'Debian 11' + + let :title do + 'test' + end + + context 'plain' do + let :params do + { + db: 'test', + role: 'test' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + end + + context 'sequence' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'usage', + object_type: 'sequence' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + + it do + expect(subject).to contain_postgresql_psql('grant:test') + .with_command(%r{GRANT USAGE ON SEQUENCE "test" TO\s* "test"}m) + .with_unless(%r{SELECT 1 WHERE has_sequence_privilege\('test',\s* 'test', 'USAGE'\)}m) + end + end + + context 'SeQuEnCe case insensitive object_type match' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'usage', + object_type: 'SeQuEnCe' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + + it do + expect(subject).to contain_postgresql_psql('grant:test') + .with_command(%r{GRANT USAGE ON SEQUENCE "test" TO\s* "test"}m) + .with_unless(%r{SELECT 1 WHERE has_sequence_privilege\('test',\s* 'test', 'USAGE'\)}m) + end + end + + context 'all sequences' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'usage', + object_type: 'all sequences in schema', + object_name: 'public' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + + it do + expect(subject).to contain_postgresql_psql('grant:test') + .with_command(%r{GRANT USAGE ON ALL SEQUENCES IN SCHEMA "public" TO\s* "test"}m) + .with_unless(%r{SELECT 1 WHERE NOT EXISTS \(\s*SELECT sequence_name\s* FROM information_schema\.sequences\s* WHERE sequence_schema='public'\s* EXCEPT DISTINCT\s* SELECT object_name as sequence_name\s* FROM .* WHERE .*grantee='test'\s* AND object_schema='public'\s* AND privilege_type='USAGE'\s*\)}m) # rubocop:disable Layout/LineLength + end + end + + context 'with specific db connection settings - default port' do + let :params do + { + db: 'test', + role: 'test', + connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1' } + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + it { is_expected.to contain_postgresql_psql('grant:test').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1').with_port(5432) } + end + + context 'with specific db connection settings - including port' do + let :params do + { + db: 'test', + role: 'test', + connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234' } + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + it { is_expected.to contain_postgresql_psql('grant:test').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234') } + end + + context 'with specific db connection settings - port overriden by explicit parameter' do + let :params do + { + db: 'test', + role: 'test', + connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234' }, + port: 5678 + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + it { is_expected.to contain_postgresql_psql('grant:test').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234').with_port('1234') } + end + + context 'with specific schema name' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_name: ['myschema', 'mytable'], + object_type: 'table' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + + it do + expect(subject).to contain_postgresql_psql('grant:test') + .with_command(%r{GRANT ALL ON TABLE "myschema"."mytable" TO\s* "test"}m) + .with_unless(%r{SELECT 1 WHERE has_table_privilege\('test',\s*'myschema.mytable', 'INSERT'\)}m) + end + end + + context 'with a role defined' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_name: ['myschema', 'mytable'], + object_type: 'table' + } + end + + let :pre_condition do + <<-EOS + class {'postgresql::server':} + postgresql::server::role { 'test': } + EOS + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + it { is_expected.to contain_postgresql__server__role('test') } + + it do + expect(subject).to contain_postgresql_psql('grant:test') \ + .that_requires(['Service[postgresqld_instance_main]', 'Postgresql::Server::Role[test]']) + end + end + + context 'with a role defined to PUBLIC' do + let :params do + { + db: 'test', + role: 'PUBLIC', + privilege: 'all', + object_name: ['myschema', 'mytable'], + object_type: 'table' + } + end + + let :pre_condition do + <<-EOS + class {'postgresql::server':} + postgresql::server::role { 'test': } + EOS + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + it { is_expected.to contain_postgresql__server__role('test') } + + it do + expect(subject).to contain_postgresql_psql('grant:test') + .with_command(%r{GRANT ALL ON TABLE "myschema"."mytable" TO\s* PUBLIC}m) + .with_unless(%r{SELECT 1 WHERE has_table_privilege\('public',\s*'myschema.mytable', 'INSERT'\)}m) + end + end + + context 'function' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'execute', + object_name: 'test', + object_arguments: ['text', 'boolean'], + object_type: 'function' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + + it do + expect(subject).to contain_postgresql_psql('grant:test') + .with_command(%r{GRANT EXECUTE ON FUNCTION test\(text,boolean\) TO\s* "test"}m) + .with_unless(%r{SELECT 1 WHERE has_function_privilege\('test',\s* 'test\(text,boolean\)', 'EXECUTE'\)}m) + end + end + + context 'function with schema' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'execute', + object_name: ['myschema', 'test'], + object_arguments: ['text', 'boolean'], + object_type: 'function' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + + it do + expect(subject).to contain_postgresql_psql('grant:test') + .with_command(%r{GRANT EXECUTE ON FUNCTION myschema.test\(text,boolean\) TO\s* "test"}m) + .with_unless(%r{SELECT 1 WHERE has_function_privilege\('test',\s* 'myschema.test\(text,boolean\)', 'EXECUTE'\)}m) + end + end + + context 'standalone not managing server' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'execute', + object_name: ['myschema', 'test'], + object_arguments: ['text', 'boolean'], + object_type: 'function', + group: 'postgresql', + psql_path: '/usr/bin', + psql_user: 'postgres', + psql_db: 'db', + port: 1542, + connect_settings: {} + } + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.not_to contain_class('postgresql::server') } + end + + context 'invalid object_type' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'usage', + object_type: 'invalid' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.and_raise_error(%r{parameter 'object_type' expects a match for Pattern}) } + end + + context 'invalid object_name - wrong type' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_name: 1, + object_type: 'table' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' expects a value of type (Array|Undef, Array,) or String, got Integer}) } + end + + context 'invalid object_name - insufficent array elements' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_name: ['oops'], + object_type: 'table' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + if Puppet::Util::Package.versioncmp(Puppet.version, '5.2.0') >= 0 + it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' variant 1 expects size to be 2, got 1}) } + else + it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' variant 0 expects size to be 2, got 1}) } + end + end + + context 'invalid object_name - too many array elements' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_name: ['myschema', 'mytable', 'oops'], + object_type: 'table' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + if Puppet::Util::Package.versioncmp(Puppet.version, '5.2.0') >= 0 + it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' variant 1 expects size to be 2, got 3}) } + else + it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' variant 0 expects size to be 2, got 3}) } + end + end + + context 'with specific schema name only if object exists' do + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_name: ['myschema', 'mytable'], + object_type: 'table', + onlyif_exists: true + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__grant('test') } + + it do + expect(subject).to contain_postgresql_psql('grant:test') + .with_command(%r{GRANT ALL ON TABLE "myschema"."mytable" TO\s* "test"}m) + .with_unless(%r{SELECT 1 WHERE has_table_privilege\('test',\s*'myschema.mytable', 'INSERT'\)}m) + .with_onlyif(%r{SELECT true FROM pg_tables WHERE tablename = 'mytable'}m) + end + end +end diff --git a/spec/defines/server/instance/config.rb b/spec/defines/server/instance/config.rb new file mode 100644 index 0000000000..aeab03dee2 --- /dev/null +++ b/spec/defines/server/instance/config.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::instance::config' do + let(:title) { 'main' } + + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let :facts do + os_facts + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'with defaults from config_class' do + it { is_expected.to compile.with_all_deps } + end + end + end +end diff --git a/spec/defines/server/instance/initdb.rb b/spec/defines/server/instance/initdb.rb new file mode 100644 index 0000000000..7b94bba521 --- /dev/null +++ b/spec/defines/server/instance/initdb.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::instance::initdb' do + let(:title) { 'main' } + + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let :facts do + os_facts + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'with defaults from initdb class' do + it { is_expected.to compile.with_all_deps } + end + end + end +end diff --git a/spec/defines/server/instance/late_initdb.rb b/spec/defines/server/instance/late_initdb.rb new file mode 100644 index 0000000000..354a410f6f --- /dev/null +++ b/spec/defines/server/instance/late_initdb.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::instance::late_initdb' do + let(:title) { 'main' } + + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let :facts do + os_facts + end + + let :pre_condition do + "class {'postgresql::initdb':}" + end + + context 'with defaults from initdb class' do + it { is_expected.to compile.with_all_deps } + end + end + end +end diff --git a/spec/defines/server/instance/passwd.rb b/spec/defines/server/instance/passwd.rb new file mode 100644 index 0000000000..74ad978be2 --- /dev/null +++ b/spec/defines/server/instance/passwd.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::instance::passwd' do + let(:title) { 'main' } + + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let :facts do + os_facts + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'with defaults from passwd class' do + it { is_expected.to compile.with_all_deps } + end + end + end +end diff --git a/spec/defines/server/instance/reload.rb b/spec/defines/server/instance/reload.rb new file mode 100644 index 0000000000..2b37638401 --- /dev/null +++ b/spec/defines/server/instance/reload.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::instance::reload' do + let(:title) { 'main' } + + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let :facts do + os_facts + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'with defaults from server class' do + it { is_expected.to compile.with_all_deps } + end + end + end +end diff --git a/spec/defines/server/instance/service.rb b/spec/defines/server/instance/service.rb new file mode 100644 index 0000000000..ef5ad5f1e9 --- /dev/null +++ b/spec/defines/server/instance/service.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::instance::service' do + let(:title) { 'main' } + + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let :facts do + os_facts + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'with defaults from service class' do + it { is_expected.to compile.with_all_deps } + end + end + end +end diff --git a/spec/defines/server/pg_hba_rule_spec.rb b/spec/defines/server/pg_hba_rule_spec.rb new file mode 100644 index 0000000000..7d1187001c --- /dev/null +++ b/spec/defines/server/pg_hba_rule_spec.rb @@ -0,0 +1,273 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::pg_hba_rule' do + include_examples 'Debian 11' + let :title do + 'test' + end + let :target do + tmpfilename('pg_hba_rule') + end + + context 'test template 1' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'host', + database: 'all', + user: 'all', + address: '1.1.1.1/24', + auth_method: 'md5', + target: target + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with(content: %r{host\s+all\s+all\s+1\.1\.1\.1/24\s+md5}) + end + end + + context 'test template 2' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'local', + database: 'all', + user: 'all', + auth_method: 'ident', + target: target + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with(content: %r{local\s+all\s+all\s+ident}) + end + end + + context 'test template 3' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'host', + database: 'all', + user: 'all', + address: '0.0.0.0/0', + auth_method: 'ldap', + auth_option: 'foo=bar', + target: target + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with(content: %r{host\s+all\s+all\s+0\.0\.0\.0/0\s+ldap\s+foo=bar}) + end + end + + context 'validation' do + context 'validate supported auth_method' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::globals': + version => '9.2', + } + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'local', + database: 'all', + user: 'all', + address: '0.0.0.0/0', + auth_method: 'peer', + target: target + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with( + content: %r{local\s+all\s+all\s+0\.0\.0\.0/0\s+peer}, + ) + end + end + + context 'allows scram-sha-256 on postgres 10' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::globals': + version => '10', + } + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'local', + database: 'all', + user: 'all', + address: '0.0.0.0/0', + auth_method: 'scram-sha-256', + target: target + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with( + content: %r{local\s+all\s+all\s+0\.0\.0\.0/0\s+scram-sha-256}, + ) + end + end + end + + context 'order' do + context 'default' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'local', + database: 'all', + user: 'all', + auth_method: 'ident' + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with(order: '150') + end + end + + context 'string' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'local', + database: 'all', + user: 'all', + auth_method: 'ident', + order: '12' + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with(order: '12') + end + end + + context 'short integer' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'local', + database: 'all', + user: 'all', + auth_method: 'ident', + order: 12 + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with(order: '012') + end + end + + context 'long integer' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'local', + database: 'all', + user: 'all', + auth_method: 'ident', + order: 1234 + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with(order: '1234') + end + end + + context 'pg_hba_rule with dot domain' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'host', + database: 'all', + user: 'all', + address: '.domain.tld', + auth_method: 'md5', + target: target + } + end + + it do + expect(subject).to contain_concat__fragment('pg_hba_rule_test').with(content: %r{host\s+all\s+all\s+\.domain\.tld\s+md5}) + end + end + + context 'pg_hba_rule with illegal address' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + type: 'host', + database: 'all', + user: 'all', + address: '/45', + auth_method: 'md5', + target: target + } + end + + it { is_expected.to compile.and_raise_error(%r{parameter 'address' expects a Postgresql::Pg_hba_rule_address}) } + end + end +end diff --git a/spec/defines/server/pg_ident_rule_spec.rb b/spec/defines/server/pg_ident_rule_spec.rb new file mode 100644 index 0000000000..77ebb61c84 --- /dev/null +++ b/spec/defines/server/pg_ident_rule_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::pg_ident_rule' do + include_examples 'Debian 11' + let :title do + 'test' + end + let :target do + tmpfilename('pg_ident_rule') + end + + context 'managing pg_ident' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::globals': + manage_pg_ident_conf => true, + } + class { 'postgresql::server': } + MANIFEST + end + + let :params do + { + map_name: 'thatsmymap', + system_username: 'systemuser', + database_username: 'dbuser' + } + end + + it do + expect(subject).to contain_concat__fragment('pg_ident_rule_test').with(content: %r{thatsmymap\s+systemuser\s+dbuser}) + end + end + + context 'not managing pg_ident' do + let :pre_condition do + <<-MANIFEST + class { 'postgresql::globals': + manage_pg_ident_conf => false, + } + class { 'postgresql::server': } + MANIFEST + end + let :params do + { + map_name: 'thatsmymap', + system_username: 'systemuser', + database_username: 'dbuser' + } + end + + it 'fails because $manage_pg_ident_conf is false' do + expect { catalogue }.to raise_error(Puppet::Error, + %r{postgresql::server::manage_pg_ident_conf has been disabled}) + end + end +end diff --git a/spec/defines/server/reassign_owned_by_spec.rb b/spec/defines/server/reassign_owned_by_spec.rb new file mode 100644 index 0000000000..40ca579aaa --- /dev/null +++ b/spec/defines/server/reassign_owned_by_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::reassign_owned_by' do + include_examples 'Debian 11' + + let :title do + 'test' + end + + let :params do + { + db: 'test', + old_role: 'test_old_role', + new_role: 'test_new_role' + } + end + + let :pre_condition do + <<-MANIFEST + class {'postgresql::server':} + postgresql::server::role{ ['test_old_role','test_new_role']: } + MANIFEST + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__reassign_owned_by('test') } + + it { + expect(subject).to contain_postgresql_psql('reassign_owned_by:test:REASSIGN OWNED BY "test_old_role" TO "test_new_role"') + .with_command('REASSIGN OWNED BY "test_old_role" TO "test_new_role"') + .with_onlyif(%r{SELECT tablename FROM pg_catalog.pg_tables WHERE\s*schemaname NOT IN \('pg_catalog', 'information_schema'\) AND\s*tableowner = 'test_old_role'.*}m) + .that_requires('Service[postgresqld_instance_main]') + } +end diff --git a/spec/defines/server/recovery_spec.rb b/spec/defines/server/recovery_spec.rb new file mode 100644 index 0000000000..0fc24f233f --- /dev/null +++ b/spec/defines/server/recovery_spec.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::recovery' do + include_examples 'Debian 11' + let(:title) do + 'test' + end + let :target do + tmpfilename('recovery') + end + + context 'managing recovery' do + let(:pre_condition) do + <<-MANIFEST + class { 'postgresql::globals': + manage_recovery_conf => true, + } + class { 'postgresql::server': } + MANIFEST + end + + let(:params) do + { + restore_command: 'restore_command', + recovery_target_timeline: 'recovery_target_timeline' + } + end + + it do + expect(subject).to contain_concat__fragment('test-recovery.conf') + .with(content: %r{restore_command = 'restore_command'\n+recovery_target_timeline = 'recovery_target_timeline'}) + end + end + + context 'not managing recovery' do + let(:pre_condition) do + <<-MANIFEST + class { 'postgresql::globals': + manage_recovery_conf => false, + } + class { 'postgresql::server': } + MANIFEST + end + let(:params) do + { + restore_command: '' + } + end + + it 'fails because $manage_recovery_conf is false' do + expect { catalogue }.to raise_error(Puppet::Error, + %r{postgresql::server::manage_recovery_conf has been disabled}) + end + end + + context 'not managing recovery, missing param' do + let(:pre_condition) do + <<-MANIFEST + class { 'postgresql::globals': + manage_recovery_conf => true, + } + class { 'postgresql::server': } + MANIFEST + end + + it 'fails because no param set' do + expect { catalogue }.to raise_error(Puppet::Error, + %r{postgresql::server::recovery use this resource but do not pass a parameter will avoid creating the recovery.conf, because it makes no sense.}) + end + end + + context 'managing recovery with all params' do + let(:pre_condition) do + <<-MANIFEST + class { 'postgresql::globals': + manage_recovery_conf => true, + } + class { 'postgresql::server': } + MANIFEST + end + + let(:params) do + { + restore_command: 'restore_command', + archive_cleanup_command: 'archive_cleanup_command', + recovery_end_command: 'recovery_end_command', + recovery_target_name: 'recovery_target_name', + recovery_target_time: 'recovery_target_time', + recovery_target_xid: 'recovery_target_xid', + recovery_target_inclusive: true, + recovery_target: 'recovery_target', + recovery_target_timeline: 'recovery_target_timeline', + pause_at_recovery_target: true, + standby_mode: 'on', + primary_conninfo: 'primary_conninfo', + primary_slot_name: 'primary_slot_name', + trigger_file: 'trigger_file', + recovery_min_apply_delay: 0 + } + end + + it do + expect(subject).to contain_concat__fragment('test-recovery.conf') + .with(content: %r{restore_command = 'restore_command'\n+archive_cleanup_command = 'archive_cleanup_command'\n+recovery_end_command = 'recovery_end_command'\n+recovery_target_name = 'recovery_target_name'\n+recovery_target_time = 'recovery_target_time'\n+recovery_target_xid = 'recovery_target_xid'\n+recovery_target_inclusive = true\n+recovery_target = 'recovery_target'\n+recovery_target_timeline = 'recovery_target_timeline'\n+pause_at_recovery_target = true\n+standby_mode = on\n+primary_conninfo = 'primary_conninfo'\n+primary_slot_name = 'primary_slot_name'\n+trigger_file = 'trigger_file'\n+recovery_min_apply_delay = 0\n+}) # rubocop:disable Layout/LineLength + end + end +end diff --git a/spec/defines/server/role_spec.rb b/spec/defines/server/role_spec.rb new file mode 100644 index 0000000000..0d924a345e --- /dev/null +++ b/spec/defines/server/role_spec.rb @@ -0,0 +1,402 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::role' do + include_examples 'Debian 11' + + let :title do + 'test' + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'with Password Datatype String' do + let :params do + { + password_hash: 'new-pa$s' + } + end + + it { is_expected.to contain_postgresql__server__role('test') } + + it 'has create role for "test" user with password as ****' do + expect(subject).to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(CREATE ROLE "test" ENCRYPTED PASSWORD 'new-pa$s' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1)), + 'sensitive' => 'true', + 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", + 'port' => '5432', + ) + end + + it 'has alter role for "test" user with password as ****' do + expect(subject).to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(ALTER ROLE "test" ENCRYPTED PASSWORD 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'sensitive' => 'true', + 'unless' => sensitive(%(SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'port' => '5432', + ) + end + end + + context 'with Password Datatype Sensitive[String]' do + let :params do + { + password_hash: sensitive('new-pa$s') + } + end + + it { is_expected.to contain_postgresql__server__role('test') } + + it 'has create role for "test" user with password as ****' do + expect(subject).to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(CREATE ROLE "test" ENCRYPTED PASSWORD 'new-pa$s' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1)), + 'sensitive' => 'true', + 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", + 'port' => '5432', + ) + end + + it 'has alter role for "test" user with password as ****' do + expect(subject).to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(ALTER ROLE "test" ENCRYPTED PASSWORD 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'sensitive' => 'true', + 'unless' => sensitive(%(SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'port' => '5432', + ) + end + end + + context 'with specific db connection settings - default port' do + let :params do + { + password_hash: 'new-pa$s', + connect_settings: { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + } + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql__server__role('test') } + + it 'has create role for "test" user with password as ****' do + expect(subject).to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(CREATE ROLE "test" ENCRYPTED PASSWORD 'new-pa$s' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1)), + 'sensitive' => 'true', + 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", + 'port' => 5432, + 'connect_settings' => { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + }, + ).that_requires('Service[postgresqld_instance_main]') + end + + it 'has alter role for "test" user with password as ****' do + expect(subject).to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(ALTER ROLE "test" ENCRYPTED PASSWORD 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'sensitive' => 'true', + 'unless' => sensitive(%(SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'port' => '5432', + 'connect_settings' => { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + }, + ) + end + end + + context 'with specific db connection settings - including port' do + let :params do + { + password_hash: 'new-pa$s', + connect_settings: { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + } + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql__server__role('test') } + + it 'has create role for "test" user with password as ****' do + expect(subject).to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(CREATE ROLE "test" ENCRYPTED PASSWORD 'new-pa$s' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1)), + 'sensitive' => 'true', + 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", + 'connect_settings' => { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + }, + ) + end + + it 'has alter role for "test" user with password as ****' do + expect(subject).to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(ALTER ROLE "test" ENCRYPTED PASSWORD 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'sensitive' => 'true', + 'unless' => sensitive(%(SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'connect_settings' => { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + }, + ) + end + end + + context 'with update_password set to false' do + let :params do + { + password_hash: 'new-pa$s', + update_password: false + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it 'does not have alter role for "test" user with password as **** if update_password is false' do + expect(subject).not_to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + end + end + + context 'with version >= 14' do + let :pre_condition do + <<-CONDITION + class { 'postgresql::globals': + version => '14', + } + -> class { 'postgresql::server': } + CONDITION + end + + let :params do + { + password_hash: 'new-pa$s' + } + end + + it 'use "scram-sha-256" passwords' do + expect(subject).to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(ALTER ROLE "test" ENCRYPTED PASSWORD 'SCRAM-SHA-256$4096:dGVzdA==$ouY1SZtT3yAonoIzvLCooZPtHkO7WigotDMNWL/xSms=:wEl4ewQJMRO2W5lHfiDvtlbmPcHnF0J1iBe6l82YnrQ=')), + 'sensitive' => 'true', + 'unless' => sensitive( + %(SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'SCRAM-SHA-256$4096:dGVzdA==$ouY1SZtT3yAonoIzvLCooZPtHkO7WigotDMNWL/xSms=:wEl4ewQJMRO2W5lHfiDvtlbmPcHnF0J1iBe6l82YnrQ='), + ), + ) + end + end + + context 'with password_encryption "scram-sha-256"' do + let :pre_condition do + <<-CONDITION + class { 'postgresql::server': + password_encryption => 'scram-sha-256', + } + CONDITION + end + + let :params do + { + password_hash: 'new-pa$s', + connect_settings: { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + } + } + end + + it 'is expect to use "scram-sha-256" hashed password' do + expect(subject).to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(ALTER ROLE "test" ENCRYPTED PASSWORD 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'sensitive' => 'true', + 'unless' => sensitive(%(SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'connect_settings' => { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + }, + ) + end + end + + context 'with password_encryption "scram-sha-256" and older DBVERSION in connect_settings' do + let :pre_condition do + <<-CONDITION + class { 'postgresql::server': + password_encryption => 'scram-sha-256', + } + CONDITION + end + + let :params do + { + password_hash: 'new-pa$s', + connect_settings: { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + } + } + end + + it 'is expect to use "md5" hashed password' do + expect(subject).to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(ALTER ROLE "test" ENCRYPTED PASSWORD 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'sensitive' => 'true', + 'unless' => sensitive(%(SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'connect_settings' => { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + }, + ) + end + end + + context 'with password_encryption "scram-sha-256" and set hash type "md5"' do + let :pre_condition do + <<-CONDITION + class { 'postgresql::server': + password_encryption => 'scram-sha-256', + } + CONDITION + end + + let :params do + { + password_hash: 'new-pa$s', + hash: 'md5' + } + end + + it 'is expect to use "md5" hashed password' do + expect(subject).to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(ALTER ROLE "test" ENCRYPTED PASSWORD 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'sensitive' => 'true', + 'unless' => sensitive(%(SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + ) + end + end + + context 'with password_encryption "scram-sha-256" and "md5" hashed password' do + let :pre_condition do + <<-CONDITION + class { 'postgresql::server': + password_encryption => 'scram-sha-256', + } + CONDITION + end + + let :params do + { + password_hash: 'md5b6f7fcbbabb4befde4588a26c1cfd2fa' + } + end + + it 'is expect to use definded "md5" password_hash' do + expect(subject).to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + .with( + 'command' => sensitive(%(ALTER ROLE "test" ENCRYPTED PASSWORD 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + 'sensitive' => 'true', + 'unless' => sensitive(%(SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa')), + ) + end + end + + context 'with ensure set to absent' do + let :params do + { + ensure: 'absent' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it 'has drop role for "test" user if ensure absent' do + expect(subject).to contain_postgresql_psql('DROP ROLE "test"').that_requires('Service[postgresqld_instance_main]') + end + end + + context 'without including postgresql::server' do + it { is_expected.to compile } + it { is_expected.to contain_postgresql__server__role('test') } + end + + context 'standalone not managing server' do + let :params do + { + password_hash: 'new-pa$s', + connect_settings: { + 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1', + 'PGPORT' => '1234', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' + }, + psql_user: 'postgresql', + psql_group: 'postgresql', + psql_path: '/usr/bin', + module_workdir: '/tmp', + db: 'db' + } + end + + let :pre_condition do + '' + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.not_to contain_class('postgresql::server') } + end +end diff --git a/spec/defines/server/schema_spec.rb b/spec/defines/server/schema_spec.rb new file mode 100644 index 0000000000..a7bbf28412 --- /dev/null +++ b/spec/defines/server/schema_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::schema' do + include_examples 'Debian 11' + + let :title do + 'test' + end + + let :params do + { + owner: 'jane', + db: 'janedb' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql__server__schema('test') } + + context 'with different owner' do + let :params do + { + owner: 'nate', + db: 'natedb' + } + end + + it { is_expected.to contain_postgresql_psql('natedb: ALTER SCHEMA "test" OWNER TO "nate"') } + end +end diff --git a/spec/defines/server/table_grant_spec.rb b/spec/defines/server/table_grant_spec.rb new file mode 100644 index 0000000000..66c3624451 --- /dev/null +++ b/spec/defines/server/table_grant_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::table_grant' do + include_examples 'Debian 11' + + let :title do + 'test' + end + + let :params do + { + privilege: 'ALL', + db: 'test', + role: 'test', + table: 'foo' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql__server__table_grant('test') } + it { is_expected.to contain_postgresql__server__grant('table:test') } +end diff --git a/spec/defines/server/tablespace_spec.rb b/spec/defines/server/tablespace_spec.rb new file mode 100644 index 0000000000..4322961307 --- /dev/null +++ b/spec/defines/server/tablespace_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::tablespace' do + include_examples 'Debian 11' + + let :title do + 'test' + end + + let :params do + { + location: '/srv/data/foo' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_file('/srv/data/foo').with_ensure('directory') } + it { is_expected.to contain_postgresql__server__tablespace('test') } + it { is_expected.to contain_postgresql_psql('CREATE TABLESPACE "test"').that_requires('Service[postgresqld_instance_main]') } + + context 'with different owner' do + let :params do + { + location: '/srv/data/foo', + owner: 'test_owner' + } + end + + it { is_expected.to contain_postgresql_psql('ALTER TABLESPACE "test" OWNER TO "test_owner"') } + end + + context 'with manage_location set to false' do + let :params do + { + location: '/srv/data/foo', + manage_location: false + } + end + + let :pre_condition do + " + class {'postgresql::server':} + file {'/srv/data/foo': ensure => 'directory'} + " + end + + it { is_expected.to contain_file('/srv/data/foo').with_ensure('directory') } + end +end diff --git a/spec/defines/server_instance_spec.rb b/spec/defines/server_instance_spec.rb new file mode 100644 index 0000000000..ea63146fe4 --- /dev/null +++ b/spec/defines/server_instance_spec.rb @@ -0,0 +1,234 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server_instance' do + include_examples 'RedHat 8' + + let :pre_condition do + "class { 'postgresql::globals': + encoding => 'UTF-8', + locale => 'en_US.UTF-8', + manage_package_repo => false, + manage_dnf_module => true, + needs_initdb => true, + version => '13', + } + # stop default main instance + class { 'postgresql::server': + service_ensure => 'stopped', + service_enable => false, + }" + end + let(:title) { 'test1' } + let(:params) do + { + 'instance_user': 'ins_test1', + 'instance_group': 'ins_test1', + 'instance_directories': { '/opt/pgsql': { 'ensure' => 'directory' }, + '/opt/pgsql/backup': { 'ensure' => 'directory' }, + '/opt/pgsql/data': { 'ensure' => 'directory' }, + '/opt/pgsql/data/13': { 'ensure' => 'directory' }, + '/opt/pgsql/data/home': { 'ensure' => 'directory' }, + '/opt/pgsql/wal': { 'ensure' => 'directory' }, + '/opt/pgsql/log': { 'ensure' => 'directory' }, + '/opt/pgsql/log/13': { 'ensure' => 'directory' }, + '/opt/pgsql/log/13/test1': { 'ensure' => 'directory' }, }, + 'config_settings': { 'pg_hba_conf_path' => '/opt/pgsql/data/13/test1/pg_hba.conf', + 'postgresql_conf_path' => '/opt/pgsql/data/13/test1/postgresql.conf', + 'pg_ident_conf_path' => '/opt/pgsql/data/13/test1/pg_ident.conf', + 'datadir' => '/opt/pgsql/data/13/test1', + 'service_name' => 'postgresql@13-test1', + 'port' => 5433, + 'pg_hba_conf_defaults' => false }, + 'service_settings': { 'service_name' => 'postgresql@13-test1', + 'service_status' => 'systemctl status postgresql@13-test1.service', + 'service_ensure' => 'running', + 'service_enable' => true }, + 'initdb_settings': { 'auth_local' => 'peer', + 'auth_host' => 'md5', + 'needs_initdb' => true, + 'datadir' => '/opt/pgsql/data/13/test1', + 'encoding' => 'UTF-8', + 'lc_messages' => 'en_US.UTF8', + 'locale' => 'en_US.UTF8', + 'data_checksums' => false, + 'group' => 'postgres', + 'user' => 'postgres', + 'username' => 'ins_test1' }, + 'config_entries': { 'authentication_timeout': { 'value' => '1min', + 'comment' => 'a test' }, + 'log_statement_stats': { 'value' => 'off' }, + 'autovacuum_vacuum_scale_factor': { 'value' => 0.3 }, }, + 'databases': { 'testdb1': { 'encoding' => 'UTF8', + 'locale' => 'en_US.UTF8', + 'owner' => 'dba_test1' }, + 'testdb2': { 'encoding' => 'UTF8', + 'locale' => 'en_US.UTF8', + 'owner' => 'dba_test1' }, }, + 'roles': { 'ins_test1': { 'superuser' => true, + 'login' => true, }, + 'dba_test1': { 'createdb' => true, + 'login' => true, }, + 'app_test1': { 'login' => true }, + 'rep_test1': { 'replication' => true, + 'login' => true }, + 'rou_test1': { 'login' => true }, + 'val_test1': { 'login' => true, + 'valid_until' => '2030-01-01 00:00:00+00' }, }, + 'pg_hba_rules': { 'local all INSTANCE user': { 'type' => 'local', + 'database' => 'all', + 'user' => 'ins_test1', + 'auth_method' => 'peer', + 'order' => 1 }, + 'local all DB user': { 'type' => 'local', + 'database' => 'all', + 'user' => 'dba_test1', + 'auth_method' => 'peer', + 'order' => 2 }, + 'local all APP user': { 'type' => 'local', + 'database' => 'all', + 'user' => 'app_test1', + 'auth_method' => 'peer', + 'order' => 3 }, + 'local all READONLY user': { 'type' => 'local', + 'database' => 'all', + 'user' => 'rou_test1', + 'auth_method' => 'peer', + 'order' => 4 }, + 'remote all INSTANCE user PGADMIN server': { 'type' => 'host', + 'database' => 'all', + 'user' => 'ins_test1', + 'address' => '192.168.22.131/32', + 'auth_method' => 'md5', + 'order' => 5 }, + 'local replication INSTANCE user': { 'type' => 'local', + 'database' => 'replication', + 'user' => 'ins_test1', + 'auth_method' => 'peer', + 'order' => 6 }, + 'local replication REPLICATION user': { 'type' => 'local', + 'database' => 'replication', + 'user' => 'rep_test1', + 'auth_method' => 'peer', + 'order' => 7 }, }, + } + end + + context 'with postgresql instance test1' do + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server_instance('test1') } + it { is_expected.to contain_user('ins_test1') } + it { is_expected.to contain_group('ins_test1') } + it { is_expected.to contain_service('postgresqld_instance_test1').with_name('postgresql@13-test1').with_status('systemctl status postgresql@13-test1.service') } + it { is_expected.to contain_systemd__dropin_file('postgresql@13-test1.conf') } + it { is_expected.to contain_postgresql_conn_validator('validate_service_is_running_instance_test1') } + it { is_expected.to contain_postgresql_conf('port_for_instance_test1') } + it { is_expected.to contain_postgresql_conf('log_statement_stats_test1') } + it { is_expected.to contain_postgresql_conf('data_directory_for_instance_test1') } + it { is_expected.to contain_postgresql_conf('autovacuum_vacuum_scale_factor_test1') } + it { is_expected.to contain_postgresql_conf('authentication_timeout_test1') } + it { is_expected.to contain_postgresql__server__role('app_test1') } + it { is_expected.to contain_postgresql__server__role('dba_test1') } + it { is_expected.to contain_postgresql__server__role('ins_test1') } + it { is_expected.to contain_postgresql__server__role('rep_test1') } + it { is_expected.to contain_postgresql__server__role('rou_test1') } + it { is_expected.to contain_anchor('postgresql::server::service::begin::test1') } + it { is_expected.to contain_anchor('postgresql::server::service::end::test1') } + it { is_expected.to contain_class('Postgresql::Dnfmodule') } + it { is_expected.to contain_class('Postgresql::Server::Install') } + it { is_expected.to contain_class('Postgresql::Server::Reload') } + it { is_expected.to contain_concat__fragment('pg_hba_rule_local all APP user for instance test1') } + it { is_expected.to contain_concat__fragment('pg_hba_rule_local all DB user for instance test1') } + it { is_expected.to contain_concat__fragment('pg_hba_rule_local all INSTANCE user for instance test1') } + it { is_expected.to contain_concat__fragment('pg_hba_rule_local all READONLY user for instance test1') } + it { is_expected.to contain_concat__fragment('pg_hba_rule_local replication INSTANCE user for instance test1') } + it { is_expected.to contain_concat__fragment('pg_hba_rule_local replication REPLICATION user for instance test1') } + it { is_expected.to contain_concat__fragment('pg_hba_rule_remote all INSTANCE user PGADMIN server for instance test1') } + it { is_expected.to contain_concat('/opt/pgsql/data/13/test1/pg_hba.conf') } + it { is_expected.to contain_concat('/opt/pgsql/data/13/test1/pg_ident.conf') } + it { is_expected.to contain_exec('postgresql_initdb_instance_test1') } + it { is_expected.to contain_file('/opt/pgsql/backup') } + it { is_expected.to contain_file('/opt/pgsql/data/13/test1/postgresql.conf') } + it { is_expected.to contain_file('/opt/pgsql/data/13/test1') } + it { is_expected.to contain_file('/opt/pgsql/data/13') } + it { is_expected.to contain_file('/opt/pgsql/data/home') } + it { is_expected.to contain_file('/opt/pgsql/data') } + it { is_expected.to contain_file('/opt/pgsql/log/13/test1') } + it { is_expected.to contain_file('/opt/pgsql/log/13') } + it { is_expected.to contain_file('/opt/pgsql/log') } + it { is_expected.to contain_file('/opt/pgsql/wal') } + it { is_expected.to contain_file('/opt/pgsql') } + it { is_expected.to contain_postgresql__server__config_entry('authentication_timeout_test1') } + it { is_expected.to contain_postgresql__server__config_entry('autovacuum_vacuum_scale_factor_test1') } + it { is_expected.to contain_postgresql__server__config_entry('data_directory_for_instance_test1') } + it { is_expected.to contain_postgresql__server__config_entry('log_statement_stats_test1') } + it { is_expected.to contain_postgresql__server__config_entry('password_encryption_for_instance_test1') } + it { is_expected.to contain_postgresql__server__config_entry('port_for_instance_test1') } + it { is_expected.to contain_postgresql__server__database('testdb1') } + it { is_expected.to contain_postgresql__server__database('testdb2') } + it { is_expected.to contain_postgresql__server__instance__config('test1') } + it { is_expected.to contain_postgresql__server__instance__initdb('test1') } + it { is_expected.to contain_postgresql__server__instance__passwd('test1') } + it { is_expected.to contain_postgresql__server__instance__service('test1') } + it { is_expected.to contain_postgresql__server__instance__systemd('test1') } + it { is_expected.to contain_postgresql__server__pg_hba_rule('local all APP user for instance test1') } + it { is_expected.to contain_postgresql__server__pg_hba_rule('local all DB user for instance test1') } + it { is_expected.to contain_postgresql__server__pg_hba_rule('local all INSTANCE user for instance test1') } + it { is_expected.to contain_postgresql__server__pg_hba_rule('local all READONLY user for instance test1') } + it { is_expected.to contain_postgresql__server__pg_hba_rule('local replication INSTANCE user for instance test1') } + it { is_expected.to contain_postgresql__server__pg_hba_rule('local replication REPLICATION user for instance test1') } + it { is_expected.to contain_postgresql__server__pg_hba_rule('remote all INSTANCE user PGADMIN server for instance test1') } + it { is_expected.to contain_postgresql_psql('ALTER DATABASE "testdb1" OWNER TO "dba_test1"') } + it { is_expected.to contain_postgresql_psql('ALTER DATABASE "testdb2" OWNER TO "dba_test1"') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "app_test1" CONNECTION LIMIT -1') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "app_test1" INHERIT') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "app_test1" LOGIN') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "app_test1" NOCREATEDB') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "app_test1" NOCREATEROLE') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "app_test1" NOREPLICATION') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "app_test1" NOSUPERUSER') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "dba_test1" CONNECTION LIMIT -1') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "dba_test1" CREATEDB') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "dba_test1" INHERIT') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "dba_test1" LOGIN') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "dba_test1" NOCREATEROLE') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "dba_test1" NOREPLICATION') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "dba_test1" NOSUPERUSER') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "ins_test1" CONNECTION LIMIT -1') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "ins_test1" INHERIT') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "ins_test1" LOGIN') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "ins_test1" NOCREATEDB') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "ins_test1" NOCREATEROLE') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "ins_test1" NOREPLICATION') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "ins_test1" SUPERUSER') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rep_test1" CONNECTION LIMIT -1') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rep_test1" INHERIT') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rep_test1" LOGIN') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rep_test1" NOCREATEDB') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rep_test1" NOCREATEROLE') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rep_test1" NOSUPERUSER') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rep_test1" REPLICATION') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rou_test1" CONNECTION LIMIT -1') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rou_test1" INHERIT') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rou_test1" LOGIN') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rou_test1" NOCREATEDB') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rou_test1" NOCREATEROLE') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rou_test1" NOREPLICATION') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "rou_test1" NOSUPERUSER') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "val_test1" CONNECTION LIMIT -1') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "val_test1" INHERIT') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "val_test1" LOGIN') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "val_test1" NOCREATEDB') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "val_test1" NOCREATEROLE') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "val_test1" NOREPLICATION') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "val_test1" NOSUPERUSER') } + it { is_expected.to contain_postgresql_psql('ALTER ROLE "val_test1" VALID UNTIL \'2030-01-01 00:00:00+00\'') } + it { is_expected.to contain_postgresql_psql('CREATE ROLE app_test1 ENCRYPTED PASSWORD ****') } + it { is_expected.to contain_postgresql_psql('CREATE ROLE dba_test1 ENCRYPTED PASSWORD ****') } + it { is_expected.to contain_postgresql_psql('CREATE ROLE ins_test1 ENCRYPTED PASSWORD ****') } + it { is_expected.to contain_postgresql_psql('CREATE ROLE rep_test1 ENCRYPTED PASSWORD ****') } + it { is_expected.to contain_postgresql_psql('CREATE ROLE rou_test1 ENCRYPTED PASSWORD ****') } + it { is_expected.to contain_postgresql_psql('CREATE ROLE val_test1 ENCRYPTED PASSWORD ****') } + end +end diff --git a/spec/functions/postgresql_default_spec.rb b/spec/functions/postgresql_default_spec.rb new file mode 100644 index 0000000000..a1d0cd6d57 --- /dev/null +++ b/spec/functions/postgresql_default_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::default' do + let(:facts) do + { + 'os' => { + 'family' => 'Debian', + 'name' => 'Debian', + 'release' => { + 'full' => '11.7', + 'major' => '11', + 'minor' => '7', + } + } + } + end + + let(:pre_condition) do + <<~PP + class { 'postgresql::server': + } + PP + end + + # parameter in params.pp only + it { is_expected.to run.with_params('port').and_return(5432) } + + # parameter in globals.pp only + it { is_expected.to run.with_params('default_connect_settings').and_return({}) } + + it { is_expected.to run.with_params('password_encryption').and_return('md5') } + + it { is_expected.to run.with_params('a_parameter_that_does_not_exist').and_raise_error(Puppet::ParseError, %r{pick\(\): must receive at least one non empty value}) } + + context 'with overridden values' do + let(:pre_condition) do + <<~PUPPET + class { 'postgresql::globals': + password_encryption => 'scram-sha-256', + } + PUPPET + end + + it { is_expected.to run.with_params('password_encryption').and_return('scram-sha-256') } + end +end diff --git a/spec/functions/postgresql_escape_spec.rb b/spec/functions/postgresql_escape_spec.rb new file mode 100644 index 0000000000..2c140d96ea --- /dev/null +++ b/spec/functions/postgresql_escape_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql_escape' do + it_behaves_like 'postgresql_escape function' +end diff --git a/spec/functions/postgresql_password_spec.rb b/spec/functions/postgresql_password_spec.rb new file mode 100644 index 0000000000..1c75c9b6f8 --- /dev/null +++ b/spec/functions/postgresql_password_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql_password' do + include_examples 'Ubuntu 18.04' + + it_behaves_like 'postgresql_password function' +end diff --git a/spec/functions/postgresql_postgresql_acls_to_resources_hash_spec.rb b/spec/functions/postgresql_postgresql_acls_to_resources_hash_spec.rb new file mode 100644 index 0000000000..386f01d3e4 --- /dev/null +++ b/spec/functions/postgresql_postgresql_acls_to_resources_hash_spec.rb @@ -0,0 +1,151 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::postgresql_acls_to_resources_hash' do + it { is_expected.not_to be_nil } + + context 'individual transform tests' do + it do + input = 'local all postgres ident' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'postgres', + 'auth_method' => 'ident', + 'order' => '100' + } + } + expect(subject).to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input = 'local all root ident' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'root', + 'auth_method' => 'ident', + 'order' => '100' + } + } + expect(subject).to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input_array = ['local all all ident'] + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'all', + 'auth_method' => 'ident', + 'order' => '100' + } + } + expect(subject).to run.with_params(input_array, 'test', 100).and_return(result) + end + + it do + input = 'host all all 127.0.0.1/32 md5' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '127.0.0.1/32', + 'auth_method' => 'md5', + 'order' => '100' + } + } + expect(subject).to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input = 'host all all 0.0.0.0/0 md5' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '0.0.0.0/0', + 'auth_method' => 'md5', + 'order' => '100' + } + } + expect(subject).to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input = 'host all all ::1/128 md5' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '::1/128', + 'auth_method' => 'md5', + 'order' => '100' + } + } + expect(subject).to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input = 'host all all 1.1.1.1 255.255.255.0 md5' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '1.1.1.1 255.255.255.0', + 'auth_method' => 'md5', + 'order' => '100' + } + } + + expect(subject).to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input = 'host all all 1.1.1.1 255.255.255.0 ldap ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '1.1.1.1 255.255.255.0', + 'auth_method' => 'ldap', + 'auth_option' => 'ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"', + 'order' => '100' + } + } + + expect(subject).to run.with_params([input], 'test', 100).and_return(result) + end + end + + context 'error catching tests' do + it do + expect(subject).to run.with_params(['test'], 'test').and_raise_error(%r{expects 3 arguments, got 2}) + end + + it do + expect(subject).to run.with_params('test', 'test', 100).and_raise_error(%r{parameter 'acls' expects an Array value, got String}) + end + + it do + expect(subject).to run.with_params(['test'], 100, 'test').and_raise_error(%r{parameter 'id' expects a String value, got Integer}) + end + + it do + expect(subject).to run.with_params(['test'], 'test', 1).and_raise_error(%r{does not have enough parts}) + end + end + + it 'returns an empty hash when input is empty array' do + expect(subject).to run.with_params([], 'test', 100).and_return({}) + end +end diff --git a/spec/functions/postgresql_postgresql_escape_spec.rb b/spec/functions/postgresql_postgresql_escape_spec.rb new file mode 100644 index 0000000000..5c458f7d40 --- /dev/null +++ b/spec/functions/postgresql_postgresql_escape_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::postgresql_escape' do + it_behaves_like 'postgresql_escape function' +end diff --git a/spec/functions/postgresql_postgresql_password_spec.rb b/spec/functions/postgresql_postgresql_password_spec.rb new file mode 100644 index 0000000000..d66e5afea9 --- /dev/null +++ b/spec/functions/postgresql_postgresql_password_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::postgresql_password' do + include_examples 'Ubuntu 18.04' + + it_behaves_like 'postgresql_password function' +end diff --git a/spec/spec.opts b/spec/spec.opts deleted file mode 100644 index 91cd6427ed..0000000000 --- a/spec/spec.opts +++ /dev/null @@ -1,6 +0,0 @@ ---format -s ---colour ---loadby -mtime ---backtrace diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ab1e14199b..ae7c1f6818 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,31 +1,75 @@ -require 'puppetlabs_spec_helper/module_spec_helper' +# frozen_string_literal: true RSpec.configure do |c| - c.mock_with :rspec do |mock| - mock.syntax = [:expect, :should] + 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, +} + +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 + require 'deep_merge' + default_facts.deep_merge!(YAML.safe_load(File.read(f), permitted_classes: [], permitted_symbols: [], aliases: true)) + rescue StandardError => e + RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end - c.include PuppetlabsSpec::Files +end - c.before :each do - # Store any environment variables away to be restored later - @old_env = {} - ENV.each_key {|k| @old_env[k] = ENV[k]} +# read default_facts and merge them over what is provided by facterdb +default_facts.each do |fact, value| + add_custom_fact fact, value, merge_facts: true +end - if ENV['STRICT_VARIABLES'] == 'yes' - Puppet.settings[:strict_variables]=true - end +RSpec.configure do |c| + c.default_facts = default_facts + c.before :each do + # set to strictest setting for testing + # by default Puppet runs at warning level + Puppet.settings[:strict] = :warning + Puppet.settings[:strict_variables] = true + end + c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] + c.after(:suite) do + RSpec::Puppet::Coverage.report!(0) end - c.after :each do - PuppetlabsSpec::Files.cleanup + # 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 -# Convenience helper for returning parameters for a type from the -# catalogue. -def param(type, title, param) - param_value(catalogue, type, title, param) +# 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 -# With rspec-puppet v2.0 this allows coverage checks. -#at_exit { RSpec::Puppet::Coverage.report! } +# 'spec_overrides' from sync.yml will appear below this line diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 2525ec3fcc..4ac8d7e0f6 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,101 +1,6 @@ -require 'beaker-rspec/spec_helper' -require 'beaker-rspec/helpers/serverspec' -require 'beaker/puppet_install_helper' +# frozen_string_literal: true -run_puppet_install_helper +require 'puppet_litmus' +require 'spec_helper_acceptance_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_acceptance_local.rb')) -UNSUPPORTED_PLATFORMS = ['AIX','windows','Solaris','Suse'] - -class String - # Provide ability to remove indentation from strings, for the purpose of - # left justifying heredoc blocks. - def unindent - gsub(/^#{scan(/^\s*/).min_by{|l|l.length}}/, "") - end -end - -def shellescape(str) - str = str.to_s - - # An empty argument will be skipped, so return empty quotes. - return "''" if str.empty? - - str = str.dup - - # Treat multibyte characters as is. It is caller's responsibility - # to encode the string in the right encoding for the shell - # environment. - str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/, "\\\\\\1") - - # A LF cannot be escaped with a backslash because a backslash + LF - # combo is regarded as line continuation and simply ignored. - str.gsub!(/\n/, "'\n'") - - return str -end - -def psql(psql_cmd, user = 'postgres', exit_codes = [0,1], &block) - psql = "psql #{psql_cmd}" - shell("su #{shellescape(user)} -c #{shellescape(psql)}", :acceptable_exit_codes => exit_codes, &block) -end - - -RSpec.configure do |c| - # Project root - proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) - - # Readable test descriptions - c.formatter = :documentation - - # Configure all nodes in nodeset - c.before :suite do - # Install module and dependencies - puppet_module_install(:source => proj_root, :module_name => 'postgresql') - - # Set up selinux if appropriate. - if fact('osfamily') == 'RedHat' && fact('selinux') == 'true' - pp = <<-EOS - if $::osfamily == 'RedHat' and $::selinux == 'true' { - $semanage_package = $::operatingsystemmajrelease ? { - '5' => 'policycoreutils', - default => 'policycoreutils-python', - } - - package { $semanage_package: ensure => installed } - exec { 'set_postgres': - command => 'semanage port -a -t postgresql_port_t -p tcp 5433', - path => '/bin:/usr/bin/:/sbin:/usr/sbin', - subscribe => Package[$semanage_package], - } - } - EOS - - apply_manifest_on(agents, pp, :catch_failures => false) - end - - # net-tools required for netstat utility being used by be_listening - if fact('osfamily') == 'RedHat' && fact('operatingsystemmajrelease') == '7' - pp = <<-EOS - package { 'net-tools': ensure => installed } - EOS - - apply_manifest_on(agents, pp, :catch_failures => false) - end - - hosts.each do |host| - on host, "/bin/touch #{default['puppetpath']}/hiera.yaml" - on host, 'chmod 755 /root' - if fact_on(host, 'osfamily') == 'Debian' - on host, "echo \"en_US ISO-8859-1\nen_NG.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\n\" > /etc/locale.gen" - on host, '/usr/sbin/locale-gen' - on host, '/usr/sbin/update-locale' - end - - on host, puppet('module','install','puppetlabs-stdlib'), { :acceptable_exit_codes => [0,1] } - on host, puppet('module','install','puppetlabs-apt'), { :acceptable_exit_codes => [0,1] } - on host, puppet('module','install','--force','puppetlabs-concat'), { :acceptable_exit_codes => [0,1] } - end - - - end -end +PuppetLitmus.configure! diff --git a/spec/spec_helper_acceptance_local.rb b/spec/spec_helper_acceptance_local.rb new file mode 100644 index 0000000000..669741c6c1 --- /dev/null +++ b/spec/spec_helper_acceptance_local.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +require 'singleton' + +class LitmusHelper + include Singleton + include PuppetLitmus +end + +class String + def unindent + gsub(%r{^#{scan(%r{^\s*}).min_by(&:length)}}, '') + end +end + +RSpec.configure do |c| + c.before :suite do + install_dependencies + end +end + +def export_locales(locale) + LitmusHelper.instance.run_shell('echo export PATH="/opt/puppetlabs/bin:$PATH" > ~/.bashrc') + LitmusHelper.instance.run_shell('echo export LC_ALL="C" > /etc/profile.d/my-custom.lang.sh') + LitmusHelper.instance.run_shell("echo \"## #{locale} ##\" >> /etc/profile.d/my-custom.lang.sh") + LitmusHelper.instance.run_shell("echo export LANG=#{locale} >> /etc/profile.d/my-custom.lang.sh") + LitmusHelper.instance.run_shell("echo export LANGUAGE=#{locale} >> /etc/profile.d/my-custom.lang.sh") + LitmusHelper.instance.run_shell('echo export LC_COLLATE=C >> /etc/profile.d/my-custom.lang.sh') + LitmusHelper.instance.run_shell("echo export LC_CTYPE=#{locale} >> /etc/profile.d/my-custom.lang.sh") + LitmusHelper.instance.run_shell('echo export LC_ALL="C" >> ~/.bashrc') +end + +def pre_run + LitmusHelper.instance.apply_manifest("class { 'postgresql::server': postgres_password => 'postgres' }", catch_failures: true) +end + +def install_dependencies + LitmusHelper.instance.apply_manifest <<~MANIFEST + if $facts['os']['name'] == 'Ubuntu' and $facts['os']['release']['major'] == '18.04' { + package { 'iproute2': + ensure => installed, + } + } + + # needed for netstat, for serverspec checks + if $facts['os']['family'] in ['SLES', 'SUSE'] { + exec { 'Enable legacy repos': + path => '/bin:/usr/bin/:/sbin:/usr/sbin', + command => "SUSEConnect --product sle-module-legacy/${$facts['os']['distro']['release']['full']}/x86_64", + unless => "SUSEConnect --status-text | grep sle-module-legacy/${$facts['os']['distro']['release']['full']}/x86_64", + } + + package { 'net-tools-deprecated': + ensure => 'latest', + } + } + + if $facts['os']['family'] == 'RedHat' { + if versioncmp($facts['os']['release']['major'], '8') >= 0 { + $package = ['iproute', 'policycoreutils-python-utils'] + } else { + $package = 'policycoreutils-python' + } + package { $package: + ensure => installed, + } + } + MANIFEST +end + +def postgresql_version + result = LitmusHelper.instance.run_shell('psql --version') + result.stdout.match(%r{\s(\d{1,2}\.\d)})[1] +end + +def psql(psql_cmd, user = 'postgres', exit_codes = [0, 1], &block) + psql = "psql #{psql_cmd}" + LitmusHelper.instance.run_shell("cd /tmp; su #{shellescape(user)} -c #{shellescape(psql)}", acceptable_exit_codes: exit_codes, &block) +end + +def shellescape(str) + str = str.to_s + + # An empty argument will be skipped, so return empty quotes. + return "''" if str.empty? + + str = str.dup + + # Treat multibyte characters as is. It is caller's responsibility + # to encode the string in the right encoding for the shell + # environment. + str.gsub!(%r{([^A-Za-z0-9_\-.,:/@\n])}, '\\\\\\1') + + # A LF cannot be escaped with a backslash because a backslash + LF + # combo is regarded as line continuation and simply ignored. + str.gsub!(%r{\n}, "'\n'") + + str +end diff --git a/spec/spec_helper_local.rb b/spec/spec_helper_local.rb new file mode 100644 index 0000000000..930b943217 --- /dev/null +++ b/spec/spec_helper_local.rb @@ -0,0 +1,269 @@ +# frozen_string_literal: true + +RSpec.configure do |c| + c.mock_with :rspec + + c.include PuppetlabsSpec::Files + c.after :each do + PuppetlabsSpec::Files.cleanup + end +end + +if ENV['COVERAGE'] == 'yes' + require 'simplecov' + require 'simplecov-console' + require 'codecov' + + SimpleCov.formatters = [ + SimpleCov::Formatter::HTMLFormatter, + SimpleCov::Formatter::Console, + SimpleCov::Formatter::Codecov, + ] + SimpleCov.start do + track_files 'lib/**/*.rb' + + add_filter '/spec' + + # do not track vendored files + add_filter '/vendor' + add_filter '/.vendor' + + # do not track gitignored files + # this adds about 4 seconds to the coverage check + # this could definitely be optimized + add_filter do |f| + # system returns true if exit status is 0, which with git-check-ignore means file is ignored + system('git', 'check-ignore', '--quiet', f.filename) + end + end +end + +# Convenience helper for returning parameters for a type from the +# catalogue. +def param(type, title, param) + param_value(catalogue, type, title, param) +end + +shared_examples 'postgresql_password function' do + it { is_expected.not_to be_nil } + + it { + expect(subject).to run.with_params('foo', 'bar').and_return( + 'md596948aad3fcae80c08a35c9b5958cd89', + ) + } + + it { + expect(subject).to run.with_params('foo', 1234).and_return( + 'md539a0e1b308278a8de5e007cd1f795920', + ) + } + + it { + expect(subject).to run.with_params('foo', 'bar', true).and_return( + sensitive(%(md596948aad3fcae80c08a35c9b5958cd89)), + ) + } + + it { + expect(subject).to run.with_params('foo', 'bar', false, 'scram-sha-256').and_return( + 'SCRAM-SHA-256$4096:Zm9v$ea66ynZ8cS9Ty4ZkEYicwC72StsKLSwjcXIXKMgepTk=:dJYmOU6BMCaWkQOB3lrXH9OAF3lW2n3NJ26NO7Srq7U=', + ) + } + + it { + expect(subject).to run.with_params('foo', 'bar', true, 'scram-sha-256').and_return( + sensitive(%(SCRAM-SHA-256$4096:Zm9v$ea66ynZ8cS9Ty4ZkEYicwC72StsKLSwjcXIXKMgepTk=:dJYmOU6BMCaWkQOB3lrXH9OAF3lW2n3NJ26NO7Srq7U=)), + ) + } + + it { + expect(subject).to run.with_params('foo', 'bar', false, 'scram-sha-256', 'salt').and_return( + 'SCRAM-SHA-256$4096:c2FsdA==$hl63wu9L6vKIjd/UGPfpRl/hIQRBnlkoCiJ9KgxzbX0=:3Q39uiwDZ51m3iPpV8rSgISgRiYqkbnpc+wScL2lSAU=', + ) + } + + it { + expect(subject).to run.with_params('foo', 'bar', true, 'scram-sha-256', 'salt').and_return( + sensitive(%(SCRAM-SHA-256$4096:c2FsdA==$hl63wu9L6vKIjd/UGPfpRl/hIQRBnlkoCiJ9KgxzbX0=:3Q39uiwDZ51m3iPpV8rSgISgRiYqkbnpc+wScL2lSAU=)), + ) + } + + it { + expect(subject).to run.with_params('foo', 'bar', false, nil, 'salt').and_return( + 'md596948aad3fcae80c08a35c9b5958cd89', + ) + } + + it { + expect(subject).to run.with_params('foo', 'bar', true, nil, 'salt').and_return( + sensitive(%(md596948aad3fcae80c08a35c9b5958cd89)), + ) + } + + it { + expect(subject).to run.with_params('foo', 'md596948aad3fcae80c08a35c9b5958cd89', false).and_return( + 'md596948aad3fcae80c08a35c9b5958cd89', + ) + } + + it { + expect(subject).to run.with_params('foo', sensitive(%(SCRAM-SHA-256$4096:c2FsdA==$hl63wu9L6vKIjd/UGPfpRl/hIQRBnlkoCiJ9KgxzbX0=:3Q39uiwDZ51m3iPpV8rSgISgRiYqkbnpc+wScL2lSAU=)), true).and_return( + sensitive(%(SCRAM-SHA-256$4096:c2FsdA==$hl63wu9L6vKIjd/UGPfpRl/hIQRBnlkoCiJ9KgxzbX0=:3Q39uiwDZ51m3iPpV8rSgISgRiYqkbnpc+wScL2lSAU=)), + ) + } + + it { + expect(subject).to run.with_params('foo', sensitive('md596948aad3fcae80c08a35c9b5958cd89'), false).and_return( + 'md596948aad3fcae80c08a35c9b5958cd89', + ) + } + + it 'raises an error if there is only 1 argument' do + expect(subject).to run.with_params('foo').and_raise_error(StandardError) + end +end + +shared_examples 'postgresql_escape function' do + it { is_expected.not_to be_nil } + + it { + expect(subject).to run.with_params('foo') + .and_return('$$foo$$') + } + + it { + expect(subject).to run.with_params('fo$$o') + .and_return('$ed$fo$$o$ed$') + } + + it { + expect(subject).to run.with_params('foo$') + .and_return('$a$foo$$a$') + } + + it 'raises an error if there is more than 1 argument' do + expect(subject).to run.with_params(['foo'], ['foo']) + .and_raise_error(StandardError) + end +end + +# This duplicates spec_helper but we need it for add_custom_fact +include RspecPuppetFacts +# Rough conversion of grepping in the puppet source: +# grep defaultfor lib/puppet/provider/service/*.rb +# See https://github.com/voxpupuli/voxpupuli-test/blob/master/lib/voxpupuli/test/facts.rb +add_custom_fact :service_provider, ->(_os, facts) do + case facts[:osfamily].downcase + when 'archlinux', 'debian' + 'systemd' + when 'darwin' + 'launchd' + when 'freebsd' + 'freebsd' + when 'gentoo' + 'openrc' + when 'openbsd' + 'openbsd' + when 'redhat' + (facts[:operatingsystemrelease].to_i >= 7) ? 'systemd' : 'redhat' + when 'suse' + (facts[:operatingsystemmajrelease].to_i >= 12) ? 'systemd' : 'redhat' + when 'windows' + 'windows' + else + 'init' + end +end + +shared_context 'Debian 10' do + let(:facts) { on_supported_os['debian-10-x86_64'] } +end + +shared_context 'Debian 11' do + let(:facts) { on_supported_os['debian-11-x86_64'] } +end + +shared_context 'Debian 12' do + let(:facts) { on_supported_os['debian-12-x86_64'] } +end + +shared_context 'Ubuntu 18.04' do + let(:facts) { on_supported_os['ubuntu-18.04-x86_64'] } +end + +shared_context 'RedHat 7' do + let(:facts) { on_supported_os['redhat-7-x86_64'] } +end + +shared_context 'RedHat 8' do + let(:facts) { on_supported_os['redhat-8-x86_64'] } +end + +shared_context 'Fedora 33' do + let(:facts) do + { + kernel: 'Linux', + id: 'root', + path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + selinux: true, + os: { + 'architecture' => 'x86_64', + 'family' => 'RedHat', + 'hardware' => 'x86_64', + 'name' => 'Fedora', + 'release' => { + 'full' => '33', + 'major' => '33', + 'minor' => '33' + }, + selinux: { 'enabled' => true } + }, + operatingsystem: 'Fedora', + operatingsystemrelease: '33', + service_provider: 'systemd' + } + end +end + +shared_context 'Amazon 1' do + let :facts do + { + os: { + family: 'RedHat', + name: 'Amazon', + release: { + 'full' => '1.0', + 'major' => '1' + }, + selinux: { 'enabled' => true } + }, + kernel: 'Linux', + id: 'root', + path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + selinux: true, + service_provider: 'redhat' + } + end +end + +shared_context 'Gentoo' do + let :facts do + { + os: { + family: 'Gentoo', + name: 'Gentoo', + release: { + 'full' => 'unused', + 'major' => 'unused' + }, + selinux: { 'enabled' => false } + }, + kernel: 'Linux', + id: 'root', + path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + selinux: false, + service_provider: 'openrc' + } + end +end diff --git a/spec/type_aliases/pg_hba_rule_spec.rb b/spec/type_aliases/pg_hba_rule_spec.rb new file mode 100644 index 0000000000..e4d0fe007b --- /dev/null +++ b/spec/type_aliases/pg_hba_rule_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Postgresql::Pg_hba_rule' do + context 'base valid required data' do + let :data do + { + description: 'pc', + type: 'host', + database: 'all', + user: 'all', + address: '127.0.0.1/32', + auth_method: 'md5', + target: '/foo.conf', + postgresql_version: '14', + order: 3 + } + end + + it { is_expected.to allow_value(data) } + end + + context 'invalid data' do + let :data do + { + description: 'pc', + type: 'host', + database: 'all', + user: 'all', + address: '/32', + auth_method: 'md5', + target: '/foo.conf', + postgres_version: '14' + } + end + + it { is_expected.not_to allow_value(data) } + end + + context 'empty data' do + let :data do + {} + end + + it { is_expected.not_to allow_value(data) } + end +end diff --git a/spec/type_aliases/pg_hba_rule_type_spec.rb b/spec/type_aliases/pg_hba_rule_type_spec.rb new file mode 100644 index 0000000000..431db29a07 --- /dev/null +++ b/spec/type_aliases/pg_hba_rule_type_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Postgresql::Pg_hba_rule_type' do + describe 'valid values' do + [ + 'local', + 'host', + 'hostssl', + 'hostnossl', + 'hostgssenc', + 'hostnogssenc', + ].each do |value| + describe value.inspect do + it { is_expected.to allow_value(value) } + end + end + end + + describe 'invalid values' do + context 'with garbage inputs' do + [ + :symbol, + nil, + 'foobar', + '', + true, + false, + ['meep', 'meep'], + 65_538, + [95_000, 67_000], + {}, + { 'foo' => 'bar' }, + ].each do |value| + describe value.inspect do + it { is_expected.not_to allow_value(value) } + end + end + end + end +end diff --git a/spec/type_aliases/pg_hba_rules_spec.rb b/spec/type_aliases/pg_hba_rules_spec.rb new file mode 100644 index 0000000000..316de2f868 --- /dev/null +++ b/spec/type_aliases/pg_hba_rules_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Postgresql::Pg_hba_rules' do + context 'base valid required data' do + let :data do + { + foo: { + description: 'pc', + type: 'host', + database: 'all', + user: 'all', + address: '127.0.0.1/32', + auth_method: 'md5', + target: '/foo.conf', + postgresql_version: '14', + order: 1 + }, + foo2: { + description: 'pc', + type: 'host', + database: 'all', + user: 'all', + address: '127.0.0.1/32', + auth_method: 'md5', + target: '/foo.conf', + postgresql_version: '14', + order: 2 + } + } + end + + it { is_expected.to allow_value(data) } + end + + context 'empty' do + let :data do + {} + end + + it { is_expected.to allow_value(data) } + end + + context 'invalid data' do + let :data do + { + description: 'pc', + type: 'host', + database: 'all', + user: 'all', + address: '/32', + auth_method: 'md5' + } + end + + it { is_expected.not_to allow_value(data) } + end + + context 'empty value' do + let :data do + { + foo: {} + } + end + + it { is_expected.not_to allow_value(data) } + end +end diff --git a/spec/unit/classes/client_spec.rb b/spec/unit/classes/client_spec.rb deleted file mode 100644 index 3d63b4647e..0000000000 --- a/spec/unit/classes/client_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::client', :type => :class do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - } - end - - describe 'with parameters' do - let :params do - { - :validcon_script_path => '/opt/bin/my-validate-con.sh', - :package_ensure => 'absent', - :package_name => 'mypackage', - :file_ensure => 'file' - } - end - - it 'should modify package' do - is_expected.to contain_package("postgresql-client").with({ - :ensure => 'absent', - :name => 'mypackage', - :tag => 'postgresql', - }) - end - - it 'should have specified validate connexion' do - should contain_file('/opt/bin/my-validate-con.sh').with({ - :ensure => 'file', - :owner => 0, - :group => 0, - :mode => '0755' - }) - end - end - - describe 'with no parameters' do - it 'should create package with postgresql tag' do - is_expected.to contain_package('postgresql-client').with({ - :tag => 'postgresql', - }) - end - end -end diff --git a/spec/unit/classes/globals_spec.rb b/spec/unit/classes/globals_spec.rb deleted file mode 100644 index ce79336233..0000000000 --- a/spec/unit/classes/globals_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::globals', :type => :class do - context "on a debian 6" do - let (:facts) do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :lsbdistid => 'Debian', - :lsbdistcodename => 'squeeze', - } - end - - describe 'with no parameters' do - it 'should work' do - is_expected.to contain_class("postgresql::globals") - end - end - - describe 'manage_package_repo => true' do - let(:params) do - { - :manage_package_repo => true, - } - end - it 'should pull in class postgresql::repo' do - is_expected.to contain_class("postgresql::repo") - end - end - end - - context 'on redhat family systems' do - let (:facts) do - { - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', - :operatingsystemrelease => '7.1', - } - end - describe 'with no parameters' do - it 'should work' do - is_expected.to contain_class("postgresql::globals") - end - end - - describe 'manage_package_repo on RHEL => true' do - let(:params) do - { - :manage_package_repo => true, - :repo_proxy => 'http://proxy-server:8080', - } - end - - it 'should pull in class postgresql::repo' do - is_expected.to contain_class("postgresql::repo") - end - - it do - should contain_yumrepo('yum.postgresql.org').with( - 'enabled' => '1', - 'proxy' => 'http://proxy-server:8080' - ) - end - end - end -end diff --git a/spec/unit/classes/lib/devel_spec.rb b/spec/unit/classes/lib/devel_spec.rb deleted file mode 100644 index 17aa7f2171..0000000000 --- a/spec/unit/classes/lib/devel_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::lib::devel', :type => :class do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - } - end - it { is_expected.to contain_class("postgresql::lib::devel") } - - describe 'link pg_config to /usr/bin' do - it { should_not contain_file('/usr/bin/pg_config') \ - .with_ensure('link') \ - .with_target('/usr/lib/postgresql/8.4/bin/pg_config') - } - end - - describe 'disable link_pg_config' do - let(:params) {{ - :link_pg_config => false, - }} - it { should_not contain_file('/usr/bin/pg_config') } - end - - describe 'should not link pg_config on RedHat with default version' do - let(:facts) {{ - :osfamily => 'RedHat', - :operatingsystem => 'CentOS', - :operatingsystemrelease => '6.3', - :operatingsystemmajrelease => '6', - }} - it { should_not contain_file('/usr/bin/pg_config') } - end - - describe 'link pg_config on RedHat with non-default version' do - let(:facts) {{ - :osfamily => 'RedHat', - :operatingsystem => 'CentOS', - :operatingsystemrelease => '6.3', - :operatingsystemmajrelease => '6', - }} - let :pre_condition do - "class { '::postgresql::globals': version => '9.3' }" - end - - it { should contain_file('/usr/bin/pg_config') \ - .with_ensure('link') \ - .with_target('/usr/pgsql-9.3/bin/pg_config') - } - end - -end diff --git a/spec/unit/classes/lib/java_spec.rb b/spec/unit/classes/lib/java_spec.rb deleted file mode 100644 index f31c3f032e..0000000000 --- a/spec/unit/classes/lib/java_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::lib::java', :type => :class do - - describe 'on a debian based os' do - let :facts do { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - } - end - it { is_expected.to contain_package('postgresql-jdbc').with( - :name => 'libpostgresql-jdbc-java', - :ensure => 'present', - :tag => 'postgresql' - )} - end - - describe 'on a redhat based os' do - let :facts do { - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', - :operatingsystemrelease => '6.4', - } - end - it { is_expected.to contain_package('postgresql-jdbc').with( - :name => 'postgresql-jdbc', - :ensure => 'present', - :tag => 'postgresql' - )} - describe 'when parameters are supplied' do - let :params do - {:package_ensure => 'latest', :package_name => 'somepackage'} - end - it { is_expected.to contain_package('postgresql-jdbc').with( - :name => 'somepackage', - :ensure => 'latest', - :tag => 'postgresql' - )} - end - end - -end diff --git a/spec/unit/classes/lib/perl_spec.rb b/spec/unit/classes/lib/perl_spec.rb deleted file mode 100644 index 922cfa0b85..0000000000 --- a/spec/unit/classes/lib/perl_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::lib::perl', :type => :class do - - describe 'on a redhat based os' do - let :facts do { - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', - :operatingsystemrelease => '6.4', - } - end - it { is_expected.to contain_package('perl-DBD-Pg').with( - :name => 'perl-DBD-Pg', - :ensure => 'present' - )} - end - - describe 'on a debian based os' do - let :facts do { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - } - end - it { is_expected.to contain_package('perl-DBD-Pg').with( - :name => 'libdbd-pg-perl', - :ensure => 'present' - )} - end - -end diff --git a/spec/unit/classes/lib/pgdocs_spec.rb b/spec/unit/classes/lib/pgdocs_spec.rb deleted file mode 100644 index a751e987d2..0000000000 --- a/spec/unit/classes/lib/pgdocs_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::lib::docs', :type => :class do - - describe 'on a redhat based os' do - let :facts do { - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', - :operatingsystemrelease => '6.4', - } - end - it { is_expected.to contain_package('postgresql-docs').with( - :name => 'postgresql-docs', - :ensure => 'present', - :tag => 'postgresql' - )} - describe 'when parameters are supplied' do - let :params do - {:package_ensure => 'latest', :package_name => 'somepackage'} - end - it { is_expected.to contain_package('postgresql-docs').with( - :name => 'somepackage', - :ensure => 'latest', - :tag => 'postgresql' - )} - end - end - -end diff --git a/spec/unit/classes/lib/python_spec.rb b/spec/unit/classes/lib/python_spec.rb deleted file mode 100644 index 095c2e15a1..0000000000 --- a/spec/unit/classes/lib/python_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::lib::python', :type => :class do - - describe 'on a redhat based os' do - let :facts do { - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', - :operatingsystemrelease => '6.4', - } - end - it { is_expected.to contain_package('python-psycopg2').with( - :name => 'python-psycopg2', - :ensure => 'present' - )} - end - - describe 'on a debian based os' do - let :facts do { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - } - end - it { is_expected.to contain_package('python-psycopg2').with( - :name => 'python-psycopg2', - :ensure => 'present' - )} - end - -end diff --git a/spec/unit/classes/params_spec.rb b/spec/unit/classes/params_spec.rb deleted file mode 100644 index a415966e10..0000000000 --- a/spec/unit/classes/params_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::params', :type => :class do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - } - end - it { is_expected.to contain_class("postgresql::params") } -end diff --git a/spec/unit/classes/repo_spec.rb b/spec/unit/classes/repo_spec.rb deleted file mode 100644 index a9be84e7cd..0000000000 --- a/spec/unit/classes/repo_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::repo', :type => :class do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :lsbdistid => 'Debian', - :lsbdistcodename => 'squeeze', - } - end - - describe 'with no parameters' do - it 'should instantiate apt_postgresql_org class' do - is_expected.to contain_class('postgresql::repo::apt_postgresql_org') - end - end -end diff --git a/spec/unit/classes/server/config_spec.rb b/spec/unit/classes/server/config_spec.rb deleted file mode 100644 index c03032d9b3..0000000000 --- a/spec/unit/classes/server/config_spec.rb +++ /dev/null @@ -1,101 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::config', :type => :class do - let (:pre_condition) do - "include postgresql::server" - end - - describe 'on RedHat 7' do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'CentOS', - :operatingsystemrelease => '7.0', - :concat_basedir => tmpfilename('server'), - :kernel => 'Linux', - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - it 'should have the correct systemd-override file' do - is_expected.to contain_file('systemd-override').with ({ - :ensure => 'present', - :path => '/etc/systemd/system/postgresql.service', - :owner => 'root', - :group => 'root', - }) - is_expected.to contain_file('systemd-override') \ - .with_content(/.include \/usr\/lib\/systemd\/system\/postgresql.service/) - end - - describe 'with manage_package_repo => true and a version' do - let (:pre_condition) do - <<-EOS - class { 'postgresql::globals': - manage_package_repo => true, - version => '9.4', - }-> - class { 'postgresql::server': } - EOS - end - - it 'should have the correct systemd-override file' do - is_expected.to contain_file('systemd-override').with ({ - :ensure => 'present', - :path => '/etc/systemd/system/postgresql-9.4.service', - :owner => 'root', - :group => 'root', - }) - is_expected.to contain_file('systemd-override') \ - .with_content(/.include \/usr\/lib\/systemd\/system\/postgresql-9.4.service/) - end - end - end - - describe 'on Fedora 21' do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'Fedora', - :operatingsystemrelease => '21', - :concat_basedir => tmpfilename('server'), - :kernel => 'Linux', - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - it 'should have the correct systemd-override file' do - is_expected.to contain_file('systemd-override').with ({ - :ensure => 'present', - :path => '/etc/systemd/system/postgresql.service', - :owner => 'root', - :group => 'root', - }) - is_expected.to contain_file('systemd-override') \ - .with_content(/.include \/lib\/systemd\/system\/postgresql.service/) - end - - describe 'with manage_package_repo => true and a version' do - let (:pre_condition) do - <<-EOS - class { 'postgresql::globals': - manage_package_repo => true, - version => '9.4', - }-> - class { 'postgresql::server': } - EOS - end - - it 'should have the correct systemd-override file' do - is_expected.to contain_file('systemd-override').with ({ - :ensure => 'present', - :path => '/etc/systemd/system/postgresql-9.4.service', - :owner => 'root', - :group => 'root', - }) - is_expected.to contain_file('systemd-override') \ - .with_content(/.include \/lib\/systemd\/system\/postgresql-9.4.service/) - end - end - end -end diff --git a/spec/unit/classes/server/contrib_spec.rb b/spec/unit/classes/server/contrib_spec.rb deleted file mode 100644 index b84f764d0b..0000000000 --- a/spec/unit/classes/server/contrib_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::contrib', :type => :class do - let :pre_condition do - "class { 'postgresql::server': }" - end - - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - describe 'with parameters' do - let(:params) do - { - :package_name => 'mypackage', - :package_ensure => 'absent', - } - end - - it 'should create package with correct params' do - is_expected.to contain_package('postgresql-contrib').with({ - :ensure => 'absent', - :name => 'mypackage', - :tag => 'postgresql', - }) - end - end - - describe 'with no parameters' do - it 'should create package with postgresql tag' do - is_expected.to contain_package('postgresql-contrib').with({ - :tag => 'postgresql', - }) - end - end -end diff --git a/spec/unit/classes/server/initdb_spec.rb b/spec/unit/classes/server/initdb_spec.rb deleted file mode 100644 index 5ddfb70045..0000000000 --- a/spec/unit/classes/server/initdb_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::initdb', :type => :class do - let (:pre_condition) do - "include postgresql::server" - end - describe 'on RedHat' do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'CentOS', - :operatingsystemrelease => '6.0', - :concat_basedir => tmpfilename('server'), - :kernel => 'Linux', - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - it { is_expected.to contain_file('/var/lib/pgsql/data').with_ensure('directory') } - end - describe 'on Amazon' do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'Amazon', - :operatingsystemrelease => '1.0', - :concat_basedir => tmpfilename('server'), - :kernel => 'Linux', - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - it { is_expected.to contain_file('/var/lib/pgsql92/data').with_ensure('directory') } - end -end - diff --git a/spec/unit/classes/server/plperl_spec.rb b/spec/unit/classes/server/plperl_spec.rb deleted file mode 100644 index 00ddf09c5e..0000000000 --- a/spec/unit/classes/server/plperl_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::plperl', :type => :class do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('plperl'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let :pre_condition do - "class { 'postgresql::server': }" - end - - describe 'with no parameters' do - it { is_expected.to contain_class("postgresql::server::plperl") } - it 'should create package' do - is_expected.to contain_package('postgresql-plperl').with({ - :ensure => 'present', - :tag => 'postgresql', - }) - end - end - - describe 'with parameters' do - let :params do - { - :package_ensure => 'absent', - :package_name => 'mypackage', - } - end - - it { is_expected.to contain_class("postgresql::server::plperl") } - it 'should create package with correct params' do - is_expected.to contain_package('postgresql-plperl').with({ - :ensure => 'absent', - :name => 'mypackage', - :tag => 'postgresql', - }) - end - end -end diff --git a/spec/unit/classes/server/plpython_spec.rb b/spec/unit/classes/server/plpython_spec.rb deleted file mode 100644 index f2e1654115..0000000000 --- a/spec/unit/classes/server/plpython_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::plpython', :type => :class do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'CentOS', - :operatingsystemrelease => '6.0', - :concat_basedir => tmpfilename('plpython'), - :kernel => 'Linux', - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let :pre_condition do - "class { 'postgresql::server': }" - end - - describe 'on RedHat with no parameters' do - it { is_expected.to contain_class("postgresql::server::plpython") } - it 'should create package' do - is_expected.to contain_package('postgresql-plpython').with({ - :ensure => 'present', - :tag => 'postgresql', - }) - end - end - - describe 'with parameters' do - let :params do - { - :package_ensure => 'absent', - :package_name => 'mypackage', - } - end - - it { is_expected.to contain_class("postgresql::server::plpython") } - it 'should create package with correct params' do - is_expected.to contain_package('postgresql-plpython').with({ - :ensure => 'absent', - :name => 'mypackage', - :tag => 'postgresql', - }) - end - end -end diff --git a/spec/unit/classes/server/postgis_spec.rb b/spec/unit/classes/server/postgis_spec.rb deleted file mode 100644 index 1e53c21c5a..0000000000 --- a/spec/unit/classes/server/postgis_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::postgis', :type => :class do - let :pre_condition do - "class { 'postgresql::server': }" - end - - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('postgis'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - describe 'with parameters' do - let(:params) do - { - :package_name => 'mypackage', - :package_ensure => 'absent', - } - end - - it 'should create package with correct params' do - is_expected.to contain_package('postgresql-postgis').with({ - :ensure => 'absent', - :name => 'mypackage', - :tag => 'postgresql', - }) - end - end - - describe 'with no parameters' do - it 'should create package with postgresql tag' do - is_expected.to contain_package('postgresql-postgis').with({ - :tag => 'postgresql', - }) - end - end -end diff --git a/spec/unit/classes/server_spec.rb b/spec/unit/classes/server_spec.rb deleted file mode 100644 index b42343cbc8..0000000000 --- a/spec/unit/classes/server_spec.rb +++ /dev/null @@ -1,142 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server', :type => :class do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :concat_basedir => tmpfilename('server'), - :kernel => 'Linux', - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - describe 'with no parameters' do - it { is_expected.to contain_class("postgresql::params") } - it { is_expected.to contain_class("postgresql::server") } - it { is_expected.to contain_exec('postgresql_reload').with({ - 'command' => 'service postgresql reload', - }) - } - it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') - end - end - - describe 'service_ensure => running' do - let(:params) do - { - :service_ensure => 'running', - :postgres_password => 'new-p@s$word-to-set' - } - end - it { is_expected.to contain_class("postgresql::params") } - it { is_expected.to contain_class("postgresql::server") } - it { is_expected.to contain_class("postgresql::server::passwd") } - it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') - end - it 'should set postgres password' do - is_expected.to contain_exec('set_postgres_postgrespw').with({ - 'command' => '/usr/bin/psql -c "ALTER ROLE \"postgres\" PASSWORD ${NEWPASSWD_ESCAPED}"', - 'user' => 'postgres', - 'environment' => [ - "PGPASSWORD=new-p@s$word-to-set", - "NEWPASSWD_ESCAPED=$$new-p@s$word-to-set$$" - ], - 'unless' => "/usr/bin/psql -h localhost -p 5432 -c 'select 1' > /dev/null", - }) - end - end - - describe 'service_ensure => stopped' do - let(:params) {{ :service_ensure => 'stopped' }} - it { is_expected.to contain_class("postgresql::params") } - it { is_expected.to contain_class("postgresql::server") } - it 'shouldnt validate connection' do - is_expected.not_to contain_postgresql__validate_db_connection('validate_service_is_running') - end - end - - describe 'service_restart_on_change => false' do - let(:params) {{ :service_restart_on_change => false }} - it { is_expected.to contain_class("postgresql::params") } - it { is_expected.to contain_class("postgresql::server") } - it { is_expected.to_not contain_Postgresql_conf('data_directory').that_notifies('Class[postgresql::server::service]') - } - it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') - end - end - - describe 'service_restart_on_change => true' do - let(:params) {{ :service_restart_on_change => true }} - it { is_expected.to contain_class("postgresql::params") } - it { is_expected.to contain_class("postgresql::server") } - it { is_expected.to contain_Postgresql_conf('data_directory').that_notifies('Class[postgresql::server::service]') - } - it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') - end - end - - describe 'service_reload => /bin/true' do - let(:params) {{ :service_reload => '/bin/true' }} - it { is_expected.to contain_class("postgresql::params") } - it { is_expected.to contain_class("postgresql::server") } - it { is_expected.to contain_exec('postgresql_reload').with({ - 'command' => '/bin/true', - }) - } - it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') - end - end - - describe 'service_manage => true' do - let(:params) {{ :service_manage => true }} - it { is_expected.to contain_service('postgresqld') } - end - - describe 'service_manage => false' do - let(:params) {{ :service_manage => false }} - it { is_expected.not_to contain_service('postgresqld') } - it 'shouldnt validate connection' do - is_expected.not_to contain_postgresql__validate_db_connection('validate_service_is_running') - end - end - - describe 'package_ensure => absent' do - let(:params) do - { - :package_ensure => 'absent', - } - end - - it 'should remove the package' do - is_expected.to contain_package('postgresql-server').with({ - :ensure => 'purged', - }) - end - - it 'should still enable the service' do - is_expected.to contain_service('postgresqld').with({ - :ensure => 'running', - }) - end - end - - describe 'needs_initdb => true' do - let(:params) do - { - :needs_initdb => true, - } - end - - it 'should contain proper initdb exec' do - is_expected.to contain_exec('postgresql_initdb') - end - end -end diff --git a/spec/unit/defines/server/config_entry_spec.rb b/spec/unit/defines/server/config_entry_spec.rb deleted file mode 100644 index 34963b8bf9..0000000000 --- a/spec/unit/defines/server/config_entry_spec.rb +++ /dev/null @@ -1,109 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::config_entry', :type => :define do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', - :operatingsystemrelease => '6.4', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let(:title) { 'config_entry'} - - let :target do - tmpfilename('postgresql_conf') - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - context "syntax check" do - let(:params) { { :ensure => 'present'} } - it { is_expected.to contain_postgresql__server__config_entry('config_entry') } - end - - context 'ports' do - context 'redhat 6' do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', - :operatingsystemrelease => '6.4', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - let(:params) {{ :ensure => 'present', :name => 'port_spec', :value => '5432' }} - - it 'stops postgresql and changes the port' do - is_expected.to contain_exec('postgresql_stop_port') - is_expected.to contain_augeas('override PGPORT in /etc/sysconfig/pgsql/postgresql') - end - end - context 'redhat 7' do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', - :operatingsystemrelease => '7.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - let(:params) {{ :ensure => 'present', :name => 'port_spec', :value => '5432' }} - - it 'stops postgresql and changes the port' do - is_expected.to contain_file('systemd-override') - is_expected.to contain_exec('restart-systemd') - end - end - context 'fedora 19' do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'Fedora', - :operatingsystemrelease => '19', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - let(:params) {{ :ensure => 'present', :name => 'port_spec', :value => '5432' }} - - it 'stops postgresql and changes the port' do - is_expected.to contain_file('systemd-override') - is_expected.to contain_exec('restart-systemd') - end - end - end - - context "data_directory" do - let(:params) {{ :ensure => 'present', :name => 'data_directory_spec', :value => '/var/pgsql' }} - - it 'stops postgresql and changes the data directory' do - is_expected.to contain_exec('postgresql_data_directory') - is_expected.to contain_augeas('override PGDATA in /etc/sysconfig/pgsql/postgresql') - end - end - - context "passes values through appropriately" do - let(:params) {{ :ensure => 'present', :name => 'check_function_bodies', :value => 'off' }} - - it 'with no quotes' do - is_expected.to contain_postgresql_conf('check_function_bodies').with({ - :name => 'check_function_bodies', - :value => 'off' }) - end - end -end diff --git a/spec/unit/defines/server/database_grant_spec.rb b/spec/unit/defines/server/database_grant_spec.rb deleted file mode 100644 index 19dfce99fb..0000000000 --- a/spec/unit/defines/server/database_grant_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::database_grant', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let :title do - 'test' - end - - let :params do - { - :privilege => 'ALL', - :db => 'test', - :role => 'test', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__database_grant('test') } - it { is_expected.to contain_postgresql__server__grant('database:test') } -end diff --git a/spec/unit/defines/server/database_spec.rb b/spec/unit/defines/server/database_spec.rb deleted file mode 100644 index 16564d76bd..0000000000 --- a/spec/unit/defines/server/database_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::database', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - let :title do - 'test' - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__database('test') } - it { is_expected.to contain_postgresql_psql("Create db 'test'") } - - context "with comment set to 'test comment'" do - let (:params) {{ :comment => 'test comment', - :connect_settings => {} }} - - it { is_expected.to contain_postgresql_psql("COMMENT ON DATABASE test IS 'test comment'").with_connect_settings( {} ) } - end - - context "with specific db connection settings - default port" do - let :pre_condition do - "class {'postgresql::server':}" - end - - let (:params) {{ :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', }}} - - it { is_expected.to contain_postgresql_psql("Create db 'test'").with_connect_settings( { 'PGHOST' => 'postgres-db-server','DBVERSION' => '9.1' } ).with_port( 5432 ) } - end - - context "with specific db connection settings - including port" do - let :pre_condition do - "class {'postgresql::globals':} - - class {'postgresql::server':}" - end - - let (:params) {{ :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGPORT' => '1234' }}} - - it { is_expected.to contain_postgresql_psql("Create db 'test'").with_connect_settings( { 'PGHOST' => 'postgres-db-server','DBVERSION' => '9.1','PGPORT' => '1234' } ).with_port( nil ) } - - end - - context "with global db connection settings - including port" do - let :pre_condition do - "class {'postgresql::globals': - default_connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.2', - 'PGPORT' => '1234' } - } - - class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql_psql("Create db 'test'").with_connect_settings( { 'PGHOST' => 'postgres-db-server','DBVERSION' => '9.2','PGPORT' => '1234' } ).with_port( nil ) } - - end -end diff --git a/spec/unit/defines/server/db_spec.rb b/spec/unit/defines/server/db_spec.rb deleted file mode 100644 index 78e36b002c..0000000000 --- a/spec/unit/defines/server/db_spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::db', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let :title do - 'test' - end - - context 'without dbname param' do - - let :params do - { - :user => 'test', - :password => 'test', - :owner => 'tester', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__db('test') } - it { is_expected.to contain_postgresql__server__database('test').with_owner('tester') } - it { is_expected.to contain_postgresql__server__role('test').that_comes_before('Postgresql::Server::Database[test]') } - it { is_expected.to contain_postgresql__server__database_grant('GRANT test - ALL - test') } - - end - - context 'dbname' do - - let :params do - { - :dbname => 'testtest', - :user => 'test', - :password => 'test', - :owner => 'tester', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__database('testtest') } - end -end diff --git a/spec/unit/defines/server/extension_spec.rb b/spec/unit/defines/server/extension_spec.rb deleted file mode 100644 index 54386a165f..0000000000 --- a/spec/unit/defines/server/extension_spec.rb +++ /dev/null @@ -1,130 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::extension', :type => :define do - let :pre_condition do - "class { 'postgresql::server': } - postgresql::server::database { 'template_postgis': - template => 'template1', - }" - end - - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('postgis'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let (:title) { 'postgis' } - let (:params) { { - :database => 'template_postgis', - } } - - context "with mandatory arguments only" do - it { - is_expected.to contain_postgresql_psql('Add postgis extension to template_postgis').with({ - :db => 'template_postgis', - :command => 'CREATE EXTENSION "postgis"', - :unless => "SELECT t.count FROM (SELECT count(extname) FROM pg_extension WHERE extname = 'postgis') as t WHERE t.count = 1", - }).that_requires('Postgresql::Server::Database[template_postgis]') - } - end - - context "when setting package name" do - let (:params) { super().merge({ - :package_name => 'postgis', - }) } - - it { - is_expected.to contain_package('postgis').with({ - :ensure => 'present', - :name => 'postgis', - }).that_comes_before('Postgresql_psql[Add postgis extension to template_postgis]') - } - end - - context "when ensuring absence" do - let (:params) { super().merge({ - :ensure => 'absent', - :package_name => 'postgis', - }) } - - it { - is_expected.to contain_postgresql_psql('Add postgis extension to template_postgis').with({ - :db => 'template_postgis', - :command => 'DROP EXTENSION "postgis"', - :unless => "SELECT t.count FROM (SELECT count(extname) FROM pg_extension WHERE extname = 'postgis') as t WHERE t.count != 1", - }).that_requires('Postgresql::Server::Database[template_postgis]') - } - - it { - is_expected.to contain_package('postgis').with({ - :ensure => 'absent', - :name => 'postgis', - }) - } - - context "when keeping package installed" do - let (:params) { super().merge({ - :package_ensure => 'present', - }) } - - it { - is_expected.to contain_postgresql_psql('Add postgis extension to template_postgis').with({ - :db => 'template_postgis', - :command => 'DROP EXTENSION "postgis"', - :unless => "SELECT t.count FROM (SELECT count(extname) FROM pg_extension WHERE extname = 'postgis') as t WHERE t.count != 1", - }).that_requires('Postgresql::Server::Database[template_postgis]') - } - - it { - is_expected.to contain_package('postgis').with({ - :ensure => 'present', - :name => 'postgis', - }).that_requires('Postgresql_psql[Add postgis extension to template_postgis]') - } - end - end -end - -describe 'postgresql::server::extension', :type => :define do - let :pre_condition do - "class { 'postgresql::server': } - postgresql::server::database { 'template_postgis2': - template => 'template1', - }" - end - - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('postgis'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let (:title) { 'postgis_db2' } - let (:params) { { - :database => 'template_postgis2', - :extension => 'postgis', - } } - - context "with mandatory arguments only" do - it { - is_expected.to contain_postgresql_psql('Add postgis extension to template_postgis2').with({ - :db => 'template_postgis2', - :command => 'CREATE EXTENSION "postgis"', - :unless => "SELECT t.count FROM (SELECT count(extname) FROM pg_extension WHERE extname = 'postgis') as t WHERE t.count = 1", - }).that_requires('Postgresql::Server::Database[template_postgis2]') - } - end -end diff --git a/spec/unit/defines/server/grant_spec.rb b/spec/unit/defines/server/grant_spec.rb deleted file mode 100644 index 45d9cce5f1..0000000000 --- a/spec/unit/defines/server/grant_spec.rb +++ /dev/null @@ -1,136 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::grant', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let :title do - 'test' - end - - context 'plain' do - let :params do - { - :db => 'test', - :role => 'test', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__grant('test') } - end - - context 'sequence' do - let :params do - { - :db => 'test', - :role => 'test', - :privilege => 'usage', - :object_type => 'sequence', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__grant('test') } - it { is_expected.to contain_postgresql_psql('grant:test').with( - { - 'command' => "GRANT USAGE ON SEQUENCE \"test\" TO\n \"test\"", - 'unless' => "SELECT 1 WHERE has_sequence_privilege('test',\n 'test', 'USAGE')", - }) } - end - - context 'all sequences' do - let :params do - { - :db => 'test', - :role => 'test', - :privilege => 'usage', - :object_type => 'all sequences in schema', - :object_name => 'public', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__grant('test') } - it { is_expected.to contain_postgresql_psql('grant:test').with( - { - 'command' => "GRANT USAGE ON ALL SEQUENCES IN SCHEMA \"public\" TO\n \"test\"", - 'unless' => "SELECT 1 FROM (\n SELECT sequence_name\n FROM information_schema.sequences\n WHERE sequence_schema='public'\n EXCEPT DISTINCT\n SELECT object_name as sequence_name\n FROM information_schema.role_usage_grants\n WHERE object_type='SEQUENCE'\n AND grantee='test'\n AND object_schema='public'\n AND privilege_type='USAGE'\n ) P\n HAVING count(P.sequence_name) = 0", - }) } - end - - context "with specific db connection settings - default port" do - let :params do - { - :db => 'test', - :role => 'test', - :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', }, - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__grant('test') } - it { is_expected.to contain_postgresql_psql("grant:test").with_connect_settings( { 'PGHOST' => 'postgres-db-server','DBVERSION' => '9.1' } ).with_port( 5432 ) } - end - - context "with specific db connection settings - including port" do - let :params do - { - :db => 'test', - :role => 'test', - :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGPORT' => '1234', }, - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__grant('test') } - it { is_expected.to contain_postgresql_psql("grant:test").with_connect_settings( { 'PGHOST' => 'postgres-db-server','DBVERSION' => '9.1','PGPORT' => '1234' } ) } - end - - context "with specific db connection settings - port overriden by explicit parameter" do - let :params do - { - :db => 'test', - :role => 'test', - :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGPORT' => '1234', }, - :port => '5678', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__grant('test') } - it { is_expected.to contain_postgresql_psql("grant:test").with_connect_settings( { 'PGHOST' => 'postgres-db-server','DBVERSION' => '9.1','PGPORT' => '1234' } ).with_port( '5678' ) } - end -end \ No newline at end of file diff --git a/spec/unit/defines/server/pg_hba_rule_spec.rb b/spec/unit/defines/server/pg_hba_rule_spec.rb deleted file mode 100644 index f36d27ddad..0000000000 --- a/spec/unit/defines/server/pg_hba_rule_spec.rb +++ /dev/null @@ -1,198 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::pg_hba_rule', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('pg_hba'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - let :title do - 'test' - end - let :target do - tmpfilename('pg_hba_rule') - end - - context 'test template 1' do - let :pre_condition do - <<-EOS - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'host', - :database => 'all', - :user => 'all', - :address => '1.1.1.1/24', - :auth_method => 'md5', - :target => target, - } - end - it do - is_expected.to contain_concat__fragment('pg_hba_rule_test').with({ - :content => /host\s+all\s+all\s+1\.1\.1\.1\/24\s+md5/ - }) - end - end - - context 'test template 2' do - let :pre_condition do - <<-EOS - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'local', - :database => 'all', - :user => 'all', - :auth_method => 'ident', - :target => target, - } - end - it do - is_expected.to contain_concat__fragment('pg_hba_rule_test').with({ - :content => /local\s+all\s+all\s+ident/ - }) - end - end - - context 'test template 3' do - let :pre_condition do - <<-EOS - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'host', - :database => 'all', - :user => 'all', - :address => '0.0.0.0/0', - :auth_method => 'ldap', - :auth_option => 'foo=bar', - :target => target, - } - end - it do - is_expected.to contain_concat__fragment('pg_hba_rule_test').with({ - :content => /host\s+all\s+all\s+0\.0\.0\.0\/0\s+ldap\s+foo=bar/ - }) - end - end - - context 'validation' do - context 'validate type test 1' do - let :pre_condition do - <<-EOS - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'invalid', - :database => 'all', - :user => 'all', - :address => '0.0.0.0/0', - :auth_method => 'ldap', - :target => target, - } - end - it 'should fail parsing when type is not valid' do - expect { catalogue }.to raise_error(Puppet::Error, - /The type you specified \[invalid\] must be one of/) - end - end - - context 'validate auth_method' do - let :pre_condition do - <<-EOS - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'local', - :database => 'all', - :user => 'all', - :address => '0.0.0.0/0', - :auth_method => 'invalid', - :target => target, - } - end - - it 'should fail parsing when auth_method is not valid' do - expect { catalogue }.to raise_error(Puppet::Error, - /The auth_method you specified \[invalid\] must be one of/) - end - end - - context 'validate unsupported auth_method' do - let :pre_condition do - <<-EOS - class { 'postgresql::globals': - version => '9.0', - } - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'local', - :database => 'all', - :user => 'all', - :address => '0.0.0.0/0', - :auth_method => 'peer', - :target => target, - } - end - - it 'should fail parsing when auth_method is not valid' do - expect { catalogue }.to raise_error(Puppet::Error, - /The auth_method you specified \[peer\] must be one of: trust, reject, md5, password, gss, sspi, krb5, ident, ldap, radius, cert, pam/) - end - end - - context 'validate supported auth_method' do - let :pre_condition do - <<-EOS - class { 'postgresql::globals': - version => '9.2', - } - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'local', - :database => 'all', - :user => 'all', - :address => '0.0.0.0/0', - :auth_method => 'peer', - :target => target, - } - end - - it do - is_expected.to contain_concat__fragment('pg_hba_rule_test').with({ - :content => /local\s+all\s+all\s+0\.0\.0\.0\/0\s+peer/ - }) - end - end - - end -end diff --git a/spec/unit/defines/server/pg_ident_rule_spec.rb b/spec/unit/defines/server/pg_ident_rule_spec.rb deleted file mode 100644 index 71dfff866f..0000000000 --- a/spec/unit/defines/server/pg_ident_rule_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::pg_ident_rule', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('pg_ident'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - let :title do - 'test' - end - let :target do - tmpfilename('pg_ident_rule') - end - - context 'managing pg_ident' do - let :pre_condition do - <<-EOS - class { 'postgresql::globals': - manage_pg_ident_conf => true, - } - class { 'postgresql::server': } - EOS - end - - let :params do - { - :map_name => 'thatsmymap', - :system_username => 'systemuser', - :database_username => 'dbuser', - } - end - it do - is_expected.to contain_concat__fragment('pg_ident_rule_test').with({ - :content => /thatsmymap\s+systemuser\s+dbuser/ - }) - end - end - context 'not managing pg_ident' do - let :pre_condition do - <<-EOS - class { 'postgresql::globals': - manage_pg_ident_conf => false, - } - class { 'postgresql::server': } - EOS - end - let :params do - { - :map_name => 'thatsmymap', - :system_username => 'systemuser', - :database_username => 'dbuser', - } - end - it 'should fail because $manage_pg_ident_conf is false' do - expect { catalogue }.to raise_error(Puppet::Error, - /postgresql::server::manage_pg_ident_conf has been disabled/) - end - end -end diff --git a/spec/unit/defines/server/recovery_spec.rb b/spec/unit/defines/server/recovery_spec.rb deleted file mode 100644 index 8c78e3ec3b..0000000000 --- a/spec/unit/defines/server/recovery_spec.rb +++ /dev/null @@ -1,113 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::recovery', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('recovery'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - let :title do - 'test' - end - let :target do - tmpfilename('recovery') - end - - context 'managing recovery' do - let :pre_condition do - <<-EOS - class { 'postgresql::globals': - manage_recovery_conf => true, - } - class { 'postgresql::server': } - EOS - end - - let :params do - { - :restore_command => 'restore_command', - :recovery_target_timeline => 'recovery_target_timeline', - } - end - it do - is_expected.to contain_concat__fragment('recovery.conf').with({ - :content => /restore_command = 'restore_command'[\n]+recovery_target_timeline = 'recovery_target_timeline'/ - }) - end - end - context 'not managing recovery' do - let :pre_condition do - <<-EOS - class { 'postgresql::globals': - manage_recovery_conf => false, - } - class { 'postgresql::server': } - EOS - end - let :params do - { - :restore_command => '', - } - end - it 'should fail because $manage_recovery_conf is false' do - expect { catalogue }.to raise_error(Puppet::Error, - /postgresql::server::manage_recovery_conf has been disabled/) - end - end - context 'not managing recovery, missing param' do - let :pre_condition do - <<-EOS - class { 'postgresql::globals': - manage_recovery_conf => true, - } - class { 'postgresql::server': } - EOS - end - it 'should fail because no param set' do - expect { catalogue }.to raise_error(Puppet::Error, - /postgresql::server::recovery use this resource but do not pass a parameter will avoid creating the recovery.conf, because it makes no sense./) - end - end - - context 'managing recovery with all params' do - let :pre_condition do - <<-EOS - class { 'postgresql::globals': - manage_recovery_conf => true, - } - class { 'postgresql::server': } - EOS - end - - let :params do - { - :restore_command => 'restore_command', - :archive_cleanup_command => 'archive_cleanup_command', - :recovery_end_command => 'recovery_end_command', - :recovery_target_name => 'recovery_target_name', - :recovery_target_time => 'recovery_target_time', - :recovery_target_xid => 'recovery_target_xid', - :recovery_target_inclusive => true, - :recovery_target => 'recovery_target', - :recovery_target_timeline => 'recovery_target_timeline', - :pause_at_recovery_target => true, - :standby_mode => 'on', - :primary_conninfo => 'primary_conninfo', - :primary_slot_name => 'primary_slot_name', - :trigger_file => 'trigger_file', - :recovery_min_apply_delay => 0, - } - end - it do - is_expected.to contain_concat__fragment('recovery.conf').with({ - :content => /restore_command = 'restore_command'[\n]+archive_cleanup_command = 'archive_cleanup_command'[\n]+recovery_end_command = 'recovery_end_command'[\n]+recovery_target_name = 'recovery_target_name'[\n]+recovery_target_time = 'recovery_target_time'[\n]+recovery_target_xid = 'recovery_target_xid'[\n]+recovery_target_inclusive = true[\n]+recovery_target = 'recovery_target'[\n]+recovery_target_timeline = 'recovery_target_timeline'[\n]+pause_at_recovery_target = true[\n]+standby_mode = on[\n]+primary_conninfo = 'primary_conninfo'[\n]+primary_slot_name = 'primary_slot_name'[\n]+trigger_file = 'trigger_file'[\n]+recovery_min_apply_delay = 0[\n]+/ - }) - end - end -end diff --git a/spec/unit/defines/server/role_spec.rb b/spec/unit/defines/server/role_spec.rb deleted file mode 100644 index 3540d49e09..0000000000 --- a/spec/unit/defines/server/role_spec.rb +++ /dev/null @@ -1,138 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::role', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('contrib'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let :title do - 'test' - end - - let :params do - { - :password_hash => 'new-pa$s', - :connect_settings => {}, - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__role('test') } - it 'should have create role for "test" user with password as ****' do - is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****').with({ - 'command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", - 'environment' => "NEWPGPASSWD=new-pa$s", - 'unless' => "SELECT rolname FROM pg_roles WHERE rolname='test'", - 'port' => "5432", - 'connect_settings' => {}, - }) - end - it 'should have alter role for "test" user with password as ****' do - is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****').with({ - 'command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", - 'environment' => "NEWPGPASSWD=new-pa$s", - 'unless' => "SELECT usename FROM pg_shadow WHERE usename='test' and passwd='md5b6f7fcbbabb4befde4588a26c1cfd2fa'", - 'port' => "5432", - 'connect_settings' => {}, - }) - end - - context "with specific db connection settings - default port" do - let :params do - { - :password_hash => 'new-pa$s', - :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGUSER' => 'login-user', - 'PGPASSWORD' => 'login-pass' }, - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__role('test') } - it 'should have create role for "test" user with password as ****' do - is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****').with({ - 'command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", - 'environment' => "NEWPGPASSWD=new-pa$s", - 'unless' => "SELECT rolname FROM pg_roles WHERE rolname='test'", - 'port' => "5432", - - 'connect_settings' => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGUSER' => 'login-user', - 'PGPASSWORD' => 'login-pass' }, - }) - end - it 'should have alter role for "test" user with password as ****' do - is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****').with({ - 'command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", - 'environment' => "NEWPGPASSWD=new-pa$s", - 'unless' => "SELECT usename FROM pg_shadow WHERE usename='test' and passwd='md5b6f7fcbbabb4befde4588a26c1cfd2fa'", - 'port' => "5432", - - 'connect_settings' => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGUSER' => 'login-user', - 'PGPASSWORD' => 'login-pass' }, - }) - end - end - - context "with specific db connection settings - including port" do - let :params do - { - :password_hash => 'new-pa$s', - :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGPORT' => '1234', - 'PGUSER' => 'login-user', - 'PGPASSWORD' => 'login-pass' }, - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__role('test') } - it 'should have create role for "test" user with password as ****' do - is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****').with({ - 'command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", - 'environment' => "NEWPGPASSWD=new-pa$s", - 'unless' => "SELECT rolname FROM pg_roles WHERE rolname='test'", - 'connect_settings' => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGPORT' => '1234', - 'PGUSER' => 'login-user', - 'PGPASSWORD' => 'login-pass' }, - }) - end - it 'should have alter role for "test" user with password as ****' do - is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****').with({ - 'command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", - 'environment' => "NEWPGPASSWD=new-pa$s", - 'unless' => "SELECT usename FROM pg_shadow WHERE usename='test' and passwd='md5b6f7fcbbabb4befde4588a26c1cfd2fa'", - 'connect_settings' => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGPORT' => '1234', - 'PGUSER' => 'login-user', - 'PGPASSWORD' => 'login-pass' }, - }) - end - end - -end diff --git a/spec/unit/defines/server/schema_spec.rb b/spec/unit/defines/server/schema_spec.rb deleted file mode 100644 index f5d106fae9..0000000000 --- a/spec/unit/defines/server/schema_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::schema', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('schema'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let :title do - 'test' - end - - let :params do - { - :owner => 'jane', - :db => 'janedb', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { should contain_postgresql__server__schema('test') } -end diff --git a/spec/unit/defines/server/table_grant_spec.rb b/spec/unit/defines/server/table_grant_spec.rb deleted file mode 100644 index eac55bd60b..0000000000 --- a/spec/unit/defines/server/table_grant_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::table_grant', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('table_grant'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let :title do - 'test' - end - - let :params do - { - :privilege => 'ALL', - :db => 'test', - :role => 'test', - :table => 'foo', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__table_grant('test') } - it { is_expected.to contain_postgresql__server__grant('table:test') } -end diff --git a/spec/unit/defines/server/tablespace_spec.rb b/spec/unit/defines/server/tablespace_spec.rb deleted file mode 100644 index 560a50eee2..0000000000 --- a/spec/unit/defines/server/tablespace_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::server::tablespace', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :kernel => 'Linux', - :concat_basedir => tmpfilename('tablespace'), - :id => 'root', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - } - end - - let :title do - 'test' - end - - let :params do - { - :location => '/srv/data/foo', - } - end - - let :pre_condition do - "class {'postgresql::server':}" - end - - it { is_expected.to contain_postgresql__server__tablespace('test') } -end diff --git a/spec/unit/defines/validate_db_connection_spec.rb b/spec/unit/defines/validate_db_connection_spec.rb deleted file mode 100644 index 9cf5048f4e..0000000000 --- a/spec/unit/defines/validate_db_connection_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'spec_helper' - -describe 'postgresql::validate_db_connection', :type => :define do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - } - end - - let :title do - 'test' - end - - describe 'should work with only default parameters' do - it { is_expected.to contain_postgresql__validate_db_connection('test') } - end - - describe 'should work with all parameters' do - let :params do - { - :database_host => 'test', - :database_name => 'test', - :database_password => 'test', - :database_username => 'test', - :database_port => 5432, - :run_as => 'postgresq', - :sleep => 4, - :tries => 30, - } - end - it { is_expected.to contain_postgresql__validate_db_connection('test') } - - it 'should have proper path for validate command' do - is_expected.to contain_exec('validate postgres connection for test@test:5432/test').with({ - :unless => %r'^/usr/local/bin/validate_postgresql_connection.sh\s+\d+' - }) - end - end - - describe 'should work while specifying validate_connection in postgresql::client' do - - let :params do - { - :database_host => 'test', - :database_name => 'test', - :database_password => 'test', - :database_username => 'test', - :database_port => 5432 - } - end - - let :pre_condition do - "class { 'postgresql::client': validcon_script_path => '/opt/something/validate.sh' }" - end - - it 'should have proper path for validate command' do - is_expected.to contain_exec('validate postgres connection for test@test:5432/test').with({ - :unless => %r'^/opt/something/validate.sh\s+\d+' - }) - end - - end - -end diff --git a/spec/unit/functions/postgresql_acls_to_resources_hash_spec.rb b/spec/unit/functions/postgresql_acls_to_resources_hash_spec.rb deleted file mode 100644 index e21b521208..0000000000 --- a/spec/unit/functions/postgresql_acls_to_resources_hash_spec.rb +++ /dev/null @@ -1,137 +0,0 @@ -require 'spec_helper' - -describe 'postgresql_acls_to_resources_hash', :type => :puppet_function do - context 'individual transform tests' do - it do - input = 'local all postgres ident' - result = { - "postgresql class generated rule test 0"=>{ - "type"=>"local", - "database"=>"all", - "user"=>"postgres", - "auth_method"=>"ident", - "order"=>"100", - }, - } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'local all root ident' - result = { - "postgresql class generated rule test 0"=>{ - "type"=>"local", - "database"=>"all", - "user"=>"root", - "auth_method"=>"ident", - "order"=>"100", - }, - } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input_array = [ - 'local all all ident', - ] - result = { - "postgresql class generated rule test 0"=>{ - "type"=>"local", - "database"=>"all", - "user"=>"all", - "auth_method"=>"ident", - "order"=>"100", - }, - } - - is_expected.to run.with_params(input_array, 'test', 100).and_return(result) - end - - it do - input = 'host all all 127.0.0.1/32 md5' - result = { - "postgresql class generated rule test 0"=>{ - "type"=>"host", - "database"=>"all", - "user"=>"all", - "address"=>"127.0.0.1/32", - "auth_method"=>"md5", - "order"=>"100", - }, - } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'host all all 0.0.0.0/0 md5' - result = { - "postgresql class generated rule test 0"=>{ - "type"=>"host", - "database"=>"all", - "user"=>"all", - "address"=>"0.0.0.0/0", - "auth_method"=>"md5", - "order"=>"100", - }, - } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'host all all ::1/128 md5' - result = { - "postgresql class generated rule test 0"=>{ - "type"=>"host", - "database"=>"all", - "user"=>"all", - "address"=>"::1/128", - "auth_method"=>"md5", - "order"=>"100", - }, - } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'host all all 1.1.1.1 255.255.255.0 md5' - result = { - "postgresql class generated rule test 0"=>{ - "type"=>"host", - "database"=>"all", - "user"=>"all", - "address"=>"1.1.1.1 255.255.255.0", - "auth_method"=>"md5", - "order"=>"100", - }, - } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'host all all 1.1.1.1 255.255.255.0 ldap ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"' - result = { - "postgresql class generated rule test 0"=>{ - "type"=>"host", - "database"=>"all", - "user"=>"all", - "address"=>"1.1.1.1 255.255.255.0", - "auth_method"=>"ldap", - "auth_option"=>"ldapserver=ldap.example.net ldapprefix=\"cn=\" ldapsuffix=\", dc=example, dc=net\"", - "order"=>"100", - }, - } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - end - - it 'should return an empty hash when input is empty array' do - is_expected.to run.with_params([], 'test', 100).and_return({}) - end -end diff --git a/spec/unit/functions/postgresql_escape_spec.rb b/spec/unit/functions/postgresql_escape_spec.rb deleted file mode 100644 index f7eec6a83f..0000000000 --- a/spec/unit/functions/postgresql_escape_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' - -describe 'postgresql_escape', :type => :puppet_function do - it { is_expected.to run.with_params('foo'). - and_return('$$foo$$') } -end -describe 'postgresql_escape', :type => :puppet_function do - it { is_expected.to run.with_params('fo$$o'). - and_return('$ed$fo$$o$ed$') } -end diff --git a/spec/unit/functions/postgresql_password_spec.rb b/spec/unit/functions/postgresql_password_spec.rb deleted file mode 100644 index b5aa00bfd3..0000000000 --- a/spec/unit/functions/postgresql_password_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -require 'spec_helper' - -describe 'postgresql_password', :type => :puppet_function do - it { is_expected.to run.with_params('foo', 'bar'). - and_return('md596948aad3fcae80c08a35c9b5958cd89') } -end diff --git a/spec/unit/provider/postgresql_conf/parsed_spec.rb b/spec/unit/provider/postgresql_conf/parsed_spec.rb deleted file mode 100644 index a9a155e4d8..0000000000 --- a/spec/unit/provider/postgresql_conf/parsed_spec.rb +++ /dev/null @@ -1,129 +0,0 @@ -require 'spec_helper' -require "tempfile" - -provider_class = Puppet::Type.type(:postgresql_conf).provider(:parsed) - -describe provider_class do - let(:title) { 'postgresql_conf' } - let(:provider) { - conf_class = Puppet::Type.type(:postgresql_conf) - provider = conf_class.provider(:parsed) - conffile = tmpfilename('postgresql.conf') - provider.any_instance.stub(:target).and_return conffile - provider - } - - before do - end - - after :each do - provider.initvars - end - - describe "simple configuration that should be allowed" do - it "should parse a simple ini line" do - expect(provider.parse_line("listen_addreses = '*'")).to eq( - { :name=>"listen_addreses", :value=>"*", :comment=>nil, :record_type=>:parsed } - ) - end - - it "should parse a simple ini line (2)" do - expect(provider.parse_line(" listen_addreses = '*'")).to eq( - { :name=>"listen_addreses", :value=>"*", :comment=>nil, :record_type=>:parsed } - ) - end - - it "should parse a simple ini line (3)" do - expect(provider.parse_line("listen_addreses = '*' # dont mind me")).to eq( - { :name=>"listen_addreses", :value=>"*", :comment=>"dont mind me", :record_type=>:parsed } - ) - end - - it "should parse a comment" do - expect(provider.parse_line("# dont mind me")).to eq( - { :line=>"# dont mind me", :record_type=>:comment } - ) - end - - it "should parse a comment (2)" do - expect(provider.parse_line(" \t# dont mind me")).to eq( - { :line=>" \t# dont mind me", :record_type=>:comment } - ) - end - - it "should allow includes" do - expect(provider.parse_line("include puppetextra")).to eq( - { :name=>"include", :value=>"puppetextra", :comment=>nil, :record_type=>:parsed } - ) - end - - it "should allow numbers through without quotes" do - expect(provider.parse_line("wal_keep_segments = 32")).to eq( - { :name=>"wal_keep_segments", :value=>"32", :comment=>nil, :record_type=>:parsed } - ) - end - - it "should allow blanks through " do - expect(provider.parse_line("")).to eq( - { :line=>"", :record_type=>:blank } - ) - end - - it "should parse keys with dots " do - expect(provider.parse_line("auto_explain.log_min_duration = 1ms")).to eq( - { :name => "auto_explain.log_min_duration", :value => "1ms", :comment => nil, :record_type => :parsed } - ) - end - end - - describe "configuration that should be set" do - it "should set comment lines" do - expect(provider.to_line({ :line=>"# dont mind me", :record_type=>:comment })).to eq( - '# dont mind me' - ) - end - - it "should set blank lines" do - expect(provider.to_line({ :line=>"", :record_type=>:blank })).to eq( - '' - ) - end - - it "should set simple configuration" do - expect(provider.to_line({:name=>"listen_addresses", :value=>"*", :comment=>nil, :record_type=>:parsed })).to eq( - "listen_addresses = '*'" - ) - end - - it "should set simple configuration with period in name" do - expect(provider.to_line({:name => "auto_explain.log_min_duration", :value => '100ms', :comment => nil, :record_type => :parsed })).to eq( - "auto_explain.log_min_duration = 100ms" - ) - end - - it "should set simple configuration even with comments" do - expect(provider.to_line({:name=>"listen_addresses", :value=>"*", :comment=>'dont mind me', :record_type=>:parsed })).to eq( - "listen_addresses = '*' # dont mind me" - ) - end - - it 'should quote includes' do - expect(provider.to_line( {:name=>"include", :value=>"puppetextra", :comment=>nil, :record_type=>:parsed })).to eq( - "include 'puppetextra'" - ) - end - - it 'should quote multiple words' do - expect(provider.to_line( {:name=>"archive_command", :value=>"rsync up", :comment=>nil, :record_type=>:parsed })).to eq( - "archive_command = 'rsync up'" - ) - end - - it 'shouldn\'t quote numbers' do - expect(provider.to_line( {:name=>"wal_segments", :value=>"32", :comment=>nil, :record_type=>:parsed })).to eq( - "wal_segments = 32" - ) - end - end -end - diff --git a/spec/unit/provider/postgresql_conf/ruby_spec.rb b/spec/unit/provider/postgresql_conf/ruby_spec.rb new file mode 100644 index 0000000000..1a5c3e806a --- /dev/null +++ b/spec/unit/provider/postgresql_conf/ruby_spec.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +require 'spec_helper' +provider_class = Puppet::Type.type(:postgresql_conf).provider(:ruby) + +describe provider_class do + let(:resource) { Puppet::Type.type(:postgresql_conf).new(name: 'foo', key: 'foo', value: 'bar') } + let(:provider) { resource.provider } + + before(:each) do + allow(provider).to receive(:file_path).and_return('/tmp/foo') + allow(provider).to receive(:read_file).and_return('foo = bar') + allow(provider).to receive(:write_file).and_return(true) + allow(provider).to receive(:resource).and_return(key: 'your_key', line_number: 1, value: 'foo') + end + # rubocop:enable RSpec/ReceiveMessages + + it 'has a method parse_config' do + expect(provider).to respond_to(:parse_config) + end + + it 'has a method delete_header' do + expect(provider).to respond_to(:delete_header) + end + + it 'has a method add_header' do + expect(provider).to respond_to(:add_header) + end + + describe '#exists?' do + it 'returns true when a matching config item is found' do + config_data = [{ key: 'your_key', value: 'your_value' }] + expect(provider).to receive(:parse_config).and_return(config_data) + + expect(provider.exists?).to be true + end + + it 'returns false when no matching config item is found' do + config_data = [{ key: 'other_key', value: 'other_value' }] + expect(provider).to receive(:parse_config).and_return(config_data) + + expect(provider.exists?).to be false + end + + it 'raises an error when multiple matching config items are found' do + config_data = [{ key: 'your_key', value: 'value1' }, { key: 'your_key', value: 'value2' }] + expect(provider).to receive(:parse_config).and_return(config_data) + + expect { provider.exists? }.to raise_error(Puppet::Error, 'found multiple config items of your_key, please fix this') + end + end + + it 'has a method create' do + expect(provider).to respond_to(:create) + end + + it 'has a method destroy' do + expect(provider).to respond_to(:destroy) + end + + it 'has a method value' do + expect(provider).to respond_to(:value) + end + + it 'has a method value=' do + expect(provider).to respond_to(:value=) + end + + it 'has a method comment' do + expect(provider).to respond_to(:comment) + end + + it 'has a method comment=' do + expect(provider).to respond_to(:comment=) + end + + it 'is an instance of the Provider Ruby' do + expect(provider).to be_an_instance_of Puppet::Type::Postgresql_conf::ProviderRuby + end +end diff --git a/spec/unit/puppet/provider/postgresql_conn_validator/ruby_spec.rb b/spec/unit/puppet/provider/postgresql_conn_validator/ruby_spec.rb new file mode 100644 index 0000000000..ef18e65692 --- /dev/null +++ b/spec/unit/puppet/provider/postgresql_conn_validator/ruby_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Puppet::Type.type(:postgresql_conn_validator).provider(:ruby) do + let(:resource) do + Puppet::Type.type(:postgresql_conn_validator).new({ + name: 'testname' + }.merge(attributes)) + end + let(:provider) { resource.provider } + let(:attributes) do + { + psql_path: '/usr/bin/psql', + host: 'db.test.com', + port: 4444, + db_username: 'testuser', + db_password: 'testpass' + } + end + let(:connect_settings) do + { + connect_settings: { + PGPASSWORD: 'testpass', + PGHOST: 'db.test.com', + PGPORT: '1234' + } + } + end + + describe '#build_psql_cmd' do + it 'contains expected commandline options' do + expect(provider.validator.build_psql_cmd).to eq(['/usr/bin/psql', '--tuples-only', '--quiet', '--no-psqlrc', '--host', 'db.test.com', '--port', 4444, '--username', 'testuser', '--command', + 'SELECT 1']) + end + end + + describe 'connect_settings' do + it 'returns array if password is present' do + expect(provider.validator.connect_settings).to eq({ 'PGPASSWORD' => 'testpass' }) + end + + it 'returns an empty array if password is nil' do + attributes.delete(:db_password) + expect(provider.validator.connect_settings).to eq({}) + end + + it 'returns an array of settings' do + attributes.delete(:db_password) + attributes.merge! connect_settings + expect(provider.validator.connect_settings).to eq({ PGHOST: 'db.test.com', PGPASSWORD: 'testpass', PGPORT: '1234' }) + end + end + + describe '#attempt_connection' do + let(:sleep_length) { 1 } + let(:tries) { 3 } + + it 'tries the correct number of times' do + provider.validator.attempt_connection(sleep_length, tries) + end + end +end diff --git a/spec/unit/puppet/provider/postgresql_psql/ruby_spec.rb b/spec/unit/puppet/provider/postgresql_psql/ruby_spec.rb index b75bd987aa..9f2c3b55e1 100644 --- a/spec/unit/puppet/provider/postgresql_psql/ruby_spec.rb +++ b/spec/unit/puppet/provider/postgresql_psql/ruby_spec.rb @@ -1,102 +1,112 @@ +# frozen_string_literal: true + require 'spec_helper' describe Puppet::Type.type(:postgresql_psql).provider(:ruby) do let(:name) { 'rspec psql test' } let(:resource) do - Puppet::Type.type(:postgresql_psql).new({ :name => name, :provider => :ruby }.merge attributes) + Puppet::Type.type(:postgresql_psql).new({ name: name, provider: :ruby }.merge(attributes)) end - let(:provider) { resource.provider } - context("#run_sql_command") do - describe "with default attributes" do - let(:attributes) do { :db => 'spec_db' } end + describe('#run_sql_command') do + describe 'with default attributes' do + let(:attributes) { { db: 'spec_db' } } - it "executes with the given psql_path on the given DB" do + it 'executes with the given psql_path on the given DB' do expect(provider).to receive(:run_command).with(['psql', '-d', - attributes[:db], '-t', '-c', '"SELECT \'something\' as \"Custom column\""'], 'postgres', - 'postgres', {}) + attributes[:db], '-t', '-X', '-c', 'SELECT \'something\' as "Custom column"'], 'postgres', + 'postgres', {}) provider.run_sql_command('SELECT \'something\' as "Custom column"') end end - describe "with psql_path and db" do - let(:attributes) do { - :psql_path => '/opt/postgres/psql', - :psql_user => 'spec_user', - :psql_group => 'spec_group', - :cwd => '/spec', - :db => 'spec_db' - } end - - it "executes with the given psql_path on the given DB" do + + describe 'with psql_path and db' do + let(:attributes) do + { + psql_path: '/opt/postgres/psql', + psql_user: 'spec_user', + psql_group: 'spec_group', + cwd: '/spec', + db: 'spec_db' + } + end + + it 'executes with the given psql_path on the given DB' do expect(Dir).to receive(:chdir).with(attributes[:cwd]).and_yield expect(provider).to receive(:run_command).with([attributes[:psql_path], - '-d', attributes[:db], '-t', '-c', '"SELECT \'something\' as \"Custom column\""'], - attributes[:psql_user], attributes[:psql_group], {}) + '-d', attributes[:db], '-t', '-X', '-c', 'SELECT \'something\' as "Custom column"'], + attributes[:psql_user], attributes[:psql_group], {}) provider.run_sql_command('SELECT \'something\' as "Custom column"') end end - describe "with search_path string" do - let(:attributes) do { - :search_path => "schema1" - } end - it "executes with the given search_path" do - expect(provider).to receive(:run_command).with(['psql', '-t', '-c', - '"set search_path to schema1; SELECT \'something\' as \"Custom column\""'], - 'postgres', 'postgres', {}) + describe 'with search_path string' do + let(:attributes) do + { + search_path: 'schema1' + } + end + + it 'executes with the given search_path' do + expect(provider).to receive(:run_command).with(['psql', '-t', '-X', '-c', + 'set search_path to schema1; SELECT \'something\' as "Custom column"'], + 'postgres', 'postgres', {}) provider.run_sql_command('SELECT \'something\' as "Custom column"') end end - describe "with search_path array" do - let(:attributes) do { - :search_path => ['schema1','schema2'], - } end - - it "executes with the given search_path" do - expect(provider).to receive(:run_command).with(['psql', '-t', '-c', - '"set search_path to schema1,schema2; SELECT \'something\' as \"Custom column\""'], - 'postgres', - 'postgres', - {} - ) + + describe 'with search_path array' do + let(:attributes) do + { + search_path: ['schema1', 'schema2'] + } + end + + it 'executes with the given search_path' do + expect(provider).to receive(:run_command).with(['psql', '-t', '-X', '-c', + 'set search_path to schema1,schema2; SELECT \'something\' as "Custom column"'], + 'postgres', 'postgres', + {}) provider.run_sql_command('SELECT \'something\' as "Custom column"') end end end - describe "with port string" do - let(:attributes) do { :port => '5555' } end - it "executes with the given port" do - expect(provider).to receive(:run_command).with(["psql", - "-p", "5555", - "-t", "-c", "\"SELECT something\""], - "postgres", "postgres", {} ) + describe 'with port string' do + let(:attributes) { { port: '5555' } } - provider.run_sql_command("SELECT something") - end + it 'executes with the given port' do + expect(provider).to receive(:run_command).with(['psql', + '-p', '5555', + '-t', '-X', '-c', 'SELECT something'], + 'postgres', 'postgres', {}) + + provider.run_sql_command('SELECT something') end - describe "with connect_settings" do - let(:attributes) do { :connect_settings => { 'PGHOST' => '127.0.0.1' } } end + end - it "executes with the given host" do - expect(provider).to receive(:run_command).with(["psql", - "-t", "-c", - "\"SELECT something\""], - "postgres", "postgres", { 'PGHOST' => '127.0.0.1' } ) + describe 'with connect_settings' do + let(:attributes) { { connect_settings: { 'PGHOST' => '127.0.0.1' } } } - provider.run_sql_command("SELECT something") - end + it 'executes with the given host' do + expect(provider).to receive(:run_command).with(['psql', + '-t', '-X', '-c', + 'SELECT something'], + 'postgres', 'postgres', { 'PGHOST' => '127.0.0.1' }) + + provider.run_sql_command('SELECT something') end + end - context("#run_unless_sql_command") do - let(:attributes) do { } end + describe('#run_unless_sql_command') do + let(:attributes) { {} } - it "calls #run_sql_command with SQL" do + it 'calls #run_sql_command with SQL' do expect(provider).to receive(:run_sql_command).with('SELECT COUNT(*) FROM (SELECT 1) count') provider.run_unless_sql_command('SELECT 1') end diff --git a/spec/unit/puppet/provider/postgresql_replication_slot/ruby_spec.rb b/spec/unit/puppet/provider/postgresql_replication_slot/ruby_spec.rb index 4fc8b55390..032ceac752 100644 --- a/spec/unit/puppet/provider/postgresql_replication_slot/ruby_spec.rb +++ b/spec/unit/puppet/provider/postgresql_replication_slot/ruby_spec.rb @@ -1,91 +1,106 @@ +# frozen_string_literal: true + require 'spec_helper' type = Puppet::Type.type(:postgresql_replication_slot) describe type.provider(:ruby) do - let(:name) { 'standby' } - let(:resource) do - type.new({ :name => name, :provider => :ruby }.merge attributes) - end - - let(:sql_instances) do - "abc | | physical | | | t | | | 0/3000420 -def | | physical | | | t | | | 0/3000420\n" - end - + # class SuccessStatus class SuccessStatus def success? true end end - let(:success_status) { SuccessStatus.new } + # class FailStatus class FailStatus def success? false end end - let(:fail_status) { FailStatus.new } + let(:name) { 'standby' } + let(:resource) do + type.new({ name: name, provider: :ruby }.merge(attributes)) + end + let(:sql_instances) do + "abc | | physical | | | t | | | 0/3000420 +def | | physical | | | t | | | 0/3000420\n" + end + let(:success_status) { SuccessStatus.new } + let(:fail_status) { FailStatus.new } let(:provider) { resource.provider } context 'when listing instances' do - let(:attributes) do { } end - - it 'should list instances' do - provider.class.expects(:run_command).with( + before(:each) do + expect(provider.class).to receive(:run_command).with( ['psql', '-t', '-c', 'SELECT * FROM pg_replication_slots;'], - 'postgres', 'postgres').returns([sql_instances, nil]) - instances = provider.class.instances + 'postgres', 'postgres' + ).and_return([sql_instances, nil]) + end + + let(:attributes) { {} } + let(:instances) { provider.class.instances } + let(:expected) { ['abc', 'def'] } + + it 'lists instances #size' do expect(instances.size).to eq 2 - expect(instances[0].name).to eq 'abc' - expect(instances[1].name).to eq 'def' + end + + it 'lists instances #content' do + expected.each_with_index do |expect, index| + expect(instances[index].name).to eq expect + end end end context 'when creating slot' do - let(:attributes) do { :ensure => 'present' } end + let(:attributes) { { ensure: 'present' } } context 'when creation works' do - it 'should call psql and succeed' do - provider.class.expects(:run_command).with( + it 'calls psql and succeed' do + expect(provider.class).to receive(:run_command).with( ['psql', '-t', '-c', "SELECT * FROM pg_create_physical_replication_slot('standby');"], - 'postgres', 'postgres').returns([nil, success_status]) + 'postgres', 'postgres' + ).and_return([nil, success_status]) expect { provider.create }.not_to raise_error end end context 'when creation fails' do - it 'should call psql and fail' do - provider.class.expects(:run_command).with( + it 'calls psql and fail' do + expect(provider.class).to receive(:run_command).with( ['psql', '-t', '-c', "SELECT * FROM pg_create_physical_replication_slot('standby');"], - 'postgres', 'postgres').returns([nil, fail_status]) + 'postgres', 'postgres' + ).and_return([nil, fail_status]) - expect { provider.create }.to raise_error(Puppet::Error, /Failed to create replication slot standby:/) + expect { provider.create }.to raise_error(Puppet::Error, %r{Failed to create replication slot standby:}) end end end context 'when destroying slot' do - let(:attributes) do { :ensure => 'absent' } end + let(:attributes) { { ensure: 'absent' } } context 'when destruction works' do - it 'should call psql and succeed' do - provider.class.expects(:run_command).with( + it 'calls psql and succeed' do + expect(provider.class).to receive(:run_command).with( ['psql', '-t', '-c', "SELECT pg_drop_replication_slot('standby');"], - 'postgres', 'postgres').returns([nil, success_status]) + 'postgres', 'postgres' + ).and_return([nil, success_status]) expect { provider.destroy }.not_to raise_error end end context 'when destruction fails' do - it 'should call psql and fail' do - provider.class.expects(:run_command).with( + it 'calls psql and fail' do + expect(provider.class).to receive(:run_command).with( ['psql', '-t', '-c', "SELECT pg_drop_replication_slot('standby');"], - 'postgres', 'postgres').returns([nil, fail_status]) + 'postgres', 'postgres' + ).and_return([nil, fail_status]) - expect { provider.destroy }.to raise_error(Puppet::Error, /Failed to destroy replication slot standby:/) + expect { provider.destroy }.to raise_error(Puppet::Error, %r{Failed to destroy replication slot standby:}) end end end diff --git a/spec/unit/puppet/type/postgresql_conn_validator.rb b/spec/unit/puppet/type/postgresql_conn_validator.rb new file mode 100644 index 0000000000..47ae4c9930 --- /dev/null +++ b/spec/unit/puppet/type/postgresql_conn_validator.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Puppet::Type.type(:postgresql_conn_validator) do + before(:each) do + @provider_class = described_class.provide(:simple) { mk_resource_methods } + @provider_class.stub(:suitable?).and_return true # rubocop:disable RSpec/InstanceVariable + described_class.stub(:defaultprovider).and_return @provider_class # rubocop:disable RSpec/InstanceVariable + end + + describe 'when validating attributes' do + [:name, :db_name, :db_username, :command, :host, :port, :connect_settings, :sleep, :tries, :psql_path].each do |param| + it "has a #{param} parameter" do + expect(described_class.attrtype(param)).to eq(:param) + end + end + end + + describe 'when validating values' do + describe 'tries and sleep' do + [:tries, :sleep, :port].each do |param| + it "#{param} should be able to cast value as integer #string" do + expect { described_class.new(:name => 'test', param => '1') }.not_to raise_error + end + + it "#{param} should be able to cast value as integer #integer" do + expect { described_class.new(:name => 'test', param => 1) }.not_to raise_error + end + + it "#{param} should not accept non-numeric string" do + expect { described_class.new(:name => 'test', param => 'test') }.to raise_error Puppet::ResourceError + end + end + end + + describe 'connect_settings' do + it 'accepts a hash' do + expect { described_class.new(name: 'test', connect_settings: { 'PGPASSWORD' => 'test1' }) }.not_to raise_error + end + end + + describe 'port' do + it 'does not accept a word' do + expect { described_class.new(name: 'test', port: 'test') }.to raise_error Puppet::Error + end + end + end +end diff --git a/spec/unit/puppet/type/postgresql_psql_spec.rb b/spec/unit/puppet/type/postgresql_psql_spec.rb index 38833271af..871645534d 100644 --- a/spec/unit/puppet/type/postgresql_psql_spec.rb +++ b/spec/unit/puppet/type/postgresql_psql_spec.rb @@ -1,83 +1,90 @@ +# frozen_string_literal: true + require 'spec_helper' -describe Puppet::Type.type(:postgresql_psql), "when validating attributes" do - [:name, :unless, :db, :psql_path, :psql_user, :psql_group, :connect_settings].each do |attr| - it "should have a #{attr} parameter" do - expect(Puppet::Type.type(:postgresql_psql).attrtype(attr)).to eq(:param) +describe Puppet::Type.type(:postgresql_psql) do # rubocop:disable RSpec/MultipleDescribes + context 'when validating attributes' do + [:name, :unless, :db, :psql_path, :psql_user, :psql_group, :connect_settings].each do |attr| + it "has a #{attr} parameter" do + expect(Puppet::Type.type(:postgresql_psql).attrtype(attr)).to eq(:param) + end end - end - [:command].each do |attr| - it "should have a #{attr} property" do - expect(Puppet::Type.type(:postgresql_psql).attrtype(attr)).to eq(:property) + [:command].each do |attr| + it "has a #{attr} property" do + expect(Puppet::Type.type(:postgresql_psql).attrtype(attr)).to eq(:property) + end end end end -describe Puppet::Type.type(:postgresql_psql), :unless => Puppet.features.microsoft_windows? do +describe Puppet::Type.type(:postgresql_psql), unless: Puppet.features.microsoft_windows? do subject do - Puppet::Type.type(:postgresql_psql).new({:name => 'rspec'}.merge attributes) + Puppet::Type.type(:postgresql_psql).new({ name: 'rspec' }.merge(attributes)) end - describe "available attributes" do + describe 'available attributes' do { - :name => "rspec", - :command => "SELECT stuff", - :unless => "SELECT other,stuff", - :db => "postgres", - :psql_path => "/bin/false", - :psql_user => "postgres", - :psql_group => "postgres", - :cwd => "/var/lib", - :refreshonly => :true, - :search_path => [ "schema1", "schema2"], - :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', }, + name: 'rspec', + command: 'SELECT stuff', + unless: 'SELECT other,stuff', + db: 'postgres', + psql_path: '/bin/false', + psql_user: 'postgres', + psql_group: 'postgres', + cwd: '/var/lib', + refreshonly: :true, + search_path: ['schema1', 'schema2'], + connect_settings: { 'PGHOST' => 'postgres-db-server', + 'DBVERSION' => '9.1' } }.each do |attr, value| context attr do - let(:attributes) do { attr => value } end + describe [attr] + subject { super()[attr] } - describe [attr] do - subject { super()[attr] } - it { is_expected.to eq(value) } - end + let(:attributes) { { attr => value } } + + it { is_expected.to eq(value) } end end + let(:attributes) { {} } - context "default values" do - let(:attributes) do {} end + context 'default value: [:psql_path]' do + subject { super()[:psql_path] } - describe '[:psql_path]' do - subject { super()[:psql_path] } - it { is_expected.to eq("psql") } - end + it { is_expected.to eq('psql') } + end - describe '[:psql_user]' do - subject { super()[:psql_user] } - it { is_expected.to eq("postgres") } - end + context 'default value: [:psql_user]' do + subject { super()[:psql_user] } - describe '[:psql_group]' do - subject { super()[:psql_group] } - it { is_expected.to eq("postgres") } - end + it { is_expected.to eq('postgres') } + end - describe '[:cwd]' do - subject { super()[:cwd] } - it { is_expected.to eq("/tmp") } - end + context 'default value: [:psql_group]' do + subject { super()[:psql_group] } - describe '#refreshonly?' do - subject { super().refreshonly? } - it { is_expected.to be_falsey } - end + it { is_expected.to eq('postgres') } + end + + context 'default value: [:cwd]' do + subject { super()[:cwd] } + + it { is_expected.to eq('/tmp') } + end + + context 'default value: #refreshonly?' do + subject { super().refreshonly? } + + it { is_expected.to be_falsey } end end - describe "#command" do - let(:attributes) do {:command => 'SELECT stuff'} end + # rubocop:disable RSpec/SubjectStub + describe '#command' do + let(:attributes) { { command: 'SELECT stuff' } } - it "will have the value :notrun if the command should execute" do + it 'will have the value :notrun if the command should execute' do expect(subject).to receive(:should_run_sql).and_return(true) expect(subject.property(:command).retrieve).to eq(:notrun) end @@ -87,165 +94,185 @@ expect(subject.property(:command).retrieve).to eq('SELECT stuff') end - it "will call provider#run_sql_command on sync" do - expect(subject.provider).to receive(:run_sql_command).with('SELECT stuff').and_return(["done", 0]) + it 'will call provider#run_sql_command on sync' do + expect(subject.provider).to receive(:run_sql_command).with('SELECT stuff').and_return(['done', 0]) subject.property(:command).sync end end - describe "#unless" do - let(:attributes) do {:unless => 'SELECT something'} end + describe '#unless' do + let(:attributes) { { unless: 'SELECT something' } } - describe "#matches" do - it "does not fail when the status is successful" do - expect(subject.provider).to receive(:run_unless_sql_command).and_return ["1 row returned", 0] + describe '#matches' do + it 'does not fail when the status is successful' do + expect(subject.provider).to receive(:run_unless_sql_command).and_return ['1 row returned', 0] subject.parameter(:unless).matches('SELECT something') end - it "returns true when rows are returned" do - expect(subject.provider).to receive(:run_unless_sql_command).and_return ["1 row returned", 0] + it 'returns true when rows are returned' do + expect(subject.provider).to receive(:run_unless_sql_command).and_return ['1 row returned', 0] expect(subject.parameter(:unless).matches('SELECT something')).to be_truthy end - it "returns false when no rows are returned" do - expect(subject.provider).to receive(:run_unless_sql_command).and_return ["0 rows returned", 0] + it 'returns false when no rows are returned' do + expect(subject.provider).to receive(:run_unless_sql_command).and_return ['0 rows returned', 0] expect(subject.parameter(:unless).matches('SELECT something')).to be_falsey end - it "raises an error when the sql command fails" do - allow(subject.provider).to receive(:run_unless_sql_command).and_return ["Something went wrong", 1] + it 'raises an error when the sql command fails' do + allow(subject.provider).to receive(:run_unless_sql_command).and_return ['Something went wrong', 1] expect { subject.parameter(:unless).matches('SELECT something') - }.to raise_error(Puppet::Error, /Something went wrong/) + }.to raise_error(Puppet::Error, %r{Something went wrong}) end end end - describe "#should_run_sql" do - context "without 'unless'" do - [true, :true].each do |refreshonly| - context "refreshonly => #{refreshonly.inspect}" do - let(:attributes) do { - :refreshonly => refreshonly, - } end - - context "not refreshing" do - it { expect(subject.should_run_sql).to be_falsey } - end - - context "refreshing" do - it { expect(subject.should_run_sql(true)).to be_truthy } - end + describe "#should_run_sql without 'unless'" do + [true, :true].each do |refreshonly| + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly } + end + + context 'not refreshing' + it { expect(subject.should_run_sql).to be_falsey } + end + + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly } end + + context 'refreshing' + it { expect(subject.should_run_sql(true)).to be_truthy } end + end - [false, :false].each do |refreshonly| - context "refreshonly => #{refreshonly.inspect}" do - let(:attributes) do { - :refreshonly => refreshonly, - } end + [false, :false].each do |refreshonly| + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly } + end - context "not refreshing" do - it { expect(subject.should_run_sql).to be_truthy } - end + context 'not refreshing' + it { expect(subject.should_run_sql).to be_truthy } + end - context "refreshing" do - it { expect(subject.should_run_sql(true)).to be_truthy } - end + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly } end + + context 'refreshing' + it { expect(subject.should_run_sql(true)).to be_truthy } end end + end - context "with matching 'unless'" do - before { expect(subject.parameter(:unless)).to receive(:matches).with('SELECT something').and_return(true) } + describe "#should_run_sql with matching 'unless'" do + before(:each) { expect(subject.parameter(:unless)).to receive(:matches).with('SELECT something').and_return(true) } - [true, :true].each do |refreshonly| - context "refreshonly => #{refreshonly.inspect}" do - let(:attributes) do { - :refreshonly => refreshonly, - :unless => 'SELECT something', - } end + [true, :true].each do |refreshonly| + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly, unless: 'SELECT something' } + end - context "not refreshing" do - it { expect(subject.should_run_sql).to be_falsey } - end + context 'not refreshing' + it { expect(subject.should_run_sql).to be_falsey } + end - context "refreshing" do - it { expect(subject.should_run_sql(true)).to be_falsey } - end + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly, unless: 'SELECT something' } end + + context 'refreshing' + it { expect(subject.should_run_sql(true)).to be_falsey } end + end - [false, :false].each do |refreshonly| - context "refreshonly => #{refreshonly.inspect}" do - let(:attributes) do { - :refreshonly => refreshonly, - :unless => 'SELECT something', - } end + [false, :false].each do |refreshonly| + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly, unless: 'SELECT something' } + end - context "not refreshing" do - it { expect(subject.should_run_sql).to be_falsey } - end + context 'not refreshing' + it { expect(subject.should_run_sql).to be_falsey } + end - context "refreshing" do - it { expect(subject.should_run_sql(true)).to be_falsey } - end + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly, unless: 'SELECT something' } end + + context 'refreshing' + it { expect(subject.should_run_sql(true)).to be_falsey } end end + end - context "when not matching 'unless'" do - before { expect(subject.parameter(:unless)).to receive(:matches).with('SELECT something').and_return(false) } + describe "#should_run_sql when not matching 'unless'" do + before(:each) { expect(subject.parameter(:unless)).to receive(:matches).with('SELECT something').and_return(false) } - [true, :true].each do |refreshonly| - context "refreshonly => #{refreshonly.inspect}" do - let(:attributes) do { - :refreshonly => refreshonly, - :unless => 'SELECT something', - } end + [true, :true].each do |refreshonly| + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly, unless: 'SELECT something' } + end - context "not refreshing" do - it { expect(subject.should_run_sql).to be_falsey } - end + context 'not refreshing' + it { expect(subject.should_run_sql).to be_falsey } + end - context "refreshing" do - it { expect(subject.should_run_sql(true)).to be_truthy } - end + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly, unless: 'SELECT something' } end + + context 'refreshing' + it { expect(subject.should_run_sql(true)).to be_truthy } end + end - [false, :false].each do |refreshonly| - context "refreshonly => #{refreshonly.inspect}" do - let(:attributes) do { - :refreshonly => refreshonly, - :unless => 'SELECT something', - } end + [false, :false].each do |refreshonly| + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly, unless: 'SELECT something' } + end - context "not refreshing" do - it { expect(subject.should_run_sql).to be_truthy } - end + context 'not refreshing' + it { expect(subject.should_run_sql).to be_truthy } + end - context "refreshing" do - it { expect(subject.should_run_sql(true)).to be_truthy } - end + context "refreshonly => #{refreshonly.inspect}" do + let(:attributes) do + { refreshonly: refreshonly, unless: 'SELECT something' } end + + context 'refreshing' + it { expect(subject.should_run_sql(true)).to be_truthy } end end end - describe "#refresh" do - let(:attributes) do {} end + describe '#refresh' do + let(:attributes) { {} } - it "syncs command property when command should run" do + it 'syncs command property when command should run' do expect(subject).to receive(:should_run_sql).with(true).and_return(true) expect(subject.property(:command)).to receive(:sync) subject.refresh end - it "does not sync command property when command should not run" do + it 'does not sync command property when command should not run' do expect(subject).to receive(:should_run_sql).with(true).and_return(false) expect(subject.property(:command)).not_to receive(:sync) subject.refresh end end end +# rubocop:enable RSpec/NamedSubject +# rubocop:enable RSpec/SubjectStub diff --git a/spec/unit/puppet/type/postgresql_replication_slot_spec.rb b/spec/unit/puppet/type/postgresql_replication_slot_spec.rb index 0d7c668853..058e0500cb 100644 --- a/spec/unit/puppet/type/postgresql_replication_slot_spec.rb +++ b/spec/unit/puppet/type/postgresql_replication_slot_spec.rb @@ -1,11 +1,13 @@ +# frozen_string_literal: true + require 'spec_helper' describe Puppet::Type.type(:postgresql_replication_slot) do subject do - Puppet::Type.type(:postgresql_psql).new({:name => 'standby'}) + Puppet::Type.type(:postgresql_psql).new(name: 'standby') end - it 'should have a name parameter' do + it 'has a name parameter' do expect(subject[:name]).to eq 'standby' end end diff --git a/spec/unit/type/postgresql_conf_spec.rb b/spec/unit/type/postgresql_conf_spec.rb index 4214facc38..f6e972f620 100644 --- a/spec/unit/type/postgresql_conf_spec.rb +++ b/spec/unit/type/postgresql_conf_spec.rb @@ -1,49 +1,123 @@ -#! /usr/bin/env ruby +# frozen_string_literal: true + require 'spec_helper' describe Puppet::Type.type(:postgresql_conf) do - before do + before(:each) do @provider_class = described_class.provide(:simple) { mk_resource_methods } - @provider_class.stub(:suitable?).and_return true - described_class.stub(:defaultprovider).and_return @provider_class + allow(@provider_class).to receive(:suitable?).and_return true # rubocop:disable RSpec/InstanceVariable + allow(described_class).to receive(:defaultprovider).and_return @provider_class # rubocop:disable RSpec/InstanceVariable end - describe "namevar validation" do - it "should have :name as its namevar" do + describe 'namevar validation' do + it 'has :name as its namevar' do expect(described_class.key_attributes).to eq([:name]) end - it "should not invalid names" do - expect { described_class.new(:name => 'foo bar') }.to raise_error(Puppet::Error, /Invalid value/) + + it 'does not invalid names' do + expect { described_class.new(name: 'foo bar') }.to raise_error(Puppet::Error, %r{Invalid value}) end - it "should allow dots in names" do - expect { described_class.new(:name => 'foo.bar') }.to_not raise_error + + it 'allows dots in names' do + expect { described_class.new(name: 'foo.bar') }.not_to raise_error end end - describe "when validating attributes" do - [:name, :provider].each do |param| - it "should have a #{param} parameter" do + describe 'when validating attributes' do + [:name, :provider, :target].each do |param| + it "has a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:param) end end - [:value, :target].each do |property| - it "should have a #{property} property" do + [:value, :comment].each do |property| + it "has a #{property} property" do expect(described_class.attrtype(property)).to eq(:property) end end end - describe "when validating values" do - describe "ensure" do - it "should support present as a value for ensure" do - expect { described_class.new(:name => 'foo', :ensure => :present) }.to_not raise_error + describe 'when validating values' do + describe 'ensure' do + it 'supports present as a value for ensure' do + expect { described_class.new(name: 'foo', ensure: :present) }.not_to raise_error + end + + it 'supports absent as a value for ensure' do + expect { described_class.new(name: 'foo', ensure: :absent) }.not_to raise_error + end + + it 'does not support other values' do + expect { described_class.new(name: 'foo', ensure: :foo) }.to raise_error(Puppet::Error, %r{Invalid value}) + end + end + # boolean https://www.postgresql.org/docs/current/datatype-boolean.html + describe 'validate boolean values with newvalues function' do + it 'validates log_checkpoints with value on' do + expect { described_class.new(name: 'log_checkpoints', value: 'on') }.not_to raise_error + end + it 'validates log_checkpoints with value off' do + expect { described_class.new(name: 'log_checkpoints', value: 'off') }.not_to raise_error + end + it 'validates log_checkpoints with value true' do + expect { described_class.new(name: 'log_checkpoints', value: 'true') }.not_to raise_error + end + it 'validates log_checkpoints with value false' do + expect { described_class.new(name: 'log_checkpoints', value: 'false') }.not_to raise_error + end + it 'validates log_checkpoints with value yes' do + expect { described_class.new(name: 'log_checkpoints', value: 'yes') }.not_to raise_error + end + it 'validates log_checkpoints with value no' do + expect { described_class.new(name: 'log_checkpoints', value: 'no') }.not_to raise_error end - it "should support absent as a value for ensure" do - expect { described_class.new(:name => 'foo', :ensure => :absent) }.to_not raise_error + it 'validates log_checkpoints with value 1' do + expect { described_class.new(name: 'log_checkpoints', value: '1') }.not_to raise_error + end + it 'validates log_checkpoints with value 0' do + expect { described_class.new(name: 'log_checkpoints', value: '0') }.not_to raise_error + end + end + # enums https://www.postgresql.org/docs/current/datatype-enum.html + describe 'validate enum values with newvalues function' do + it 'validates ssl_min_protocol_version with value TLSv1.3' do + expect { described_class.new(name: 'ssl_min_protocol_version', value: 'TLSv1.3') }.not_to raise_error + end + it 'validates ssl_min_protocol_version with value TLSv1.1' do + expect { described_class.new(name: 'ssl_min_protocol_version', value: 'TLSv1.1') }.not_to raise_error + end + end + # integer https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-INT + describe 'validate integer values with newvalues function' do + it 'validates max_connections with value 1000' do + expect { described_class.new(name: 'max_connections', value: '1000') }.not_to raise_error + end + end + # real https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-FLOAT + describe 'validate real values with newvalues function' do + it 'validates parallel_tuple_cost with value 0.3' do + expect { described_class.new(name: 'parallel_tuple_cost', value: '0.3') }.not_to raise_error + end + end + # string https://www.postgresql.org/docs/current/datatype-character.html + describe 'validate complex string values with newvalues function' do + it 'validates log_line_prefix with value [%p] %q:%u:%d:%' do + expect { described_class.new(name: 'log_line_prefix', value: '[%p] %q:%u:%d:%x ') }.not_to raise_error + end + it 'validates log_line_prefix with value %t %q%u@%d %p %i' do + expect { described_class.new(name: 'log_line_prefix', value: '%t %q%u@%d %p %i ') }.not_to raise_error + end + it 'validates log_filename with value psql_01-%Y-%m-%d.log' do + expect { described_class.new(name: 'log_filename', value: 'psql_01-%Y-%m-%d.log') }.not_to raise_error + end + end + # string https://www.postgresql.org/docs/current/datatype-character.html + describe 'validate string values with newvalues function' do + it 'validates log_timezone with value UTC' do + expect { described_class.new(name: 'log_timezone', value: 'UTC') }.not_to raise_error end - it "should not support other values" do - expect { described_class.new(:name => 'foo', :ensure => :foo) }.to raise_error(Puppet::Error, /Invalid value/) + it 'validates ssl_ciphers with value HIGH:MEDIUM:+3DES:!aNULL' do + expect { described_class.new(name: 'ssl_ciphers', value: 'HIGH:MEDIUM:+3DES:!aNULL') }.not_to raise_error end end end diff --git a/tasks/sql.json b/tasks/sql.json new file mode 100644 index 0000000000..1cd8a04a7b --- /dev/null +++ b/tasks/sql.json @@ -0,0 +1,30 @@ +{ + "description": "Allows you to execute arbitary SQL", + "input_method": "stdin", + "parameters": { + "database": { + "description": "Database to connect to", + "type": "Optional[String[1]]" + }, + "host": { + "description": "Hostname to connect to", + "type": "Optional[String[1]]" + }, + "password": { + "description": "The password", + "type": "Optional[String[1]]" + }, + "port": { + "description": "The port", + "type": "Optional[String[1]]" + }, + "sql": { + "description": "The SQL you want to execute", + "type": "String[1]" + }, + "user": { + "description": "The user", + "type": "Optional[String[1]]" + } + } +} diff --git a/tasks/sql.rb b/tasks/sql.rb new file mode 100755 index 0000000000..d350625a38 --- /dev/null +++ b/tasks/sql.rb @@ -0,0 +1,37 @@ +#!/opt/puppetlabs/puppet/bin/ruby +# frozen_string_literal: true + +require 'json' +require 'open3' +require 'puppet' + +def get(sql, database, user, port, password, host) + env_hash = {} + env_hash['PGPASSWORD'] = password unless password.nil? + cmd_string = ['psql', '-c', sql] + cmd_string << "--dbname=#{database}" unless database.nil? + cmd_string << "--username=#{user}" unless user.nil? + cmd_string << "--port=#{port}" unless port.nil? + cmd_string << "--host=#{host}" unless host.nil? + stdout, stderr, status = Open3.capture3(env_hash, *cmd_string) + raise Puppet::Error, stderr if status != 0 + + { status: stdout.strip } +end + +params = JSON.parse($stdin.read) +database = params['database'] +host = params['host'] +password = params['password'] +port = params['port'] +sql = params['sql'] +user = params['user'] + +begin + result = get(sql, database, user, port, password, host) + puts result.to_json + exit 0 +rescue Puppet::Error => e + puts({ status: 'failure', error: e.message }.to_json) + exit 1 +end diff --git a/templates/pg_dump.sh.epp b/templates/pg_dump.sh.epp new file mode 100644 index 0000000000..c5b40db492 --- /dev/null +++ b/templates/pg_dump.sh.epp @@ -0,0 +1,116 @@ +<%- | + Boolean $compress, + Array $databases, + Optional[String[1]] $db_user, + Boolean $delete_before_dump, + String[1] $dir, + Enum['plain','custom','directory','tar'] $format, + Array $optional_args, + Optional[String[1]] $post_script, + Optional[String[1]] $pre_script, + Integer[0] $rotate, + Stdlib::Absolutepath $success_file_path, +| -%> +<%- if $facts['kernel'] == 'Linux' { -%> +#!/bin/bash +<%- } else { -%> +#!/bin/sh +<%- } -%> +# This file is managed by Puppet. DO NOT EDIT. +# +# A wrapper for pg_dump + +# Backup config +ROTATE=<%= $rotate %> +BASEDIR="<%= $dir %>" +DIR="${BASEDIR}/$(date +%F_%H-%M-%S)" + +# Pattern %FILENAME% will be replace or removed, depending +# on the pg_dump parameters. +TEMPLATE="${DIR}/%FILENAME%" + +# Use a filename suffix to better distinguish different file types. +SUFFIX=".pgdump" + +# Ensure backup directory exist. +mkdir -p $DIR + +<%- if $facts['kernel'] == 'Linux' { -%> +set -o pipefail +<%- } -%> + +<% if $pre_script { -%> + <%- flatten($pre_script).each |$_script| { %> +<%= $_script %> + <%- } -%> +<% } -%> + +cleanup() +{ + <%- if $facts['kernel'] == 'SunOS' { -%> + gfind "${BASEDIR}/" -mindepth 1 -maxdepth 1 -mtime +${ROTATE} -print0 | gxargs -0 -r rm -rf + <%- } else { -%> + find "${BASEDIR}/" -mindepth 1 -maxdepth 1 -mtime +${ROTATE} -print0 | xargs -0 -r rm -rf + <%- } -%> +} + +<% if $delete_before_dump { -%> +# Remove outdated backups unconditionally before making new backups. +cleanup +<% } -%> + +_pg_args='' + +<%- if $format == 'directory' { -%> +# The 'directory' format expects a target directory instead of a file. +TEMPLATE=$DIR +<%- } -%> + +<%- if $db_user { -%> +_pg_args="${_pg_args} --username=<%= $db_user %>" +<%- } -%> + +<%- if $optional_args { -%> + <%- $optional_args.each |$_arg| { -%> +_pg_args="${_pg_args} <%= $_arg %>" + <%- } -%> +<%- } -%> + +<%- if $databases and $databases =~ Array and !empty($databases) { -%> +_pg_args="${_pg_args} --format=<%= $format %>" + +<%# Compression is only supported by pg_dump, but not by pg_dumpall. -%> +<%- if !$compress { -%> +_pg_args="${_pg_args} --compress=0" +<%# The tar archive format does not support compression. -%> +<%- } elsif $format != 'tar' { -%> +_pg_args="${_pg_args} --compress=9" +SUFFIX="${SUFFIX}.gz" +<%- } -%> + +# Dump only selected databases + <%- $databases.each |$_db| { -%> +FILE=`echo $TEMPLATE | sed "s/%FILENAME%/<%= $_db %>$SUFFIX/;"` +pg_dump $_pg_args --file=${FILE} $@ <%= $_db %> + <%- } -%> +<%- } else { -%> +# Dump the whole instance +FILE=`echo $TEMPLATE | sed "s/%FILENAME%/all$SUFFIX/;"` +pg_dumpall $_pg_args --file=${FILE} $@ +<%- } -%> + +<% unless $delete_before_dump { -%> +# Remove outdated backups only if the new backup was successful. +if [ $? -eq 0 ] ; then + cleanup + <%- if $success_file_path { -%> + touch <%= $success_file_path %> + <%- } -%> +fi +<% } -%> + +<% if $post_script { -%> + <%- flatten($post_script).each |$_script| { %> +<%= $_script %> + <%- } -%> +<% } -%> diff --git a/templates/pg_hba_rule.conf b/templates/pg_hba_rule.conf deleted file mode 100644 index af54db5b2a..0000000000 --- a/templates/pg_hba_rule.conf +++ /dev/null @@ -1,5 +0,0 @@ - -# Rule Name: <%=@name%> -# Description: <%=@description%> -# Order: <%=@order%> -<%=@type%> <%=@database%> <%=@user%> <%=@address%> <%=@auth_method%> <%=@auth_option%> diff --git a/templates/pg_hba_rule.conf.epp b/templates/pg_hba_rule.conf.epp new file mode 100644 index 0000000000..9d54265624 --- /dev/null +++ b/templates/pg_hba_rule.conf.epp @@ -0,0 +1,16 @@ +<%- | + String[1] $name, + String[1] $description, + Variant[String, Integer] $order, + Postgresql::Pg_hba_rule_type $type, + String[1] $database, + String[1] $user, + Optional[Postgresql::Pg_hba_rule_address] $address, + String[1] $auth_method, + Optional[String] $auth_option, +| -%> +# Rule Name: <%= $name %> +# Description: <%= $description %> +# Order: <%= $order %> +<%= $type %> <%= $database %> <%= $user %> <%= $address %> <%= $auth_method %> <%= $auth_option %> + diff --git a/templates/pg_ident_rule.conf b/templates/pg_ident_rule.conf deleted file mode 100644 index 238c6e96f3..0000000000 --- a/templates/pg_ident_rule.conf +++ /dev/null @@ -1,5 +0,0 @@ - -# Rule Name: <%=@name%> -# Description: <%=@description%> -# Order: <%=@order%> -<%=@map_name%> <%=@system_username%> <%=@database_username%> diff --git a/templates/pg_ident_rule.conf.epp b/templates/pg_ident_rule.conf.epp new file mode 100644 index 0000000000..ba7ec2f855 --- /dev/null +++ b/templates/pg_ident_rule.conf.epp @@ -0,0 +1,12 @@ +<%- | + String[1] $name, + String[1] $description, + String[1] $order, + String[1] $map_name, + String[1] $system_username, + String[1] $database_username, +| -%> +# Rule Name: <%= $name %> +# Description: <%= $description %> +# Order: <%= $order %> +<%= $map_name %> <%= $system_username %> <%= $database_username %> diff --git a/templates/recovery.conf b/templates/recovery.conf deleted file mode 100644 index 6fb47892e1..0000000000 --- a/templates/recovery.conf +++ /dev/null @@ -1,47 +0,0 @@ -<% if @restore_command %> -restore_command = '<%= @restore_command %>' -<% end %> -<% if @archive_cleanup_command %> -archive_cleanup_command = '<%= @archive_cleanup_command %>' -<% end %> -<% if @recovery_end_command %> -recovery_end_command = '<%= @recovery_end_command %>' -<% end %> - -<% if @recovery_target_name %> -recovery_target_name = '<%= @recovery_target_name %>' -<% end %> -<% if @recovery_target_time %> -recovery_target_time = '<%= @recovery_target_time %>' -<% end %> -<% if @recovery_target_xid %> -recovery_target_xid = '<%= @recovery_target_xid %>' -<% end %> -<% if @recovery_target_inclusive %> -recovery_target_inclusive = <%= @recovery_target_inclusive %> -<% end %> -<% if @recovery_target %> -recovery_target = '<%= @recovery_target %>' -<% end %> -<% if @recovery_target_timeline %> -recovery_target_timeline = '<%= @recovery_target_timeline %>' -<% end %> -<% if @pause_at_recovery_target %> -pause_at_recovery_target = <%= @pause_at_recovery_target %> -<% end %> - -<% if @standby_mode %> -standby_mode = <%= @standby_mode %> -<% end %> -<% if @primary_conninfo %> -primary_conninfo = '<%= @primary_conninfo %>' -<% end %> -<% if @primary_slot_name %> -primary_slot_name = '<%= @primary_slot_name %>' -<% end %> -<% if @trigger_file %> -trigger_file = '<%= @trigger_file %>' -<% end %> -<% if @recovery_min_apply_delay %> -recovery_min_apply_delay = <%= @recovery_min_apply_delay %> -<% end %> diff --git a/templates/recovery.conf.epp b/templates/recovery.conf.epp new file mode 100644 index 0000000000..ebc28e1468 --- /dev/null +++ b/templates/recovery.conf.epp @@ -0,0 +1,64 @@ +<%- | + Optional[String] $restore_command, + Optional[String[1]] $archive_cleanup_command, + Optional[String[1]] $recovery_end_command, + Optional[String[1]] $recovery_target_name, + Optional[String[1]] $recovery_target_time, + Optional[String[1]] $recovery_target_xid, + Optional[Boolean] $recovery_target_inclusive, + Optional[String[1]] $recovery_target, + Optional[String[1]] $recovery_target_timeline, + Optional[Boolean] $pause_at_recovery_target, + Optional[String[1]] $standby_mode, + Optional[String[1]] $primary_conninfo, + Optional[String[1]] $primary_slot_name, + Optional[String[1]] $trigger_file, + Optional[Integer] $recovery_min_apply_delay, +| -%> +<% if $restore_command { -%> +restore_command = '<%= $restore_command %>' +<% } -%> +<% if $archive_cleanup_command { -%> +archive_cleanup_command = '<%= $archive_cleanup_command %>' +<% } -%> +<% if $recovery_end_command { -%> +recovery_end_command = '<%= $recovery_end_command %>' +<% } -%> + +<% if $recovery_target_name { -%> +recovery_target_name = '<%= $recovery_target_name %>' +<% } -%> +<% if $recovery_target_time { -%> +recovery_target_time = '<%= $recovery_target_time %>' +<% } -%> +<% if $recovery_target_xid { -%> +recovery_target_xid = '<%= $recovery_target_xid %>' +<% } -%> +<% if $recovery_target_inclusive { -%> +recovery_target_inclusive = <%= $recovery_target_inclusive %> +<% } -%> +<% if $recovery_target { -%> +recovery_target = '<%= $recovery_target %>' +<% } -%> +<% if $recovery_target_timeline { -%> +recovery_target_timeline = '<%= $recovery_target_timeline %>' +<% } -%> +<% if $pause_at_recovery_target { -%> +pause_at_recovery_target = <%= $pause_at_recovery_target %> +<% } -%> + +<% if $standby_mode { -%> +standby_mode = <%= $standby_mode %> +<% } -%> +<% if $primary_conninfo { -%> +primary_conninfo = '<%= $primary_conninfo %>' +<% } -%> +<% if $primary_slot_name { -%> +primary_slot_name = '<%= $primary_slot_name %>' +<% } -%> +<% if $trigger_file { -%> +trigger_file = '<%= $trigger_file %>' +<% } -%> +<% if $recovery_min_apply_delay { -%> +recovery_min_apply_delay = <%= $recovery_min_apply_delay %> +<% } -%> diff --git a/templates/systemd-override.conf.epp b/templates/systemd-override.conf.epp new file mode 100644 index 0000000000..e451ce8c88 --- /dev/null +++ b/templates/systemd-override.conf.epp @@ -0,0 +1,18 @@ +<%- | + Stdlib::Port $port, + Stdlib::Absolutepath $datadir, + Optional[String[1]] $extra_systemd_config, +| -%> +[Unit] +RequiresMountsFor=<%= $datadir %> + +[Service] +Environment=PGPORT=<%= $port %> +<%- if $facts['os']['family'] == 'Gentoo' { -%> +Environment=DATA_DIR=<%= $datadir %> +<%- } else { -%> +Environment=PGDATA=<%= $datadir %> +<%- } -%> +<% if $extra_systemd_config { -%> +<%= $extra_systemd_config %> +<% } -%> diff --git a/templates/systemd-override.erb b/templates/systemd-override.erb deleted file mode 100644 index eb4f787f77..0000000000 --- a/templates/systemd-override.erb +++ /dev/null @@ -1,8 +0,0 @@ -<%- if scope.lookupvar('::operatingsystem') == 'Fedora' -%> -.include /lib/systemd/system/<%= @service_name %>.service -<% else -%> -.include /usr/lib/systemd/system/<%= @service_name %>.service -<% end -%> -[Service] -Environment=PGPORT=<%= @port %> -Environment=PGDATA=<%= @datadir %> diff --git a/types/pg_hba_rule.pp b/types/pg_hba_rule.pp new file mode 100644 index 0000000000..b4759f3220 --- /dev/null +++ b/types/pg_hba_rule.pp @@ -0,0 +1,14 @@ +# @summary type for all parameters in the postgresql::server::hba_rule defined resource +# @see https://github.com/puppetlabs/puppetlabs-postgresql/blob/main/manifests/server/pg_hba_rule.pp +type Postgresql::Pg_hba_rule = Struct[{ + Optional[description] => String, + type => Postgresql::Pg_hba_rule_type, + database => String, + user => String, + Optional[address] => Optional[Postgresql::Pg_hba_rule_address], + auth_method => String, + Optional[auth_option] => Optional[String], + Optional[order] => Variant[String,Integer], + Optional[target] => Stdlib::Absolutepath, + Optional[postgresql_version] => String, +}] diff --git a/types/pg_hba_rule_address.pp b/types/pg_hba_rule_address.pp new file mode 100644 index 0000000000..3955f00c0a --- /dev/null +++ b/types/pg_hba_rule_address.pp @@ -0,0 +1,10 @@ +# @summary Supported address types +# @see https://www.postgresql.org/docs/current/auth-pg-hba-conf.html +type Postgresql::Pg_hba_rule_address = Variant[ + Stdlib::IP::Address::V4::CIDR, + Stdlib::IP::Address::V6::CIDR, + Stdlib::Fqdn, + Enum['all', 'samehost', 'samenet'], + # RegExp for a DNS domain - also starting with a single dot + Pattern[/^\.(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$/], +] diff --git a/types/pg_hba_rule_type.pp b/types/pg_hba_rule_type.pp new file mode 100644 index 0000000000..bbf4360748 --- /dev/null +++ b/types/pg_hba_rule_type.pp @@ -0,0 +1,3 @@ +# @summary enum for all different types for the pg_hba_conf +# @see https://www.postgresql.org/docs/current/auth-pg-hba-conf.html +type Postgresql::Pg_hba_rule_type = Enum['local', 'host', 'hostssl', 'hostnossl', 'hostgssenc', 'hostnogssenc'] diff --git a/types/pg_hba_rules.pp b/types/pg_hba_rules.pp new file mode 100644 index 0000000000..9f010bc040 --- /dev/null +++ b/types/pg_hba_rules.pp @@ -0,0 +1,3 @@ +# @summary validates a hash of entries for postgresql::server::pg_hab_conf +# @see https://github.com/puppetlabs/puppetlabs-postgresql/blob/main/manifests/server/pg_hba_rule.pp +type Postgresql::Pg_hba_rules = Hash[String[1], Postgresql::Pg_hba_rule] diff --git a/types/pg_password_encryption.pp b/types/pg_password_encryption.pp new file mode 100644 index 0000000000..7512174a89 --- /dev/null +++ b/types/pg_password_encryption.pp @@ -0,0 +1,4 @@ +# @summary the supported password_encryption +# Note that this Enum is also defined in: +# lib/puppet/functions/postgresql/postgresql_password.rb +type Postgresql::Pg_password_encryption = Enum['md5', 'scram-sha-256']