diff --git a/pmm_qa/percona-distribution-postgresql/data/etcd.conf.yaml.j2 b/pmm_qa/percona-distribution-postgresql/data/etcd.conf.yaml.j2 index 6ecb4235..b27b7326 100644 --- a/pmm_qa/percona-distribution-postgresql/data/etcd.conf.yaml.j2 +++ b/pmm_qa/percona-distribution-postgresql/data/etcd.conf.yaml.j2 @@ -4,9 +4,9 @@ initial-cluster-token: PostgreSQL_HA_Cluster_1 initial-cluster-state: new listen-peer-urls: http://0.0.0.0:2380 -initial-advertise-peer-urls: http://pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}:2380 +initial-advertise-peer-urls: http://pdpgsql_pmm_patroni_{{ pdpgsql_version }}_{{ item }}:2380 listen-client-urls: http://0.0.0.0:2379 -advertise-client-urls: http://pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}:2379 +advertise-client-urls: http://pdpgsql_pmm_patroni_{{ pdpgsql_version }}_{{ item }}:2379 -initial-cluster: node1=http://pdpgsql_pmm_patroni_{{ pg_version }}_1:2380,node2=http://pdpgsql_pmm_patroni_{{ pg_version }}_2:2380,node3=http://pdpgsql_pmm_patroni_{{ pg_version }}_3:2380 +initial-cluster: node1=http://pdpgsql_pmm_patroni_{{ pdpgsql_version }}_1:2380,node2=http://pdpgsql_pmm_patroni_{{ pdpgsql_version }}_2:2380,node3=http://pdpgsql_pmm_patroni_{{ pdpgsql_version }}_3:2380 diff --git a/pmm_qa/percona-distribution-postgresql/data/patroni.yml.j2 b/pmm_qa/percona-distribution-postgresql/data/patroni.yml.j2 index 13ec02f5..3c68d869 100644 --- a/pmm_qa/percona-distribution-postgresql/data/patroni.yml.j2 +++ b/pmm_qa/percona-distribution-postgresql/data/patroni.yml.j2 @@ -1,13 +1,13 @@ scope: patroni_cls namespace: /var/lib/pgsql/config/ -name: pg_node_{{ item }} +name: {{ container_prefix }}{{ item }} restapi: listen: 0.0.0.0:8008 - connect_address: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}:8008" + connect_address: "{{ container_prefix }}{{ item }}:8008" etcd3: - host: "pdpgsql_pmm_patroni_{{ pg_version }}_1:2379" + host: "{{ container_prefix }}1:2379" bootstrap: dcs: @@ -29,7 +29,7 @@ bootstrap: wal_log_hints: "on" archive_mode: "on" archive_timeout: 600s - archive_command: "cp -f %p /home/postgres/archived/%f" + archive_command: pgbackrest --stanza=patroni_backup --log-level-console=info archive-push /var/lib/postgresql/{{ pdpgsql_version }}/main/pg_wal/%f pg_hba: - host replication replicator 127.0.0.1/32 md5 - host replication replicator 172.18.0.0/16 md5 @@ -51,9 +51,9 @@ bootstrap: postgresql: listen: 0.0.0.0:5432 - connect_address: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}:5432" - data_dir: /var/lib/pgsql/{{ pg_version}}/data - bin_dir: /usr/pgsql-{{ pg_version }}/bin + connect_address: "{{ container_prefix }}{{ item }}:5432" + data_dir: /var/lib/postgresql/{{ pdpgsql_version }}/main + bin_dir: /usr/lib/postgresql/{{ pdpgsql_version }}/bin pgpass: /tmp/pgpass authentication: @@ -62,14 +62,14 @@ postgresql: password: replPasswd superuser: username: postgres - password: postgres + password: pass+this create_replica_methods: - pgbackrest - basebackup pgbackrest: - command: pgbackrest --stanza=patroni_backup restore --type=none + command: pgbackrest --stanza=patroni_backup restore --pg1-path=/var/lib/postgresql/{{ pdpgsql_version }}/main --type=none keep_data: true no_params: true diff --git a/pmm_qa/percona-distribution-postgresql/data/pg_hba.conf.j2 b/pmm_qa/percona-distribution-postgresql/data/pg_hba.conf.j2 index 8488d8cc..f2371208 100644 --- a/pmm_qa/percona-distribution-postgresql/data/pg_hba.conf.j2 +++ b/pmm_qa/percona-distribution-postgresql/data/pg_hba.conf.j2 @@ -1,3 +1,4 @@ host replication {{ replication_user }} 0.0.0.0/0 md5 host all all 0.0.0.0/0 md5 local all postgres trust +local all all md5 \ No newline at end of file diff --git a/pmm_qa/percona-distribution-postgresql/data/pg_hba_replica.conf.j2 b/pmm_qa/percona-distribution-postgresql/data/pg_hba_replica.conf.j2 index 8488d8cc..f2371208 100644 --- a/pmm_qa/percona-distribution-postgresql/data/pg_hba_replica.conf.j2 +++ b/pmm_qa/percona-distribution-postgresql/data/pg_hba_replica.conf.j2 @@ -1,3 +1,4 @@ host replication {{ replication_user }} 0.0.0.0/0 md5 host all all 0.0.0.0/0 md5 local all postgres trust +local all all md5 \ No newline at end of file diff --git a/pmm_qa/percona-distribution-postgresql/data/pgsm_run_queries.sh b/pmm_qa/percona-distribution-postgresql/data/pgsm_run_queries.sh new file mode 100644 index 00000000..0afaa2be --- /dev/null +++ b/pmm_qa/percona-distribution-postgresql/data/pgsm_run_queries.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +## Running Queries +wget https://raw.githubusercontent.com/percona/pmm-agent/main/testqueries/postgres/pg_stat_monitor_load.sql +while true +do + su postgres bash -c 'psql -d contrib_regression -f pg_stat_monitor_load.sql' + su postgres bash -c 'psql -d sbtest1 -f pg_stat_monitor_load.sql' + sleep 30 +done diff --git a/pmm_qa/percona-distribution-postgresql/data/pgsql_load.sql b/pmm_qa/percona-distribution-postgresql/data/pgsql_load.sql new file mode 100644 index 00000000..81a4fa90 --- /dev/null +++ b/pmm_qa/percona-distribution-postgresql/data/pgsql_load.sql @@ -0,0 +1,115 @@ +-- ======================================== +-- CREATE TABLES +-- ======================================== + +CREATE TABLE students ( + student_id SERIAL PRIMARY KEY, + first_name VARCHAR(50), + last_name VARCHAR(50), + birth_date DATE +); + +CREATE TABLE classes ( + class_id SERIAL PRIMARY KEY, + name VARCHAR(100), + teacher VARCHAR(100) +); + +CREATE TABLE enrollments ( + enrollment_id SERIAL PRIMARY KEY, + student_id INTEGER REFERENCES students(student_id), + class_id INTEGER REFERENCES classes(class_id), + enrollment_date DATE DEFAULT CURRENT_DATE +); + +-- ======================================== +-- INSERT MOCK DATA +-- ======================================== + +INSERT INTO students (first_name, last_name, birth_date) VALUES +('Alice', 'Smith', '2005-04-10'), +('Bob', 'Johnson', '2006-08-15'), +('Charlie', 'Brown', '2004-12-01'); + +INSERT INTO classes (name, teacher) VALUES +('Mathematics', 'Mrs. Taylor'), +('History', 'Mr. Anderson'), +('Science', 'Dr. Reynolds'); + +INSERT INTO enrollments (student_id, class_id) VALUES +(1, 1), +(1, 2), +(2, 2), +(3, 1), +(3, 3); + +-- ======================================== +-- SIMULATE DEAD TUPLES +-- ======================================== + + +INSERT INTO students (first_name, last_name, birth_date) +SELECT 'John', 'Doe', CURRENT_DATE - (random() * 5000)::int +FROM generate_series(1, 100000); + +-- These updates and deletes will create dead tuples + +-- Update records (old versions become dead) +UPDATE students +SET last_name = last_name || '_updated' +WHERE student_id IN (1, 2); + +-- Delete records (deleted rows become dead) +DELETE FROM enrollments +WHERE enrollment_id IN (SELECT enrollment_id FROM enrollments LIMIT 2); + +-- Disable autovacuum temporarily (for demo) +ALTER TABLE students SET (autovacuum_enabled = false); +ALTER TABLE enrollments SET (autovacuum_enabled = false); + +-- ======================================== +-- SELECT QUERIES +-- ======================================== + +-- Get all students +SELECT * FROM students; + +-- Get all students enrolled in Mathematics +SELECT s.first_name, s.last_name +FROM students s +JOIN enrollments e ON s.student_id = e.student_id +JOIN classes c ON e.class_id = c.class_id +WHERE c.name = 'Mathematics'; + +-- Count students per class +SELECT c.name, COUNT(e.student_id) AS student_count +FROM classes c +LEFT JOIN enrollments e ON c.class_id = e.class_id +GROUP BY c.name; + +-- ======================================== +-- UPDATE QUERIES +-- ======================================== + +-- Change Bob's last name +UPDATE students +SET last_name = 'Williams' +WHERE first_name = 'Bob' AND last_name = 'Johnson'; + +-- Update the teacher for the History class +UPDATE classes +SET teacher = 'Ms. Carter' +WHERE name = 'History'; + +-- ======================================== +-- DELETE QUERIES +-- ======================================== + +-- Remove Charlie from Science class +DELETE FROM enrollments +WHERE student_id = (SELECT student_id FROM students WHERE first_name = 'Charlie') + AND class_id = (SELECT class_id FROM classes WHERE name = 'Science'); + +-- Delete a student completely +DELETE FROM students +WHERE first_name = 'Alice' AND last_name = 'Smith'; diff --git a/pmm_qa/percona-distribution-postgresql/data/postgresql-primary.conf b/pmm_qa/percona-distribution-postgresql/data/postgresql-primary.conf.j2 similarity index 74% rename from pmm_qa/percona-distribution-postgresql/data/postgresql-primary.conf rename to pmm_qa/percona-distribution-postgresql/data/postgresql-primary.conf.j2 index eb09610b..d5bda4cd 100644 --- a/pmm_qa/percona-distribution-postgresql/data/postgresql-primary.conf +++ b/pmm_qa/percona-distribution-postgresql/data/postgresql-primary.conf.j2 @@ -3,7 +3,8 @@ max_wal_senders = 10 wal_keep_size = 64MB hot_standby = on listen_addresses = '*' -hba_file = '/etc/postgresql/pg_hba.conf' +hba_file = '/etc/postgresql/{{ pdpgsql_version }}/main/pg_hba.conf' +data_directory = '/var/lib/postgresql/{{ pdpgsql_version }}/main' shared_preload_libraries = 'pg_stat_monitor' track_activity_query_size=2048 track_io_timing=ON diff --git a/pmm_qa/percona-distribution-postgresql/data/postgres-replica.conf b/pmm_qa/percona-distribution-postgresql/data/postgresql-replica.conf.j2 similarity index 71% rename from pmm_qa/percona-distribution-postgresql/data/postgres-replica.conf rename to pmm_qa/percona-distribution-postgresql/data/postgresql-replica.conf.j2 index 3336ed77..4dca55b0 100644 --- a/pmm_qa/percona-distribution-postgresql/data/postgres-replica.conf +++ b/pmm_qa/percona-distribution-postgresql/data/postgresql-replica.conf.j2 @@ -1,4 +1,5 @@ -hba_file = '/etc/postgresql/pg_hba.conf' +hba_file = '/etc/postgresql/{{ pdpgsql_version }}/main/pg_hba.conf' +data_directory = '/var/lib/postgresql/{{ pdpgsql_version }}/main' shared_preload_libraries = 'pg_stat_monitor' track_activity_query_size=2048 track_io_timing=ON @@ -11,4 +12,4 @@ pg_stat_monitor.pgsm_enable_query_plan=1 log_connections = on log_disconnections = on log_replication_commands = on -log_statement = 'all' +log_statement = 'all' \ No newline at end of file diff --git a/pmm_qa/percona-distribution-postgresql/data/postgresql-single.conf.j2 b/pmm_qa/percona-distribution-postgresql/data/postgresql-single.conf.j2 new file mode 100644 index 00000000..d8f1f2e6 --- /dev/null +++ b/pmm_qa/percona-distribution-postgresql/data/postgresql-single.conf.j2 @@ -0,0 +1,12 @@ +listen_addresses = '*' +hba_file = '/etc/postgresql/{{ pdpgsql_version }}/main/pg_hba.conf' +data_directory = '/var/lib/postgresql/{{ pdpgsql_version }}/main' +shared_preload_libraries = 'pg_stat_monitor' +track_activity_query_size=2048 +track_io_timing=ON +max_connections=1000 +pg_stat_monitor.pgsm_enable_query_plan = 'yes' +log_connections = on +log_disconnections = on +log_replication_commands = on +log_statement = 'all' diff --git a/pmm_qa/percona-distribution-postgresql/percona-distribution-postgres-setup.yml b/pmm_qa/percona-distribution-postgresql/percona-distribution-postgres-setup.yml index ce64aed4..e9de8de3 100644 --- a/pmm_qa/percona-distribution-postgresql/percona-distribution-postgres-setup.yml +++ b/pmm_qa/percona-distribution-postgresql/percona-distribution-postgres-setup.yml @@ -5,12 +5,12 @@ connection: local gather_facts: yes vars: - pg_version: "{{ lookup('env', 'PGSQL_VERSION') | default('17', true) }}" + pdpgsql_version: "{{ lookup('env', 'PDPGSQL_VERSION') | default('17', true) }}" replication_user: "repl_user" replication_password: "GRgrO9301RuF" root_password: "GRgrO9301RuF" pdpgsql_port: 5432 - nodes_count: "{{ (lookup('env', 'NODES_COUNT') | default('2', true)) | int }}" + nodes_count: "{{ (lookup('env', 'NODES_COUNT') | default('1', true)) | int }}" network_name: "pmm-qa" data_dir: "{{ lookup('env', 'HOME') }}/pgsql_cluster_data" pmm_server_ip: "{{ lookup('vars', 'extra_pmm_server_ip', default=lookup('env','PMM_SERVER_IP') | default('127.0.0.1', true) ) }}" @@ -21,12 +21,22 @@ setup_type: "{{ lookup('env', 'SETUP_TYPE') }}" random_service_name_value: "" docker_repo: "percona/percona-distribution-postgresql" + container_prefix: "pdpgsql_pmm{{ (setup_type|default('')) and '_' ~ setup_type }}_{{ pdpgsql_version }}_" tasks: - - name: Display binary log status for primary + - name: Display setup type selected debug: msg: "{{ setup_type }}" + - name: Create Docker network + shell: docker network create {{ network_name }} + ignore_errors: yes + become: true + + - name: Install Percona Distribution for Postgres + include_tasks: tasks/install-percona-distribution-postgresql-single.yml + when: setup_type != "replication" and setup_type != "patroni" + - name: Install Percona Distribution for Postgres with Replication include_tasks: tasks/percona-distribution-postgres-replication-setup.yml when: setup_type == "replication" diff --git a/pmm_qa/percona-distribution-postgresql/tasks/install-pdpgsql.yml b/pmm_qa/percona-distribution-postgresql/tasks/install-pdpgsql.yml new file mode 100644 index 00000000..8f00c735 --- /dev/null +++ b/pmm_qa/percona-distribution-postgresql/tasks/install-pdpgsql.yml @@ -0,0 +1,44 @@ +- name: Start containers for Percona Distribution for Postgresql + shell: | + docker run -d \ + --name={{ container_prefix }}{{ item }} \ + --restart=always \ + --network {{ network_name }} \ + -e POSTGRES_PASSWORD={{ root_password }} \ + --privileged --cgroupns=host \ + -v /sys/fs/cgroup:/sys/fs/cgroup:rw \ + -v /var/lib/containerd \ + -p {{ pdpgsql_port + (item - 1) }}:5432 \ + antmelekhin/docker-systemd:ubuntu-24.04 + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Install dependencies + shell: | + docker exec {{ container_prefix }}{{ item }} apt-get update + docker exec {{ container_prefix }}{{ item }} apt-get -y install wget gnupg2 lsb-release curl + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Install Percona Release + shell: | + docker exec {{ container_prefix }}{{ item }} wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb + docker exec {{ container_prefix }}{{ item }} dpkg -i ./percona-release_latest.generic_all.deb + docker exec {{ container_prefix }}{{ item }} percona-release enable ppg-{{ pdpgsql_version }} + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Install Percona Distribution for PostgreSQL + shell: | + docker exec -u root {{ container_prefix }}{{ item }} apt-get install -y percona-postgresql-{{ pdpgsql_version }} percona-pgbackrest percona-pg-stat-monitor{{ pdpgsql_version }} + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Start Percona distribution for Postgresql + shell: docker exec -u root {{ container_prefix }}{{ item }} systemctl start postgresql + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Wait 5 seconds for Percona Distribution for postgresql to start + pause: + seconds: 5 diff --git a/pmm_qa/percona-distribution-postgresql/tasks/install-percona-distribution-postgresql-single.yml b/pmm_qa/percona-distribution-postgresql/tasks/install-percona-distribution-postgresql-single.yml new file mode 100644 index 00000000..c631dcb0 --- /dev/null +++ b/pmm_qa/percona-distribution-postgresql/tasks/install-percona-distribution-postgresql-single.yml @@ -0,0 +1,94 @@ +- name: Remove old data folders + shell: 'rm -fr {{ data_dir }}' + become: true + +- name: Create data directories + file: + path: "{{ data_dir }}/node{{ item }}/data" + state: directory + mode: '0755' + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Generate pg_hba.conf for primary node + template: + src: data/pg_hba.conf.j2 + dest: "{{ data_dir }}/node{{ item }}/pg_hba.conf" + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Generate postgres.conf for primary node + template: + src: data/postgresql-single.conf.j2 + dest: "{{ data_dir }}/node1/postgresql.conf" + become: true + +- name: Install Percona Distribution for Postgres + include_tasks: tasks/install-pdpgsql.yml + +- name: Install pg stat monitor. + include_tasks: ./tasks/install_pg_stat-monitor.yml + +- name: Install and add pmm client. + include_tasks: ../tasks/install_pmm_client.yml + vars: + container_name: "{{ container_prefix }}{{ item }}" + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Copy config files + shell: | + docker cp {{ data_dir }}/node{{ item }}/postgresql.conf {{ container_prefix }}{{ item }}:/etc/postgresql/{{ pdpgsql_version }}/main/postgresql.conf + docker cp {{ data_dir }}/node{{ item }}/pg_hba.conf {{ container_prefix }}{{ item }}:/etc/postgresql/{{ pdpgsql_version }}/main/pg_hba.conf + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Restart Percona distribution for Postgresql + shell: docker exec -u root {{ container_prefix }}{{ item }} systemctl restart postgresql + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Create PostgreSQL user 'pmm' with password and grant pg_monitor + shell: | + docker exec -u postgres {{ container_prefix }}{{ item }} psql -U postgres -d {{ db_name | default('postgres') }} -c " + DO \$\$ + BEGIN + IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'pmm') THEN + CREATE ROLE pmm LOGIN PASSWORD 'pmm'; + END IF; + GRANT pg_monitor TO pmm; + END + \$\$; + " + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Add service to pmm server + shell: | + docker exec {{ container_prefix }}{{ item }} pmm-admin add postgresql --username=pmm --password=pmm --query-source=pgstatmonitor {{ container_prefix }}{{ item }}{{ random_service_name_value }} --debug 127.0.0.1:5432 + docker exec {{ container_prefix }}{{ item }} pmm-admin add postgresql --username=pmm --password=pmm --query-source=pgstatmonitor --socket=/var/run/postgresql socket_{{ container_prefix }}{{ item }}{{ random_service_name_value }} + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Run queries for generating data + shell: docker exec {{ container_prefix }}{{ item }} bash ./data/pgsm_run_queries.sh & + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Copy a file into the container + shell: docker cp ./data/pgsql_load.sql {{ container_prefix }}{{ item }}:/pgsql_load.sql + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Create database if it doesn't exist + shell: docker exec {{ container_prefix }}{{ item }} psql -U postgres -c "CREATE DATABASE school;" + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Run SQL script using docker exec + shell: docker exec {{ container_prefix }}{{ item }} psql -U postgres -d school -f /pgsql_load.sql > /dev/null + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Change postgres user password + shell: | + docker exec -u postgres {{ container_prefix }}1 psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'pass+this';" \ No newline at end of file diff --git a/pmm_qa/percona-distribution-postgresql/tasks/install_pg_stat-monitor.yml b/pmm_qa/percona-distribution-postgresql/tasks/install_pg_stat-monitor.yml index 146f17e7..b191fb0f 100644 --- a/pmm_qa/percona-distribution-postgresql/tasks/install_pg_stat-monitor.yml +++ b/pmm_qa/percona-distribution-postgresql/tasks/install_pg_stat-monitor.yml @@ -1,7 +1,5 @@ - name: Detect OS inside the container - community.docker.docker_container_exec: - container: "{{ container_name }}_1" - command: cat /etc/os-release + shell: docker exec {{ container_prefix }}1 cat /etc/os-release register: container_os_info - name: Set distro family (debian/rhel) @@ -16,34 +14,23 @@ }} - name: Install dependencies inside Debian-family container - community.docker.docker_container_exec: - container: "{{ container_name }}_{{ item }}" - command: > - sh -c ' - apt-get update && - apt-get install percona-pg-stat-monitor{{ pg_version }} - ' - user: "root" + shell: | + docker exec {{ container_prefix }}{{ item }} apt update + docker exec {{ container_prefix }}{{ item }} apt install -y percona-pg-stat-monitor{{ pdpgsql_version }} when: distro_family == "debian" loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Install dependencies inside RHEL-family container - community.docker.docker_container_exec: - container: "{{ container_name }}_{{ item }}" - command: > - sh -c ' - microdnf install percona-pg-stat-monitor{{ pg_version }} - ' - user: "root" + shell: docker exec {{ container_prefix }}{{ item }} microdnf install percona-pg-stat-monitor{{ pdpgsql_version }} when: distro_family == "rhel" loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Create pg_stat_statements extension - community.docker.docker_container_exec: - container: "{{ container_name }}_1" - user: postgres - command: > + shell: | + docker exec -u postgres {{ container_prefix }}1 \ + env PGPASSWORD=postgres \ psql -U postgres -d 'postgres' -c " CREATE EXTENSION IF NOT EXISTS pg_stat_monitor; SELECT pg_stat_monitor_version(); " + diff --git a/pmm_qa/percona-distribution-postgresql/tasks/percona-distribution-postgres-patroni-setup.yml b/pmm_qa/percona-distribution-postgresql/tasks/percona-distribution-postgres-patroni-setup.yml index fdf71fc0..e5d79490 100644 --- a/pmm_qa/percona-distribution-postgresql/tasks/percona-distribution-postgres-patroni-setup.yml +++ b/pmm_qa/percona-distribution-postgresql/tasks/percona-distribution-postgres-patroni-setup.yml @@ -2,163 +2,145 @@ set_fact: nodes_count: 3 when: nodes_count | int < 3 + - name: Set external facing port in patroni setup set_fact: pdpgsql_port: 6432 - name: Remove old data folders shell: 'rm -fr {{ data_dir }}' + become: true - name: Create data directories file: path: "{{ data_dir }}/node{{ item }}/data" state: directory mode: '0755' + become: true loop: "{{ range(1, nodes_count | int + 1) | list }}" -- name: Fix permissions on data directory +- name: Generate postgres.conf for primary node + template: + src: data/postgresql-primary.conf.j2 + dest: "{{ data_dir }}/node1/postgresql.conf" become: true - file: - path: "{{ data_dir }}/node{{ item }}/data" - owner: 1001 - group: 1001 - recurse: yes - loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Generate etcd configuration template: src: data/etcd.conf.yaml.j2 dest: "{{ data_dir }}/node{{ item }}/etcd.conf.yaml" + become: true loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Generate patroni configuration template: src: data/patroni.yml.j2 dest: "{{ data_dir }}/node{{ item }}/patroni.yml" + become: true loop: "{{ range(1, nodes_count | int + 1) | list }}" -- name: Create Docker network - community.docker.docker_network: - name: "{{ network_name }}" - state: present - ignore_errors: yes - -- name: Start PostgreSQL containers - community.docker.docker_container: - name: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}" - image: oraclelinux:9 - state: started - restart_policy: always - command: sleep infinity - networks: - - name: "{{ network_name }}" - volumes: - - "{{ data_dir }}/node{{ item }}/data:/data/db" - - "{{ data_dir }}/node{{ item }}/etcd.conf.yaml:/etcd.conf.yaml:ro" - - "{{ data_dir }}/node{{ item }}/patroni.yml:/etc/patroni/patroni.yml:ro" - ports: - - "{{ pdpgsql_port + item - 1 }}:5432" - loop: "{{ range(1, nodes_count | int + 1) | list }}" +- name: Generate postgres.conf for primary node + template: + src: data/postgresql-primary.conf.j2 + dest: "{{ data_dir }}/node1/postgresql.conf" + become: true + +- name: Generate postgres.conf for replica nodes + template: + src: data/postgresql-replica.conf.j2 + dest: "{{ data_dir }}/node{{ item }}/postgresql.conf" + become: true + loop: "{{ range(2, nodes_count | int + 1) | list }}" + +- name: Install Percona distribution for Postgresql + include_tasks: tasks/install-pdpgsql.yml -- name: Install required packages in Oracle Linux container - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}" - user: root - command: > - /bin/sh -c ' - dnf config-manager --set-enabled ol9_codeready_builder - dnf install perl-IPC-Run -y - dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm - dnf config-manager --set-enabled crb - dnf install -y python3-pip python3-devel binutils python3-click - ' +- name: Copy config files to all nodes + shell: | + docker cp {{ data_dir }}/node{{ item }}/patroni.yml {{ container_prefix }}{{ item }}:/patroni.yml + docker cp {{ data_dir }}/node{{ item }}/etcd.conf.yaml {{ container_prefix }}{{ item }}:/etcd.conf.yaml + become: true loop: "{{ range(1, nodes_count | int + 1) | list }}" -- name: Install Percona Distribution for PostgresSQL - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}" - user: root - command: > - /bin/sh -c ' - dnf module disable postgresql - dnf install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm - percona-release enable ppg-{{ pg_version }} - dnf install -y percona-pg-stat-monitor{{ pg_version }} percona-postgresql{{ pg_version }}-server percona-patroni etcd python3-python-etcd percona-pgbackrest - patroni --version - ' +- name: Install dependencies for Percona Distribution for PostgresSQL + shell: | + docker exec -u root {{ container_prefix }}{{ item }} apt-get install -y percona-patroni etcd python3-etcd percona-pgbackrest + docker exec -u root {{ container_prefix }}{{ item }} patroni --version + become: true loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Start etcd service - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}" - user: root - command: > - /bin/sh -c ' - rm -rf /var/lib/pgsql/{{ pg_version }}/data/* - ps aux | grep postgres - rm -f /data/db/postmaster.pid - mkdir -p /data/db/logs - mkdir /pg_wal - touch /dev/watchdog - nohup etcd --config-file /etcd.conf.yaml > /data/db/logs/etcd.log 2>&1 & - chown -R postgres:postgres /data/db/logs - chown -R postgres:postgres /dev/watchdog - chown -R postgres:postgres /pg_wal - ' + shell: | + docker exec {{ container_prefix }}{{ item }} /bin/sh -c ' + ps aux | grep postgres + rm -f /data/db/postmaster.pid + mkdir -p /data/db/logs + mkdir /pg_wal + touch /dev/watchdog + nohup etcd --config-file /etcd.conf.yaml > /data/db/logs/etcd.log 2>&1 & + chown -R postgres:postgres /data/db/logs + chown -R postgres:postgres /dev/watchdog + chown -R postgres:postgres /pg_wal + chown -R postgres:postgres /var/lib/postgresql/{{ pdpgsql_version }}/main/ + ' + become: true loop: "{{ range(1, nodes_count | int + 1) | list }}" +- name: Prepare replication user and config file for primary node + shell: | + docker cp {{ data_dir }}/node1/postgresql.conf {{ container_prefix }}1:/var/lib/postgresql/{{ pdpgsql_version }}/main + docker exec -u postgres {{ container_prefix }}1 psql -c "CREATE ROLE replicator WITH LOGIN REPLICATION PASSWORD 'replPasswd';" + docker exec -u postgres {{ container_prefix }}1 mkdir -p /var/lib/pgbackrest/archive/patroni_backup + docker exec -u postgres {{ container_prefix }}1 chown -R postgres:postgres /var/lib/pgbackrest + docker exec -u postgres {{ container_prefix }}1 pgbackrest --stanza=patroni_backup --pg1-path=/var/lib/postgresql/{{ pdpgsql_version }}/main stanza-create + become: true -- name: Wait 5 seconds to etcd to start - pause: - seconds: 5 - -- name: Start patroni service - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}" - user: postgres - command: > - /bin/sh -c ' - nohup patroni /etc/patroni/patroni.yml > /data/db/logs/patroni.log 2>&1 & - ' - loop: "{{ range(1, nodes_count | int + 1) | list }}" - -- name: Install microdnf - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}" - user: root - command: > - /bin/sh -c ' - dnf install -y microdnf - ' - loop: "{{ range(1, nodes_count | int + 1) | list }}" +- name: Remove data folder on replica nodes. + shell: | + docker exec {{ container_prefix }}{{ item }} rm -fr /var/lib/postgresql/{{ pdpgsql_version }}/main + become: true + loop: "{{ range(2, nodes_count | int + 1) | list }}" - name: Install pg stat monitor. include_tasks: ./tasks/install_pg_stat-monitor.yml - vars: - container_name: "pdpgsql_pmm_patroni_{{ pg_version }}" - name: Grant pg_monitor to postgres user - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_1" - user: postgres - command: > - bash -c ' - psql -U postgres -d {{ db_name | default("postgres") }} -c " - GRANT pg_monitor TO postgres; - " - ' + shell: | + docker exec -u postgres {{ container_prefix }}1 bash -c ' + psql -d {{ db_name | default("postgres") }} -c "GRANT pg_monitor TO postgres;" + ' + become: true + +- name: Change postgres user password + shell: | + docker exec -u postgres {{ container_prefix }}1 psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'pass+this';" + become: true + +- name: Stop Percona distribution for Postgresql, due to being managed by patroni + shell: docker exec -u root {{ container_prefix }}{{ item }} systemctl stop postgresql + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Start patroni service in all nodes + shell: > + docker exec -u postgres {{ container_prefix }}{{ item }} /bin/sh -c "nohup patroni /patroni.yml > /data/db/logs/patroni.log 2>&1 &" + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Show logs from patroni for debug + shell: docker exec -u postgres {{ container_prefix }}{{ item }} cat /data/db/logs/patroni.log + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Install and add pmm client. include_tasks: ../tasks/install_pmm_client.yml vars: - container_name: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}" + container_name: "{{ container_prefix }}{{ item }}" loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Get already connected services to pmm server - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_1" - command: > - sh -c 'curl --location --insecure -u"admin:{{ admin_password }}" -s --request GET "http://{{ pmm_server_ip }}:{{ '80' if pmm_server_ip is match('^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$') else '8080' }}/v1/management/services" | jq -r ".services[].service_name"' + shell: docker exec {{ container_prefix }}1 sh -c 'curl --location --insecure -u"admin:{{ admin_password }}" -s --request GET "http://{{ pmm_server_ip }}:{{ "80" if pmm_server_ip is match('^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$') else "8080" }}/v1/management/services" | jq -r ".services[].service_name"' + become: true register: pmm_server_services - name: Display already connected services to pmm server @@ -171,29 +153,34 @@ set_fact: random_service_name_value: "_{{ 9999 | random + 1 }}" loop: "{{ range(1, nodes_count | int + 1) | list }}" - when: "('pdpgsql_pmm_patroni_' ~ pg_version ~ '_' ~ item) in pmm_server_services.stdout" + when: "('pdpgsql_pmm_patroni_' ~ pdpgsql_version ~ '_' ~ item) in pmm_server_services.stdout" - name: Add service to pmm server - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}" - command: pmm-admin add postgresql --username=postgres --cluster=pdpgsql_patroni_cluster --environment=pdpgsql_patroni_environment --password=postgres --query-source=pgstatmonitor pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}{{ random_service_name_value }} --debug 127.0.0.1:5432 + shell: docker exec {{ container_prefix }}{{ item }} pmm-admin add postgresql --username=postgres --cluster=pdpgsql_patroni_cluster --environment=pdpgsql_patroni_environment --password=pass+this --query-source=pgstatmonitor {{ container_prefix }}{{ item }}{{ random_service_name_value }} --debug 127.0.0.1:5432 + become: true loop: "{{ range(1, nodes_count | int + 1) | list }}" -- name: Add patroni service to pmm server - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_1" - command: pmm-admin add external --listen-port=8008 --service-name=patroni_service_1{{ random_service_name_value }} +- name: Add patroni primary service to pmm server + shell: docker exec {{ container_prefix }}1 pmm-admin add external --listen-port=8008 --service-name=patroni_service_1{{ random_service_name_value }} + become: true -- name: Add patroni service to pmm server - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_{{ item }}" - command: pmm-admin add external --listen-port=8008 --cluster=pdpgsql_patroni_service_cluster --environment=pdpgsql_patroni_service_environment --service-name=patroni_service_{{ item }}{{ random_service_name_value }} +- name: Add patroni replication service to pmm server + shell: docker exec {{ container_prefix }}{{ item }} pmm-admin add external --listen-port=8008 --cluster=pdpgsql_patroni_service_cluster --environment=pdpgsql_patroni_service_environment --service-name=patroni_service_{{ item }}{{ random_service_name_value }} + become: true loop: "{{ range(2, nodes_count | int + 1) | list }}" +- name: Copy a file into the container + shell: docker cp ./data/pgsql_load.sql {{ container_prefix }}1:/pgsql_load.sql + become: true + +- name: Create database if it doesn't exist + shell: docker exec {{ container_prefix }}1 psql -U postgres -c "CREATE DATABASE school;" + become: true + +- name: Run SQL script using docker exec + shell: docker exec {{ container_prefix }}1 psql -U postgres -d school -f /pgsql_load.sql > /dev/null + become: true + - name: Log Patroni cluster - community.docker.docker_container_exec: - container: "pdpgsql_pmm_patroni_{{ pg_version }}_1" - command: > - /bin/sh -c ' - patronictl -c /etc/patroni/patroni.yml list - ' + shell: docker exec {{ container_prefix }}1 patronictl -c /patroni.yml list + become: true diff --git a/pmm_qa/percona-distribution-postgresql/tasks/percona-distribution-postgres-replication-setup.yml b/pmm_qa/percona-distribution-postgresql/tasks/percona-distribution-postgres-replication-setup.yml index 1dc6a06d..9700dcf7 100644 --- a/pmm_qa/percona-distribution-postgresql/tasks/percona-distribution-postgres-replication-setup.yml +++ b/pmm_qa/percona-distribution-postgresql/tasks/percona-distribution-postgres-replication-setup.yml @@ -1,28 +1,44 @@ -- name: Create Docker network - community.docker.docker_network: - name: "{{ network_name }}" - state: present - ignore_errors: yes +- name: Chance to correct nodes count for replication + set_fact: + nodes_count: 2 + when: nodes_count | int < 2 and setup_type == "replication" - name: Remove old data folders shell: 'rm -fr {{ data_dir }}' + become: true - name: Create data directories file: path: "{{ data_dir }}/node{{ item }}/data" state: directory mode: '0755' + become: true loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Generate pg_hba.conf for primary node template: src: data/pg_hba.conf.j2 dest: "{{ data_dir }}/node1/pg_hba.conf" + become: true + +- name: Generate postgres.conf for primary node + template: + src: data/postgresql-primary.conf.j2 + dest: "{{ data_dir }}/node1/postgresql.conf" + become: true + +- name: Generate postgres.conf for replica nodes + template: + src: data/postgresql-replica.conf.j2 + dest: "{{ data_dir }}/node{{ item }}/postgresql.conf" + become: true + loop: "{{ range(2, nodes_count | int + 1) | list }}" - name: Generate pg_hba.conf for replica node template: src: data/pg_hba_replica.conf.j2 dest: "{{ data_dir }}/node{{ item }}/pg_hba.conf" + become: true loop: "{{ range(2, nodes_count | int + 1) | list }}" - name: Fix permissions on data directory @@ -34,173 +50,108 @@ recurse: yes loop: "{{ range(1, nodes_count | int + 1) | list }}" -- name: Remove old PostgreSQL primary container - community.docker.docker_container: - name: "pdpgsql_pmm_replication_{{ pg_version }}_1" - image: "{{ docker_repo }}:{{ pg_version }}" - restart_policy: always - state: absent - ignore_errors: yes - -- name: Start PostgreSQL primary container - community.docker.docker_container: - name: "pdpgsql_pmm_replication_{{ pg_version }}_1" - image: "{{ docker_repo }}:{{ pg_version }}" - restart_policy: always - state: started - recreate: true - networks: - - name: "{{ network_name }}" - env: - POSTGRES_PASSWORD: "{{ root_password }}" - volumes: - - "{{ data_dir }}/node1/data:/data/db" - - "./data/postgresql-primary.conf:/etc/postgresql/postgresql.conf:ro" - - "{{ data_dir }}/node1/pg_hba.conf:/etc/postgresql/pg_hba.conf:ro" - command: -c config_file=/etc/postgresql/postgresql.conf - ports: - - "{{ pdpgsql_port }}:5432" - -- name: Wait for PgSQL to be available - wait_for: - host: localhost - port: "{{ pdpgsql_port }}" - delay: 10 - timeout: 300 +- name: Prepare and install Percona Distribution for Postgresql + include_tasks: tasks/install-pdpgsql.yml + +- name: Install pg stat monitor. + include_tasks: ./tasks/install_pg_stat-monitor.yml + vars: + container_name: "{{ container_prefix }}" + +- name: Stop Percona distribution for Postgresql + shell: docker exec -u root {{ container_prefix }}{{ item }} systemctl stop postgresql + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" + +- name: Copy config files to primary node + shell: | + docker cp {{ data_dir }}/node1/postgresql.conf {{ container_prefix }}1:/etc/postgresql/{{ pdpgsql_version }}/main/postgresql.conf + docker cp {{ data_dir }}/node1/pg_hba.conf {{ container_prefix }}1:/etc/postgresql/{{ pdpgsql_version }}/main/pg_hba.conf + become: true + +- name: Start Percona distribution for Postgresql primary node + shell: docker exec -u root {{ container_prefix }}1 systemctl start postgresql + become: true + +- name: Wait 5 seconds for Percona Distribution for postgresql to start + pause: + seconds: 5 - name: Create replication user - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_1" - user: postgres - command: > - psql -c " - CREATE ROLE {{ replication_user }} WITH REPLICATION LOGIN ENCRYPTED PASSWORD '{{ replication_password }}'; - " - -- name: Stop and remove replica if exists - community.docker.docker_container: - name: "pdpgsql_pmm_replication_{{ pg_version }}_{{ item }}" - state: absent - loop: "{{ range(2, nodes_count | int + 1) | list }}" - ignore_errors: yes - -- name: Start Percona Distribution PostgreSQL replica container - community.docker.docker_container: - name: "pdpgsql_pmm_replication_{{ pg_version }}_{{ item }}" - image: "{{ docker_repo }}:{{ pg_version }}" - restart_policy: "no" - state: started - command: sleep infinity - networks: - - name: "{{ network_name }}" - env: - POSTGRES_INITDB_SKIP: "yes" - POSTGRES_PASSWORD: "{{ root_password }}" - volumes: - - "{{ data_dir }}/node{{ item }}/data:/data/db" - - "./data/postgres-replica.conf:/etc/postgresql/postgresql.conf:ro" - - "{{ data_dir }}/node{{ item }}/pg_hba.conf:/etc/postgresql/pg_hba.conf:ro" - loop: "{{ range(2, nodes_count | int + 1) | list }}" + shell: docker exec {{ container_prefix }}1 psql -U postgres -c "CREATE ROLE {{ replication_user }} WITH REPLICATION LOGIN ENCRYPTED PASSWORD '{{ replication_password }}';" + become: true - name: Wipe replica data directory before basebackup - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_{{ item }}" - user: root - command: rm -rf /data/db/* + shell: docker exec {{ container_prefix }}{{ item }} rm -rf /var/lib/postgresql/{{ pdpgsql_version }}/main/ + become: true loop: "{{ range(2, nodes_count | int + 1) | list }}" -- name: Create PostgreSQL user 'pmm' with password - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_1" - user: postgres - command: > - bash -c ' - psql -U postgres -d {{ db_name | default("postgres") }} -c " - CREATE USER pmm WITH PASSWORD '\''pmm'\''; - GRANT pg_monitor TO pmm; - " - ' +- name: Create PostgreSQL user 'pmm' with password and grant pg_monitor + shell: | + docker exec -u postgres {{ container_prefix }}1 psql -U postgres -d {{ db_name | default('postgres') }} -c " + DO \$\$ + BEGIN + IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'pmm') THEN + CREATE ROLE pmm LOGIN PASSWORD 'pmm'; + END IF; + GRANT pg_monitor TO pmm; + END + \$\$; + " + become: true - name: Create custom database - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_1" - user: postgres - command: > - bash -c " - echo \" - CREATE DATABASE test_database; - \\c test_database - GRANT CONNECT ON DATABASE test_database TO pmm; - GRANT USAGE ON SCHEMA public TO pmm; - GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO pmm; - ALTER DEFAULT PRIVILEGES IN SCHEMA public - GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO pmm; - \" | psql -U postgres -v ON_ERROR_STOP=1 - " + shell: | + docker exec -u postgres {{ container_prefix }}1 bash -c " + echo \" + CREATE DATABASE test_database; + \\c test_database + GRANT CONNECT ON DATABASE test_database TO pmm; + GRANT USAGE ON SCHEMA public TO pmm; + GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO pmm; + ALTER DEFAULT PRIVILEGES IN SCHEMA public + GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO pmm; + \" | psql -U postgres -v ON_ERROR_STOP=1 + " + become: true - name: Run pg_basebackup from primary to replica - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_{{ item }}" - user: root - command: > - bash -c " - export PGPASSWORD='{{ replication_password }}' && \ - timeout 120s \ - pg_basebackup --pgdata=/data/db -R -v -Fp -Xs -P \ - --host=pdpgsql_pmm_replication_{{ pg_version }}_1 --port=5432 -U {{ replication_user }} > /tmp/pg_basebackup.log 2>&1 - " - loop: "{{ range(2, nodes_count | int + 1) | list }}" - -- name: Remove temporary backup container - docker_container: - name: "pdpgsql_pmm_replication_{{ pg_version }}_{{ item }}" - state: absent + shell: | + docker exec -u root {{ container_prefix }}{{ item }} bash -c " + export PGPASSWORD='{{ replication_password }}' && \ + timeout 120s \ + pg_basebackup --pgdata=/var/lib/postgresql/{{ pdpgsql_version }}/main -R -v -Fp -Xs -P \ + --host={{ container_prefix}}1 --port=5432 -U {{ replication_user }} + " + become: true loop: "{{ range(2, nodes_count | int + 1) | list }}" -- name: Fix permissions on data directory +- name: Copy config files to replica nodes + shell: | + docker cp {{ data_dir }}/node{{ item }}/postgresql.conf {{ container_prefix }}{{ item }}:/etc/postgresql/{{ pdpgsql_version }}/main/postgresql.conf + docker cp {{ data_dir }}/node{{ item }}/pg_hba.conf {{ container_prefix }}{{ item }}:/etc/postgresql/{{ pdpgsql_version }}/main/pg_hba.conf + docker exec {{ container_prefix}}{{ item }} chown -R postgres:postgres /var/lib/postgresql/{{ pdpgsql_version }}/main become: true - file: - path: "{{ data_dir }}/node{{ item }}/data" - owner: 1001 - group: 1001 - recurse: yes loop: "{{ range(2, nodes_count | int + 1) | list }}" -- name: Restart Percona Distribution PostgreSQL container with custom command - community.docker.docker_container: - name: "pdpgsql_pmm_replication_{{ pg_version }}_{{ item }}" - image: "{{ docker_repo }}:{{ pg_version }}" - restart: true - state: started - command: -c config_file=/etc/postgresql/postgresql.conf - networks: - - name: "{{ network_name }}" - env: - POSTGRES_PASSWORD: "{{ root_password }}" - volumes: - - "{{ data_dir }}/node{{ item }}/data:/data/db" - - "./data/postgres-replica.conf:/etc/postgresql/postgresql.conf:ro" - - "{{ data_dir }}/node1/pg_hba.conf:/etc/postgresql/pg_hba.conf:ro" - ports: - - "{{ pdpgsql_port + item - 1}}:5432" - loop: "{{ range(2, nodes_count | int + 1) | list }}" +- name: Start Percona distribution for Postgresql + shell: docker exec -u root {{ container_prefix }}{{ item }} systemctl start postgresql + become: true + loop: "{{ range(1, nodes_count | int + 1) | list }}" -- name: Install pg stat monitor. - include_tasks: ./tasks/install_pg_stat-monitor.yml - vars: - container_name: "pdpgsql_pmm_replication_{{ pg_version }}" +- name: Wait 5 seconds for Percona Distribution for postgresql to start + pause: + seconds: 5 - name: Install and add pmm client. include_tasks: ../tasks/install_pmm_client.yml vars: - container_name: "pdpgsql_pmm_replication_{{ pg_version }}_{{ item }}" + container_name: "{{ container_prefix }}{{ item }}" loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Get already connected services to pmm server - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_1" - command: > - sh -c 'curl --location --insecure -u"admin:{{ admin_password }}" -s --request GET "http://{{ pmm_server_ip }}:{{ '80' if pmm_server_ip is match('^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$') else '8080' }}/v1/management/services" | jq -r ".services[].service_name"' + shell: docker exec {{ container_prefix }}1 sh -c 'curl --location --insecure -u"admin:{{ admin_password }}" -s --request GET "http://{{ pmm_server_ip }}:{{ "80" if pmm_server_ip is match('^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$') else "8080" }}/v1/management/services" | jq -r ".services[].service_name"' + become: true register: pmm_server_services - name: Display already connected services to pmm server @@ -213,61 +164,54 @@ set_fact: random_service_name_value: "_{{ 9999 | random + 1 }}" loop: "{{ range(1, nodes_count | int + 1) | list }}" - when: "('pdpgsql_pmm_' ~ pg_version ~ '_' ~ item) in pmm_server_services.stdout" + when: "('pdpgsql_pmm_' ~ pdpgsql_version ~ '_' ~ item) in pmm_server_services.stdout" - name: Add service to pmm server - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_{{ item }}" - command: pmm-admin add postgresql --username=pmm --password=pmm --cluster=pdpgsql_replication_cluster --environment=pdpgsql_replication_environment --query-source=pgstatmonitor pdpgsql_pmm_replication_{{ pg_version }}_{{ item }}{{ random_service_name_value }} --debug 127.0.0.1:5432 + shell: docker exec {{ container_prefix }}{{ item }} pmm-admin add postgresql --username=pmm --password=pmm --cluster=pdpgsql_replication_cluster --environment=pdpgsql_replication_environment --query-source=pgstatmonitor {{ container_prefix}}{{ item }}{{ random_service_name_value }} --debug 127.0.0.1:5432 + become: true loop: "{{ range(1, nodes_count | int + 1) | list }}" - name: Create pg_custom_publication view using psql - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_1" - user: postgres - command: > - bash -c 'psql -U postgres -d postgres < - psql -U postgres -d test_database -c " - CREATE EXTENSION IF NOT EXISTS pg_stat_monitor; - SELECT pg_stat_monitor_version(); - " + shell: | + docker exec -u postgres {{ container_prefix }}1 bash -c 'psql -U postgres -d postgres < - sh -c "nohup bash -c 'while true; do echo Starting insert at $(date +\"%Y-%m-%d %H:%M:%S\"); psql -U postgres -d test_database -f /load_pgsql.sql; sleep 30; done' > /tmp/sql_loop.log 2>&1 &" + shell: | + docker exec {{ container_prefix }}1 sh -c 'nohup bash -c "while true; do echo Starting insert at \$(date +\"%Y-%m-%d %H:%M:%S\"); psql -U postgres -d test_database -f /load_pgsql.sql; sleep 30; done" > /tmp/sql_loop.log 2>&1 &' + become: true - name: Create logical replication slots - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_1" - user: postgres - command: psql -U postgres -d postgres -c "SELECT * FROM pg_create_logical_replication_slot('test_slot', 'test_decoding');" - -- name: Check replication status on primary - community.docker.docker_container_exec: - container: "pdpgsql_pmm_replication_{{ pg_version }}_1" - user: postgres - command: psql -c "SELECT * FROM pg_stat_replication;" + shell: docker exec {{ container_prefix }}1 psql -U postgres -d postgres -c "SELECT * FROM pg_create_logical_replication_slot('test_slot', 'test_decoding');" + become: true + +- name: Copy a file into the container + shell: docker cp ./data/pgsql_load.sql {{ container_prefix }}1:/pgsql_load.sql + become: true + +- name: Create database if it doesn't exist + shell: docker exec {{ container_prefix }}1 psql -U postgres -c "CREATE DATABASE school;" + become: true + +- name: Run SQL script using docker exec + shell: docker exec {{ container_prefix }}1 psql -U postgres -d school -f /pgsql_load.sql > /dev/null + become: true + +- name: Change postgres user password + shell: | + docker exec -u postgres {{ container_prefix }}1 psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'pass+this';" + become: true diff --git a/pmm_qa/pmm-framework.py b/pmm_qa/pmm-framework.py index 7b477332..27f48f22 100755 --- a/pmm_qa/pmm-framework.py +++ b/pmm_qa/pmm-framework.py @@ -187,43 +187,24 @@ def setup_pdpgsql(db_type, db_version=None, db_config=None, args=None): # Gather Version details pdpgsql_version = os.getenv('PDPGSQL_VERSION') or db_version or database_configs[db_type]["versions"][-1] setup_type_value = get_value('SETUP_TYPE', db_type, args, db_config).lower() - print(f"Setup type is {setup_type_value}") - if setup_type_value in ("replication", "replica", "patroni"): - # Define environment variables for playbook - env_vars = { - 'PGSTAT_MONITOR_BRANCH': 'main', - 'PDPGSQL_VERSION': pdpgsql_version, - 'PMM_SERVER_IP': args.pmm_server_ip or container_name or '127.0.0.1', - 'PDPGSQL_PGSM_CONTAINER': 'pdpgsql_pgsm_pmm_' + str(pdpgsql_version), - 'CLIENT_VERSION': get_value('CLIENT_VERSION', db_type, args, db_config), - 'USE_SOCKET': get_value('USE_SOCKET', db_type, args, db_config), - 'ADMIN_PASSWORD': os.getenv('ADMIN_PASSWORD') or args.pmm_server_password or 'admin', - 'PDPGSQL_PGSM_PORT': 5447, - 'DISTRIBUTION': '', - 'PMM_QA_GIT_BRANCH': os.getenv('PMM_QA_GIT_BRANCH') or 'v3', - 'SETUP_TYPE': setup_type_value - } - - # Ansible playbook filename - playbook_filename = 'percona-distribution-postgresql/percona-distribution-postgres-setup.yml' - else: - # Define environment variables for playbook - env_vars = { - 'PGSTAT_MONITOR_BRANCH': 'main', - 'PDPGSQL_VERSION': pdpgsql_version, - 'PMM_SERVER_IP': args.pmm_server_ip or container_name or '127.0.0.1', - 'PDPGSQL_PGSM_CONTAINER': 'pdpgsql_pgsm_pmm_' + str(pdpgsql_version), - 'CLIENT_VERSION': get_value('CLIENT_VERSION', db_type, args, db_config), - 'USE_SOCKET': get_value('USE_SOCKET', db_type, args, db_config), - 'ADMIN_PASSWORD': os.getenv('ADMIN_PASSWORD') or args.pmm_server_password or 'admin', - 'PDPGSQL_PGSM_PORT': 5447, - 'DISTRIBUTION': '', - 'PMM_QA_GIT_BRANCH': os.getenv('PMM_QA_GIT_BRANCH') or 'v3' - } + # Define environment variables for playbook + env_vars = { + 'PGSTAT_MONITOR_BRANCH': 'main', + 'PDPGSQL_VERSION': pdpgsql_version, + 'PMM_SERVER_IP': args.pmm_server_ip or container_name or '127.0.0.1', + 'PDPGSQL_PGSM_CONTAINER': 'pdpgsql_pgsm_pmm_' + str(pdpgsql_version), + 'CLIENT_VERSION': get_value('CLIENT_VERSION', db_type, args, db_config), + 'USE_SOCKET': get_value('USE_SOCKET', db_type, args, db_config), + 'ADMIN_PASSWORD': os.getenv('ADMIN_PASSWORD') or args.pmm_server_password or 'admin', + 'PDPGSQL_PGSM_PORT': 5447, + 'DISTRIBUTION': '', + 'PMM_QA_GIT_BRANCH': os.getenv('PMM_QA_GIT_BRANCH') or 'v3', + 'SETUP_TYPE': setup_type_value + } - # Ansible playbook filename - playbook_filename = 'pdpgsql_pgsm_setup.yml' + # Ansible playbook filename + playbook_filename = 'percona-distribution-postgresql/percona-distribution-postgres-setup.yml' # Call the function to run the Ansible playbook run_ansible_playbook(playbook_filename, env_vars, args) diff --git a/pmm_qa/postgresql/postgresql-setup.yml b/pmm_qa/postgresql/postgresql-setup.yml index 42b14ea7..aa9277ef 100644 --- a/pmm_qa/postgresql/postgresql-setup.yml +++ b/pmm_qa/postgresql/postgresql-setup.yml @@ -64,7 +64,7 @@ POSTGRES_PASSWORD: "{{ root_password }}" volumes: - "{{ data_dir }}/node1/data:/var/lib/postgresql/data" - - "./data/postgresql-primary.conf:/etc/postgresql/postgresql.conf:ro" + - "./data/postgresql-primary.conf.j2:/etc/postgresql/postgresql.conf:ro" - "{{ data_dir }}/node1/pg_hba.conf:/etc/postgresql/pg_hba.conf:ro" command: -c config_file=/etc/postgresql/postgresql.conf ports: @@ -172,7 +172,7 @@ POSTGRES_PASSWORD: "{{ root_password }}" volumes: - "{{ data_dir }}/node{{ item }}/data:/var/lib/postgresql/data" - - "./data/postgres-replica.conf:/etc/postgresql/postgresql.conf:ro" + - "./data/postgresql-replica.conf.j2:/etc/postgresql/postgresql.conf:ro" - "{{ data_dir }}/node1/pg_hba.conf:/etc/postgresql/pg_hba.conf:ro" ports: - "{{ pgsql_port + item - 1 }}:5432" diff --git a/pmm_qa/scripts/database_options.py b/pmm_qa/scripts/database_options.py index b58373fd..a3ebc05e 100644 --- a/pmm_qa/scripts/database_options.py +++ b/pmm_qa/scripts/database_options.py @@ -43,7 +43,7 @@ "SETUP_TYPE": ""} }, "PDPGSQL": { - "versions": ["11", "12", "13", "14", "15", "16", "17"], + "versions": ["11", "12", "13", "14", "15", "16", "18", "17"], "configurations": {"CLIENT_VERSION": "3-dev-latest", "USE_SOCKET": "", "SETUP_TYPE": ""} }, "SSL_PDPGSQL": { diff --git a/pmm_qa/tasks/install_pmm_client.yml b/pmm_qa/tasks/install_pmm_client.yml index 430f2b05..6cae6f38 100644 --- a/pmm_qa/tasks/install_pmm_client.yml +++ b/pmm_qa/tasks/install_pmm_client.yml @@ -16,7 +16,7 @@ - name: Set correct pmm server port set_fact: pmm_server_port: 443 - when: pmm_server_ip | default('') | regex_search('\.') + when: pmm_server_ip | default('') | regex_search('\.') | bool - name: Set correct pmm server port set_fact: