From 8c240f463e840cc2c1db64ef62bb2309f94e76fb Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Thu, 13 Feb 2025 03:24:15 +0100
Subject: [PATCH] add postgresql role for ens. psql and opt. some dbs and users
 are set up

Add postgresql role for ensuring postgresql is installed.
Furthermore the role optionally takes some basic configuration to ensure
databases with their owners and users are set up as specified.

This is a requirement for a new netbox role.
---
 roles/postgresql/README.md                | 37 +++++++++++++++++++++++
 roles/postgresql/defaults/main.yaml       |  2 ++
 roles/postgresql/meta/argument_specs.yaml | 28 +++++++++++++++++
 roles/postgresql/tasks/main.yaml          | 28 +++++++++++++++++
 4 files changed, 95 insertions(+)
 create mode 100644 roles/postgresql/README.md
 create mode 100644 roles/postgresql/defaults/main.yaml
 create mode 100644 roles/postgresql/meta/argument_specs.yaml
 create mode 100644 roles/postgresql/tasks/main.yaml

diff --git a/roles/postgresql/README.md b/roles/postgresql/README.md
new file mode 100644
index 0000000..6457931
--- /dev/null
+++ b/roles/postgresql/README.md
@@ -0,0 +1,37 @@
+# Role `postgresql`
+
+Ensures `postgresql` is installed by installing the distributions package.  
+Also ensures the optionally given databases and users are set up as specified.
+
+## Supported Distributions
+
+Should work on Debian-based distributions.
+
+## Required Arguments
+
+None.
+
+## Optional Arguments
+
+- `postgresql__dbs`: List of databases with their owner to ensure are set up.  
+- `postgresql__dbs.*.name`: Name of the database.
+- `postgresql__dbs.*.owner`: Owner of the database.
+- `postgresql__users`: List of users to ensure are set up.
+- `postgresql__users.*.name`: Name of the user.
+- `postgresql__users.*.password`: Optional password for the user.
+   If left unset, the user will have no password set, but can still connect using [peer authentication](https://www.postgresql.org/docs/current/auth-peer.html) on the local system.
+   (Peer authentication works when a password is set as well.)
+
+## Example Arguments
+
+```yaml
+postgresql__dbs:
+  - name: netbox
+    owner: netbox
+  - name: foo
+    owner: bar
+postgresql__users:
+  - name: netbox
+    password: super_secret
+  - name: bar
+```
diff --git a/roles/postgresql/defaults/main.yaml b/roles/postgresql/defaults/main.yaml
new file mode 100644
index 0000000..21fcd46
--- /dev/null
+++ b/roles/postgresql/defaults/main.yaml
@@ -0,0 +1,2 @@
+postgresql__dbs: [ ]
+postgresql__users: [ ]
diff --git a/roles/postgresql/meta/argument_specs.yaml b/roles/postgresql/meta/argument_specs.yaml
new file mode 100644
index 0000000..28e5813
--- /dev/null
+++ b/roles/postgresql/meta/argument_specs.yaml
@@ -0,0 +1,28 @@
+argument_specs:
+  main:
+    options:
+      postgresql__dbs:
+        type: list
+        elements: dict
+        required: false
+        default: [ ]
+        options:
+          name:
+            type: str
+            required: true
+          owner:
+            type: str
+            required: true
+      postgresql__users:
+        type: list
+        elements: dict
+        required: false
+        default: [ ]
+        options:
+          name:
+            type: str
+            required: true
+          password:
+            type: str
+            required: false
+            default: ""
diff --git a/roles/postgresql/tasks/main.yaml b/roles/postgresql/tasks/main.yaml
new file mode 100644
index 0000000..fc61857
--- /dev/null
+++ b/roles/postgresql/tasks/main.yaml
@@ -0,0 +1,28 @@
+- name: Ensure postgresql is installed
+  ansible.builtin.apt:
+    name:
+      - postgresql
+  become: true
+
+- name: Ensure Python library for community.postgresql is installed if needed
+  ansible.builtin.apt:
+    name:
+      - python3-psycopg
+  become: true
+  when: postgresql__dbs != [ ] or postgresql__users != [ ]
+
+- name: Ensure users
+  community.postgresql.postgresql_user:
+    name: "{{ item.name }}"
+    password: "{{ item.password | default('') }}"
+  become: true
+  become_user: postgres
+  loop: "{{ postgresql__users }}"
+
+- name: Ensure dbs with owners
+  community.postgresql.postgresql_db:
+    name: "{{ item.name }}"
+    owner: "{{ item.owner }}"
+  become: true
+  become_user: postgres
+  loop: "{{ postgresql__dbs }}"