diff --git a/roles/backup/tasks/cleanup.yml b/roles/backup/tasks/cleanup.yml index 11dc6d07..3cfc89c9 100644 --- a/roles/backup/tasks/cleanup.yml +++ b/roles/backup/tasks/cleanup.yml @@ -3,10 +3,9 @@ # After copying secret files to the PVC, delete the local tmp copies - name: Clean up _secrets directory ansible.builtin.file: - path: "{{ playbook_dir }}/_secrets" + path: "_secrets" state: absent - - name: Delete any existing management pod community.kubernetes.k8s: name: "{{ meta.name }}-db-management" diff --git a/roles/backup/tasks/postgres.yml b/roles/backup/tasks/postgres.yml index 80a933a2..a8eb5ec5 100644 --- a/roles/backup/tasks/postgres.yml +++ b/roles/backup/tasks/postgres.yml @@ -69,7 +69,7 @@ namespace: "{{ tower_backup_pvc_namespace }}" pod: "{{ meta.name }}-db-management" command: >- - chmod 0600 {{ backup_dir }}/tower.db + chmod 0600 {{ backup_dir }}/tower.db && chown postgres:root {{ backup_dir }}/tower.db - name: Set pg_dump command set_fact: diff --git a/roles/backup/tasks/secrets.yml b/roles/backup/tasks/secrets.yml index 2e62a88f..c7b8a520 100644 --- a/roles/backup/tasks/secrets.yml +++ b/roles/backup/tasks/secrets.yml @@ -21,7 +21,7 @@ template: src: secret_key_secret.yml.j2 dest: "_secrets/secret_key_secret.yml" - mode: '0600' + mode: '0700' - name: Set secret key template set_fact: @@ -49,7 +49,7 @@ template: src: admin_password_secret.yml.j2 dest: "_secrets/admin_password_secret.yml" - mode: '0600' + mode: '0700' - name: Set admin_password template set_fact: @@ -77,7 +77,7 @@ template: src: broadcast_websocket_secret.yml.j2 dest: "_secrets/broadcast_websocket_secret.yml" - mode: '0600' + mode: '0700' - name: Set broadcast_websocket template set_fact: @@ -110,7 +110,7 @@ template: src: postgres_secret.yml.j2 dest: "_secrets/postgres_secret.yml" - mode: '0600' + mode: '0700' - name: Set postgres configuration set_fact: diff --git a/roles/restore/README.md b/roles/restore/README.md index 1325c402..ae262c11 100644 --- a/roles/restore/README.md +++ b/roles/restore/README.md @@ -33,7 +33,13 @@ spec: tower_backup_dir: /backups/tower-openshift-backup-2021-04-02-03:25:08 ``` -Note that the `tower_name` above is the name of the AWX deployment you intend to create and restore to. +Note that the `tower_name` above is the name of the AWX deployment you intend to create and restore to. + +The namespace specified is the namespace the resulting AWX deployment will be in. The namespace you specified must be pre-created. + +``` +kubectl create ns my-namespace +``` Finally, use `kubectl` to create the restore object in your cluster: diff --git a/roles/restore/defaults/main.yml b/roles/restore/defaults/main.yml index 3bafde7e..29a91b76 100644 --- a/roles/restore/defaults/main.yml +++ b/roles/restore/defaults/main.yml @@ -6,6 +6,7 @@ tower_name: '' tower_backup_pvc: '' tower_backup_pvc_namespace: 'default' +# TODO: If the backup_dir is not provided, it should default to the most recent backup based on the timestamp at the end of the file name. # Required: backup name, found on the awxbackup object tower_backup_dir: '' diff --git a/roles/restore/tasks/apply_secret.yml b/roles/restore/tasks/apply_secret.yml new file mode 100644 index 00000000..69e87505 --- /dev/null +++ b/roles/restore/tasks/apply_secret.yml @@ -0,0 +1,24 @@ +--- + +- name: Get secret definition from pvc + community.kubernetes.k8s_exec: + namespace: "{{ tower_backup_pvc_namespace }}" + pod: "{{ meta.name }}-db-management" + command: >- + bash -c "cat '{{ tower_backup_dir }}/{{ item }}.yml'" + register: awx_object + +- name: Write temp secret definition template file + copy: + dest: "_definitions/{{ item }}.yml.j2" + content: | + {{ awx_object.stdout }} + mode: '0600' + +- name: Apply secret + k8s: + state: "{{ state | default('present') }}" + namespace: "{{ namespace | default('default') }}" + apply: yes + wait: yes + template: "_definitions/{{ item }}.yml.j2" diff --git a/roles/restore/tasks/cleanup.yml b/roles/restore/tasks/cleanup.yml index 7b094f32..e9ea732e 100644 --- a/roles/restore/tasks/cleanup.yml +++ b/roles/restore/tasks/cleanup.yml @@ -1,5 +1,10 @@ --- +- name: Clean up _secrets directory + ansible.builtin.file: + path: "_definitions" + state: absent + - name: Delete any existing management pod community.kubernetes.k8s: name: "{{ meta.name }}-db-management" diff --git a/roles/restore/tasks/init.yml b/roles/restore/tasks/init.yml index f650a568..c6a500bb 100644 --- a/roles/restore/tasks/init.yml +++ b/roles/restore/tasks/init.yml @@ -1,13 +1,12 @@ --- +- name: Set default pvc name + set_fact: + _default_backup_pvc: "{{ meta.name }}-backup-claim" -- name: Delete any existing management pod - community.kubernetes.k8s: - name: "{{ meta.name }}-db-management" - kind: Pod - namespace: "{{ tower_backup_pvc_namespace }}" - state: absent - force: true - wait: true +# by default, it will re-use the old pvc if already created (unless pvc is provided) +- name: Set PVC to use for backup + set_fact: + backup_pvc: "{{ tower_backup_pvc | default(_default_backup_pvc, 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 @@ -30,20 +29,19 @@ - name: Fail early if pvc is defined but does not exist fail: - msg: "{{ tower_backup_pvc }} does not exist, please create this pvc first." + msg: "{{ error_msg }}" when: - tower_backup_pvc != '' - 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" - -# by default, it will re-use the old pvc if already created (unless pvc is provided) -- name: Set PVC to use for backup - set_fact: - backup_pvc: "{{ tower_backup_pvc | default(_default_backup_pvc, true) }}" +- name: Delete any existing management pod + community.kubernetes.k8s: + name: "{{ meta.name }}-db-management" + kind: Pod + namespace: "{{ tower_backup_pvc_namespace }}" + state: absent + force: true + wait: true - name: Create management pod from templated deployment config community.kubernetes.k8s: @@ -52,3 +50,36 @@ state: present template: "management-pod.yml.j2" wait: true + +- name: Check to make sure backup directory exists on PVC + community.kubernetes.k8s_exec: + namespace: "{{ tower_backup_pvc_namespace }}" + pod: "{{ meta.name }}-db-management" + command: >- + bash -c "stat {{ tower_backup_dir }}" + register: stat_backup_dir + +- debug: + msg: "{{stat_backup_dir}}" + +- name: Error if backup dir is missing + block: + - name: Set error message + set_fact: + error_msg: "{{ tower_backup_dir }} does not exist, see the towerBackupDirectory status on your AWXBackup for the correct tower_backup_dir." + + - name: Handle error + import_tasks: error_handling.yml + + - name: Fail early if backup dir provided does not exist + fail: + msg: "{{ error_msg }}" + when: + - tower_backup_dir != '' + - stat_backup_dir.return_code != 0 + +- name: Make _definitions directory + file: + path: "_definitions" + state: directory + mode: '0700' diff --git a/roles/restore/tasks/init_awx.yml b/roles/restore/tasks/init_awx.yml index be72f5cb..47c74322 100644 --- a/roles/restore/tasks/init_awx.yml +++ b/roles/restore/tasks/init_awx.yml @@ -1,11 +1,31 @@ --- + +- name: Get AWX object definition from pvc + community.kubernetes.k8s_exec: + namespace: "{{ tower_backup_pvc_namespace }}" + pod: "{{ meta.name }}-db-management" + command: >- + bash -c "cat '{{ tower_backup_dir }}/awx_object.yml'" + register: awx_object + +- name: Write temp AWX definition template file + copy: + dest: "_definitions/awx_object.yml.j2" + content: | + {{ awx_object.stdout }} + mode: '0600' + - name: Deploy AWX k8s: state: "{{ state | default('present') }}" namespace: "{{ namespace | default('default') }}" apply: yes wait: yes - template: "{{ tower_backup_dir }}/awx_object.yml" + template: "_definitions/awx_object.yml.j2" + wait: true + + +# TODO: The awx object and secrets need to be applied from the awx-operator, because that is where the service account is?. So we will need to either copy them over or pipe them into a template command # TODO: Add logic to allow users to provide override values here, # or to specify spec values that were not in the backed up AWX object. diff --git a/roles/restore/tasks/init_secrets.yml b/roles/restore/tasks/init_secrets.yml new file mode 100644 index 00000000..dab44259 --- /dev/null +++ b/roles/restore/tasks/init_secrets.yml @@ -0,0 +1,9 @@ +--- + +- name: Get secret definition from pvc + include_tasks: apply_secrets.yml + with_items: + - secret_key_secret + - admin_password_secret + - broadcast_websocket_secret + - postgres_secret diff --git a/roles/restore/tasks/main.yml b/roles/restore/tasks/main.yml index 8b072d73..63d1138d 100644 --- a/roles/restore/tasks/main.yml +++ b/roles/restore/tasks/main.yml @@ -14,12 +14,10 @@ register: this_restore - block: - - include_tasks: preflight.yml + - include_tasks: init.yml - include_tasks: init_awx.yml - - include_tasks: init.yml - - include_tasks: postgres.yml - include_tasks: secrets.yml diff --git a/roles/restore/tasks/preflight.yml b/roles/restore/tasks/preflight.yml deleted file mode 100644 index d9c98553..00000000 --- a/roles/restore/tasks/preflight.yml +++ /dev/null @@ -1,33 +0,0 @@ ---- - -- name: Create namespace for deployment - k8s: - name: "{{ meta.namespace }}" - kind: Namespace - state: present - -# 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: "{{ tower_backup_pvc_namespace }}" - register: provided_pvc - when: - - tower_backup_pvc != '' - -- name: Surface error to user - block: - - name: Set error message - set_fact: - error_msg: "{{ tower_backup_pvc }} does not exist, please create this pvc first." - - - name: Handle error - import_tasks: error_handling.yml - - - 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: - - tower_backup_pvc != '' - - provided_pvc.resources | length == 0