Refactor backup role & store secrets as well

This commit is contained in:
Christian M. Adams
2021-03-25 01:31:18 -04:00
parent 13397f41ad
commit 0a82fec359
9 changed files with 253 additions and 157 deletions

View File

@@ -1,3 +1,8 @@
---
deployment_type: "awx"
tower_postgres_image: postgres:12
# Secret Names
tower_secret_key_secret: "{{ meta.name }}-secret-key"
tower_admin_password_secret: "{{ meta.name }}-admin-password"
# tower_postgres_configuration_secret: "{{ meta.name }}-postgres-configuration"

View File

@@ -0,0 +1,7 @@
---
- name: Test Getting and Storing Secrets (OCP)
hosts: localhost
tasks:
- import_tasks: tasks/secrets.yml

View File

@@ -0,0 +1,9 @@
---
- name: Delete any existing management pod
community.kubernetes.k8s:
name: "{{ meta.name }}-db-management"
kind: Pod
namespace: "{{ meta.namespace }}"
state: absent
force: true

View File

@@ -0,0 +1,54 @@
---
- name: Delete any existing management pod
community.kubernetes.k8s:
name: "{{ meta.name }}-db-management"
kind: Pod
namespace: "{{ meta.namespace }}"
state: absent
force: true
wait: true
# Check to make sure provided pvc exists, error loudly if not. Otherwise, the management pod will just stay in pending state forever.
- name: Check provided PVC exists
k8s_info:
name: "{{ tower_backup_pvc }}"
kind: PersistentVolumeClaim
namespace: "{{ meta.namespace }}"
register: provided_pvc
when:
- tower_backup_pvc != '' or tower_backup_pvc is defined
- name: Fail early if pvc is defined but does not exist
fail:
msg: "{{ tower_backup_pvc }} does not exist, please create this pvc first."
when: provided_pvc.resources | length == 0
# If tower_backup_pvc is defined, use in management-pod.yml.j2
- name: Set default pvc name
set_fact:
_default_backup_pvc: "{{ meta.name }}-backup-claim"
- name: Set PVC to use for backup
set_fact:
backup_pvc: "{{ tower_backup_pvc | default(_default_backup_pvc, true)}}"
# TODO: re-use the old pvc if already created (unless pvc is provided)
# TODO: allow users to configure their own storage class for dynamically creating a pvc?
- name: Create PVC for backup
community.kubernetes.k8s:
kind: PersistentVolumeClaim
namespace: "{{ meta.namespace }}"
template: "backup_pvc.yml.j2"
when:
- tower_backup_pvc == '' or tower_backup_pvc is not defined
- name: Create management pod from templated deployment config
community.kubernetes.k8s:
name: "{{ meta.name }}-db-management"
kind: Deployment
namespace: "{{ meta.namespace }}"
state: present
template: "management-pod.yml.j2"
wait: true

View File

