#!/usr/bin/ansible-playbook
---
#--------------------------------------------------------------#
# chown watchdog                                   [pg_watchdog]
#--------------------------------------------------------------#
- name: grant postgres dbsu watchdog owner
  tags: pg_watchdog
  ignore_errors: true
  when: patroni_watchdog_mode != 'off'
  file: path=/dev/watchdog owner={{ pg_dbsu }} group=postgres


#--------------------------------------------------------------#
# Launch patroni primary                            [pg_primary]
#--------------------------------------------------------------#
# primary first , replica next, never re-run this task
- name: launch patroni primary
  tags: pg_primary
  any_errors_fatal: true
  when: pg_role == 'primary'
  block:

    - name: launch patroni primary
      systemd: name=patroni state=restarted enabled=yes daemon_reload=yes

    - name: wait for patroni primary
      wait_for: host={{ inventory_hostname }} port={{ patroni_port }} state=started timeout=60

    - name: check postgres primary ready
      become_user: "{{ pg_dbsu }}"
      shell: |
        {{ pg_bin_dir }}/pg_isready -t 5 -p {{ pg_port }}
      register: result
      retries: 6
      until: result.rc == 0
      delay: 5

    - name: remove postgres backup conf
      file: path={{ item }} state=absent
      ignore_errors: true
      with_items:
        - /pg/data/postgresql.conf.backup
        - /pg/data/postgresql.base.conf.backup
        - /pg/data/pg_hba.conf.backup
        - /pg/data/pg_ident.conf.backup

    - name: render postgres hba rules
      become_user: "{{ pg_dbsu }}"
      template: src=pg_hba.conf dest=/pg/data/pg_hba.conf owner={{ pg_dbsu }} group=postgres mode=0600

    - name: copy extra files to postgres primary
      when: pg_files is defined and pg_files | length > 0
      become_user: "{{ pg_dbsu }}"
      copy: src={{ item }} dest=/pg/data/{{ item|basename }}  owner={{ pg_dbsu }} group=postgres mode=0600
      with_items: "{{ pg_files }}"

    - name: overwrite postgres primary parameters
      become_user: "{{ pg_dbsu }}"
      copy:
        dest: /pg/data/postgresql.auto.conf
        owner: "{{ pg_dbsu }}"
        group: postgres
        mode: 0600
        content: |
          # Do not edit this file or use ALTER SYSTEM manually!
          # It is managed by Pigsty & Ansible automatically!
          {% set list_params = ['search_path', 'temp_tablespaces', 'local_preload_libraries', 'session_preload_libraries', 'log_destination', 'shared_preload_libraries', 'unix_socket_directories', 'debug_io_direct'] %}
          {% for key, value in pg_parameters.items() %}
          {% if key in list_params %}
          {{ key }} = {{ value }}
          {% else %}
          {{ key }} = '{{ value }}'
          {% endif %}
          {% endfor %}

    - name: restart postgres via patroni
      tags: pg_restart
      become_user: "{{ pg_dbsu }}"
      shell: |
        {% if pg_mode|default('pgsql') == 'citus' %} 
        /usr/bin/patronictl -c /etc/patroni/patroni.yml restart {{ pg_shard }} --group {{ pg_group }} --force
        {% else %}
        /usr/bin/patronictl -c /etc/patroni/patroni.yml restart {{ pg_cluster }} --force
        {% endif %}
      args:
        executable: /bin/bash

    - name: wait for postgres primary
      wait_for: host={{ inventory_hostname }} port={{ pg_port }} state=started timeout=60

    - name: check postgres primary ready
      become_user: "{{ pg_dbsu }}"
      shell: |
        {{ pg_bin_dir }}/pg_isready -t 5 -p {{ pg_port }}
      register: result
      retries: 12
      until: result.rc == 0
      delay: 5


#--------------------------------------------------------------#
# init postgres cluster                                [pg_init]
#--------------------------------------------------------------#
- name: init postgres cluster
  tags: pg_init
  any_errors_fatal: true
  when: pg_role == 'primary'
  block:

    - name: render init sql and scripts
      template: src="{{ item.src }}" dest={{ item.dest }} owner={{ item.owner|default(pg_dbsu) }} group=postgres mode={{ item.mode }}
      with_items:
        - { src: "pg-init-roles.sql"    ,dest: "/pg/tmp/pg-init-roles.sql"    ,mode: "0640" }
        - { src: "pg-init-template.sql" ,dest: "/pg/tmp/pg-init-template.sql" ,mode: "0640" }
        - { src: "{{ pg_init }}"        ,dest: "/pg/bin/pg-init" ,owner: root ,mode: "0740" }

    - name: init postgres cluster
      tags: pg_init_exec
      become_user: "{{ pg_dbsu }}"
      command: bash /pg/bin/pg-init

    - name: check postgres primary inited
      tags: pg_init_exec
      become_user: "{{ pg_dbsu }}"
      shell: |
        {{ pg_bin_dir }}/pg_isready -t 5 -p {{ pg_port }}
      register: result
      retries: 6
      until: result.rc == 0
      delay: 5


