Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@
# This file also serves as a documentation for such a variables.

# Examples of role input variables:
postgresql_version: "{{ '16' if ansible_facts['os_family'] == 'RedHat'
and ansible_facts['distribution'] != 'Fedora'
and ansible_facts['distribution_major_version'] == '10'
else '13' }}"
postgresql_version: null
postgresql_password: null
postgresql_cert_name: null
# the container build environment's RAM is independent from the deployment
# (regardless if it's a bootc or system container one), so disable tuning there
# by default
postgresql_server_tuning: "{{ false if (ansible_connection | d('')) == 'buildah' else true }}"
postgresql_server_tuning: null
postgresql_ssl_enable: false

# If you want to generate the certificas in the postgresql role
Expand Down
195 changes: 195 additions & 0 deletions meta/argument_specs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# SPDX-License-Identifier: MIT
---
argument_specs:
main:
short_description: The postgresql role.
description: >
The postgresql role installs and configures a PostgreSQL database
server. It supports version selection, optional password
configuration, SSL/TLS certificates, server tuning, custom
configuration files, and SQL script execution.
options:
postgresql_version:
type: raw
default: null
description: >
The major version of PostgreSQL to install and configure.
Accepts a version string such as `13` or `16`, or an
integer major version. When unset, the default version
depends on the target platform; for example RHEL 10
defaults to `16`.
postgresql_password:
type: raw
default: null
description: >
The password for the PostgreSQL superuser (`postgres`). When
set, password authentication is enabled in `pg_hba.conf`.
Accepts `null` or a string password value.
postgresql_cert_name:
type: raw
default: null
description: >
The base path or name of TLS certificate and key files to use
for the server, without the `.crt` or `.key` suffix. For
example, `/etc/certs/server` refers to `/etc/certs/server.crt`
and `/etc/certs/server.key`. Accepts `null` or a string.
postgresql_server_tuning:
type: raw
default: null
description: >
Whether to apply memory-based tuning settings such as
`shared_buffers` and `effective_cache_size` based on system
memory. Accepts `null`, `true`, or `false`. When unset,
tuning is enabled on booted systems and disabled in container
build environments.
postgresql_ssl_enable:
type: bool
default: false
description: >
Whether to enable SSL/TLS for PostgreSQL connections by
setting `ssl = on` in the server configuration.
postgresql_certificates:
type: list
elements: dict
default: []
description: >
A list of certificate request specifications passed to the
certificate role for generating TLS certificates used by
PostgreSQL.
options:
name:
type: str
required: true
description: >
The name of the certificate. A full path can be used to
choose the directory where files will be stored.
ca:
type: str
required: true
description: >
The CA that will issue the certificate (for example
`self-sign` or `ipa`).
dns:
type: raw
Comment thread
richm marked this conversation as resolved.
description: >
A domain name or list of domain names to include in the
certificate Subject Alternative Name (SAN).
email:
type: raw
description: >
An email address or list of email addresses to include in
the certificate Subject Alternative Name (SAN).
ip:
type: raw
description: >
An IP address or list of IP addresses to include in the
certificate Subject Alternative Name (SAN).
auto_renew:
type: bool
default: true
description: >
Whether the certificate should be renewed automatically
before it expires.
owner:
type: str
description: >
The user name or user id for the certificate and key
files.
group:
type: str
description: >
The group name or group id for the certificate and key
files.
mode:
type: raw
description: >
The file system permissions for the certificate and key
files. Accepts a string (for example `0644`) or an
integer.
key_size:
type: int
description: >
The key size in bits.
common_name:
type: str
description: >
The Common Name requested for the certificate subject.
country:
type: str
description: >
The country code requested for the certificate subject.
state:
type: str
description: >
The state requested for the certificate subject.
locality:
type: str
description: >
The locality requested for the certificate subject.
organization:
type: str
description: >
The organization requested for the certificate subject.
organizational_unit:
type: str
description: >
The organizational unit requested for the certificate
subject.
contact_email:
type: str
description: >
The contact email requested for the certificate subject.
key_usage:
type: list
elements: str
choices:
- digitalSignature
- nonRepudiation
- keyEncipherment
- dataEncipherment
- keyAgreement
- keyCertSign
- cRLSign
- encipherOnly
- decipherOnly
default:
- digitalSignature
- keyEncipherment
description: >
The allowed Key Usage extensions for the certificate.
extended_key_usage:
type: list
elements: str
default:
- id-kp-serverAuth
- id-kp-clientAuth
description: >
The Extended Key Usage attributes for the certificate.
run_before:
type: str
description: >
A command to run before saving the certificate.
run_after:
type: str
description: >
A command to run after saving the certificate.
principal:
type: raw
description: >
A Kerberos principal or list of Kerberos principals.
provider:
type: str
default: certmonger
description: >
The underlying method used to request and manage the
certificate.
issuer:
type: str
description: >
The issuer certificate nickname or template name.
postgresql_secure_logging:
type: bool
default: true
description: >
Whether to suppress logging of sensitive commands such as
password changes. Set to `false` for troubleshooting.
122 changes: 122 additions & 0 deletions tasks/assert_role_vars.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# SPDX-License-Identifier: MIT
---
- name: Assert postgresql_version is a string or integer
ansible.builtin.assert:
that:
- >-
(postgresql_version is string and postgresql_version is match("^[1-9][0-9]*$"))
or (postgresql_version | type_debug) == 'int'
fail_msg: >-
postgresql_version must be a string or integer,
got {{ postgresql_version | type_debug }}
when:
- postgresql_version is defined
- postgresql_version is not none