@@ -1,163 +1,14 @@
---
- include_tasks: init.yml
# - include_tasks: init.yml
- include_tasks: postgres.yml
- include_tasks: secrets.yml
- include_tasks: projects.yml
# - include_tasks: postgres.yml
- include_tasks: conf.yml
#
## - include_tasks: conf.yml
#
## - include_tasks: download.yml
- include_tasks: download.yml
- name: Check for specified PostgreSQL configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_postgres_configuration_secret }}'
register: _custom_pg_config_resources
when: tower_postgres_configuration_secret | length
- name: Check for default PostgreSQL configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-postgres-configuration'
register: _default_pg_config_resources
- name: Set PostgreSQL configuration
set_fact:
pg_config: '{{ _custom_pg_config_resources["resources"] | default([]) | length | ternary(_custom_pg_config_resources, _default_pg_config_resources) }}'
- name: Store Database Configuration
set_fact:
awx_postgres_user: "{{ pg_config['resources'][0]['data']['username'] | b64decode }}"
awx_postgres_pass: "{{ pg_config['resources'][0]['data']['password'] | b64decode }}"
awx_postgres_database: "{{ pg_config['resources'][0]['data']['database'] | b64decode }}"
awx_postgres_port: "{{ pg_config['resources'][0]['data']['port'] | b64decode }}"
awx_postgres_host: "{{ pg_config['resources'][0]['data']['host'] | b64decode }}"
- name: Get the postgres pod information
k8s_info:
kind: Pod
namespace: '{{ meta.namespace }}'
label_selectors:
- "app={{ meta.name }}-postgres"
register: postgres_pod
until: "postgres_pod['resources'][0]['status']['phase'] == 'Running'"
delay: 5
retries: 60
- name: Set the resource pod name as a variable.
set_fact:
postgres_pod_name: "{{ postgres_pod['resources'][0]['metadata']['name'] }}"
- name: Determine the timestamp for the backup once for all nodes
set_fact:
now: '{{ lookup("pipe", "date +%F-%T") }}'
- name: Delete any existing management pod
community.kubernetes.k8s:
name: "{{ meta.name }}-db-management"
kind: Pod
namespace: "{{ meta.namespace }}"
state: absent
force: true
wait: true
# Check to make sure provided pvc exists, error loudly if not. Otherwise, the management pod will just stay in pending state forever.
- name: Check provided PVC exists
k8s_info:
name: "{{ tower_backup_pvc }}"
kind: PersistentVolumeClaim
namespace: "{{ meta.namespace }}"
register: provided_pvc
when:
- tower_backup_pvc != '' or tower_backup_pvc is defined
- name: Fail early if pvc is defined but does not exist
fail:
msg: "{{ tower_backup_pvc }} does not exist, please create this pvc first."
when: provided_pvc.resources | length == 0
# If tower_backup_pvc is defined, use in management-pod.yml.j2
- name: Set default pvc name
set_fact:
_default_backup_pvc: "{{ meta.name }}-backup-claim"
- name: Set PVC to use for backup
set_fact:
backup_pvc: "{{ tower_backup_pvc | default(_default_backup_pvc, true)}}"
# TODO: re-use the old pvc if already created (unless pvc is provided)
# TODO: allow users to configure their own storage class for dynamically creating a pvc?
- name: Create PVC for backup
community.kubernetes.k8s:
kind: PersistentVolumeClaim
namespace: "{{ meta.namespace }}"
template: "backup_pvc.yml.j2"
when:
- tower_backup_pvc == '' or tower_backup_pvc is not defined
- name: Create management pod from templated deployment config
community.kubernetes.k8s:
name: "{{ meta.name }}-db-management"
kind: Deployment
namespace: "{{ meta.namespace }}"
state: present
template: "management-pod.yml.j2"
wait: true
- name: Set backup directory name
set_fact:
_backup_dir: "/backups/tower-openshift-backup-{{ now }}"
- name: Create directory for backup
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ meta.name }}-db-management"
command: >-
mkdir -p {{ _backup_dir }}
- name: Precreate file for database dump
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ meta.name }}-db-management"
command: >-
touch {{ _backup_dir }}/tower.db
- name: Set permissions on file for database dump
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ meta.name }}-db-management"
command: >-
chmod 0600 {{ _backup_dir }}/tower.db
- name: Set pg_dump command
set_fact:
pgdump: >-
pg_dump --clean --create
-h {{ awx_postgres_host }}
-U {{ awx_postgres_user }}
-d {{ awx_postgres_database }}
-p {{ awx_postgres_port }}
- name: Write pg_dump to backup on PVC
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ meta.name }}-db-management"
command: >-
bash -c "PGPASSWORD={{ awx_postgres_pass }} {{ pgdump }} > {{ _backup_dir }}/tower.db"
register: data_migration
# TODO: Backup secret key and other secrets - look at trad tower backup pattern
# TODO: Compare final backup tar with one from a trad tower
- name: Delete any existing management pod
community.kubernetes.k8s:
name: "{{ meta.name }}-db-management"
kind: Pod
namespace: "{{ meta.namespace }}"
state: absent
force: true
- include_tasks: cleanup.yml

View File

