diff --git a/create-database-backup.yml b/create-database-backup.yml new file mode 100644 index 0000000..a3107e1 --- /dev/null +++ b/create-database-backup.yml @@ -0,0 +1,126 @@ +--- + +# creates database backup +# - postgres +# - executed on stage specific server: {{ stage }}-postgres-01 +# - creates database backup for specifix database + +# Parameters: +# playbook inventory +# stage := the type of the stage (e.g. dev, int, qa, prod) +# tenant_id := (unique key for the tenant, e.g. customer) +# cluster_name := (business name for the cluster, e.g. product, department ) +# cluster_size := (WIP node count for the cluster) (Currently max is 2 master/slave) +# cluster_services_str := (services to setup, e.g. 'connect,wordpress') +# custom_backup_name := defines a substring for backup file => {{ stage }}_{{ tenant_id }}_{{ cluster_name }}_{{ cluster_services_str }}__gehtdichnixan.sql +# smardigo message callback +# scope_id := (scope id of the management process) +# process_instance_id := (process instance id of the management process) +# smardigo_management_action := (smardigo management action anme of the management process) + +############################################################# +# Creating inventory dynamically for given parameters +############################################################# + +- hosts: localhost + gather_facts: false + connection: local + + pre_tasks: + - name: "Check if ansible version is at least 2.10.x" + assert: + that: + - ansible_version.major >= 2 + - ansible_version.minor >= 10 + msg: "The ansible version has to be at least ({{ ansible_version.full }})" + + - set_fact: + cluster_services: "{{ cluster_services_str | split(',') }}" + + tasks: + - name: "Add postgres servers to hosts if necessary" + add_host: + name: "{{ stage }}-postgres-01" + groups: + - "stage_{{ stage }}" + - "{{ item }}" + changed_when: False + with_items: "{{ cluster_services }}" + when: item in ['connect', 'management_connect', 'keycloak', 'webdav', 'gitea', 'workflow_index', 'workflow_proxy'] + +############################################################# +# create database backup +############################################################# + +- hosts: "stage_{{ stage }}" + serial: "{{ serial_number | default(1) }}" + remote_user: root + vars: + ansible_ssh_host: "{{ stage_server_domain }}" + + roles: + - role: connect-postgres + vars: + database_create: False + database_backup: True + when: "'connect' in group_names" + + - role: gitea-postgres + vars: + database_create: False + database_backup: True + when: "'gitea' in group_names" + + - role: keycloak-postgres + vars: + database_create: False + database_backup: True + when: "'keycloak' in group_names" + + - role: webdav-postgres + vars: + database_create: False + database_backup: True + when: "'webdav' in group_names" + + - role: workflow-index-postgres + vars: + database_create: False + database_backup: True + when: "'workflow_index' in group_names" + + - role: workflow-proxy-postgres + vars: + database_create: False + database_backup: True + when: "'workflow_proxy' in group_names" + +############################################################# +# Sending smardigo management message to process +############################################################# + +- hosts: "stage_{{ stage }}" + serial: "{{ serial_number | default(1) }}" + gather_facts: false + connection: local + run_once: true + + tasks: + - name: "Sending smardigo management message <{{ smardigo_management_action }}> to <{{ scope_id }}/{{ process_instance_id }}>" + uri: + url: "{{ smardigo_management_url }}" + method: POST + body_format: json + body: "{{ lookup('template','smardigo-management-message.json.j2') }}" + headers: + accept: "*/*" + Content-Type: "application/json" + Smardigo-User-Token: "{{ smardigo_management_token }}" + status_code: [200] + delegate_to: 127.0.0.1 + retries: 5 + delay: 5 + when: + - scope_id is defined + - process_instance_id is defined + - smardigo_management_action is defined diff --git a/evil-remove-server.yml b/evil-remove-server.yml new file mode 100644 index 0000000..26c83ca --- /dev/null +++ b/evil-remove-server.yml @@ -0,0 +1,50 @@ +--- +- hosts: '{{ host | default("all") }}' + serial: "{{ serial_number | default(5) }}" + vars: + ansible_ssh_host: "{{ stage_server_domain }}" + become: yes + gather_facts: no + + vars_prompt: + - name: "check_deleting" + prompt: "Are you sure to delete the following servers: {{ play_hosts }}? yes / no(default) " + private: no + default: 'no' + - name: "check_deleting_2nd" + prompt: "Are you COMPLETELY sure to delete them: {{ play_hosts }}? yes / no(default) " + private: no + default: 'no' + + pre_tasks: + - name: "Check if ansible version is at least 2.10.x" + assert: + that: + - ansible_version.major >= 2 + - ansible_version.minor >= 10 + msg: "The ansible version has to be at least ({{ ansible_version.full }})" + delegate_to: 127.0.0.1 + become: false + + - name: "Import autodiscover pre-tasks" + include_tasks: tasks/autodiscover_pre_tasks.yml + tags: + - always + + tasks: + - block: + - name: "Delete server <{{ inventory_hostname }}>" + include_role: + name: hcloud + tasks_from: _set_server_state + vars: + - server_state: "absent" + - name: "Delete DNS entry <{{ inventory_hostname }}> for <{{ domain }}>" + include_role: + name: _digitalocean + tasks_from: _remove_dns + vars: + record_to_remove: '{{ inventory_hostname }}' + when: + - check_deleting == 'yes' + - check_deleting_2nd == 'yes' diff --git a/restore-database-backup.yml b/restore-database-backup.yml new file mode 100644 index 0000000..98ec9f3 --- /dev/null +++ b/restore-database-backup.yml @@ -0,0 +1,132 @@ +--- + +# restores a database backup +# - postgres +# - executed on stage specific server: {{ stage }}-postgres-01 +# - restores a database backup + +# Parameters: +# playbook inventory +# stage := the type of the stage (e.g. dev, int, qa, prod) +# tenant_id := (unique key for the tenant, e.g. customer) +# cluster_name := (business name for the cluster, e.g. product, department ) +# cluster_size := (WIP node count for the cluster) (Currently max is 2 master/slave) +# cluster_services_str := (services to setup, e.g. 'connect,wordpress') +# custom_backup_name := defines a substring for backup file => {{ stage }}_{{ tenant_id }}_{{ cluster_name }}_{{ cluster_services_str }}__gehtdichnixan.sql +# smardigo message callback +# scope_id := (scope id of the management process) +# process_instance_id := (process instance id of the management process) +# smardigo_management_action := (smardigo management action anme of the management process) + +############################################################# +# Creating inventory dynamically for given parameters +############################################################# + +- hosts: localhost + gather_facts: false + connection: local + + pre_tasks: + - name: "Check if ansible version is at least 2.10.x" + assert: + that: + - ansible_version.major >= 2 + - ansible_version.minor >= 10 + msg: "The ansible version has to be at least ({{ ansible_version.full }})" + + - set_fact: + cluster_services: "{{ cluster_services_str | split(',') }}" + + tasks: + - name: "Add postgres servers to hosts if necessary" + add_host: + name: "{{ stage }}-postgres-01" + groups: + - "stage_{{ stage }}" + - "{{ item }}" + changed_when: False + with_items: "{{ cluster_services }}" + when: item in ['connect', 'management_connect', 'keycloak', 'webdav', 'gitea', 'workflow_index', 'workflow_proxy'] + +############################################################# +# Setup databases for created inventory +############################################################# + +- hosts: "stage_{{ stage }}" + serial: "{{ serial_number | default(1) }}" + remote_user: root + vars: + ansible_ssh_host: "{{ stage_server_domain }}" + + roles: + - role: connect-postgres + vars: + database_create: False + database_backup: False + database_restore: True + when: "'connect' in group_names" + + - role: gitea-postgres + vars: + database_create: False + database_backup: False + database_restore: True + when: "'gitea' in group_names" + + - role: keycloak-postgres + vars: + database_create: False + database_backup: False + database_restore: True + when: "'keycloak' in group_names" + + - role: webdav-postgres + vars: + database_create: False + database_backup: False + database_restore: True + when: "'webdav' in group_names" + + - role: workflow-index-postgres + vars: + database_create: False + database_backup: False + database_restore: True + when: "'workflow_index' in group_names" + + - role: workflow-proxy-postgres + vars: + database_create: False + database_backup: False + database_restore: True + when: "'workflow_proxy' in group_names" + +############################################################# +# Sending smardigo management message to process +############################################################# + +- hosts: "stage_{{ stage }}" + serial: "{{ serial_number | default(1) }}" + gather_facts: false + connection: local + run_once: true + + tasks: + - name: "Sending smardigo management message <{{ smardigo_management_action }}> to <{{ scope_id }}/{{ process_instance_id }}>" + uri: + url: "{{ smardigo_management_url }}" + method: POST + body_format: json + body: "{{ lookup('template','smardigo-management-message.json.j2') }}" + headers: + accept: "*/*" + Content-Type: "application/json" + Smardigo-User-Token: "{{ smardigo_management_token }}" + status_code: [200] + delegate_to: 127.0.0.1 + retries: 5 + delay: 5 + when: + - scope_id is defined + - process_instance_id is defined + - smardigo_management_action is defined diff --git a/roles/connect-postgres/defaults/main.yml b/roles/connect-postgres/defaults/main.yml index 2f51301..2ad8c06 100644 --- a/roles/connect-postgres/defaults/main.yml +++ b/roles/connect-postgres/defaults/main.yml @@ -4,3 +4,7 @@ postgres_acls: - name: "{{ connect_postgres_database }}" password: "{{ connect_postgres_password }}" trusted_cidr_entry: "{{ shared_service_network }}" + +database_create: True +database_backup: False +database_restore: False diff --git a/roles/connect-postgres/tasks/main.yml b/roles/connect-postgres/tasks/main.yml index 4c21e56..f766ee4 100644 --- a/roles/connect-postgres/tasks/main.yml +++ b/roles/connect-postgres/tasks/main.yml @@ -7,3 +7,19 @@ include_role: name: postgres tasks_from: _postgres-acls + when: + - database_create + +- name: "Create postgres backup" + include_role: + name: postgres + tasks_from: _create-backup + when: + - database_backup + +- name: "Restore postgres backup" + include_role: + name: postgres + tasks_from: _restore-backup + when: + - database_restore diff --git a/roles/gitea-postgres/defaults/main.yml b/roles/gitea-postgres/defaults/main.yml index 20b08ba..236b1f2 100644 --- a/roles/gitea-postgres/defaults/main.yml +++ b/roles/gitea-postgres/defaults/main.yml @@ -4,3 +4,7 @@ postgres_acls: - name: "{{ gitea_postgres_database }}" password: "{{ gitea_postgres_password }}" trusted_cidr_entry: "{{ shared_service_network }}" + +database_create: True +database_backup: False +database_restore: False diff --git a/roles/gitea-postgres/tasks/main.yml b/roles/gitea-postgres/tasks/main.yml index 4c21e56..f766ee4 100644 --- a/roles/gitea-postgres/tasks/main.yml +++ b/roles/gitea-postgres/tasks/main.yml @@ -7,3 +7,19 @@ include_role: name: postgres tasks_from: _postgres-acls + when: + - database_create + +- name: "Create postgres backup" + include_role: + name: postgres + tasks_from: _create-backup + when: + - database_backup + +- name: "Restore postgres backup" + include_role: + name: postgres + tasks_from: _restore-backup + when: + - database_restore diff --git a/roles/keycloak-postgres/defaults/main.yml b/roles/keycloak-postgres/defaults/main.yml index 46a4be6..6e3df88 100644 --- a/roles/keycloak-postgres/defaults/main.yml +++ b/roles/keycloak-postgres/defaults/main.yml @@ -4,3 +4,7 @@ postgres_acls: - name: "{{ keycloak_postgres_database }}" password: "{{ keycloak_postgres_password }}" trusted_cidr_entry: "{{ shared_service_network }}" + +database_create: True +database_backup: False +database_restore: False diff --git a/roles/keycloak-postgres/tasks/main.yml b/roles/keycloak-postgres/tasks/main.yml index 4c21e56..f766ee4 100644 --- a/roles/keycloak-postgres/tasks/main.yml +++ b/roles/keycloak-postgres/tasks/main.yml @@ -7,3 +7,19 @@ include_role: name: postgres tasks_from: _postgres-acls + when: + - database_create + +- name: "Create postgres backup" + include_role: + name: postgres + tasks_from: _create-backup + when: + - database_backup + +- name: "Restore postgres backup" + include_role: + name: postgres + tasks_from: _restore-backup + when: + - database_restore diff --git a/roles/postgres/defaults/main.yml b/roles/postgres/defaults/main.yml index d7e328d..a307aa4 100644 --- a/roles/postgres/defaults/main.yml +++ b/roles/postgres/defaults/main.yml @@ -9,3 +9,7 @@ default_shared_buffers: 256MB postgres_listen_addresses: "listen_addresses = 'localhost,{{ stage_private_server_ip }}'" database_state: present + +database_create: True +database_backup: False +database_restore: False diff --git a/roles/postgres/tasks/_create-backup.yml b/roles/postgres/tasks/_create-backup.yml new file mode 100644 index 0000000..2de157f --- /dev/null +++ b/roles/postgres/tasks/_create-backup.yml @@ -0,0 +1,19 @@ +--- +- set_fact: + backup_path: "/backups" + +- name: "Create backup directory" + file: + path: "{{ backup_path }}" + state: directory + owner: "postgres" + group: "postgres" + +- name: "Creating backup ${dbname}__{{ custom_backup_name }}.sql ..." + become: true + become_user: postgres + postgresql_db: + name: "{{ item.name }}" + state: dump + target: "{{ backup_path }}/{{ item.name }}__{{ custom_backup_name }}.sql" + loop: "{{ postgres_acls }}" diff --git a/roles/postgres/tasks/_restore-backup.yml b/roles/postgres/tasks/_restore-backup.yml new file mode 100644 index 0000000..421c08c --- /dev/null +++ b/roles/postgres/tasks/_restore-backup.yml @@ -0,0 +1,9 @@ +--- +- name: "Restoring backup ${dbname}__{{ custom_backup_name }}.sql ..." + become: true + become_user: postgres + postgresql_db: + name: "{{ item.name }}" + state: restore + target: "{{ backup_directory }}/{{ item.name }}__{{ custom_backup_name }}.sql" + loop: "{{ postgres_acls }}" diff --git a/roles/postgres/tasks/base-requirements_backup.yml b/roles/postgres/tasks/base-requirements_backup.yml new file mode 100644 index 0000000..90f8be6 --- /dev/null +++ b/roles/postgres/tasks/base-requirements_backup.yml @@ -0,0 +1,58 @@ +--- +- name: creating some hcloud volumes for backup purpose + delegate_to: localhost + become: false + hcloud_volume: + api_token: "{{ hetzner_authentication_token }}" + name: "postgres-backup--{{ inventory_hostname }}--vol{{ item }}" + server: "{{ inventory_hostname }}" + labels: + stage: "{{ stage }}" + used_for: "{{ inventory_hostname }}" + size: 10 + state: present + delete_protection: yes + loop: "{{ range(1,2) | list }}" + register: created_volume + +- name: getting all hcloud volumes for + delegate_to: localhost + become: false + hcloud_volume_info: + api_token: "{{ hetzner_authentication_token }}" + label_selector: "stage={{ stage }},used_for={{ inventory_hostname }}" + register: hcloud_volumes_found + +- set_fact: + pvs: "{{ hcloud_volumes_found.hcloud_volume_info | json_query(jmesquery) }}" + vg_name: vg.postgres_backup + lv_name: lv.postgres_backup + vars: + jmesquery: "[*].linux_device" + +- name: Create a volume group on top of all found hcloud volumes + community.general.lvg: + vg: "{{ vg_name }}" + pvs: "{{ pvs }}" + pvresize: yes + register: create_vg + +- name: Create logical volume + community.general.lvol: + vg: "{{ vg_name }}" + lv: "{{ lv_name }}" + size: '100%FREE' + when: + - create_vg.changed + +- name: format volume + filesystem: + fstype: ext4 + dev: "/dev/{{ vg_name }}/{{ lv_name }}" + +- name: mount created LVM volume + mount: + path: "{{ backup_directory }}" + src: "/dev/{{ vg_name }}/{{ lv_name }}" + fstype: ext4 + state: mounted diff --git a/roles/postgres/tasks/main.yml b/roles/postgres/tasks/main.yml index 6ac3848..4c1253f 100644 --- a/roles/postgres/tasks/main.yml +++ b/roles/postgres/tasks/main.yml @@ -11,7 +11,28 @@ include_tasks: master-requirements.yml when: server_type == "master" +# Master requirements for postgres +- name: Include Master Requirements + include_tasks: base-requirements_backup.yml + when: server_type == "master" + # Slave requirements for postgres - name: Include Slave Requirements include_tasks: slave-requirements.yml when: server_type == "slave" + when: + - database_create + +- name: "Create postgres backup" + include_role: + name: postgres + tasks_from: _create-backup + when: + - database_backup + +- name: "Restore postgres backup" + include_role: + name: postgres + tasks_from: _restore-backup + when: + - database_restore diff --git a/roles/webdav-postgres/defaults/main.yml b/roles/webdav-postgres/defaults/main.yml index 6fa6b7e..783916b 100644 --- a/roles/webdav-postgres/defaults/main.yml +++ b/roles/webdav-postgres/defaults/main.yml @@ -4,3 +4,7 @@ postgres_acls: - name: "{{ webdav_postgres_database }}" password: "{{ webdav_postgres_password }}" trusted_cidr_entry: "{{ shared_service_network }}" + +database_create: True +database_backup: False +database_restore: False diff --git a/roles/webdav-postgres/tasks/main.yml b/roles/webdav-postgres/tasks/main.yml index 334cbeb..329b98b 100644 --- a/roles/webdav-postgres/tasks/main.yml +++ b/roles/webdav-postgres/tasks/main.yml @@ -6,3 +6,19 @@ include_role: name: postgres tasks_from: _postgres-acls + when: + - database_create + +- name: "Create postgres backup" + include_role: + name: postgres + tasks_from: _create-backup + when: + - database_backup + +- name: "Restore postgres backup" + include_role: + name: postgres + tasks_from: _restore-backup + when: + - database_restore diff --git a/roles/workflow-index-postgres/defaults/main.yml b/roles/workflow-index-postgres/defaults/main.yml index 56c7701..145b47b 100644 --- a/roles/workflow-index-postgres/defaults/main.yml +++ b/roles/workflow-index-postgres/defaults/main.yml @@ -7,3 +7,7 @@ postgres_acls: - name: "{{ workflow_index_postgres_database }}" password: "{{ workflow_index_postgres_password }}" trusted_cidr_entry: "{{ shared_service_network }}" + +database_create: True +database_backup: False +database_restore: False diff --git a/roles/workflow-index-postgres/tasks/main.yml b/roles/workflow-index-postgres/tasks/main.yml index f80676b..453d894 100644 --- a/roles/workflow-index-postgres/tasks/main.yml +++ b/roles/workflow-index-postgres/tasks/main.yml @@ -7,3 +7,19 @@ include_role: name: postgres tasks_from: _postgres-acls + when: + - database_create + +- name: "Create postgres backup" + include_role: + name: postgres + tasks_from: _create-backup + when: + - database_backup + +- name: "Restore postgres backup" + include_role: + name: postgres + tasks_from: _restore-backup + when: + - database_restore diff --git a/roles/workflow-proxy-postgres/defaults/main.yml b/roles/workflow-proxy-postgres/defaults/main.yml index 3e1583e..b06ace8 100644 --- a/roles/workflow-proxy-postgres/defaults/main.yml +++ b/roles/workflow-proxy-postgres/defaults/main.yml @@ -7,3 +7,7 @@ postgres_acls: - name: "{{ workflow_proxy_postgres_database }}" password: "{{ workflow_proxy_postgres_password }}" trusted_cidr_entry: "{{ shared_service_network }}" + +database_create: True +database_backup: False +database_restore: False diff --git a/roles/workflow-proxy-postgres/tasks/main.yml b/roles/workflow-proxy-postgres/tasks/main.yml index f80676b..453d894 100644 --- a/roles/workflow-proxy-postgres/tasks/main.yml +++ b/roles/workflow-proxy-postgres/tasks/main.yml @@ -7,3 +7,19 @@ include_role: name: postgres tasks_from: _postgres-acls + when: + - database_create + +- name: "Create postgres backup" + include_role: + name: postgres + tasks_from: _create-backup + when: + - database_backup + +- name: "Restore postgres backup" + include_role: + name: postgres + tasks_from: _restore-backup + when: + - database_restore