diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..12ed4ff --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,6 @@ +FROM puppet/pdk:latest + +# [Optional] Uncomment this section to install additional packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends + diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000..a719361 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,38 @@ +# devcontainer + + +For format details, see https://aka.ms/devcontainer.json. + +For config options, see the README at: +https://github.com/microsoft/vscode-dev-containers/tree/v0.140.1/containers/puppet + +``` json +{ + "name": "Puppet Development Kit (Community)", + "dockerFile": "Dockerfile", + + // Set *default* container specific settings.json values on container create. + "settings": { + "terminal.integrated.profiles.linux": { + "bash": { + "path": "bash", + } + } + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "puppet.puppet-vscode", + "rebornix.Ruby" + ], + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "pdk --version", +} +``` + + + diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..fe7a8b1 --- /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-latest.yml b/.fixtures-latest.yml index f97627f..1a807b4 100644 --- a/.fixtures-latest.yml +++ b/.fixtures-latest.yml @@ -2,23 +2,22 @@ # See https://github.com/puppetlabs/puppetlabs_spec_helper#using-fixtures for details --- fixtures: - repositories: + forge_modules: stdlib: - repo: https://github.com/puppetlabs/puppetlabs-stdlib.git + repo: puppetlabs/stdlib postgresql: - repo: https://github.com/puppetlabs/puppetlabs-postgresql.git + repo: puppetlabs/postgresql # Needed by Postgresql module apt: - repo: https://github.com/puppetlabs/puppetlabs-apt.git + repo: puppetlabs/apt python: - repo: https://github.com/voxpupuli/puppet-python.git + repo: puppet/python # Needed by Python module epel: - repo: https://github.com/voxpupuli/puppet-epel.git + repo: puppet/epel systemd: - repo: https://github.com/camptocamp/puppet-systemd.git + repo: puppet/systemd yumrepo_core: - repo: git://github.com/puppetlabs/puppetlabs-yumrepo_core - puppet_version: ">= 6.0.0" + repo: puppetlabs/yumrepo_core symlinks: - etcd: "#{source_dir}" + patroni: "#{source_dir}" diff --git a/.fixtures.yml b/.fixtures.yml index d7c9898..2373b43 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -2,30 +2,29 @@ # See https://github.com/puppetlabs/puppetlabs_spec_helper#using-fixtures for details --- fixtures: - repositories: + forge_modules: stdlib: - repo: https://github.com/puppetlabs/puppetlabs-stdlib.git - ref: v6.0.0 + repo: puppetlabs/stdlib + ref: '9.4.1' postgresql: - repo: https://github.com/puppetlabs/puppetlabs-postgresql.git - ref: v6.4.0 + repo: puppetlabs/postgresql + ref: '10.0.2' # Needed by Postgresql module apt: - repo: https://github.com/puppetlabs/puppetlabs-apt.git - ref: v7.5.0 + repo: puppetlabs/apt + ref: '9.1.0' python: - repo: https://github.com/voxpupuli/puppet-python.git - ref: v4.0.0 + repo: puppet/python + ref: '7.0.0' # Needed by Python module epel: - repo: https://github.com/voxpupuli/puppet-epel.git - ref: v3.0.0 + repo: puppet/epel + ref: '5.0.0' systemd: - repo: https://github.com/camptocamp/puppet-systemd.git - ref: 2.0.0 + repo: puppet/systemd + ref: '6.1.0' yumrepo_core: - repo: git://github.com/puppetlabs/puppetlabs-yumrepo_core - ref: 1.0.1 - puppet_version: ">= 6.0.0" + repo: puppetlabs/yumrepo_core + ref: '2.0.0' symlinks: - etcd: "#{source_dir}" + patroni: "#{source_dir}" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..3ad9440 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,94 @@ +name: CI + +on: + push: + branches: + - main + - master + pull_request: + +jobs: + unit: + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.allow_failure }} + strategy: + fail-fast: false + matrix: + include: + - ruby: 2.7.8 + puppet: 7 + fixtures: .fixtures.yml + allow_failure: false + - ruby: 2.7.8 + puppet: 7 + fixtures: .fixtures-latest.yml + allow_failure: true + - ruby: 3.2.2 + puppet: 8 + fixtures: .fixtures.yml + allow_failure: false + - ruby: 3.2.2 + puppet: 8 + fixtures: .fixtures-latest.yml + allow_failure: true + env: + BUNDLE_WITHOUT: system_tests:release + PUPPET_GEM_VERSION: "~> ${{ matrix.puppet }}.0" + FIXTURES_YML: ${{ matrix.fixtures }} + name: Puppet ${{ matrix.puppet }} (Ruby ${{ matrix.ruby }} fixtures=${{ matrix.fixtures }}) + steps: + - uses: actions/checkout@v3 + - name: Setup ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + cache-version: 2 + bundler: '2.1.0' + - name: Validate + run: bundle exec rake check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop syntax lint metadata_lint + - name: Run tests + run: bundle exec rake parallel_spec + acceptance: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + set: + - "el8" + - "el9" + - "debian-11" + - "ubuntu-2004" + - "ubuntu-2204" + puppet: + - "puppet7" + - "puppet8" + env: + BUNDLE_WITHOUT: development:release + BEAKER_debug: true + name: + steps: + - name: Enable IPv6 on docker + run: | + echo '{"ipv6":true,"fixed-cidr-v6":"2001:db8:1::/64"}' | sudo tee /etc/docker/daemon.json + sudo service docker restart + # https://github.com/actions/virtual-environments/issues/181#issuecomment-610874237 + - name: apparmor + run: | + set -x + sudo apt-get remove mysql-server --purge + sudo apt-get install apparmor-profiles + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + - uses: actions/checkout@v3 + - name: Setup ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '2.7' + bundler-cache: true + cache-version: 2 + bundler: '2.1.0' + - name: Run tests + run: bundle exec rake beaker + env: + BEAKER_PUPPET_COLLECTION: ${{ matrix.puppet }} + BEAKER_set: ${{ matrix.set }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..da72f01 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,31 @@ +name: Release + +on: + push: + tags: + - '*' + +env: + BUNDLE_WITHOUT: system_tests + +jobs: + deploy: + name: 'deploy to forge' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '2.7' + bundler-cache: true + cache-version: 2 + bundler: '2.1.0' + - name: Build and Deploy + env: + # Configure secrets here: + # https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets + BLACKSMITH_FORGE_USERNAME: 'tailoredautomation' + BLACKSMITH_FORGE_API_KEY: '${{ secrets.PUPPET_FORGE_API_KEY }}' + run: bundle exec rake module:push diff --git a/.gitignore b/.gitignore index 2767022..988dcbb 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ .project .envrc /inventory.yaml +/spec/fixtures/litmus_inventory.yaml diff --git a/.pdkignore b/.pdkignore index e6215cd..fcf8a0e 100644 --- a/.pdkignore +++ b/.pdkignore @@ -25,6 +25,7 @@ .project .envrc /inventory.yaml +/spec/fixtures/litmus_inventory.yaml /appveyor.yml /.fixtures.yml /Gemfile @@ -40,3 +41,5 @@ /.yardopts /spec/ /.vscode/ +/.sync.yml +/.devcontainer/ diff --git a/.puppet-lint.rc b/.puppet-lint.rc index 53fcb9a..75071c7 100644 --- a/.puppet-lint.rc +++ b/.puppet-lint.rc @@ -1,2 +1,5 @@ +--no-80chars-check +--no-140chars-check +--no-manifest_whitespace_opening_brace_after-check --relative --fail_on_warnings diff --git a/.rubocop.yml b/.rubocop.yml index 5307849..9bf7843 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,12 +1,12 @@ --- require: +- rubocop-performance - rubocop-rspec -- rubocop-i18n AllCops: DisplayCopNames: true - TargetRubyVersion: '2.1' + TargetRubyVersion: '2.5' Include: - - "./**/*.rb" + - "**/*.rb" Exclude: - bin/* - ".vendor/**/*" @@ -18,16 +18,9 @@ AllCops: - "**/Puppetfile" - "**/Vagrantfile" - "**/Guardfile" -Metrics/LineLength: +Layout/LineLength: Description: People have wide screens, use them. Max: 200 -GetText: - Enabled: false -GetText/DecorateString: - Description: We don't want to decorate test output. - Exclude: - - spec/**/* - Enabled: false RSpec/BeforeAfterAll: Description: Beware of using after(:all) as it may cause state to leak between tests. A necessary evil in acceptance testing. @@ -36,14 +29,13 @@ RSpec/BeforeAfterAll: 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/BracesAroundHashParameters: - Description: Braces are required by Ruby 2.7. Cop removed from RuboCop v0.80.0. - See https://github.com/rubocop-hq/rubocop/pull/7643 - Enabled: true Style/ClassAndModuleChildren: Description: Compact style reduces the required amount of indentation. EnforcedStyle: compact @@ -72,41 +64,193 @@ Style/TrailingCommaInArguments: Description: Prefer always trailing comma on multiline argument lists. This makes diffs, and re-ordering nicer. EnforcedStyleForMultiline: comma -Style/TrailingCommaInLiteral: +Style/TrailingCommaInArrayLiteral: Description: Prefer always trailing comma on multiline literals. This makes diffs, and re-ordering nicer. EnforcedStyleForMultiline: comma Style/SymbolArray: Description: Using percent style obscures symbolic intent of array's contents. EnforcedStyle: brackets +Layout/FirstHashElementIndentation: + Enabled: false +Performance/RegexpMatch: + Enabled: false RSpec/MessageSpies: EnforcedStyle: receive +RSpec/NamedSubject: + Enabled: false Style/Documentation: Exclude: - lib/puppet/parser/functions/**/* - spec/**/* +Style/HashEachMethods: + Enabled: false 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 -GetText/DecorateFunctionMessage: +Bundler/InsecureProtocolSource: + Enabled: false +Gemspec/DuplicatedAssignment: + Enabled: false +Gemspec/OrderedDependencies: + Enabled: false +Gemspec/RequiredRubyVersion: Enabled: false -GetText/DecorateStringFormattingUsingInterpolation: +Gemspec/RubyVersionGlobalsUsage: Enabled: false -GetText/DecorateStringFormattingUsingPercent: +Layout/ArgumentAlignment: + Enabled: false +Layout/BeginEndAlignment: + Enabled: false +Layout/ClosingHeredocIndentation: + Enabled: false +Layout/EmptyComment: + Enabled: false +Layout/EmptyLineAfterGuardClause: + Enabled: false +Layout/EmptyLinesAroundArguments: + Enabled: false +Layout/EmptyLinesAroundAttributeAccessor: Enabled: false Layout/EndOfLine: Enabled: false -Layout/IndentHeredoc: +Layout/FirstArgumentIndentation: + Enabled: false +Layout/HashAlignment: + Enabled: false +Layout/HeredocIndentation: + Enabled: false +Layout/LeadingEmptyLines: + Enabled: false +Layout/SpaceAroundMethodCallOperator: + Enabled: false +Layout/SpaceInsideArrayLiteralBrackets: + Enabled: false +Layout/SpaceInsideReferenceBrackets: + Enabled: false +Lint/BigDecimalNew: + Enabled: false +Lint/BooleanSymbol: + Enabled: false +Lint/ConstantDefinitionInBlock: + Enabled: false +Lint/DeprecatedOpenSSLConstant: + Enabled: false +Lint/DisjunctiveAssignmentInConstructor: + Enabled: false +Lint/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: @@ -119,19 +263,267 @@ Metrics/ParameterLists: Enabled: false Metrics/PerceivedComplexity: Enabled: false +Migration/DepartmentName: + Enabled: false +Naming/AccessorMethodName: + Enabled: false +Naming/BlockParameterName: + Enabled: false +Naming/HeredocDelimiterCase: + Enabled: false +Naming/HeredocDelimiterNaming: + Enabled: false +Naming/MemoizedInstanceVariableName: + Enabled: false +Naming/MethodParameterName: + Enabled: false +Naming/RescuedExceptionsVariableName: + Enabled: false +Naming/VariableNumber: + Enabled: false +Performance/BindCall: + Enabled: false +Performance/DeletePrefix: + Enabled: false +Performance/DeleteSuffix: + Enabled: false +Performance/InefficientHashSearch: + Enabled: false +Performance/UnfreezeString: + Enabled: false +Performance/UriDefaultParser: + Enabled: false +RSpec/Be: + Enabled: false +RSpec/Capybara/CurrentPathExpectation: + Enabled: false +RSpec/Capybara/FeatureMethods: + Enabled: false +RSpec/Capybara/VisibilityMatcher: + Enabled: false +RSpec/ContextMethod: + Enabled: false +RSpec/ContextWording: + Enabled: false RSpec/DescribeClass: Enabled: false +RSpec/EmptyHook: + Enabled: false +RSpec/EmptyLineAfterExample: + Enabled: false +RSpec/EmptyLineAfterExampleGroup: + Enabled: false +RSpec/EmptyLineAfterHook: + Enabled: false RSpec/ExampleLength: Enabled: false -RSpec/MessageExpectation: +RSpec/ExampleWithoutDescription: + Enabled: false +RSpec/ExpectChange: + Enabled: false +RSpec/ExpectInHook: + Enabled: false +RSpec/FactoryBot/AttributeDefinedStatically: + Enabled: false +RSpec/FactoryBot/CreateList: + Enabled: false +RSpec/FactoryBot/FactoryClassName: + Enabled: false +RSpec/HooksBeforeExamples: + Enabled: false +RSpec/ImplicitBlockExpectation: + Enabled: false +RSpec/ImplicitSubject: + Enabled: false +RSpec/LeakyConstantDeclaration: + Enabled: false +RSpec/LetBeforeExamples: + Enabled: false +RSpec/MissingExampleGroupArgument: Enabled: false RSpec/MultipleExpectations: Enabled: false +RSpec/MultipleMemoizedHelpers: + Enabled: false +RSpec/MultipleSubjects: + Enabled: false RSpec/NestedGroups: Enabled: false +RSpec/PredicateMatcher: + Enabled: false +RSpec/ReceiveCounts: + Enabled: false +RSpec/ReceiveNever: + Enabled: false +RSpec/RepeatedExampleGroupBody: + Enabled: false +RSpec/RepeatedExampleGroupDescription: + Enabled: false +RSpec/RepeatedIncludeExample: + Enabled: false +RSpec/ReturnFromStub: + Enabled: false +RSpec/SharedExamples: + Enabled: false +RSpec/StubbedMock: + Enabled: false +RSpec/UnspecifiedException: + Enabled: false +RSpec/VariableDefinition: + Enabled: false +RSpec/VoidExpect: + Enabled: false +RSpec/Yield: + Enabled: false +Security/Open: + Enabled: false +Style/AccessModifierDeclarations: + Enabled: false +Style/AccessorGrouping: + Enabled: false Style/AsciiComments: Enabled: false +Style/BisectedAttrAccessor: + Enabled: false +Style/CaseLikeIf: + Enabled: false +Style/ClassEqualityComparison: + Enabled: false +Style/ColonMethodDefinition: + Enabled: false +Style/CombinableLoops: + Enabled: false +Style/CommentedKeyword: + Enabled: false +Style/Dir: + Enabled: false +Style/DoubleCopDisableDirective: + Enabled: false +Style/EmptyBlockParameter: + Enabled: false +Style/EmptyLambdaParameter: + Enabled: false +Style/Encoding: + Enabled: false +Style/EvalWithLocation: + Enabled: false +Style/ExpandPathArguments: + Enabled: false +Style/ExplicitBlockArgument: + Enabled: false +Style/ExponentialNotation: + Enabled: false +Style/FloatDivision: + Enabled: false +Style/FrozenStringLiteralComment: + Enabled: false +Style/GlobalStdStream: + Enabled: false +Style/HashAsLastArrayItem: + Enabled: false +Style/HashLikeCase: + Enabled: false +Style/HashTransformKeys: + Enabled: false +Style/HashTransformValues: + Enabled: false Style/IfUnlessModifier: Enabled: false +Style/KeywordParametersOrder: + Enabled: false +Style/MinMax: + Enabled: false +Style/MixinUsage: + Enabled: false +Style/MultilineWhenThen: + Enabled: false +Style/NegatedUnless: + Enabled: false +Style/NumericLiterals: + Enabled: false +Style/NumericPredicate: + Enabled: false +Style/OptionalBooleanParameter: + Enabled: false +Style/OrAssignment: + Enabled: false +Style/RandomWithOffset: + Enabled: false +Style/RedundantAssignment: + Enabled: false +Style/RedundantCondition: + Enabled: false +Style/RedundantConditional: + Enabled: false +Style/RedundantFetchBlock: + Enabled: false +Style/RedundantFileExtensionInRequire: + Enabled: false +Style/RedundantRegexpCharacterClass: + Enabled: false +Style/RedundantRegexpEscape: + Enabled: false +Style/RedundantSelfAssignment: + Enabled: false +Style/RedundantSort: + Enabled: false +Style/RescueStandardError: + Enabled: false +Style/SingleArgumentDig: + Enabled: false +Style/SlicingWithRange: + Enabled: false +Style/SoleNestedConditional: + Enabled: false +Style/StderrPuts: + Enabled: false +Style/StringConcatenation: + Enabled: false +Style/Strip: + Enabled: false Style/SymbolProc: Enabled: false +Style/TrailingBodyOnClass: + Enabled: false +Style/TrailingBodyOnMethodDefinition: + Enabled: false +Style/TrailingBodyOnModule: + Enabled: false +Style/TrailingCommaInHashLiteral: + Enabled: false +Style/TrailingMethodEndStatement: + Enabled: false +Style/UnpackFirst: + Enabled: false +Lint/DuplicateBranch: + Enabled: false +Lint/DuplicateRegexpCharacterClassElement: + Enabled: false +Lint/EmptyBlock: + Enabled: false +Lint/EmptyClass: + Enabled: false +Lint/NoReturnInBeginEndBlocks: + Enabled: false +Lint/ToEnumArguments: + Enabled: false +Lint/UnexpectedBlockArity: + Enabled: false +Lint/UnmodifiedReduceAccumulator: + Enabled: false +Performance/CollectionLiteralInLoop: + Enabled: false +Style/ArgumentsForwarding: + Enabled: false +Style/CollectionCompact: + Enabled: false +Style/DocumentDynamicEvalDefinition: + Enabled: false +Style/NegatedIfElseCondition: + Enabled: false +Style/NilLambda: + Enabled: false +Style/RedundantArgument: + Enabled: false +Style/SwapValues: + Enabled: false diff --git a/.sync.yml b/.sync.yml index 3b22268..b3ec10c 100644 --- a/.sync.yml +++ b/.sync.yml @@ -1,42 +1,16 @@ +.github/workflows/ci.yaml: + acceptance_matrix: + set: + - el8 + - el9 + - debian-11 + - ubuntu-2004 + - ubuntu-2204 + puppet: + - puppet7 + - puppet8 .travis.yml: - dist: xenial - extras: - - env: CHECK="parallel_spec" PUPPET_GEM_VERSION="~> 5" FIXTURES_YML=".fixtures-latest.yml" - rvm: 2.4.9 - stage: spec - - env: CHECK="parallel_spec" PUPPET_GEM_VERSION="~> 6" FIXTURES_YML=".fixtures-latest.yml" - rvm: 2.5.7 - stage: spec - allow_failures: - - env: CHECK="parallel_spec" PUPPET_GEM_VERSION="~> 5" FIXTURES_YML=".fixtures-latest.yml" - rvm: 2.4.9 - - env: CHECK="parallel_spec" PUPPET_GEM_VERSION="~> 6" FIXTURES_YML=".fixtures-latest.yml" - rvm: 2.5.7 - docker_defaults: - dist: xenial - docker_sets: - - set: centos-7 - collection: puppet5 - - set: centos-7 - collection: puppet6 - - set: centos-8 - collection: puppet5 - - set: centos-8 - collection: puppet6 - - set: debian-9 - collection: puppet5 - - set: debian-9 - collection: puppet6 - - set: debian-10 - collection: puppet5 - - set: debian-10 - collection: puppet6 - - set: ubuntu-1804 - collection: puppet5 - - set: ubuntu-1804 - collection: puppet5 - user: tailoredautomation - secure: "x4sufb/wyxHY9ftHqrfqEfNqkzSSFLUZcRLyf/QfmXGrhus0+H9MTcV8wMKFBlp0MbnXnHAl7JZSeZdfCrcDc/l+IfZ42ZR3VIA+SRyhKv3Ads72qEMUKwwybla+tE3yGRc1dNhBc7KiavmFKYhzHQcVOJSbH2dHpntp2ss/LuZ+uUC7bUM8Omeq6t8rqcYo+zxNTGxiQ20zSvmcAP8N1Uysmrj504l/ANwnWCtgAm/hZ5xMbw/Gy25dkLiFlCEXBDp3y7BAP5wIlFoq0W3t6Q1/aPJvj4FKRdTcw6JvQ/v/znXKZrGasQ7avQk645qDbdJ10V3b15XljIRw557HpOOI3NmNwL1csO/tM7S5nvjAfsMf/veLk1DIZoNdmwmXmvfgAmZcOdaxzi4Q+7VK8t56Nk7j8favmkIGn1O+cCoXUTloBmb+GL0djYOQqdlmE4gOJ1qqTt4LTca7xW6EcaM7KuIVBP3IsctajM0gxF1TqRrZgP3KfmMjXYXjOsSlzykowjDc84gUddwg+b1MsKhFegRdpTepVWSHCCT4Z+MaGLD8z0QQx/1HCkFfmOXy0ZvEVZUWdjkRx7H4wmqajqHH+dggs3Y3EL9JRJInDYaLkm4HJhbb/v+g90g4aiSScrOD661Iq8/vV/k+DqSTAnAwDg15rPRig0Rs4E6vmVg=" + delete: true .gitlab-ci.yml: delete: true appveyor.yml: @@ -50,19 +24,13 @@ Rakefile: spec/spec_helper.rb: coverage_report: true minimum_code_coverage_percentage: 100 -spec/acceptance/nodesets/centos-6.yml: - delete: true -spec/acceptance/nodesets/centos-7.yml: +spec/acceptance/nodesets/el8.yml: unmanaged: true -spec/acceptance/nodesets/centos-8.yml: +spec/acceptance/nodesets/el9.yml: unmanaged: true -spec/acceptance/nodesets/ubuntu-1604.yml: - delete: true -spec/acceptance/nodesets/ubuntu-1804.yml: +spec/acceptance/nodesets/ubuntu-2004.yml: unmanaged: true -spec/acceptance/nodesets/debian-8.yml: - delete: true -spec/acceptance/nodesets/debian-9.yml: +spec/acceptance/nodesets/ubuntu-2204.yml: unmanaged: true -spec/acceptance/nodesets/debian-10.yml: +spec/acceptance/nodesets/debian-11.yml: unmanaged: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f3ee1da..0000000 --- a/.travis.yml +++ /dev/null @@ -1,157 +0,0 @@ ---- -os: linux -dist: xenial -language: ruby -cache: bundler -before_install: - - bundle -v - - rm -f Gemfile.lock - - "# Update system gems if requested. This is useful to temporarily workaround troubles in the test runner" - - "# See https://github.com/puppetlabs/pdk-templates/commit/705154d5c437796b821691b707156e1b056d244f for an example of how this was used" - - "# Ignore exit code of SIGPIPE'd yes to not fail with shell's pipefail set" - - '[ -z "$RUBYGEMS_VERSION" ] || (yes || true) | gem update --system $RUBYGEMS_VERSION' - - gem --version - - bundle -v -script: - - 'bundle exec rake $CHECK' -bundler_args: --without system_tests -rvm: - - 2.5.7 -env: - global: - - FACTER_GEM_VERSION="< 4.0" -stages: - - static - - spec - - acceptance - - - if: tag =~ ^v\d - name: deploy -jobs: - fast_finish: true - include: - - - bundler_args: --with system_tests - dist: xenial - env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_set=centos-7 BEAKER_TESTMODE=apply - rvm: 2.5.7 - script: bundle exec rake beaker - services: docker - stage: acceptance - sudo: required - - - bundler_args: --with system_tests - dist: xenial - env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_set=centos-7 BEAKER_TESTMODE=apply - rvm: 2.5.7 - script: bundle exec rake beaker - services: docker - stage: acceptance - sudo: required - - - bundler_args: --with system_tests - dist: xenial - env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_set=centos-8 BEAKER_TESTMODE=apply - rvm: 2.5.7 - script: bundle exec rake beaker - services: docker - stage: acceptance - sudo: required - - - bundler_args: --with system_tests - dist: xenial - env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_set=centos-8 BEAKER_TESTMODE=apply - rvm: 2.5.7 - script: bundle exec rake beaker - services: docker - stage: acceptance - sudo: required - - - bundler_args: --with system_tests - dist: xenial - env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_set=debian-9 BEAKER_TESTMODE=apply - rvm: 2.5.7 - script: bundle exec rake beaker - services: docker - stage: acceptance - sudo: required - - - bundler_args: --with system_tests - dist: xenial - env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_set=debian-9 BEAKER_TESTMODE=apply - rvm: 2.5.7 - script: bundle exec rake beaker - services: docker - stage: acceptance - sudo: required - - - bundler_args: --with system_tests - dist: xenial - env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_set=debian-10 BEAKER_TESTMODE=apply - rvm: 2.5.7 - script: bundle exec rake beaker - services: docker - stage: acceptance - sudo: required - - - bundler_args: --with system_tests - dist: xenial - env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_set=debian-10 BEAKER_TESTMODE=apply - rvm: 2.5.7 - script: bundle exec rake beaker - services: docker - stage: acceptance - sudo: required - - - bundler_args: --with system_tests - dist: xenial - env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_set=ubuntu-1804 BEAKER_TESTMODE=apply - rvm: 2.5.7 - script: bundle exec rake beaker - services: docker - stage: acceptance - sudo: required - - - env: CHECK="check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop syntax lint metadata_lint" - stage: static - - - env: PUPPET_GEM_VERSION="~> 5.0" CHECK=parallel_spec - rvm: 2.4.9 - stage: spec - - - env: PUPPET_GEM_VERSION="~> 6.0" CHECK=parallel_spec - rvm: 2.5.7 - stage: spec - - - env: DEPLOY_TO_FORGE=yes - stage: deploy - - - env: CHECK="parallel_spec" PUPPET_GEM_VERSION="~> 5" FIXTURES_YML=".fixtures-latest.yml" - rvm: 2.4.9 - stage: spec - - - env: CHECK="parallel_spec" PUPPET_GEM_VERSION="~> 6" FIXTURES_YML=".fixtures-latest.yml" - rvm: 2.5.7 - stage: spec - allow_failures: - - - env: CHECK="parallel_spec" PUPPET_GEM_VERSION="~> 5" FIXTURES_YML=".fixtures-latest.yml" - rvm: 2.4.9 - - - env: CHECK="parallel_spec" PUPPET_GEM_VERSION="~> 6" FIXTURES_YML=".fixtures-latest.yml" - rvm: 2.5.7 -branches: - only: - - master - - /^v\d/ -notifications: - email: false -deploy: - provider: puppetforge - username: tailoredautomation - password: - secure: "x4sufb/wyxHY9ftHqrfqEfNqkzSSFLUZcRLyf/QfmXGrhus0+H9MTcV8wMKFBlp0MbnXnHAl7JZSeZdfCrcDc/l+IfZ42ZR3VIA+SRyhKv3Ads72qEMUKwwybla+tE3yGRc1dNhBc7KiavmFKYhzHQcVOJSbH2dHpntp2ss/LuZ+uUC7bUM8Omeq6t8rqcYo+zxNTGxiQ20zSvmcAP8N1Uysmrj504l/ANwnWCtgAm/hZ5xMbw/Gy25dkLiFlCEXBDp3y7BAP5wIlFoq0W3t6Q1/aPJvj4FKRdTcw6JvQ/v/znXKZrGasQ7avQk645qDbdJ10V3b15XljIRw557HpOOI3NmNwL1csO/tM7S5nvjAfsMf/veLk1DIZoNdmwmXmvfgAmZcOdaxzi4Q+7VK8t56Nk7j8favmkIGn1O+cCoXUTloBmb+GL0djYOQqdlmE4gOJ1qqTt4LTca7xW6EcaM7KuIVBP3IsctajM0gxF1TqRrZgP3KfmMjXYXjOsSlzykowjDc84gUddwg+b1MsKhFegRdpTepVWSHCCT4Z+MaGLD8z0QQx/1HCkFfmOXy0ZvEVZUWdjkRx7H4wmqajqHH+dggs3Y3EL9JRJInDYaLkm4HJhbb/v+g90g4aiSScrOD661Iq8/vV/k+DqSTAnAwDg15rPRig0Rs4E6vmVg=" - on: - tags: true - all_branches: true - condition: "$DEPLOY_TO_FORGE = yes" diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c313e8..a1309e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,76 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org). +## [v2.1.0](https://github.com/tailored-automation/puppet-module-patroni/tree/v2.1.0) (2025-01-04) + +[Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/v2.0.1...v2.1.0) + +### Added + +- Harden the datatypes [\#48](https://github.com/tailored-automation/puppet-module-patroni/pull/48) ([ghoneycutt](https://github.com/ghoneycutt)) + +## [v2.0.1](https://github.com/tailored-automation/puppet-module-patroni/tree/v2.0.1) (2025-01-04) + +[Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/v2.0.0...v2.0.1) + +### Fixed + +- Fix existing issues so tests work again [\#47](https://github.com/tailored-automation/puppet-module-patroni/pull/47) ([ghoneycutt](https://github.com/ghoneycutt)) + +### Merged pull requests: + +- Fix crash if pg password starting with bracket [\#42](https://github.com/tailored-automation/puppet-module-patroni/pull/42) ([ghoneycutt](https://github.com/ghoneycutt)) +- Fix crash if pg password starting with bracket [\#39](https://github.com/tailored-automation/puppet-module-patroni/pull/39) ([mouchymouchy](https://github.com/mouchymouchy)) +- adding standby cluster config [\#31](https://github.com/tailored-automation/puppet-module-patroni/pull/31) ([plmayekar](https://github.com/plmayekar)) + +## [v2.0.0](https://github.com/tailored-automation/puppet-module-patroni/tree/v2.0.0) (2023-11-27) + +[Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/v1.6.0...v2.0.0) + +### Changed + +- Major updates, see description [\#37](https://github.com/tailored-automation/puppet-module-patroni/pull/37) ([treydock](https://github.com/treydock)) + +### Merged pull requests: + +- PDK update [\#34](https://github.com/tailored-automation/puppet-module-patroni/pull/34) ([ghoneycutt](https://github.com/ghoneycutt)) +- Fix CI [\#32](https://github.com/tailored-automation/puppet-module-patroni/pull/32) ([ghoneycutt](https://github.com/ghoneycutt)) +- PDK Update [\#25](https://github.com/tailored-automation/puppet-module-patroni/pull/25) ([treydock](https://github.com/treydock)) + +## [v1.6.0](https://github.com/tailored-automation/puppet-module-patroni/tree/v1.6.0) (2021-11-02) + +[Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/v1.5.0...v1.6.0) + +### Added + +- Add ability to configure Patroni DCS configs [\#24](https://github.com/tailored-automation/puppet-module-patroni/pull/24) ([treydock](https://github.com/treydock)) + +## [v1.5.0](https://github.com/tailored-automation/puppet-module-patroni/tree/v1.5.0) (2021-06-19) + +[Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/v1.4.0...v1.5.0) + +### Added + +- Add Puppet 7 and use Github Actions [\#22](https://github.com/tailored-automation/puppet-module-patroni/pull/22) ([treydock](https://github.com/treydock)) +- enable support for cipher flag [\#21](https://github.com/tailored-automation/puppet-module-patroni/pull/21) ([mrstrozy](https://github.com/mrstrozy)) + +## [v1.4.0](https://github.com/tailored-automation/puppet-module-patroni/tree/v1.4.0) (2021-04-28) + +[Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/v1.3.0...v1.4.0) + +### Added + +- Add support for specifying a custom pip provider [\#19](https://github.com/tailored-automation/puppet-module-patroni/pull/19) ([ghoneycutt](https://github.com/ghoneycutt)) + +## [v1.3.0](https://github.com/tailored-automation/puppet-module-patroni/tree/v1.3.0) (2021-04-07) + +[Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/v1.2.0...v1.3.0) + +### Merged pull requests: + +- Fix acceptance tests [\#14](https://github.com/tailored-automation/puppet-module-patroni/pull/14) ([treydock](https://github.com/treydock)) +- Make managing the postgresql package repo optional [\#12](https://github.com/tailored-automation/puppet-module-patroni/pull/12) ([ghoneycutt](https://github.com/ghoneycutt)) + ## [v1.2.0](https://github.com/tailored-automation/puppet-module-patroni/tree/v1.2.0) (2020-10-17) [Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/v1.1.0...v1.2.0) @@ -28,7 +98,7 @@ All notable changes to this project will be documented in this file. The format [Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/v1.0.0...v1.0.1) -### UNCATEGORIZED PRS; GO LABEL THEM +### Merged pull requests: - Fix release process [\#4](https://github.com/tailored-automation/puppet-module-patroni/pull/4) ([treydock](https://github.com/treydock)) - Fix links in metadata and documentation [\#3](https://github.com/tailored-automation/puppet-module-patroni/pull/3) ([ghoneycutt](https://github.com/ghoneycutt)) @@ -37,7 +107,7 @@ All notable changes to this project will be documented in this file. The format [Full Changelog](https://github.com/tailored-automation/puppet-module-patroni/compare/0.1.6...v1.0.0) -### UNCATEGORIZED PRS; GO LABEL THEM +### Merged pull requests: - V1 [\#1](https://github.com/tailored-automation/puppet-module-patroni/pull/1) ([ghoneycutt](https://github.com/ghoneycutt)) @@ -71,4 +141,4 @@ All notable changes to this project will be documented in this file. The format -\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d7f1765..5e35566 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,4 +3,4 @@ 1. Update metadata.json version, eg: `pdk bundle exec rake module:bump:{major,minor,patch}` 1. Run release task, eg: `pdk bundle exec rake release` 1. Update GitHub pages, eg: `pdk bundle exec rake strings:gh_pages:update` -1. Push to GitHub: `git push --tags origin master` +1. Push to GitHub: `git push --tags origin main` diff --git a/Gemfile b/Gemfile index 8b16414..a7fdc62 100644 --- a/Gemfile +++ b/Gemfile @@ -17,32 +17,24 @@ ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments minor_version = ruby_version_segments[0..1].join('.') group :development do - gem "facter", '< 4.0', require: false - gem "fast_gettext", '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') - gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') - gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9') - gem "json", '= 2.0.4', require: false if Gem::Requirement.create('~> 2.4.2').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "rb-readline", '= 0.5.5', require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "puppet-module-posix-default-r#{minor_version}", '~> 0.4', require: false, platforms: [:ruby] - gem "puppet-module-posix-dev-r#{minor_version}", '~> 0.4', require: false, platforms: [:ruby] - gem "puppet-module-win-default-r#{minor_version}", '~> 0.4', require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "puppet-module-win-dev-r#{minor_version}", '~> 0.4', require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "puppet-lint-param-docs", require: false - gem "github_changelog_generator", require: false, git: 'https://github.com/skywinder/github-changelog-generator', ref: '20ee04ba1234e9e83eb2ffb5056e23d641c7a018' if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.2.2') - gem "coveralls", require: false + gem "voxpupuli-test", '6.0.0', require: false + gem "rubocop-performance", '~> 1.18', require: false + gem "faraday", '~> 1.0', require: false + gem "github_changelog_generator", require: false + gem "puppet-blacksmith", require: false + gem "puppet-strings", require: false + gem "coveralls", require: false end group :system_tests do - gem "puppet-module-posix-system-r#{minor_version}", require: false, platforms: [:ruby] - gem "puppet-module-win-system-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "beaker", *location_for(ENV['BEAKER_VERSION'] || '~> 4.0') + gem "beaker", *location_for(ENV['BEAKER_VERSION'] || '~> 4.29') gem "beaker-abs", *location_for(ENV['BEAKER_ABS_VERSION'] || '~> 0.1') gem "beaker-pe", require: false gem "beaker-hostgenerator" gem "beaker-rspec" gem "beaker-docker" gem "beaker-puppet" + gem "beaker-puppet_install_helper", require: false + gem "beaker-module_install_helper", require: false end puppet_version = ENV['PUPPET_GEM_VERSION'] @@ -51,6 +43,8 @@ hiera_version = ENV['HIERA_GEM_VERSION'] gems = {} +gems['rake'] = [require: false] +gems['puppetlabs_spec_helper'] = [require: false] gems['puppet'] = location_for(puppet_version) # If facter or hiera versions have been specified via the environment @@ -59,16 +53,6 @@ gems['puppet'] = location_for(puppet_version) gems['facter'] = location_for(facter_version) if facter_version gems['hiera'] = location_for(hiera_version) if hiera_version -if Gem.win_platform? && puppet_version =~ %r{^(file:///|git://)} - # If we're using a Puppet gem on Windows which handles its own win32-xxx gem - # dependencies (>= 3.5.0), set the maximum versions (see PUP-6445). - gems['win32-dir'] = ['<= 0.4.9', require: false] - gems['win32-eventlog'] = ['<= 0.6.5', require: false] - gems['win32-process'] = ['<= 0.7.5', require: false] - gems['win32-security'] = ['<= 0.2.5', require: false] - gems['win32-service'] = ['0.8.8', require: false] -end - gems.each do |gem_name, gem_params| gem gem_name, *gem_params end diff --git a/README.md b/README.md index 4d23c0b..7c01e97 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,25 @@ node pgarb { } ``` +Some values such as the PostgreSQL `max_connections` require changes to the [DCS configuration](https://patroni.readthedocs.io/en/latest/dynamic_configuration.html). +This example shows using the `patroni_dcs_config` type with an `Exec` that will restart the Patroni cluster. + +```puppet +include patroni + +patroni_dcs_config { 'postgresql.parameters.max_connections': + value => 200, + notify => Exec['patroni-restart-pending'], +} + +exec { 'patroni-restart-pending': + path => '/usr/bin:/bin:/usr/sbin:/sbin', + command => "sleep 60 ; ${patroni::patronictl} -c ${patroni::config_path} restart ${patroni::scope} --pending --force", + refreshonly => true, + require => Service['patroni'], +} +``` + ## Reference All of the Patroni settings I could find in the [Patroni Settings Documentation](https://github.com/zalando/patroni/blob/master/docs/SETTINGS.rst) are mapped to this module. diff --git a/REFERENCE.md b/REFERENCE.md index 31d9e64..12bd9f2 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -8,31 +8,161 @@ * [`patroni`](#patroni): Manages a Patroni instance +### Resource types + +* [`patroni_dcs_config`](#patroni_dcs_config): Manages Patroni DCS configuration options +* [`patronictl_config`](#patronictl_config): Abstract type to configure other types + ## Classes -### `patroni` +### `patroni` Manages a Patroni instance #### Parameters -The following parameters are available in the `patroni` class. +The following parameters are available in the `patroni` class: + +* [`scope`](#-patroni--scope) +* [`namespace`](#-patroni--namespace) +* [`hostname`](#-patroni--hostname) +* [`dcs_loop_wait`](#-patroni--dcs_loop_wait) +* [`dcs_ttl`](#-patroni--dcs_ttl) +* [`dcs_retry_timeout`](#-patroni--dcs_retry_timeout) +* [`dcs_maximum_lag_on_failover`](#-patroni--dcs_maximum_lag_on_failover) +* [`dcs_master_start_timeout`](#-patroni--dcs_master_start_timeout) +* [`dcs_synchronous_mode`](#-patroni--dcs_synchronous_mode) +* [`dcs_synchronous_mode_strict`](#-patroni--dcs_synchronous_mode_strict) +* [`dcs_postgresql_use_pg_rewind`](#-patroni--dcs_postgresql_use_pg_rewind) +* [`dcs_postgresql_use_slots`](#-patroni--dcs_postgresql_use_slots) +* [`dcs_postgresql_recovery_conf`](#-patroni--dcs_postgresql_recovery_conf) +* [`dcs_postgresql_parameters`](#-patroni--dcs_postgresql_parameters) +* [`bootstrap_method`](#-patroni--bootstrap_method) +* [`initdb_data_checksums`](#-patroni--initdb_data_checksums) +* [`initdb_encoding`](#-patroni--initdb_encoding) +* [`initdb_locale`](#-patroni--initdb_locale) +* [`bootstrap_pg_hba`](#-patroni--bootstrap_pg_hba) +* [`bootstrap_users`](#-patroni--bootstrap_users) +* [`bootstrap_post_bootstrap`](#-patroni--bootstrap_post_bootstrap) +* [`bootstrap_post_init`](#-patroni--bootstrap_post_init) +* [`superuser_username`](#-patroni--superuser_username) +* [`superuser_password`](#-patroni--superuser_password) +* [`replication_username`](#-patroni--replication_username) +* [`replication_password`](#-patroni--replication_password) +* [`callback_on_reload`](#-patroni--callback_on_reload) +* [`callback_on_restart`](#-patroni--callback_on_restart) +* [`callback_on_role_change`](#-patroni--callback_on_role_change) +* [`callback_on_start`](#-patroni--callback_on_start) +* [`callback_on_stop`](#-patroni--callback_on_stop) +* [`pgsql_connect_address`](#-patroni--pgsql_connect_address) +* [`pgsql_create_replica_methods`](#-patroni--pgsql_create_replica_methods) +* [`pgsql_data_dir`](#-patroni--pgsql_data_dir) +* [`pgsql_config_dir`](#-patroni--pgsql_config_dir) +* [`pgsql_bin_dir`](#-patroni--pgsql_bin_dir) +* [`pgsql_listen`](#-patroni--pgsql_listen) +* [`pgsql_use_unix_socket`](#-patroni--pgsql_use_unix_socket) +* [`pgsql_pgpass_path`](#-patroni--pgsql_pgpass_path) +* [`pgsql_recovery_conf`](#-patroni--pgsql_recovery_conf) +* [`pgsql_custom_conf`](#-patroni--pgsql_custom_conf) +* [`pgsql_parameters`](#-patroni--pgsql_parameters) +* [`pgsql_pg_hba`](#-patroni--pgsql_pg_hba) +* [`pgsql_pg_ctl_timeout`](#-patroni--pgsql_pg_ctl_timeout) +* [`pgsql_use_pg_rewind`](#-patroni--pgsql_use_pg_rewind) +* [`pgsql_remove_data_directory_on_rewind_failure`](#-patroni--pgsql_remove_data_directory_on_rewind_failure) +* [`pgsql_replica_method`](#-patroni--pgsql_replica_method) +* [`manage_postgresql_repo`](#-patroni--manage_postgresql_repo) +* [`use_consul`](#-patroni--use_consul) +* [`consul_host`](#-patroni--consul_host) +* [`consul_url`](#-patroni--consul_url) +* [`consul_port`](#-patroni--consul_port) +* [`consul_scheme`](#-patroni--consul_scheme) +* [`consul_token`](#-patroni--consul_token) +* [`consul_verify`](#-patroni--consul_verify) +* [`consul_register_service`](#-patroni--consul_register_service) +* [`consul_service_check_interval`](#-patroni--consul_service_check_interval) +* [`consul_consistency`](#-patroni--consul_consistency) +* [`consul_cacert`](#-patroni--consul_cacert) +* [`consul_cert`](#-patroni--consul_cert) +* [`consul_key`](#-patroni--consul_key) +* [`consul_dc`](#-patroni--consul_dc) +* [`consul_checks`](#-patroni--consul_checks) +* [`use_etcd`](#-patroni--use_etcd) +* [`etcd_host`](#-patroni--etcd_host) +* [`etcd_hosts`](#-patroni--etcd_hosts) +* [`etcd_url`](#-patroni--etcd_url) +* [`etcd_proxyurl`](#-patroni--etcd_proxyurl) +* [`etcd_srv`](#-patroni--etcd_srv) +* [`etcd_protocol`](#-patroni--etcd_protocol) +* [`etcd_username`](#-patroni--etcd_username) +* [`etcd_password`](#-patroni--etcd_password) +* [`etcd_cacert`](#-patroni--etcd_cacert) +* [`etcd_cert`](#-patroni--etcd_cert) +* [`etcd_key`](#-patroni--etcd_key) +* [`use_exhibitor`](#-patroni--use_exhibitor) +* [`exhibitor_hosts`](#-patroni--exhibitor_hosts) +* [`exhibitor_poll_interval`](#-patroni--exhibitor_poll_interval) +* [`exhibitor_port`](#-patroni--exhibitor_port) +* [`use_kubernetes`](#-patroni--use_kubernetes) +* [`kubernetes_namespace`](#-patroni--kubernetes_namespace) +* [`kubernetes_labels`](#-patroni--kubernetes_labels) +* [`kubernetes_scope_label`](#-patroni--kubernetes_scope_label) +* [`kubernetes_role_label`](#-patroni--kubernetes_role_label) +* [`kubernetes_use_endpoints`](#-patroni--kubernetes_use_endpoints) +* [`kubernetes_pod_ip`](#-patroni--kubernetes_pod_ip) +* [`kubernetes_ports`](#-patroni--kubernetes_ports) +* [`restapi_ciphers`](#-patroni--restapi_ciphers) +* [`restapi_connect_address`](#-patroni--restapi_connect_address) +* [`restapi_listen`](#-patroni--restapi_listen) +* [`restapi_username`](#-patroni--restapi_username) +* [`restapi_password`](#-patroni--restapi_password) +* [`restapi_certfile`](#-patroni--restapi_certfile) +* [`restapi_keyfile`](#-patroni--restapi_keyfile) +* [`restapi_cafile`](#-patroni--restapi_cafile) +* [`restapi_verify_client`](#-patroni--restapi_verify_client) +* [`use_zookeeper`](#-patroni--use_zookeeper) +* [`zookeeper_hosts`](#-patroni--zookeeper_hosts) +* [`watchdog_mode`](#-patroni--watchdog_mode) +* [`watchdog_device`](#-patroni--watchdog_device) +* [`watchdog_safety_margin`](#-patroni--watchdog_safety_margin) +* [`manage_postgresql`](#-patroni--manage_postgresql) +* [`postgresql_version`](#-patroni--postgresql_version) +* [`package_name`](#-patroni--package_name) +* [`version`](#-patroni--version) +* [`install_dependencies`](#-patroni--install_dependencies) +* [`manage_python`](#-patroni--manage_python) +* [`install_method`](#-patroni--install_method) +* [`install_dir`](#-patroni--install_dir) +* [`python_class_version`](#-patroni--python_class_version) +* [`python_venv_version`](#-patroni--python_venv_version) +* [`manage_venv_package`](#-patroni--manage_venv_package) +* [`config_path`](#-patroni--config_path) +* [`config_owner`](#-patroni--config_owner) +* [`config_group`](#-patroni--config_group) +* [`config_mode`](#-patroni--config_mode) +* [`service_name`](#-patroni--service_name) +* [`service_ensure`](#-patroni--service_ensure) +* [`service_enable`](#-patroni--service_enable) +* [`custom_pip_provider`](#-patroni--custom_pip_provider) +* [`is_standby`](#-patroni--is_standby) +* [`standby_cluster_host`](#-patroni--standby_cluster_host) +* [`standby_cluster_port`](#-patroni--standby_cluster_port) +* [`standby_cluster_primary_slot_name`](#-patroni--standby_cluster_primary_slot_name) + +##### `scope` -##### `scope` - -Data type: `String` +Data type: `String[1]` Refer to Patroni Global `scope` setting -##### `namespace` +##### `namespace` -Data type: `String` +Data type: `String[1]` Refer to Patroni Global `namespace` setting Default value: `'/service/'` -##### `hostname` +##### `hostname` Data type: `String` @@ -40,7 +170,7 @@ Refer to Patroni Global `name` setting Default value: `$facts['networking']['hostname']` -##### `dcs_loop_wait` +##### `dcs_loop_wait` Data type: `Integer` @@ -48,7 +178,7 @@ Refer to Patroni Dynamic Configuration Settings `loop_wait` setting Default value: `10` -##### `dcs_ttl` +##### `dcs_ttl` Data type: `Integer` @@ -56,7 +186,7 @@ Refer to Patroni Dynamic Configuration Settings `ttl` setting Default value: `30` -##### `dcs_retry_timeout` +##### `dcs_retry_timeout` Data type: `Integer` @@ -64,7 +194,7 @@ Refer to Patroni Dynamic Configuration Settings `retry_timeout` setting Default value: `10` -##### `dcs_maximum_lag_on_failover` +##### `dcs_maximum_lag_on_failover` Data type: `Integer` @@ -72,7 +202,7 @@ Refer to Patroni Dynamic Configuration Settings `maximum_lag_on_failover` settin Default value: `1048576` -##### `dcs_master_start_timeout` +##### `dcs_master_start_timeout` Data type: `Integer` @@ -80,39 +210,39 @@ Refer to Patroni Dynamic Configuration Settings `master_start_timeout` setting Default value: `300` -##### `dcs_synchronous_mode` +##### `dcs_synchronous_mode` Data type: `Boolean` Refer to Patroni Dynamic Configuration Settings `synchronous_mode` setting -Default value: ``false`` +Default value: `false` -##### `dcs_synchronous_mode_strict` +##### `dcs_synchronous_mode_strict` Data type: `Boolean` Refer to Patroni Dynamic Configuration Settings `synchronous_mode_strict` setting -Default value: ``false`` +Default value: `false` -##### `dcs_postgresql_use_pg_rewind` +##### `dcs_postgresql_use_pg_rewind` Data type: `Boolean` Refer to Patroni Dynamic Configuration Settings `postgresql_use_pg_rewind` setting -Default value: ``true`` +Default value: `true` -##### `dcs_postgresql_use_slots` +##### `dcs_postgresql_use_slots` Data type: `Boolean` Refer to Patroni Dynamic Configuration Settings `postgresql_use_slots` setting -Default value: ``true`` +Default value: `true` -##### `dcs_postgresql_recovery_conf` +##### `dcs_postgresql_recovery_conf` Data type: `Hash` @@ -120,7 +250,7 @@ Refer to Patroni Dynamic Configuration Settings `postgresql_recovery_conf` setti Default value: `{}` -##### `dcs_postgresql_parameters` +##### `dcs_postgresql_parameters` Data type: `Hash` @@ -128,7 +258,7 @@ Refer to Patroni Dynamic Configuration Settings `postgresql_parameters` setting Default value: `{}` -##### `bootstrap_method` +##### `bootstrap_method` Data type: `String[1]` @@ -136,15 +266,15 @@ Refer to Bootstrap configuration settings `method` setting Default value: `'initdb'` -##### `initdb_data_checksums` +##### `initdb_data_checksums` Data type: `Boolean` Refer to Bootstrap configuration settings `data-checksums` setting -Default value: ``true`` +Default value: `true` -##### `initdb_encoding` +##### `initdb_encoding` Data type: `String` @@ -152,7 +282,7 @@ Refer to Bootstrap configuration settings `encoding` setting Default value: `'UTF8'` -##### `initdb_locale` +##### `initdb_locale` Data type: `String` @@ -160,18 +290,22 @@ Refer to Bootstrap configuration settings `locale` setting Default value: `'en_US.utf8'` -##### `bootstrap_pg_hba` +##### `bootstrap_pg_hba` Data type: `Array[String]` Refer to Bootstrap configuration settings `pg_hba` setting -Default value: `[ +Default value: + +```puppet +[ 'host all all 0.0.0.0/0 md5', 'host replication rep_user 0.0.0.0/0 md5', - ]` + ] +``` -##### `bootstrap_users` +##### `bootstrap_users` Data type: `Hash` @@ -179,23 +313,23 @@ Refer to Bootstrap configuration settings `users` setting Default value: `{}` -##### `bootstrap_post_bootstrap` +##### `bootstrap_post_bootstrap` Data type: `Variant[Undef,String]` Refer to Bootstrap configuration settings `post_bootstrap` setting -Default value: ``undef`` +Default value: `undef` -##### `bootstrap_post_init` +##### `bootstrap_post_init` Data type: `Variant[Undef,String]` Refer to Bootstrap configuration settings `post_init` setting -Default value: ``undef`` +Default value: `undef` -##### `superuser_username` +##### `superuser_username` Data type: `String` @@ -203,7 +337,7 @@ Refer to PostgreSQL configuration settings superuser username Default value: `'postgres'` -##### `superuser_password` +##### `superuser_password` Data type: `String` @@ -211,7 +345,7 @@ Refer to PostgreSQL configuration settings superuser password Default value: `'changeme'` -##### `replication_username` +##### `replication_username` Data type: `String` @@ -219,7 +353,7 @@ Refer to PostgreSQL configuration settings replication username Default value: `'rep_user'` -##### `replication_password` +##### `replication_password` Data type: `String` @@ -227,47 +361,47 @@ Refer to PostgreSQL configuration settings replication password Default value: `'changeme'` -##### `callback_on_reload` +##### `callback_on_reload` Data type: `Variant[Undef,String]` Refer to PostgreSQL configuration settings callbacks `on_reload` -Default value: ``undef`` +Default value: `undef` -##### `callback_on_restart` +##### `callback_on_restart` Data type: `Variant[Undef,String]` Refer to PostgreSQL configuration settings callbacks `on_restart` -Default value: ``undef`` +Default value: `undef` -##### `callback_on_role_change` +##### `callback_on_role_change` Data type: `Variant[Undef,String]` Refer to PostgreSQL configuration settings callbacks `on_role_change` -Default value: ``undef`` +Default value: `undef` -##### `callback_on_start` +##### `callback_on_start` Data type: `Variant[Undef,String]` Refer to PostgreSQL configuration settings callbacks `on_start` -Default value: ``undef`` +Default value: `undef` -##### `callback_on_stop` +##### `callback_on_stop` Data type: `Variant[Undef,String]` Refer to PostgreSQL configuration settings callbacks `on_stop` -Default value: ``undef`` +Default value: `undef` -##### `pgsql_connect_address` +##### `pgsql_connect_address` Data type: `String` @@ -275,7 +409,7 @@ Refer to PostgreSQL configuration settings `connect_address` setting Default value: `"${facts['networking']['fqdn']}:5432"` -##### `pgsql_create_replica_methods` +##### `pgsql_create_replica_methods` Data type: `Array[String]` @@ -283,31 +417,31 @@ Refer to PostgreSQL configuration settings `create_replica_methods` setting Default value: `['basebackup']` -##### `pgsql_data_dir` +##### `pgsql_data_dir` Data type: `Optional[Stdlib::Unixpath]` Refer to PostgreSQL configuration settings `data_dir` setting -Default value: ``undef`` +Default value: `undef` -##### `pgsql_config_dir` +##### `pgsql_config_dir` Data type: `Variant[Undef,String]` Refer to PostgreSQL configuration settings `config_dir` setting -Default value: ``undef`` +Default value: `undef` -##### `pgsql_bin_dir` +##### `pgsql_bin_dir` Data type: `Variant[Undef,String]` Refer to PostgreSQL configuration settings `bin_dir` setting -Default value: ``undef`` +Default value: `undef` -##### `pgsql_listen` +##### `pgsql_listen` Data type: `String` @@ -315,15 +449,15 @@ Refer to PostgreSQL configuration settings `listen` setting Default value: `'0.0.0.0:5432'` -##### `pgsql_use_unix_socket` +##### `pgsql_use_unix_socket` Data type: `Boolean` Refer to PostgreSQL configuration settings `use_unix_socket` setting -Default value: ``false`` +Default value: `false` -##### `pgsql_pgpass_path` +##### `pgsql_pgpass_path` Data type: `String` @@ -331,7 +465,7 @@ Refer to PostgreSQL configuration settings `pgpass_path` setting Default value: `'/tmp/pgpass0'` -##### `pgsql_recovery_conf` +##### `pgsql_recovery_conf` Data type: `Hash` @@ -339,15 +473,15 @@ Refer to PostgreSQL configuration settings `recovery_conf` setting Default value: `{}` -##### `pgsql_custom_conf` +##### `pgsql_custom_conf` Data type: `Variant[Undef,String]` Refer to PostgreSQL configuration settings `custom_conf` setting -Default value: ``undef`` +Default value: `undef` -##### `pgsql_parameters` +##### `pgsql_parameters` Data type: `Hash` @@ -355,7 +489,7 @@ Refer to PostgreSQL configuration settings `parameters` setting Default value: `{}` -##### `pgsql_pg_hba` +##### `pgsql_pg_hba` Data type: `Array[String]` @@ -363,7 +497,7 @@ Refer to PostgreSQL configuration settings `pg_hba` setting Default value: `[]` -##### `pgsql_pg_ctl_timeout` +##### `pgsql_pg_ctl_timeout` Data type: `Integer` @@ -371,23 +505,23 @@ Refer to PostgreSQL configuration settings `pg_ctl_timeout` setting Default value: `60` -##### `pgsql_use_pg_rewind` +##### `pgsql_use_pg_rewind` Data type: `Boolean` Refer to PostgreSQL configuration settings `use_pg_rewind` setting -Default value: ``true`` +Default value: `true` -##### `pgsql_remove_data_directory_on_rewind_failure` +##### `pgsql_remove_data_directory_on_rewind_failure` Data type: `Boolean` Refer to PostgreSQL configuration settings `remove_data_directory_on_rewind_failure` setting -Default value: ``false`` +Default value: `false` -##### `pgsql_replica_method` +##### `pgsql_replica_method` Data type: `Array[Hash]` @@ -395,15 +529,23 @@ Refer to PostgreSQL configuration settings `replica_method` setting Default value: `[]` -##### `use_consul` +##### `manage_postgresql_repo` + +Data type: `Boolean` + +Should the postgresql module manage the package repo + +Default value: `true` + +##### `use_consul` Data type: `Boolean` Boolean to use Consul for configuration storage -Default value: ``false`` +Default value: `false` -##### `consul_host` +##### `consul_host` Data type: `String` @@ -411,15 +553,15 @@ Refer to Consul configuration `host` setting Default value: `'localhost'` -##### `consul_url` +##### `consul_url` Data type: `Variant[Undef,String]` Refer to Consul configuration `url` setting -Default value: ``undef`` +Default value: `undef` -##### `consul_port` +##### `consul_port` Data type: `Stdlib::Port` @@ -427,7 +569,7 @@ Refer to Consul configuration `port` setting Default value: `8500` -##### `consul_scheme` +##### `consul_scheme` Data type: `Enum['http','https']` @@ -435,95 +577,95 @@ Refer to Consul configuration `scheme` setting Default value: `'http'` -##### `consul_token` +##### `consul_token` Data type: `Variant[Undef,String]` Refer to Consul configuration `token` setting -Default value: ``undef`` +Default value: `undef` -##### `consul_verify` +##### `consul_verify` Data type: `Boolean` Refer to Consul configuration `verify` setting -Default value: ``false`` +Default value: `false` -##### `consul_register_service` +##### `consul_register_service` Data type: `Optional[Boolean]` Refer to Consul configuration `register_service` setting -Default value: ``undef`` +Default value: `undef` -##### `consul_service_check_interval` +##### `consul_service_check_interval` Data type: `Optional[String]` Refer to Consul configuration `service_check_interval` setting -Default value: ``undef`` +Default value: `undef` -##### `consul_consistency` +##### `consul_consistency` Data type: `Optional[Enum['default', 'consistent', 'stale']]` Refer to Consul configuration `consistency` setting -Default value: ``undef`` +Default value: `undef` -##### `consul_cacert` +##### `consul_cacert` Data type: `Variant[Undef,String]` Refer to Consul configuration `cacert` setting -Default value: ``undef`` +Default value: `undef` -##### `consul_cert` +##### `consul_cert` Data type: `Variant[Undef,String]` Refer to Consul configuration `cert` setting -Default value: ``undef`` +Default value: `undef` -##### `consul_key` +##### `consul_key` Data type: `Variant[Undef,String]` Refer to Consul configuration `key` setting -Default value: ``undef`` +Default value: `undef` -##### `consul_dc` +##### `consul_dc` Data type: `Variant[Undef,String]` Refer to Consul configuration `dc` setting -Default value: ``undef`` +Default value: `undef` -##### `consul_checks` +##### `consul_checks` Data type: `Variant[Undef,String]` Refer to Consul configuration `checks` setting -Default value: ``undef`` +Default value: `undef` -##### `use_etcd` +##### `use_etcd` Data type: `Boolean` Boolean to use Etcd for configuration storage -Default value: ``false`` +Default value: `false` -##### `etcd_host` +##### `etcd_host` Data type: `String` @@ -531,7 +673,7 @@ Refer to Etcd configuration `host` setting Default value: `'127.0.0.1:2379'` -##### `etcd_hosts` +##### `etcd_hosts` Data type: `Array[String]` @@ -539,31 +681,31 @@ Refer to Etcd configuration `hosts` setting Default value: `[]` -##### `etcd_url` +##### `etcd_url` Data type: `Variant[Undef,String]` Refer to Etcd configuration `url` setting -Default value: ``undef`` +Default value: `undef` -##### `etcd_proxyurl` +##### `etcd_proxyurl` Data type: `Variant[Undef,String]` Refer to Etcd configuration `proxy` setting -Default value: ``undef`` +Default value: `undef` -##### `etcd_srv` +##### `etcd_srv` Data type: `Variant[Undef,String]` Refer to Etcd configuration `srv` setting -Default value: ``undef`` +Default value: `undef` -##### `etcd_protocol` +##### `etcd_protocol` Data type: `Enum['http','https']` @@ -571,55 +713,55 @@ Refer to Etcd configuration `protocol` setting Default value: `'http'` -##### `etcd_username` +##### `etcd_username` Data type: `Variant[Undef,String]` Refer to Etcd configuration `username` setting -Default value: ``undef`` +Default value: `undef` -##### `etcd_password` +##### `etcd_password` Data type: `Variant[Undef,String]` Refer to Etcd configuration `password` setting -Default value: ``undef`` +Default value: `undef` -##### `etcd_cacert` +##### `etcd_cacert` Data type: `Variant[Undef,String]` Refer to Etcd configuration `cacert` setting -Default value: ``undef`` +Default value: `undef` -##### `etcd_cert` +##### `etcd_cert` Data type: `Variant[Undef,String]` Refer to Etcd configuration `cert` setting -Default value: ``undef`` +Default value: `undef` -##### `etcd_key` +##### `etcd_key` Data type: `Variant[Undef,String]` Refer to Etcd configuration `key` setting -Default value: ``undef`` +Default value: `undef` -##### `use_exhibitor` +##### `use_exhibitor` Data type: `Boolean` Boolean to use Exhibitor configuration storage -Default value: ``false`` +Default value: `false` -##### `exhibitor_hosts` +##### `exhibitor_hosts` Data type: `Array[String]` @@ -627,7 +769,7 @@ Refer to Exhibitor configuration `hosts` setting Default value: `[]` -##### `exhibitor_poll_interval` +##### `exhibitor_poll_interval` Data type: `Integer` @@ -635,7 +777,7 @@ Refer to Exhibitor configuration `poll_interval` setting Default value: `10` -##### `exhibitor_port` +##### `exhibitor_port` Data type: `Integer` @@ -643,15 +785,15 @@ Refer to Exhibitor configuration `port` setting Default value: `8080` -##### `use_kubernetes` +##### `use_kubernetes` Data type: `Boolean` Boolean to use Kubernetes configuration storage -Default value: ``false`` +Default value: `false` -##### `kubernetes_namespace` +##### `kubernetes_namespace` Data type: `String` @@ -659,7 +801,7 @@ Refer to Kubernetes configuration `namespace` setting Default value: `'default'` -##### `kubernetes_labels` +##### `kubernetes_labels` Data type: `Hash` @@ -667,47 +809,55 @@ Refer to Kubernetes configuration `labels` setting Default value: `{}` -##### `kubernetes_scope_label` +##### `kubernetes_scope_label` Data type: `Variant[Undef,String]` Refer to Kubernetes configuration `scope_label` setting -Default value: ``undef`` +Default value: `undef` -##### `kubernetes_role_label` +##### `kubernetes_role_label` Data type: `Variant[Undef,String]` Refer to Kubernetes configuration `role_label` setting -Default value: ``undef`` +Default value: `undef` -##### `kubernetes_use_endpoints` +##### `kubernetes_use_endpoints` Data type: `Boolean` Refer to Kubernetes configuration `use_endpoints` setting -Default value: ``false`` +Default value: `false` -##### `kubernetes_pod_ip` +##### `kubernetes_pod_ip` Data type: `Variant[Undef,String]` Refer to Kubernetes configuration `pod_ip` setting -Default value: ``undef`` +Default value: `undef` -##### `kubernetes_ports` +##### `kubernetes_ports` Data type: `Variant[Undef,String]` Refer to Kubernetes configuration `ports` setting -Default value: ``undef`` +Default value: `undef` -##### `restapi_connect_address` +##### `restapi_ciphers` + +Data type: `Optional[String]` + +Refer to REST API configuration `ciphers` setting + +Default value: `undef` + +##### `restapi_connect_address` Data type: `String` @@ -715,7 +865,7 @@ Refer to REST API configuration `connect_address` setting Default value: `"${facts['networking']['fqdn']}:8008"` -##### `restapi_listen` +##### `restapi_listen` Data type: `String` @@ -723,71 +873,71 @@ Refer to REST API configuration `listen` setting Default value: `'0.0.0.0:8008'` -##### `restapi_username` +##### `restapi_username` Data type: `Variant[Undef,String]` Refer to REST API configuration `username` setting -Default value: ``undef`` +Default value: `undef` -##### `restapi_password` +##### `restapi_password` Data type: `Variant[Undef,String]` Refer to REST API configuration `password` setting -Default value: ``undef`` +Default value: `undef` -##### `restapi_certfile` +##### `restapi_certfile` Data type: `Variant[Undef,String]` Refer to REST API configuration `certfile` setting -Default value: ``undef`` +Default value: `undef` -##### `restapi_keyfile` +##### `restapi_keyfile` Data type: `Variant[Undef,String]` Refer to REST API configuration `keyfile` setting -Default value: ``undef`` +Default value: `undef` -##### `restapi_cafile` +##### `restapi_cafile` Data type: `Optional[String]` Refer to REST API configuration `cafile` setting -Default value: ``undef`` +Default value: `undef` -##### `restapi_verify_client` +##### `restapi_verify_client` Data type: `Optional[Enum['none','optional','required']]` Refer to REST API configuration `verify_client` setting -Default value: ``undef`` +Default value: `undef` -##### `use_zookeeper` +##### `use_zookeeper` Data type: `Boolean` Boolean to enable Zookeeper configuration storage -Default value: ``false`` +Default value: `false` -##### `zookeeper_hosts` +##### `zookeeper_hosts` -Data type: `Array[String]` +Data type: `Array[String[1]]` Refer to Zookeeper configuration `hosts` setting Default value: `[]` -##### `watchdog_mode` +##### `watchdog_mode` Data type: `Enum['off','automatic','required']` @@ -795,15 +945,15 @@ Refer to Watchdog configuration `mode` setting Default value: `'automatic'` -##### `watchdog_device` +##### `watchdog_device` -Data type: `String` +Data type: `Stdlib::Absolutepath` Refer to Watchdog configuration `device` setting Default value: `'/dev/watchdog'` -##### `watchdog_safety_margin` +##### `watchdog_safety_margin` Data type: `Integer` @@ -811,55 +961,55 @@ Refer to Watchdog configuration `safety_margin` setting Default value: `5` -##### `manage_postgresql` +##### `manage_postgresql` Data type: `Boolean` Boolean to determine if postgresql is managed -Default value: ``true`` +Default value: `true` -##### `postgresql_version` +##### `postgresql_version` -Data type: `Optional[String]` +Data type: `Optional[String[1]]` Version of postgresql passed to postgresql::globals class -Default value: ``undef`` +Default value: `undef` -##### `package_name` +##### `package_name` -Data type: `String` +Data type: `String[1]` Patroni package name, only used when `install_method` is `package` Default value: `'patroni'` -##### `version` +##### `version` -Data type: `String` +Data type: `String[1]` Version of Patroni to install Default value: `'present'` -##### `install_dependencies` +##### `install_dependencies` -Data type: `Array` +Data type: `Array[String[1]]` Install dependencies, only used when `install_method` is `pip` Default value: `[]` -##### `manage_python` +##### `manage_python` Data type: `Boolean` Manage Python class, only used when `install_method` is `pip` -Default value: ``true`` +Default value: `true` -##### `install_method` +##### `install_method` Data type: `Enum['package','pip']` @@ -867,7 +1017,7 @@ Install method Default value: `'pip'` -##### `install_dir` +##### `install_dir` Data type: `Stdlib::Absolutepath` @@ -875,77 +1025,197 @@ Install directory, only used when `install_method` is `pip` Default value: `'/opt/app/patroni'` -##### `python_class_version` +##### `python_class_version` -Data type: `String` +Data type: `String[1]` The version of Python to pass to Python class Only used when `install_method` is `pip` Default value: `'36'` -##### `python_venv_version` +##### `python_venv_version` -Data type: `String` +Data type: `String[1]` The version of Python to pass to Python virtualenv defined type Only used when `install_method` is `pip` Default value: `'3.6'` -##### `config_path` +##### `manage_venv_package` -Data type: `String` +Data type: `Boolean` + +Whether to manage the Python venv package + +Default value: `true` + +##### `config_path` + +Data type: `Stdlib::Absolutepath` Path to Patroni configuration file Default value: `'/opt/app/patroni/etc/postgresql.yml'` -##### `config_owner` +##### `config_owner` -Data type: `String` +Data type: `String[1]` Patroni configuration file owner Default value: `'postgres'` -##### `config_group` +##### `config_group` -Data type: `String` +Data type: `String[1]` Patroni configuration file group Default value: `'postgres'` -##### `config_mode` +##### `config_mode` -Data type: `String` +Data type: `Stdlib::Filemode` Patroni configuration file mode Default value: `'0600'` -##### `service_name` +##### `service_name` -Data type: `String` +Data type: `String[1]` Name of Patroni service Default value: `'patroni'` -##### `service_ensure` +##### `service_ensure` -Data type: `String` +Data type: `Enum['running', 'stopped']` Patroni service ensure property Default value: `'running'` -##### `service_enable` +##### `service_enable` Data type: `Boolean` Patroni service enable property -Default value: ``true`` +Default value: `true` + +##### `custom_pip_provider` + +Data type: `Optional[String[1]]` + +Use custom pip path when installing pip packages + +Default value: `undef` + +##### `is_standby` + +Data type: `Boolean` + +Boolean to use Standby cluster + +Default value: `false` + +##### `standby_cluster_host` + +Data type: `String` + +Refer to Standby configuration `host` setting + +Default value: `'127.0.0.1'` + +##### `standby_cluster_port` + +Data type: `Stdlib::Port` + +Refer to Standby configuration `port` setting + +Default value: `5432` + +##### `standby_cluster_primary_slot_name` + +Data type: `String[1]` + +Refer to Standby configuration `slot` setting + +Default value: `'patroni'` + +## Resource types + +### `patroni_dcs_config` + +Manages Patroni DCS configuration options + +#### Examples + +##### Set PostgreSQL max connections + +```puppet +patroni_dcs_config { 'postgresql.params.max_connections': + value => '200', +} +``` + +#### Properties + +The following properties are available in the `patroni_dcs_config` type. + +##### `value` + +The value to assign the DCS configuration + +#### Parameters + +The following parameters are available in the `patroni_dcs_config` type. + +* [`name`](#-patroni_dcs_config--name) +* [`provider`](#-patroni_dcs_config--provider) + +##### `name` + +namevar + +The DCS configuration option name + +##### `provider` + +The specific backend to use for this `patroni_dcs_config` resource. You will seldom need to specify this --- Puppet will +usually discover the appropriate provider for your platform. + +### `patronictl_config` + +**NOTE** This is a private type not intended to be used directly. + +#### Parameters + +The following parameters are available in the `patronictl_config` type. + +* [`config`](#-patronictl_config--config) +* [`name`](#-patronictl_config--name) +* [`path`](#-patronictl_config--path) + +##### `config` + +patronictl config + +Default value: `/opt/app/patroni/etc/postgresql.yml` + +##### `name` + +namevar + +The name of the resource. + +##### `path` + +patronictl path + +Default value: `/opt/app/patroni/bin/patronictl` diff --git a/Rakefile b/Rakefile index 1505b25..a010b3a 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,7 @@ # frozen_string_literal: true -require 'puppet_litmus/rake_tasks' if Bundler.rubygems.find_name('puppet_litmus').any? +require 'bundler' +require 'beaker-rspec/rake_task' if Bundler.rubygems.find_name('beaker-rspec').any? require 'puppetlabs_spec_helper/rake_tasks' require 'puppet-syntax/tasks/puppet-syntax' require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any? @@ -39,9 +40,13 @@ def changelog_future_release returnVal end +PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.send('disable_140chars') +PuppetLint.configuration.send('disable_manifest_whitespace_opening_brace_after') PuppetLint.configuration.send('disable_relative') PuppetLint.configuration.send('fail_on_warnings') + if Bundler.rubygems.find_name('github_changelog_generator').any? GitHubChangelogGenerator::RakeTask.new :changelog do |config| raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil? @@ -52,7 +57,7 @@ if Bundler.rubygems.find_name('github_changelog_generator').any? config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)." config.add_pr_wo_labels = true config.issues = false - config.merge_prefix = "### UNCATEGORIZED PRS; GO LABEL THEM" + config.merge_prefix = "### Merged pull requests:" config.configure_sections = { "Changed" => { "prefix" => "### Changed", @@ -60,11 +65,11 @@ if Bundler.rubygems.find_name('github_changelog_generator').any? }, "Added" => { "prefix" => "### Added", - "labels" => ["feature", "enhancement"], + "labels" => ["enhancement", "feature"], }, "Fixed" => { "prefix" => "### Fixed", - "labels" => ["bugfix"], + "labels" => ["bug", "documentation", "bugfix"], }, } end @@ -72,16 +77,15 @@ else desc 'Generate a Changelog from GitHub' task :changelog do raise <= Gem::Version.new('2.2.2')" + version: '~> 1.15' + condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')" EOM end end diff --git a/data/os/Debian.yaml b/data/os/Debian.yaml index 38589d8..8478aff 100644 --- a/data/os/Debian.yaml +++ b/data/os/Debian.yaml @@ -2,5 +2,4 @@ patroni::config_path: '/etc/patroni/config.yml' patroni::install_dependencies: - gcc - - python3-psycopg2 patroni::python_class_version: '3' diff --git a/data/os/Debian/10.yaml b/data/os/Debian/10.yaml deleted file mode 100644 index c6f29b0..0000000 --- a/data/os/Debian/10.yaml +++ /dev/null @@ -1,2 +0,0 @@ ---- -patroni::python_venv_version: '3.7' diff --git a/data/os/Debian/11.yaml b/data/os/Debian/11.yaml new file mode 100644 index 0000000..7483d1a --- /dev/null +++ b/data/os/Debian/11.yaml @@ -0,0 +1,2 @@ +--- +patroni::python_venv_version: '3.9' diff --git a/data/os/Debian/9.yaml b/data/os/Debian/9.yaml deleted file mode 100644 index 71b5b12..0000000 --- a/data/os/Debian/9.yaml +++ /dev/null @@ -1,2 +0,0 @@ ---- -patroni::python_venv_version: '3.5' diff --git a/data/os/RedHat.yaml b/data/os/RedHat.yaml index 9e3e95b..16c673a 100644 --- a/data/os/RedHat.yaml +++ b/data/os/RedHat.yaml @@ -2,4 +2,4 @@ patroni::config_path: '/opt/app/patroni/etc/postgresql.yml' patroni::install_dependencies: - gcc - - python3-psycopg2 +patroni::manage_venv_package: false diff --git a/data/os/RedHat/8.yaml b/data/os/RedHat/8.yaml index f31509f..a9d39c9 100644 --- a/data/os/RedHat/8.yaml +++ b/data/os/RedHat/8.yaml @@ -1,3 +1,4 @@ --- +patroni::manage_postgresql_repo: false patroni::python_class_version: '3' -patroni::python_venv_version: '3' +patroni::python_venv_version: '3.6' diff --git a/data/os/RedHat/9.yaml b/data/os/RedHat/9.yaml new file mode 100644 index 0000000..f19d62b --- /dev/null +++ b/data/os/RedHat/9.yaml @@ -0,0 +1,4 @@ +--- +patroni::manage_postgresql_repo: false +patroni::python_class_version: '3' +patroni::python_venv_version: '3.9' diff --git a/data/os/Ubuntu.yaml b/data/os/Ubuntu.yaml index 38589d8..8478aff 100644 --- a/data/os/Ubuntu.yaml +++ b/data/os/Ubuntu.yaml @@ -2,5 +2,4 @@ patroni::config_path: '/etc/patroni/config.yml' patroni::install_dependencies: - gcc - - python3-psycopg2 patroni::python_class_version: '3' diff --git a/data/os/Ubuntu/18.04.yaml b/data/os/Ubuntu/18.04.yaml deleted file mode 100644 index 5c79d5d..0000000 --- a/data/os/Ubuntu/18.04.yaml +++ /dev/null @@ -1,2 +0,0 @@ ---- -patroni::python_venv_version: '3.6' diff --git a/data/os/Ubuntu/20.04.yaml b/data/os/Ubuntu/20.04.yaml new file mode 100644 index 0000000..1fe6d21 --- /dev/null +++ b/data/os/Ubuntu/20.04.yaml @@ -0,0 +1,2 @@ +--- +patroni::python_venv_version: '3.8' diff --git a/data/os/Ubuntu/22.04.yaml b/data/os/Ubuntu/22.04.yaml new file mode 100644 index 0000000..7534044 --- /dev/null +++ b/data/os/Ubuntu/22.04.yaml @@ -0,0 +1,2 @@ +--- +patroni::python_venv_version: '3.10' diff --git a/examples/patroni.pp b/examples/patroni.pp index 4470a1f..94aaebd 100644 --- a/examples/patroni.pp +++ b/examples/patroni.pp @@ -1,4 +1,4 @@ -class { '::postgresql::globals': +class { 'postgresql::globals': encoding => 'UTF-8', locale => 'en_US.UTF-8', manage_package_repo => true, diff --git a/lib/puppet/provider/patroni_dcs_config/patronictl.rb b/lib/puppet/provider/patroni_dcs_config/patronictl.rb new file mode 100644 index 0000000..3ff5123 --- /dev/null +++ b/lib/puppet/provider/patroni_dcs_config/patronictl.rb @@ -0,0 +1,62 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'patronictl')) + +Puppet::Type.type(:patroni_dcs_config).provide(:patronictl, parent: Puppet::Provider::Patronictl) do + desc 'Provider for patroni_dcs_config using patronictl' + + mk_resource_methods + + defaultfor kernel: ['Linux'] + + def self.instances + configs = [] + begin + output = patronictl(['show-config']) + rescue Exception => e # rubocop:disable RescueException + Puppet.err('Failed to fetch patronictl configurations') + puts e.backtrace + end + Puppet.debug("show-config output: #{output}") + data = YAML.safe_load(output) + flatten_hash(data).each_pair do |key, value| + config = {} + config[:name] = key + config[:value] = value + configs << new(config) + end + configs + end + + def self.prefetch(resources) + configs = instances + resources.keys.each do |name| + if provider = configs.find { |c| c.name == name } # rubocop:disable AssignmentInCondition + resources[name].provider = provider + end + end + end + + def initialize(value = {}) + super(value) + @property_flush = {} + end + + type_properties.each do |prop| + define_method "#{prop}=".to_sym do |value| + @property_flush[prop] = value + end + end + + def edit_config(value) + patronictl(['edit-config', '--force', '--quiet', '-s', value]) + rescue Exception => e # rubocop:disable RescueException + raise Puppet::Error, "patronictl edit-config for #{resource[:name]} failed\nError message: #{e.message}" + end + + def create + edit_config("#{resource[:name]}=#{resource[:value]}") + end + + def flush + edit_config("#{resource[:name]}=#{@property_flush[:value]}") + end +end diff --git a/lib/puppet/provider/patronictl.rb b/lib/puppet/provider/patronictl.rb new file mode 100644 index 0000000..cfdea1b --- /dev/null +++ b/lib/puppet/provider/patronictl.rb @@ -0,0 +1,40 @@ +# Parent class for patronictl providers +class Puppet::Provider::Patronictl < Puppet::Provider + initvars + + class << self + attr_accessor :path + attr_accessor :config + end + + def self.patronictl(args, options = {}) + cmd = [@path] + ['-c', @config] + args + default_options = { combine: true, override_locale: false, custom_environment: { 'LC_ALL' => 'en_US.utf8' } } + ret = execute(cmd, default_options.merge(options)) + ret + end + + def patronictl(*args) + self.class.patronictl(*args) + end + + def self.type_properties + resource_type.validproperties.reject { |p| p.to_sym == :ensure } + end + + def type_properties + self.class.type_properties + end + + def self.flatten_hash(hash) + hash.each_with_object({}) do |(k, v), h| + if v.is_a? Hash + flatten_hash(v).map do |h_k, h_v| + h["#{k}.#{h_k}"] = h_v + end + else + h[k] = v + end + end + end +end diff --git a/lib/puppet/type/patroni_dcs_config.rb b/lib/puppet/type/patroni_dcs_config.rb new file mode 100644 index 0000000..50c21ec --- /dev/null +++ b/lib/puppet/type/patroni_dcs_config.rb @@ -0,0 +1,21 @@ +Puppet::Type.newtype(:patroni_dcs_config) do + desc <<-DESC +@summary Manages Patroni DCS configuration options +@example Set PostgreSQL max connections + patroni_dcs_config { 'postgresql.params.max_connections': + value => '200', + } +DESC + + newparam(:name, namevar: true) do + desc 'The DCS configuration option name' + end + + newproperty(:value) do + desc 'The value to assign the DCS configuration' + end + + autorequire(:service) do + ['patroni'] + end +end diff --git a/lib/puppet/type/patronictl_config.rb b/lib/puppet/type/patronictl_config.rb new file mode 100644 index 0000000..a725ded --- /dev/null +++ b/lib/puppet/type/patronictl_config.rb @@ -0,0 +1,38 @@ +Puppet::Type.newtype(:patronictl_config) do + desc <<-DESC +@summary Abstract type to configure other types +**NOTE** This is a private type not intended to be used directly. +DESC + + newparam(:name, namevar: true) do + desc 'The name of the resource.' + end + + newparam(:path) do + desc 'patronictl path' + defaultto('/opt/app/patroni/bin/patronictl') + end + + newparam(:config) do + desc 'patronictl config' + defaultto('/opt/app/patroni/etc/postgresql.yml') + end + + # First collect all types with patronictl provider that come from this module + # For each patronictl type, set the class variable 'chunk_size' used by + # each provider to list resources + # Return empty array since we are not actually generating resources + def generate + patronictl_types = [] + Dir[File.join(File.dirname(__FILE__), '../provider/patroni_*/patronictl.rb')].each do |file| + type = File.basename(File.dirname(file)) + patronictl_types << type.to_sym + end + patronictl_types.each do |type| + provider_class = Puppet::Type.type(type).provider(:patronictl) + provider_class.path = self[:path] + provider_class.config = self[:config] + end + [] + end +end diff --git a/manifests/init.pp b/manifests/init.pp index 7d7e2a2..7f046b5 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -94,6 +94,8 @@ # Refer to PostgreSQL configuration settings `remove_data_directory_on_rewind_failure` setting # @param pgsql_replica_method # Refer to PostgreSQL configuration settings `replica_method` setting +# @param manage_postgresql_repo +# Should the postgresql module manage the package repo # @param use_consul # Boolean to use Consul for configuration storage # @param consul_host @@ -172,6 +174,8 @@ # Refer to Kubernetes configuration `pod_ip` setting # @param kubernetes_ports # Refer to Kubernetes configuration `ports` setting +# @param restapi_ciphers +# Refer to REST API configuration `ciphers` setting # @param restapi_connect_address # Refer to REST API configuration `connect_address` setting # @param restapi_listen @@ -220,6 +224,8 @@ # @param python_venv_version # The version of Python to pass to Python virtualenv defined type # Only used when `install_method` is `pip` +# @param manage_venv_package +# Whether to manage the Python venv package # @param config_path # Path to Patroni configuration file # @param config_owner @@ -234,6 +240,8 @@ # Patroni service ensure property # @param service_enable # Patroni service enable property +# @param custom_pip_provider +# Use custom pip path when installing pip packages # @param is_standby # Boolean to use Standby cluster # @param standby_cluster_host @@ -242,17 +250,11 @@ # Refer to Standby configuration `port` setting # @param standby_cluster_primary_slot_name # Refer to Standby configuration `slot` setting -# @param tags -# Boolean to use tag feature of patroni -# @param tags_parameters -# Refer to `tags` setting -# - class patroni ( # Global Settings - String $scope, - String $namespace = '/service/', + String[1] $scope, + String[1] $namespace = '/service/', String $hostname = $facts['networking']['hostname'], # Bootstrap Settings @@ -281,7 +283,7 @@ Boolean $is_standby = false, String $standby_cluster_host = '127.0.0.1', Stdlib::Port $standby_cluster_port = 5432, - Optional[String] $standby_cluster_primary_slot_name = 'patroni', + String[1] $standby_cluster_primary_slot_name = 'patroni', # PostgreSQL Settings String $superuser_username = 'postgres', @@ -309,6 +311,7 @@ Boolean $pgsql_use_pg_rewind = true, Boolean $pgsql_remove_data_directory_on_rewind_failure = false, Array[Hash] $pgsql_replica_method = [], + Boolean $manage_postgresql_repo = true, # Consul Settings Boolean $use_consul = false, @@ -358,6 +361,7 @@ Variant[Undef,String] $kubernetes_ports = undef, # REST API Settings + Optional[String] $restapi_ciphers = undef, String $restapi_connect_address = "${facts['networking']['fqdn']}:8008", String $restapi_listen = '0.0.0.0:8008', Variant[Undef,String] $restapi_username = undef, @@ -369,11 +373,11 @@ # ZooKeeper Settings Boolean $use_zookeeper = false, - Array[String] $zookeeper_hosts = [], + Array[String[1]] $zookeeper_hosts = [], # Watchdog Settings Enum['off','automatic','required'] $watchdog_mode = 'automatic', - String $watchdog_device = '/dev/watchdog', + Stdlib::Absolutepath $watchdog_device = '/dev/watchdog', Integer $watchdog_safety_margin = 5, # Tags settings @@ -382,40 +386,68 @@ # Module Specific Settings Boolean $manage_postgresql = true, - Optional[String] $postgresql_version = undef, - String $package_name = 'patroni', - String $version = 'present', - Array $install_dependencies = [], + Optional[String[1]] $postgresql_version = undef, + String[1] $package_name = 'patroni', + String[1] $version = 'present', + Array[String[1]] $install_dependencies = [], Boolean $manage_python = true, Enum['package','pip'] $install_method = 'pip', Stdlib::Absolutepath $install_dir = '/opt/app/patroni', - String $python_class_version = '36', - String $python_venv_version = '3.6', - String $config_path = '/opt/app/patroni/etc/postgresql.yml', - String $config_owner = 'postgres', - String $config_group = 'postgres', - String $config_mode = '0600', - String $service_name = 'patroni', - String $service_ensure = 'running', + String[1] $python_class_version = '36', + String[1] $python_venv_version = '3.6', + Boolean $manage_venv_package = true, + Stdlib::Absolutepath $config_path = '/opt/app/patroni/etc/postgresql.yml', + String[1] $config_owner = 'postgres', + String[1] $config_group = 'postgres', + Stdlib::Filemode $config_mode = '0600', + String[1] $service_name = 'patroni', + Enum['running', 'stopped'] $service_ensure = 'running', Boolean $service_enable = true, + Optional[String[1]] $custom_pip_provider = undef, ) { - if $manage_postgresql { class { 'postgresql::globals': encoding => 'UTF-8', locale => 'en_US.UTF-8', - manage_package_repo => true, + manage_package_repo => $manage_postgresql_repo, version => $postgresql_version, } + include postgresql::params + $default_data_dir = $postgresql::params::datadir $default_bin_dir = $postgresql::params::bindir + + if $manage_postgresql_repo == true { + $postgres_repo_require = 'Class[Postgresql::Repo]' + } else { + $postgres_repo_require = undef + } + package { 'patroni-postgresql-package': ensure => present, name => $postgresql::params::server_package_name, - require => Class['postgresql::repo'], + require => $postgres_repo_require, before => Service['patroni'], } + + package { 'patroni-postgresql-devel-package': + ensure => present, + name => $postgresql::params::devel_package_name, + require => $postgres_repo_require, + before => Service['patroni'], + } + if $install_method == 'pip' { + Package['patroni-postgresql-devel-package'] -> Python::Pip['psycopg2'] + } + + if $facts['os']['family'] == 'RedHat' and $manage_postgresql_repo and $default_bin_dir != '/usr/bin' { + file { '/usr/bin/pg_config': + ensure => 'link', + target => "${default_bin_dir}/pg_config", + } + } + exec { 'patroni-clear-datadir': path => '/usr/bin:/bin', command => "/bin/rm -rf ${default_data_dir}", @@ -434,76 +466,59 @@ if $install_method == 'pip' { if $manage_python { class { 'python': - version => $python_class_version, - dev => 'present', - virtualenv => 'present', + version => $python_class_version, + dev => 'present', + venv => 'present', + manage_venv_package => $manage_venv_package, } } - ensure_packages($install_dependencies, {'before' => Python::Pip['patroni']}) + + ensure_packages($install_dependencies, { 'before' => Python::Pip['patroni'] }) + exec { 'patroni-mkdir-install_dir': command => "/bin/mkdir -p ${install_dir}", creates => $install_dir, } - if $facts['os']['family'] == 'RedHat' { - python::virtualenv { 'patroni': - version => $python_venv_version, - venv_dir => $install_dir, - virtualenv => 'virtualenv-3', - systempkgs => true, - distribute => false, - environment => ["PIP_PREFIX=${install_dir}"], - require => Exec['patroni-mkdir-install_dir'], - } + + python::pyvenv { 'patroni': + version => $python_venv_version, + venv_dir => $install_dir, + systempkgs => true, + environment => ["PIP_PREFIX=${install_dir}"], + require => Exec['patroni-mkdir-install_dir'], } - if $facts['os']['family'] == 'Debian' { - # create python virtual env without using the python::pyvenv - # python::pyvenv upgrades pip and setuptools which leads to failure installing cdiff and ydiff - - #python::pyvenv { 'patroni': - # version => $python_venv_version, - # venv_dir => $install_dir, - # systempkgs => true, - # environment => ["PIP_PREFIX=${install_dir}"], - # require => Exec['patroni-mkdir-install_dir'], - #} - - $python_version_parts = split($facts['python3_version'], '[.]') - $python_version = sprintf('%s.%s', $python_version_parts[0], $python_version_parts[1]) - - # pyvenv is deprecated since 3.6 and will be removed in 3.8 - if (versioncmp($python_version, '3.6') >=0) { - $virtualenv_cmd = "python${python_version} -m venv" - } else { - $virtualenv_cmd = "pyvenv-${python_version}" - } - # create python venv for patroni - # unless activate exists and VIRTUAL_ENV is correct we re-create the virtualenv - exec { 'patroni_custom_pyvenv': - command => "${virtualenv_cmd} --clear --system-site-packages ${install_dir}", - creates => "${install_dir}/bin/activate", - path => ['/bin', '/usr/bin', '/usr/sbin', '/usr/local/bin'], - unless => "grep '^[\\t]*VIRTUAL_ENV=[\\\\'\\\"]*${install_dir}[\\\"\\\\'][\\t ]*$' ${install_dir}/bin/activate", - } + if $custom_pip_provider { + $virtualenv = undef + } else { + $virtualenv = $install_dir } + python::pip { 'patroni': - ensure => $version, - virtualenv => $install_dir, - environment => ["PIP_PREFIX=${install_dir}"], - before => File['patroni_config'], + ensure => $version, + environment => ["PIP_PREFIX=${install_dir}"], + pip_provider => $custom_pip_provider, + virtualenv => $virtualenv, + before => File['patroni_config'], } + $dependency_params = { - 'virtualenv' => $install_dir, - 'before' => Python::Pip['patroni'], - 'environment' => ["PIP_PREFIX=${install_dir}"], + 'before' => Python::Pip['patroni'], + 'pip_provider' => $custom_pip_provider, + 'virtualenv' => $virtualenv, + 'environment' => ["PIP_PREFIX=${install_dir}"], } + python::pip { 'psycopg2': * => $dependency_params } + if $use_consul { python::pip { 'python-consul': * => $dependency_params } } + if $use_etcd { python::pip { 'python-etcd': * => $dependency_params } } + if $use_exhibitor or $use_zookeeper { python::pip { 'kazoo': * => $dependency_params } } @@ -518,13 +533,15 @@ if $install_method == 'pip' { $config_dir = dirname($config_path) file { 'patroni_config_dir': - ensure => 'directory', - path => $config_dir, - owner => 'postgres', - group => 'postgres', - mode => '0755', + ensure => 'directory', + path => $config_dir, + owner => 'postgres', + group => 'postgres', + mode => '0755', + require => Python::Pyvenv['patroni'], } } + file { 'patroni_config': ensure => 'file', path => $config_path, @@ -553,4 +570,10 @@ name => $service_name, enable => $service_enable, } + + $patronictl = "${install_dir}/bin/patronictl" + patronictl_config { 'puppet': + path => $patronictl, + config => $config_path, + } } diff --git a/metadata.json b/metadata.json index 0365e70..9cd21b6 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "tailoredautomation-patroni", - "version": "1.2.0", + "version": "2.1.0", "author": "tailoredautomation", "summary": "Install and manages Patroni for high-availability PostgreSQL", "license": "Apache-2.0", @@ -10,55 +10,54 @@ "dependencies": [ { "name": "puppetlabs/stdlib", - "version_requirement": ">= 4.25.0 < 7.0.0" + "version_requirement": ">= 6.4.0 < 10.0.0" }, { "name": "puppetlabs/postgresql", - "version_requirement": ">= 4.9.0 < 7.0.0" + "version_requirement": ">= 6.4.0 < 11.0.0" }, { - "name": "stankevich/python", - "version_requirement": ">= 1.12.0 <6.0.0" + "name": "puppet/python", + "version_requirement": ">= 6.0.0 <8.0.0" }, { - "name": "camptocamp/systemd", - "version_requirement": ">= 1.0.0 <3.0.0" + "name": "puppet/systemd", + "version_requirement": ">= 5.0.0 <7.0.0" } ], "operatingsystem_support": [ { - "operatingsystem": "CentOS", + "operatingsystem": "RedHat", "operatingsystemrelease": [ - "7", - "8" + "8", + "9" ] }, { - "operatingsystem": "OracleLinux", + "operatingsystem": "Rocky", "operatingsystemrelease": [ - "7", - "8" + "8", + "9" ] }, { - "operatingsystem": "RedHat", + "operatingsystem": "Debian", "operatingsystemrelease": [ - "7", - "8" + "11" ] }, { - "operatingsystem": "Debian", + "operatingsystem": "Ubuntu", "operatingsystemrelease": [ - "9", - "10" + "20.04", + "22.04" ] } ], "requirements": [ { "name": "puppet", - "version_requirement": ">= 5.5.10 < 7.0.0" + "version_requirement": ">= 7.0.0 < 9.0.0" } ], "tags": [ @@ -68,7 +67,7 @@ "cluster", "ha" ], - "pdk-version": "1.18.1", - "template-url": "https://github.com/tailored-automation/pdk-templates.git#master", - "template-ref": "heads/master-0-g952cfd1" + "pdk-version": "3.0.0", + "template-url": "https://github.com/tailored-automation/pdk-templates.git#main", + "template-ref": "heads/main-0-g8e0611a" } diff --git a/spec/acceptance/nodesets/centos-7.yml b/spec/acceptance/nodesets/centos-7.yml deleted file mode 100644 index a3faf2c..0000000 --- a/spec/acceptance/nodesets/centos-7.yml +++ /dev/null @@ -1,35 +0,0 @@ -HOSTS: - patroni1: - roles: - - agent - - default - - patroni1 - platform: el-7-x86_64 - hypervisor: docker - image: centos:7 - docker_preserve_image: true - docker_cmd: - - '/usr/sbin/init' - docker_image_commands: - - 'yum install -y wget which cronie iproute initscripts' - docker_container_name: 'patroni1-el7' - patroni2: - roles: - - agent - - patroni2 - platform: el-7-x86_64 - hypervisor: docker - image: centos:7 - docker_preserve_image: true - docker_cmd: - - '/usr/sbin/init' - docker_image_commands: - - 'yum install -y wget which cronie iproute initscripts' - docker_container_name: 'patroni2-el7' -CONFIG: - log_level: debug - type: foss -ssh: - password: root - auth_methods: ["password"] - diff --git a/spec/acceptance/nodesets/debian-10.yml b/spec/acceptance/nodesets/debian-11.yml similarity index 67% rename from spec/acceptance/nodesets/debian-10.yml rename to spec/acceptance/nodesets/debian-11.yml index c4f5b5b..799125e 100644 --- a/spec/acceptance/nodesets/debian-10.yml +++ b/spec/acceptance/nodesets/debian-11.yml @@ -4,36 +4,44 @@ HOSTS: - agent - default - patroni1 - platform: debian-10-amd64 + platform: debian-11-amd64 hypervisor: docker - image: debian:10 + image: debian:11 docker_preserve_image: true docker_cmd: - '/sbin/init' docker_image_commands: - - 'apt-get install -y wget net-tools systemd-sysv locales apt-transport-https ca-certificates' + - 'apt-get install -y wget net-tools systemd-sysv locales apt-transport-https ca-certificates iproute2' - 'echo "LC_ALL=en_US.UTF-8" >> /etc/environment' - 'echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen' - 'echo "LANG=en_US.UTF-8" > /etc/locale.conf' - 'locale-gen en_US.UTF-8' - docker_container_name: 'patroni1-debian10' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 + docker_container_name: 'patroni1-debian11' patroni2: roles: - agent - patroni2 - platform: debian-10-amd64 + platform: debian-11-amd64 hypervisor: docker - image: debian:10 + image: debian:11 docker_preserve_image: true docker_cmd: - '/sbin/init' docker_image_commands: - - 'apt-get install -y wget net-tools systemd-sysv locales apt-transport-https ca-certificates' + - 'apt-get install -y wget net-tools systemd-sysv locales apt-transport-https ca-certificates iproute2' - 'echo "LC_ALL=en_US.UTF-8" >> /etc/environment' - 'echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen' - 'echo "LANG=en_US.UTF-8" > /etc/locale.conf' - 'locale-gen en_US.UTF-8' - docker_container_name: 'patroni2-debian10' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 + docker_container_name: 'patroni2-debian11' CONFIG: log_level: debug type: foss diff --git a/spec/acceptance/nodesets/debian-9.yml b/spec/acceptance/nodesets/debian-9.yml deleted file mode 100644 index 7d64f5e..0000000 --- a/spec/acceptance/nodesets/debian-9.yml +++ /dev/null @@ -1,43 +0,0 @@ -HOSTS: - patroni1: - roles: - - agent - - default - - patroni1 - platform: debian-9-amd64 - hypervisor: docker - image: debian:9 - docker_preserve_image: true - docker_cmd: - - '/sbin/init' - docker_image_commands: - - 'apt-get install -y wget net-tools systemd-sysv locales apt-transport-https ca-certificates' - - 'echo "LC_ALL=en_US.UTF-8" >> /etc/environment' - - 'echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen' - - 'echo "LANG=en_US.UTF-8" > /etc/locale.conf' - - 'locale-gen en_US.UTF-8' - docker_container_name: 'patroni1-debian9' - patroni2: - roles: - - agent - - patroni2 - platform: debian-9-amd64 - hypervisor: docker - image: debian:9 - docker_preserve_image: true - docker_cmd: - - '/sbin/init' - docker_image_commands: - - 'apt-get install -y wget net-tools systemd-sysv locales apt-transport-https ca-certificates' - - 'echo "LC_ALL=en_US.UTF-8" >> /etc/environment' - - 'echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen' - - 'echo "LANG=en_US.UTF-8" > /etc/locale.conf' - - 'locale-gen en_US.UTF-8' - docker_container_name: 'patroni2-debian9' -CONFIG: - log_level: debug - type: foss -ssh: - password: root - auth_methods: ["password"] - diff --git a/spec/acceptance/nodesets/centos-8.yml b/spec/acceptance/nodesets/el8.yml similarity index 69% rename from spec/acceptance/nodesets/centos-8.yml rename to spec/acceptance/nodesets/el8.yml index 82f6df1..ec57a08 100644 --- a/spec/acceptance/nodesets/centos-8.yml +++ b/spec/acceptance/nodesets/el8.yml @@ -6,14 +6,18 @@ HOSTS: - patroni1 platform: el-8-x86_64 hypervisor: docker - image: centos:8 + image: rockylinux/rockylinux:8 docker_preserve_image: true docker_cmd: - '/usr/sbin/init' docker_image_commands: - 'yum install -y dnf-utils' - - 'dnf config-manager --set-enabled PowerTools' + - 'dnf config-manager --set-enabled powertools' - 'yum install -y wget which cronie iproute initscripts langpacks-en glibc-all-langpacks' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 docker_container_name: 'patroni1-el8' patroni2: roles: @@ -21,14 +25,18 @@ HOSTS: - patroni2 platform: el-8-x86_64 hypervisor: docker - image: centos:8 + image: rockylinux/rockylinux:8 docker_preserve_image: true docker_cmd: - '/usr/sbin/init' docker_image_commands: - 'yum install -y dnf-utils' - - 'dnf config-manager --set-enabled PowerTools' + - 'dnf config-manager --set-enabled powertools' - 'yum install -y wget which cronie iproute initscripts langpacks-en glibc-all-langpacks' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 docker_container_name: 'patroni2-el8' CONFIG: log_level: debug diff --git a/spec/acceptance/nodesets/el9.yml b/spec/acceptance/nodesets/el9.yml new file mode 100644 index 0000000..06d4b91 --- /dev/null +++ b/spec/acceptance/nodesets/el9.yml @@ -0,0 +1,47 @@ +HOSTS: + patroni1: + roles: + - agent + - default + - patroni1 + platform: el-9-x86_64 + hypervisor: docker + image: rockylinux/rockylinux:9 + docker_preserve_image: true + docker_cmd: + - '/usr/sbin/init' + docker_image_commands: + - 'yum install -y dnf-utils' + - 'dnf config-manager --set-enabled crb' + - 'yum install -y wget which cronie iproute initscripts langpacks-en glibc-all-langpacks' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 + docker_container_name: 'patroni1-el9' + patroni2: + roles: + - agent + - patroni2 + platform: el-9-x86_64 + hypervisor: docker + image: rockylinux/rockylinux:9 + docker_preserve_image: true + docker_cmd: + - '/usr/sbin/init' + docker_image_commands: + - 'yum install -y dnf-utils' + - 'dnf config-manager --set-enabled crb' + - 'yum install -y wget which cronie iproute initscripts langpacks-en glibc-all-langpacks' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 + docker_container_name: 'patroni2-el9' +CONFIG: + log_level: debug + type: foss +ssh: + password: root + auth_methods: ["password"] + diff --git a/spec/acceptance/nodesets/ubuntu-1804.yml b/spec/acceptance/nodesets/ubuntu-2004.yml similarity index 66% rename from spec/acceptance/nodesets/ubuntu-1804.yml rename to spec/acceptance/nodesets/ubuntu-2004.yml index d7ae7c1..264b536 100644 --- a/spec/acceptance/nodesets/ubuntu-1804.yml +++ b/spec/acceptance/nodesets/ubuntu-2004.yml @@ -4,30 +4,38 @@ HOSTS: - agent - default - patroni1 - platform: ubuntu-18.04-amd64 + platform: ubuntu-20.04-amd64 hypervisor : docker - image: ubuntu:18.04 + image: ubuntu:20.04 docker_preserve_image: true docker_cmd: '["/sbin/init"]' docker_image_commands: - "rm -f /etc/dpkg/dpkg.cfg.d/excludes" - 'apt-get install -y wget net-tools locales apt-transport-https ca-certificates iproute2' - 'locale-gen en_US.UTF-8' - docker_container_name: 'patroni1-ubuntu1804' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 + docker_container_name: 'patroni1-ubuntu2004' patroni2: roles: - agent - patroni2 - platform: ubuntu-18.04-amd64 + platform: ubuntu-20.04-amd64 hypervisor : docker - image: ubuntu:18.04 + image: ubuntu:20.04 docker_preserve_image: true docker_cmd: '["/sbin/init"]' docker_image_commands: - "rm -f /etc/dpkg/dpkg.cfg.d/excludes" - 'apt-get install -y wget net-tools locales apt-transport-https ca-certificates iproute2' - 'locale-gen en_US.UTF-8' - docker_container_name: 'patroni2-ubuntu1804' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 + docker_container_name: 'patroni2-ubuntu2004' CONFIG: log_level: debug type: foss diff --git a/spec/acceptance/nodesets/ubuntu-2204.yml b/spec/acceptance/nodesets/ubuntu-2204.yml new file mode 100644 index 0000000..702b3a0 --- /dev/null +++ b/spec/acceptance/nodesets/ubuntu-2204.yml @@ -0,0 +1,45 @@ +HOSTS: + patroni1: + roles: + - agent + - default + - patroni1 + platform: ubuntu-22.04-amd64 + hypervisor : docker + image: ubuntu:22.04 + docker_preserve_image: true + docker_cmd: '["/sbin/init"]' + docker_image_commands: + - "rm -f /etc/dpkg/dpkg.cfg.d/excludes" + - 'apt-get install -y wget net-tools locales apt-transport-https ca-certificates iproute2' + - 'locale-gen en_US.UTF-8' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 + docker_container_name: 'patroni1-ubuntu2204' + patroni2: + roles: + - agent + - patroni2 + platform: ubuntu-22.04-amd64 + hypervisor : docker + image: ubuntu:22.04 + docker_preserve_image: true + docker_cmd: '["/sbin/init"]' + docker_image_commands: + - "rm -f /etc/dpkg/dpkg.cfg.d/excludes" + - 'apt-get install -y wget net-tools locales apt-transport-https ca-certificates iproute2' + - 'locale-gen en_US.UTF-8' + docker_env: + - LANG=en_US.UTF-8 + - LANGUAGE=en_US.UTF-8 + - LC_ALL=en_US.UTF-8 + docker_container_name: 'patroni2-ubuntu2204' +CONFIG: + log_level: debug + type: foss +ssh: + password: root + auth_methods: ["password"] + diff --git a/spec/acceptance/patroni_spec.rb b/spec/acceptance/patroni_spec.rb index 1303e4f..a08dd72 100644 --- a/spec/acceptance/patroni_spec.rb +++ b/spec/acceptance/patroni_spec.rb @@ -3,49 +3,49 @@ describe 'patroni class:' do patroni1 = hosts_as('patroni1')[0] patroni2 = hosts_as('patroni2')[0] + etcd = <<-EOS + class { 'etcd': + config => { + 'data-dir' => '/var/lib/etcd', + 'name' => $facts['networking']['hostname'], + 'initial-advertise-peer-urls' => "http://${facts['networking']['hostname']}:2380", + 'listen-peer-urls' => 'http://0.0.0.0:2380', + 'listen-client-urls' => 'http://0.0.0.0:2379', + 'advertise-client-urls' => "http://${facts['networking']['hostname']}:2379", + 'initial-cluster-token' => 'etcd-cluster-1', + 'initial-cluster' => 'patroni1=http://patroni1:2380,patroni2=http://patroni2:2380', + 'initial-cluster-state' => 'new', + 'enable-v2' => true, + }, + } + EOS + pp = <<-EOS + class { 'patroni': + scope => 'cluster', + use_etcd => true, + pgsql_connect_address => "${facts['networking']['fqdn']}:5432", + restapi_connect_address => "${facts['networking']['fqdn']}:8008", + pgsql_parameters => { + 'max_connections' => 5000, + }, + bootstrap_pg_hba => [ + 'local all postgres ident', + 'host all all 0.0.0.0/0 md5', + 'host replication repl 0.0.0.0/0 md5', + ], + pgsql_pg_hba => [ + 'local all postgres ident', + 'host all all 0.0.0.0/0 md5', + 'host replication repl 0.0.0.0/0 md5', + ], + superuser_username => 'postgres', + superuser_password => 'postgrespassword', + replication_username => 'repl', + replication_password => 'replpassword', + } + EOS context 'default parameters' do it 'runs successfully' do - etcd = <<-EOS - class { 'etcd': - config => { - 'data-dir' => '/var/lib/etcd', - 'name' => $facts['networking']['hostname'], - 'initial-advertise-peer-urls' => "http://${facts['networking']['hostname']}:2380", - 'listen-peer-urls' => 'http://0.0.0.0:2380', - 'listen-client-urls' => 'http://0.0.0.0:2379', - 'advertise-client-urls' => "http://${facts['networking']['hostname']}:2379", - 'initial-cluster-token' => 'etcd-cluster-1', - 'initial-cluster' => 'patroni1=http://patroni1:2380,patroni2=http://patroni2:2380', - 'initial-cluster-state' => 'new', - 'enable-v2' => true, - }, - } - EOS - pp = <<-EOS - class { 'patroni': - scope => 'cluster', - use_etcd => true, - pgsql_connect_address => "${facts['networking']['fqdn']}:5432", - restapi_connect_address => "${facts['networking']['fqdn']}:8008", - pgsql_parameters => { - 'max_connections' => 5000, - }, - bootstrap_pg_hba => [ - 'local all postgres ident', - 'host all all 0.0.0.0/0 md5', - 'host replication repl 0.0.0.0/0 md5', - ], - pgsql_pg_hba => [ - 'local all postgres ident', - 'host all all 0.0.0.0/0 md5', - 'host replication repl 0.0.0.0/0 md5', - ], - superuser_username => 'postgres', - superuser_password => 'postgrespassword', - replication_username => 'repl', - replication_password => 'replpassword', - } - EOS apply_manifest_on(patroni1, etcd) apply_manifest_on(patroni2, etcd, catch_failures: true) apply_manifest_on(patroni1, etcd, catch_failures: true) @@ -70,4 +70,30 @@ class { 'patroni': it { is_expected.to be_running } end end + + context 'add DCS config' do + it 'runs successfully' do + dcs_pp = <<-EOS + #{pp} + patroni_dcs_config { 'postgresql.parameters.max_connections': + value => 200, + notify => Exec['patroni-restart-pending'], + } + + exec { 'patroni-restart-pending': + path => '/usr/bin:/bin:/usr/sbin:/sbin', + command => "sleep 60 ; ${patroni::patronictl} -c ${patroni::config_path} restart ${patroni::scope} --pending --force", + environment => ['LC_ALL=en_US.utf8'], + refreshonly => true, + require => Service['patroni'], + } + EOS + apply_manifest_on(patroni1, dcs_pp, catch_failures: true) + apply_manifest_on(patroni1, dcs_pp, catch_changes: true) + end + + describe command('ps aux | grep postgres') do + its(:stdout) { is_expected.to match %r{max_connections=200} } + end + end end diff --git a/spec/classes/patroni_spec.rb b/spec/classes/init_spec.rb similarity index 83% rename from spec/classes/patroni_spec.rb rename to spec/classes/init_spec.rb index fa66407..12e4969 100644 --- a/spec/classes/patroni_spec.rb +++ b/spec/classes/init_spec.rb @@ -8,21 +8,21 @@ # same tests for OracleLinux and RedHat. supported_os: [ { - 'operatingsystem' => 'CentOS', - 'operatingsystemrelease' => ['7', '8'], + 'operatingsystem' => 'RedHat', + 'operatingsystemrelease' => ['8', '9'], }, { 'operatingsystem' => 'Debian', - 'operatingsystemrelease' => ['9', '10'], + 'operatingsystemrelease' => ['11'], }, { 'operatingsystem' => 'Ubuntu', - 'operatingsystemrelease' => ['18.04'], + 'operatingsystemrelease' => ['20.04', '22.04'], }, ], } - on_supported_os(test_on).each do |os, os_facts| + on_supported_os(test_on).sort.each do |os, os_facts| context "on #{os}" do let(:facts) { os_facts } let(:node) { 'localhost' } @@ -35,7 +35,7 @@ is_expected.to contain_class('postgresql::globals').with( encoding: 'UTF-8', locale: 'en_US.UTF-8', - manage_package_repo: 'true', + manage_package_repo: platform_data(platform, :manage_postgresql_repo), version: platform_data(platform, :postgresql_version), ) end @@ -43,10 +43,24 @@ it do is_expected.to contain_package('patroni-postgresql-package').with( ensure: 'present', - require: 'Class[Postgresql::Repo]', + require: platform_data(platform, :postgres_repo_require), before: 'Service[patroni]', ) end + it do + is_expected.to contain_package('patroni-postgresql-devel-package').with( + ensure: 'present', + require: platform_data(platform, :postgres_repo_require), + before: ['Service[patroni]', 'Python::Pip[psycopg2]'], + ) + end + it do + if platform_data(platform, :pg_config_link) + is_expected.to contain_file('/usr/bin/pg_config').with_ensure('link') + else + is_expected.not_to contain_file('/usr/bin/pg_config') + end + end it do is_expected.to contain_exec('patroni-clear-datadir').with( path: '/usr/bin:/bin', @@ -61,7 +75,6 @@ is_expected.to contain_class('python').with( version: platform_data(platform, :python_class_version), dev: 'present', - virtualenv: 'present', ) end it 'installs dependencies' do @@ -76,29 +89,14 @@ ) end - case os_facts[:os]['family'] - when 'RedHat' - it do - is_expected.to contain_python__virtualenv('patroni').with( - version: platform_data(platform, :python_venv_version), - venv_dir: '/opt/app/patroni', - virtualenv: 'virtualenv-3', - systempkgs: 'true', - distribute: 'false', - environment: ['PIP_PREFIX=/opt/app/patroni'], - require: 'Exec[patroni-mkdir-install_dir]', - ) - end - when 'Debian' - it do - is_expected.to contain_python__pyvenv('patroni').with( - version: platform_data(platform, :python_venv_version), - venv_dir: '/opt/app/patroni', - systempkgs: 'true', - environment: ['PIP_PREFIX=/opt/app/patroni'], - require: 'Exec[patroni-mkdir-install_dir]', - ) - end + it do + is_expected.to contain_python__pyvenv('patroni').with( + version: platform_data(platform, :python_venv_version), + venv_dir: '/opt/app/patroni', + systempkgs: 'true', + environment: ['PIP_PREFIX=/opt/app/patroni'], + require: 'Exec[patroni-mkdir-install_dir]', + ) end it do @@ -127,6 +125,7 @@ owner: 'postgres', group: 'postgres', mode: '0755', + require: 'Python::Pyvenv[patroni]', ) end @@ -279,6 +278,30 @@ ) end + it do + is_expected.to contain_patronictl_config('puppet').with( + path: '/opt/app/patroni/bin/patronictl', + config: platform_data(platform, :config_path), + ) + end + + context 'is_standby => true' do + let(:params) { { 'scope' => 'testscope', 'is_standby' => true } } + + it 'has valid config' do + content = catalogue.resource('file', 'patroni_config').send(:parameters)[:content] + config = YAML.safe_load(content) + expected = { + 'standby_cluster' => { + 'host' => '127.0.0.1', + 'port' => 5432, + 'primary_slot_name' => 'patroni', + }, + } + expect(config['bootstrap']['dcs']).to include(expected) + end + end + context 'use_etcd => true' do let(:params) { { 'scope' => 'testscope', 'use_etcd' => true } } @@ -358,7 +381,6 @@ it { is_expected.to compile.with_all_deps } it { is_expected.not_to contain_class('python') } it { is_expected.not_to contain_exec('patroni-mkdir-install_dir') } - it { is_expected.not_to contain_python__virtualenv('patroni') } it { is_expected.not_to contain_python__pyenv('patroni') } it { is_expected.not_to contain_python__pip('patroni') } @@ -383,21 +405,11 @@ creates: '/usr/local/patroni', ) end - case os_facts[:os]['family'] - when 'RedHat' - it do - is_expected.to contain_python__virtualenv('patroni').with( - venv_dir: '/usr/local/patroni', - environment: ['PIP_PREFIX=/usr/local/patroni'], - ) - end - when 'Debian' - it do - is_expected.to contain_python__pyvenv('patroni').with( - venv_dir: '/usr/local/patroni', - environment: ['PIP_PREFIX=/usr/local/patroni'], - ) - end + it do + is_expected.to contain_python__pyvenv('patroni').with( + venv_dir: '/usr/local/patroni', + environment: ['PIP_PREFIX=/usr/local/patroni'], + ) end it do is_expected.to contain_python__pip('patroni').with( @@ -416,6 +428,19 @@ expect(content).to include('ExecStart=/usr/local/patroni/bin/patroni ${PATRONI_CONFIG_LOCATION}') end end + + context 'custom_pip_provider => /usr/bin/pip3' do + let(:params) { { 'scope' => 'testscope', 'custom_pip_provider' => '/usr/bin/pip3' } } + + it { is_expected.to compile.with_all_deps } + + it do + is_expected.to contain_python__pip('patroni').with( + pip_provider: '/usr/bin/pip3', + virtualenv: 'system', + ) + end + end end end end diff --git a/spec/fixtures/unit/provider/patroni_dcs_config/patronictl/config.out b/spec/fixtures/unit/provider/patroni_dcs_config/patronictl/config.out new file mode 100644 index 0000000..8cd6130 --- /dev/null +++ b/spec/fixtures/unit/provider/patroni_dcs_config/patronictl/config.out @@ -0,0 +1,12 @@ +loop_wait: 10 +master_start_timeout: 300 +maximum_lag_on_failover: 1048576 +postgresql: + parameters: + max_connections: 200 + use_pg_rewind: true + use_slots: true +retry_timeout: 10 +synchronous_mode: false +synchronous_mode_strict: false +ttl: 30 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bed24fa..a26dbcb 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -25,7 +25,7 @@ next unless File.exist?(f) && File.readable?(f) && File.size?(f) begin - default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) + default_facts.merge!(YAML.safe_load(File.read(f))) rescue => e RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end @@ -48,6 +48,18 @@ c.after(:suite) do RSpec::Puppet::Coverage.report!(100) end + + # Filter backtrace noise + backtrace_exclusion_patterns = [ + %r{spec_helper}, + %r{gems}, + ] + + if c.respond_to?(:backtrace_exclusion_patterns) + c.backtrace_exclusion_patterns = backtrace_exclusion_patterns + elsif c.respond_to?(:backtrace_clean_patterns) + c.backtrace_clean_patterns = backtrace_exclusion_patterns + end end # Ensures that a module is defined diff --git a/spec/spec_helper_local.rb b/spec/spec_helper_local.rb index 353b841..48330fe 100644 --- a/spec/spec_helper_local.rb +++ b/spec/spec_helper_local.rb @@ -3,43 +3,56 @@ def platform_data(p, d) data = { - 'CentOS-7' => { + 'RedHat-7' => { postgresql_version: '9.6', data_dir: '/var/lib/pgsql/9.6/data', bin_dir: '/usr/pgsql-9.6/bin', + pg_config_link: true, python_class_version: '36', - install_dependencies: ['gcc', 'python3-psycopg2'], python_venv_version: '3.6', }, - 'CentOS-8' => { + 'RedHat-8' => { + manage_postgresql_repo: false, + postgres_repo_require: nil, data_dir: '/var/lib/pgsql/data', bin_dir: '/usr/bin', - python_venv_version: '3', + python_venv_version: '3.6', }, - 'Debian-9' => { - data_dir: '/var/lib/postgresql/9.6/main', - bin_dir: '/usr/lib/postgresql/9.6/bin', - python_venv_version: '3.5', + 'RedHat-9' => { + manage_postgresql_repo: false, + postgres_repo_require: nil, + data_dir: '/var/lib/pgsql/data', + bin_dir: '/usr/bin', + python_venv_version: '3.9', + }, + 'Debian-11' => { + data_dir: '/var/lib/postgresql/13/main', + bin_dir: '/usr/lib/postgresql/13/bin', + python_venv_version: '3.9', config_dir: '/etc/patroni', config_path: '/etc/patroni/config.yml', }, - 'Debian-10' => { - data_dir: '/var/lib/postgresql/11/main', - bin_dir: '/usr/lib/postgresql/11/bin', + 'Ubuntu-20.04' => { + data_dir: '/var/lib/postgresql/12/main', + bin_dir: '/usr/lib/postgresql/12/bin', + python_venv_version: '3.8', config_dir: '/etc/patroni', config_path: '/etc/patroni/config.yml', }, - 'Ubuntu-18.04' => { - data_dir: '/var/lib/postgresql/10/main', - bin_dir: '/usr/lib/postgresql/10/bin', - python_venv_version: '3.6', + 'Ubuntu-22.04' => { + data_dir: '/var/lib/postgresql/14/main', + bin_dir: '/usr/lib/postgresql/14/bin', + python_venv_version: '3.10', config_dir: '/etc/patroni', config_path: '/etc/patroni/config.yml', }, 'default' => { postgresql_version: nil, + manage_postgresql_repo: true, + postgres_repo_require: 'Class[Postgresql::Repo]', + pg_config_link: false, python_class_version: '3', - install_dependencies: ['gcc', 'python3-psycopg2'], + install_dependencies: ['gcc'], python_venv_version: '3.7', config_dir: '/opt/app/patroni/etc', config_path: '/opt/app/patroni/etc/postgresql.yml', diff --git a/spec/unit/patroni_dcs_config_spec.rb b/spec/unit/patroni_dcs_config_spec.rb new file mode 100644 index 0000000..cd7e86f --- /dev/null +++ b/spec/unit/patroni_dcs_config_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' +require 'puppet/type/patroni_dcs_config' + +describe Puppet::Type.type(:patroni_dcs_config) do + let(:default_config) { { name: 'foo', value: 'bar' } } + let(:config) { default_config } + let(:resource) { described_class.new(config) } + + it 'adds to catalog without raising an error' do + catalog = Puppet::Resource::Catalog.new + expect { + catalog.add_resource resource + }.not_to raise_error + end + + it 'requires a name' do + expect { + described_class.new({}) + }.to raise_error(Puppet::Error, 'Title or name must be provided') + end + + it 'accepts integer value' do + config[:value] = 1 + expect(resource[:value]).to eq(1) + end +end diff --git a/spec/unit/provider/patroni_dcs_config/patronictl_spec.rb b/spec/unit/provider/patroni_dcs_config/patronictl_spec.rb new file mode 100644 index 0000000..92ae476 --- /dev/null +++ b/spec/unit/provider/patroni_dcs_config/patronictl_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Puppet::Type.type(:patroni_dcs_config).provider(:patronictl) do + let(:provider) { described_class } + let(:type) { Puppet::Type.type(:patroni_dcs_config) } + let(:resource) { type.new(name: 'foo', value: 'bar') } + + describe 'self.instances' do + it 'creates instances' do + allow(provider).to receive(:patronictl).with(['show-config']).and_return(my_fixture_read('config.out')) + expect(provider.instances.length).to eq(10) + instance = provider.instances.select { |i| i.instance_variable_get('@property_hash')[:name] == 'postgresql.parameters.max_connections' } + expect(instance[0].instance_variable_get('@property_hash')[:value]).to eq(200) + end + end + + describe 'create' do + it 'creates DCS config' do + expect(resource.provider).to receive(:patronictl).with(['edit-config', '--force', '--quiet', '-s', 'foo=bar']) + resource.provider.create + end + end + + describe 'flush' do + it 'updates DCS config' do + expect(resource.provider).to receive(:patronictl).with(['edit-config', '--force', '--quiet', '-s', 'foo=1']) + resource.provider.value = 1 + resource.provider.flush + end + end +end diff --git a/templates/postgresql.yml.erb b/templates/postgresql.yml.erb index f0ecffb..6ed8051 100644 --- a/templates/postgresql.yml.erb +++ b/templates/postgresql.yml.erb @@ -85,10 +85,10 @@ postgresql: authentication: superuser: username: <%= @superuser_username %> - password: <%= @superuser_password %> + password: '<%= @superuser_password %>' replication: username: <%= @replication_username %> - password: <%= @replication_password %> + password: '<%= @replication_password %>' <% unless @callback_on_reload == nil && @callback_on_restart == nil && @callback_on_role_change == nil && @callback_on_start == nil && @callback_on_stop == nil -%> callbacks: <% if @callback_on_reload != nil -%> @@ -150,10 +150,13 @@ restapi: <% if @restapi_certfile != nil -%> certfile: <%= @restapi_certfile %> <% end -%> +<% if @restapi_ciphers != nil -%> + ciphers: <%= @restapi_ciphers %> +<% end -%> <% if @restapi_keyfile != nil -%> keyfile: <%= @restapi_keyfile %> <% end -%> -<% if @restapi_cafile != nil %> +<% if @restapi_cafile != nil -%> cafile: <%= @restapi_cafile %> <% end -%> <% if @restapi_verify_client != nil -%>