@@ -0,0 +1,91 @@
---
- name: Check for specified PostgreSQL configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_postgres_configuration_secret }}'
register: _custom_pg_config_resources
when: tower_postgres_configuration_secret | length
- name: Check for default PostgreSQL configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-postgres-configuration'
register: _default_pg_config_resources
- name: Set PostgreSQL configuration
set_fact:
pg_config: '{{ _custom_pg_config_resources["resources"] | default([]) | length | ternary(_custom_pg_config_resources, _default_pg_config_resources) }}'
- name: Store Database Configuration
set_fact:
awx_postgres_user: "{{ pg_config['resources'][0]['data']['username'] | b64decode }}"
awx_postgres_pass: "{{ pg_config['resources'][0]['data']['password'] | b64decode }}"
awx_postgres_database: "{{ pg_config['resources'][0]['data']['database'] | b64decode }}"
awx_postgres_port: "{{ pg_config['resources'][0]['data']['port'] | b64decode }}"
awx_postgres_host: "{{ pg_config['resources'][0]['data']['host'] | b64decode }}"
- name: Get the postgres pod information
k8s_info:
kind: Pod
namespace: '{{ meta.namespace }}'
label_selectors:
- "app={{ meta.name }}-{{ deployment_type }}-postgres"
register: postgres_pod
until: "postgres_pod['resources'][0]['status']['phase'] == 'Running'"
delay: 5
retries: 60
- name: Set the resource pod name as a variable.
set_fact:
postgres_pod_name: "{{ postgres_pod['resources'][0]['metadata']['name'] }}"
- name: Determine the timestamp for the backup once for all nodes
set_fact:
now: '{{ lookup("pipe", "date +%F-%T") }}'
- name: Set backup directory name
set_fact:
_backup_dir: "/backups/tower-openshift-backup-{{ now }}"
- name: Create directory for backup
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ meta.name }}-db-management"
command: >-
mkdir -p {{ _backup_dir }}
- name: Precreate file for database dump
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ meta.name }}-db-management"
command: >-
touch {{ _backup_dir }}/tower.db
- name: Set permissions on file for database dump
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ meta.name }}-db-management"
command: >-
chmod 0600 {{ _backup_dir }}/tower.db
- name: Set pg_dump command
set_fact:
pgdump: >-
pg_dump --clean --create
-h {{ awx_postgres_host }}
-U {{ awx_postgres_user }}
-d {{ awx_postgres_database }}
-p {{ awx_postgres_port }}
- name: Write pg_dump to backup on PVC
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ meta.name }}-db-management"
command: >-
bash -c "PGPASSWORD={{ awx_postgres_pass }} {{ pgdump }} > {{ _backup_dir }}/tower.db"
register: data_migration
# TODO: Backup secret key and other secrets - look at trad tower backup pattern
# TODO: Compare final backup tar with one from a trad tower

View File

@@ -0,0 +1,59 @@
---
# TODO: Get Secret_key value/s
# TODO: Store Secret_key value/s in a way that can be made into another secret upon restore
# The general idea here is that the user provides the name for the current deployment, we grab secrets based on that, then when it is restored, we restore to whatever name/namespace is specified at the time of restore
- name: Make _secrets directory
file:
path: "{{ playbook_dir }}/_secrets"
state: directory
- name: Get secret_key
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_secret_key_secret }}'
register: _secret_key
- name: Set secret key
set_fact:
secret_key: "{{ _secret_key['resources'][0]['data']['secret_key'] | b64decode }}"
- name: Template secret_key definition
template:
src: secret_key.yml.j2
dest: "{{ playbook_dir }}/_secrets/secrets.yml"
mode: '0600'
# dest: pvc # potentially just do a copy task, loop through definition files
- name: Get admin_password
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_admin_password_secret }}'
register: _admin_password
# TODO: check if admin_password secret name is provided, and check for that? use defaults.yml
- name: Set admin_password
set_fact:
admin_password: "{{ _admin_password['resources'][0]['data']['password'] | b64decode }}"
- name: Template admin_password definition
template:
src: admin_password.yml.j2
dest: "{{ playbook_dir }}/_secrets/admin_password.yml"
mode: '0600'
# TODO: Secrets to back up: tower-secret-key, tower1-admin-password, tower1-app-credentials, tower1-broadcast-websocket, tower1-dockercfg-q8qd2, tower1-postgres-configuration
# Do we need the service-account-token? probably? `tower1-token-hn2hm`, tower1-token-slllw
# After copying secret files to the PVC, delete the local tmp copies
- name: Clean up _secrets directory
ansible.builtin.file:
path: "{{ playbook_dir }}/_secrets"
state: absent

View File

@@ -0,0 +1,10 @@
---
apiVersion: v1
kind: Secret
metadata:
{% raw %}
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
{% endraw %}
stringData:
password: '{{ admin_password }}'

View File

@@ -0,0 +1,10 @@
---
apiVersion: v1
kind: Secret
metadata:
{% raw %}
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
{% endraw %}
stringData:
secret_key: '{{ secret_key }}'