--- - name: "Create role {{ postgres_replicator_user }} if necessary" community.postgresql.postgresql_user: name: "{{ postgres_replicator_user }}" role_attr_flags: LOGIN,REPLICATION login_user: "{{ postgres_admin_user }}" state: present become: true become_user: "{{ postgres_admin_user }}" - name: "Change passwords with scram-sha-256 for postgres superuser and replicator user" community.postgresql.postgresql_user: name: "{{ item.name }}" password: "{{ item.password }}" encrypted: true login_user: "{{ postgres_admin_user }}" environment: PGOPTIONS: "-c password_encryption=scram-sha-256" become: true become_user: postgres loop: - name: "{{ postgres_admin_user }}" password: "{{ postgres_admin_password }}" - name: "{{ postgres_replicator_user }}" password: "{{ postgres_replicator_user_password }}" - name: "Setup pg_hba.conf for replicator user" ansible.builtin.lineinfile: state: present regex: "^host[ ]+replication[ ]+replicator" line: "host replication replicator {{ shared_service_pg_slave_ip }}/32 trust" path: /etc/postgresql/{{ default_postgres_version }}/main/pg_hba.conf register: pg_hba_conf_replicator - name: "Set 'wal_level = replica' for master postgresql instance" ansible.builtin.lineinfile: state: present regex: "^wal_level" line: "wal_level = replica" path: /etc/postgresql/{{ default_postgres_version }}/main/postgresql.conf register: wal_level - name: "Set 'max_wal_senders = 10' for master postgresql instance" ansible.builtin.lineinfile: state: present regex: "^max_wal_senders" line: "max_wal_senders = 10" path: /etc/postgresql/{{ default_postgres_version }}/main/postgresql.conf register: max_wal_senders - name: "Set 'archive_mode = on' for master postgresql instance" ansible.builtin.lineinfile: state: present regex: "^archive_mode" line: "archive_mode = on" path: /etc/postgresql/{{ default_postgres_version }}/main/postgresql.conf register: archive_mode - name: "Set 'archive_command = cp -f %p /postgresql/replication/%f' for master postgresql instance" ansible.builtin.lineinfile: state: present regex: "^archive_command" line: "archive_command = 'cp -f %p /postgresql/replication/%f'" path: /etc/postgresql/{{ default_postgres_version }}/main/postgresql.conf register: archive_command - name: "Set 'wal_keep_size = 16' for master postgresql instance" ansible.builtin.lineinfile: state: present regex: "^wal_keep_size" line: "wal_keep_size = 16" path: /etc/postgresql/{{ default_postgres_version }}/main/postgresql.conf register: wal_keep_size - name: "Install nfs packages" ansible.builtin.apt: name: - nfs-kernel-server - nfs-common state: present update_cache: true cache_valid_time: 900 - name: "Create nfs share for archive" ansible.builtin.lineinfile: path: /etc/exports regex: "^/postgresql/replication" line: "/postgresql/replication/ {{ shared_service_pg_slave_ip }}/32(rw,crossmnt,root_squash,no_subtree_check,sync)" state: present register: nfsshare_archive_check - name: "Get service facts" ansible.builtin.service_facts: - name: "Check existence of necessary services" vars: services: - name: postgresql.service - name: nfs-kernel-server.service block: - name: "Check state of {{ item.name }}" ansible.builtin.fail: msg: "{{ item.name }} is not present on this system, why? It should have been there!" when: ansible_facts.services[item.name] is not defined loop: "{{ services }}" - name: "Restart nfs-server if necessary" # noqa no-handler ansible.builtin.service: name: nfs-kernel-server state: restarted when: nfsshare_archive_check.changed or ansible_facts.services["nfs-kernel-server.service"].state != "active" - name: "Restart postgres if necessary" # noqa no-handler ansible.builtin.service: name: postgresql state: restarted when: pg_hba_conf_replicator.changed or wal_level.changed or archive_mode.changed or archive_command.changed or max_wal_senders.changed or wal_keep_size.changed or ansible_facts.services["postgresql.service"].state != "active" - name: "Create extension pgcrypto for template1" # noqa no-changed-when become: true become_user: postgres ansible.builtin.shell: '/usr/bin/psql template1 -c "create extension if not exists pgcrypto;"' - name: "Check database replication_cron exists" # noqa no-changed-when become: true become_user: postgres ansible.builtin.shell: '/usr/bin/psql -Atc "SELECT count(*) FROM pg_database WHERE datname = ''replication_cron''"' register: database_replication_check - name: "Create replication_cron update database" # noqa no-changed-when become: true become_user: postgres ansible.builtin.shell: '/usr/bin/psql -c "CREATE DATABASE replication_cron;"' when: database_replication_check.stdout == "0" - name: "Create replication update schema" # noqa no-changed-when become: true become_user: postgres ansible.builtin.shell: '/usr/bin/psql replication_cron -c "CREATE SCHEMA IF NOT EXISTS replication_cron;"' - name: "Create replication update table" # noqa no-changed-when become: true become_user: postgres ansible.builtin.shell: '/usr/bin/psql replication_cron -c "CREATE TABLE IF NOT EXISTS replication_cron.replication_cron (dt timestamp);"' - name: "Create dummy update data" # noqa command-instead-of-shell become: true become_user: postgres ansible.builtin.shell: >- /usr/bin/psql replication_cron -c "INSERT INTO replication_cron.replication_cron SELECT NOW() WHERE NOT EXISTS (SELECT 1 FROM replication_cron.replication_cron)" register: cmd_ret changed_when: cmd_ret.rc != 0 - name: "Ensure a cron runs every 5 minutes and update replication check table" ansible.builtin.cron: name: "update replication table" minute: "*/5" job: su - postgres -c "/usr/bin/psql replication_cron -c \"UPDATE replication_cron.replication_cron SET dt=now();\"" - name: "Check replication slot exists" # noqa no-changed-when become: true become_user: postgres ansible.builtin.shell: '/usr/bin/psql -Atc "select count(*) from pg_replication_slots where slot_name=''pgstandby1''"' register: replication_slot_check - name: "Create replication-slot" # noqa no-changed-when become: true become_user: postgres ansible.builtin.shell: '/usr/bin/psql -Atc "SELECT pg_create_physical_replication_slot(''pgstandby1'');"' when: replication_slot_check.stdout == "0" register: cmd_ret changed_when: cmd_ret.rc != 0 - name: "Ensure test db stuff" block: - name: "Copy testdb.sql to ensure test DB" ansible.builtin.copy: src: "{{ item }}" dest: "/tmp/{{ item }}" mode: "0444" owner: postgres group: postgres loop: - testdb.sql - name: "Drop test DB if exists" become: true become_user: postgres community.postgresql.postgresql_db: name: dummytestdb state: absent - name: "Ensure test DB" become: true become_user: postgres community.postgresql.postgresql_db: name: dummytestdb - name: "Ensure content for test DB" become: true become_user: postgres community.postgresql.postgresql_db: name: dummytestdb state: restore target: /tmp/testdb.sql