#--------------------------------------------------------------#
# Write PGPASS                                         [pg_pass]
#--------------------------------------------------------------#
- name: write default userpass to .pgpass
  tags: pg_pass
  become_user: "{{ pg_dbsu }}"
  block:

    - name: add dbsu password to pgpass if exists
      when: pg_dbsu_password is defined and pg_dbsu_password != ''
      shell: /bin/bash /pg/bin/pg-pass-add "{{ pg_dbsu }}" "{{ pg_dbsu_password }}"
      args: { executable: /bin/bash }
      no_log: true

    - name: add system user to pgpass
      shell: /bin/bash /pg/bin/pg-pass-add "{{ item.username }}" "{{ item.password }}"
      with_items:
        - { username: "{{ pg_replication_username }}", password: "{{ pg_replication_password }}" }
        - { username: "{{ pg_monitor_username }}" ,password: "{{ pg_monitor_password }}" }
        - { username: "{{ pg_admin_username }}", password: "{{ pg_admin_password }}" }
      args: { executable: /bin/bash }
      no_log: true

#--------------------------------------------------------------#
# Launch replicas                                   [pg_replica]
#--------------------------------------------------------------#
# bootstrap other replicas
- name: launch patroni replicas
  tags: pg_replica
  any_errors_fatal: true
  when: pg_role != 'primary'
  block:

    - name: check replication connectivity
      become_user: "{{ pg_dbsu }}"
      environment:
        PGPASSWORD: "{{ pg_replication_password }}"
      shell: |
        {{ pg_bin_dir }}/psql -w -h {{ pg_primary_ip }} -p {{ pg_port }} -U {{ pg_replication_username }} -d postgres -Atc 'SELECT 1;'

    - name: launch patroni replica
      systemd: name=patroni state=restarted enabled=yes daemon_reload=yes

    - name: wait for patroni replica
      wait_for: host={{ inventory_hostname }} port={{ patroni_port }} state=started timeout=30

    # NOTICE: may take quite a long time for existing cluster
    - name: wait for postgres replica
      wait_for: host={{ inventory_hostname }} port={{ pg_port }} state=started timeout=86400

    - name: check postgres replica ready
      become_user: "{{ pg_dbsu }}"
      shell: |
        {{ pg_bin_dir }}/pg_isready -t 5 -p {{ pg_port }}
      register: result
      retries: 6
      until: result.rc == 0
      delay: 5

#--------------------------------------------------------------#
# Copy Files (Optional)                                [pg_file]
#--------------------------------------------------------------#
# some postgres kernel fork require a key/licence file
- name: copy extra files to pgdata
  tags: pg_file
  when: pg_files is defined and pg_files | length > 0
  become_user: "{{ pg_dbsu }}"
  copy: src={{ item }} dest=/pg/data/{{ item|basename }}  owner={{ pg_dbsu }} group=postgres mode=0600
  with_items: "{{ pg_files }}"

#--------------------------------------------------------------#
# Generate HBA                                          [pg_hba]
#--------------------------------------------------------------#
- name: render postgres hba rules
  tags: pg_hba
  become_user: "{{ pg_dbsu }}"
  template: src=pg_hba.conf dest=/pg/data/pg_hba.conf owner={{ pg_dbsu }} group=postgres mode=0600

#--------------------------------------------------------------#
# Generate postgresql.auto.conf                       [pg_param]
#--------------------------------------------------------------#
- name: overwrite postgres parameters
  tags: pg_param
  become_user: "{{ pg_dbsu }}"
  copy:
    dest: /pg/data/postgresql.auto.conf
    owner: "{{ pg_dbsu }}"
    group: postgres
    mode: 0600
    content: |
      # Do not edit this file or use ALTER SYSTEM manually!
      # It is managed by Pigsty & Ansible automatically!
      {% set list_params = ['search_path', 'temp_tablespaces', 'local_preload_libraries', 'session_preload_libraries', 'log_destination', 'shared_preload_libraries', 'unix_socket_directories', 'debug_io_direct'] %}
      {% for key, value in pg_parameters.items() %}
      {% if key in list_params %}
      {{ key }} = {{ value }}
      {% else %}
      {{ key }} = '{{ value }}'
      {% endif %}
      {% endfor %}


#--------------------------------------------------------------#
# Reload Patroni Conf                                [pg_reload]
#--------------------------------------------------------------#
- name: reload postgres config
  tags: pg_reload
  when: pg_reload|bool
  become_user: "{{ pg_dbsu }}"
  shell: |
    {{ pg_bin_dir }}/pg_ctl -D {{ pg_data }} reload
  args: { executable: /bin/bash }


#--------------------------------------------------------------#
# Reload Patroni Conf                           [patroni_reload]
#--------------------------------------------------------------#
- name: reload patroni config
  tags: patroni_reload
  when: pg_reload|bool
  systemd: name=patroni state=reloaded daemon_reload=yes


#--------------------------------------------------------------#
# Adjust Patroni mode                               [pg_patroni]
#--------------------------------------------------------------#
# patroni_mode controls this section
- name: pause patroni
  tags: pg_patroni
  ignore_errors: true
  when: patroni_mode == 'pause' and pg_role == 'primary'
  command: /usr/bin/patronictl -c /etc/patroni/patroni.yml pause

# this will degrade cluster into a raw cluster
- name: remove patroni
  tags: pg_patroni
  when: patroni_mode == 'remove'
  block:

    - name: stop patroni replicas
      when: pg_role != 'primary'
      systemd: name=patroni state=stopped enabled=no daemon_reload=yes

    - name: stop patroni primary
      when: pg_role == 'primary'
      systemd: name=patroni state=stopped enabled=no daemon_reload=yes

    - name: launch raw postgres primary
      when: pg_role == 'primary'
      systemd: name=postgres state=restarted enabled=yes daemon_reload=yes

    - name: launch raw postgres replicas
      when: pg_role != 'primary'
      systemd: name=postgres state=restarted enabled=yes daemon_reload=yes

    - name: wait for raw postgres
      wait_for: host={{ inventory_hostname }} port={{ pg_port }} state=started timeout=60
...