- name: Assert postgresql_password is null or a string
ansible.builtin.assert:
that:
- >-
(postgresql_password is none)
or (postgresql_password is string)
fail_msg: >-
postgresql_password must be null or a string,
got {{ postgresql_password | type_debug }}

- name: Assert postgresql_cert_name is null or a string
ansible.builtin.assert:
that:
- >-
(postgresql_cert_name is none)
or (postgresql_cert_name is string)
fail_msg: >-
postgresql_cert_name must be null or a string,
got {{ postgresql_cert_name | type_debug }}

- name: Assert postgresql_server_tuning is null or a boolean
ansible.builtin.assert:
that:
- >-
(postgresql_server_tuning is none)
or (postgresql_server_tuning is sameas true)
or (postgresql_server_tuning is sameas false)
fail_msg: >-
postgresql_server_tuning must be null or a boolean,
got {{ postgresql_server_tuning | type_debug }}

- name: Assert dns in postgresql_certificates is a string or list of strings
ansible.builtin.assert:
that:
- >-
item.dns is string
or (item.dns is sequence and item.dns is not mapping
and item.dns | reject('string') | list | length == 0)
fail_msg: >-
postgresql_certificates[{{ idx }}].dns must be a string or list of
strings, got {{ item.dns | type_debug }}
loop: "{{ postgresql_certificates }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.dns is defined

- name: Assert email in postgresql_certificates is a string or list of strings
ansible.builtin.assert:
that:
- >-
item.email is string
or (item.email is sequence and item.email is not mapping
and item.email | reject('string') | list | length == 0)
fail_msg: >-
postgresql_certificates[{{ idx }}].email must be a string or list of
strings, got {{ item.email | type_debug }}
loop: "{{ postgresql_certificates }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.email is defined

- name: Assert ip in postgresql_certificates is a string or list of strings
ansible.builtin.assert:
that:
- >-
item.ip is string
or (item.ip is sequence and item.ip is not mapping
and item.ip | reject('string') | list | length == 0)
fail_msg: >-
postgresql_certificates[{{ idx }}].ip must be a string or list of
strings, got {{ item.ip | type_debug }}
loop: "{{ postgresql_certificates }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.ip is defined

- name: Assert principal in postgresql_certificates is a string or list of strings
ansible.builtin.assert:
that:
- >-
item.principal is string
or (item.principal is sequence and item.principal is not mapping
and item.principal | reject('string') | list | length == 0)
fail_msg: >-
postgresql_certificates[{{ idx }}].principal must be a string or list of
strings, got {{ item.principal | type_debug }}
loop: "{{ postgresql_certificates }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.principal is defined

- name: Assert mode in postgresql_certificates is a string or integer
ansible.builtin.assert:
that:
- (item.mode | type_debug) in ['str', 'int', 'unicode']
fail_msg: >-
postgresql_certificates[{{ idx }}].mode must be a string or integer,
got {{ item.mode | type_debug }}
loop: "{{ postgresql_certificates }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.mode is defined
13 changes: 8 additions & 5 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
- name: Set platform/version specific variables
include_tasks: tasks/set_vars.yml

- name: Validate role parameters
ansible.builtin.include_tasks: assert_role_vars.yml

- name: Gather the package facts
package_facts:
no_log: "{{ ansible_verbosity < 3 }}"
Expand All @@ -15,15 +18,15 @@
when:
- ansible_facts["os_family"] == "RedHat"
- ansible_facts["distribution_major_version"] == "8"
- postgresql_version | string not in __postgresql_versions_el8
- __postgresql_version | string not in __postgresql_versions_el8

- name: Check if requested version is supported in system (RHEL9)
fail:
msg: RHEL 9 supports only Postgresql 13, 15, 16 and 18
when:
- ansible_facts["os_family"] == "RedHat"
- ansible_facts["distribution_major_version"] == "9"
- postgresql_version | string not in __postgresql_versions_el9
- __postgresql_version | string not in __postgresql_versions_el9

- name: Check if requested version is supported in system (RHEL10)
fail:
Expand All @@ -33,17 +36,17 @@
when:
- ansible_facts["os_family"] == "RedHat"
- ansible_facts["distribution_major_version"] == "10"
- postgresql_version | string not in __postgresql_versions_el10
- __postgresql_version | string not in __postgresql_versions_el10

- name: Check requested and installed version of Postgresql
fail:
msg: >-
Setting version {{ postgresql_version }} while
Setting version {{ __postgresql_version }} while
{{ ansible_facts.packages['postgresql'][0].version }} is installed
when:
- "'postgresql' in ansible_facts.packages"
- ansible_facts.packages["postgresql"][0].version |
regex_search('([0-9]*).', '\\1') | first != postgresql_version | string
regex_search('([0-9]*).', '\\1') | first != __postgresql_version | string

# rpm ostree pkg mgr cannot handle @groups/modules
# so just assume the packages are present
Expand Down
Loading