From 75089b0a8bc1fc6b172436c1f59fccf6c18d901f Mon Sep 17 00:00:00 2001 From: Geoffrey van Wyk Date: Thu, 23 Nov 2023 02:24:11 +0200 Subject: [PATCH 1/4] bugfix: Cannot copy database The additional fix is to restart the database to kill connections to it. All reset code has been moved into one place. --- tasks/install_moodle.yml | 93 ---------------- tasks/reset_moodle.yml | 229 +++++++++++++++++++++++++++------------ 2 files changed, 162 insertions(+), 160 deletions(-) diff --git a/tasks/install_moodle.yml b/tasks/install_moodle.yml index 5ed52a3..3f5d811 100644 --- a/tasks/install_moodle.yml +++ b/tasks/install_moodle.yml @@ -33,96 +33,3 @@ moodle_cfg_disableupdateautodeploy: true moodle_cfg_noemailever: true moodle_cfg_preventexecpath: true - -- name: Set instance identifier for Moodle {{ sandbox_item.version }} - ansible.builtin.set_fact: - sandbox_moodle_instance: >- - {{ sandbox_domain }}-moodle-{{ sandbox_item.version }} - -- name: Set PHP version - ansible.builtin.set_fact: - sandbox_php_version: "{{ - '8.1' if (sandbox_item.branch == 'MOODLE_402_STABLE') or - (sandbox_item.branch == 'MOODLE_401_STABLE') - else '8.0' if (sandbox_item.branch == 'MOODLE_400_STABLE') or - (sandbox_item.branch == 'MOODLE_311_STABLE') - else '7.4' }}" - -- name: Enable Moodle's maintenance mode {{ sandbox_item.version }} - ansible.builtin.command: - chdir: /var/www/html/moodle-{{ sandbox_item.version }} - cmd: php{{ sandbox_php_version }} admin/cli/maintenance.php --enable - changed_when: no # Set for passing Molecule idempotency test. - -- name: Does archive of moodledata exists for Moodle {{ sandbox_item.version }}? - ansible.builtin.stat: - path: /var/www/moodledata-fresh-{{ sandbox_moodle_instance }}.tar.gz - register: moodledata_archive - -- name: Prepare for reset of moodledata {{ sandbox_item.version }} - when: not moodledata_archive.stat.exists - become: yes - block: - - name: Rename moodledata as fresh {{ sandbox_item.version }} - ansible.builtin.command: - cmd: > - mv /var/www/moodledata-{{ sandbox_moodle_instance }} - /var/www/moodledata-fresh-{{ sandbox_moodle_instance }} - creates: /var/www/moodledata-fresh-{{ sandbox_moodle_instance }} - - - name: Archive fresh moodledata {{ sandbox_item.version }} - community.general.archive: - path: /var/www/moodledata-fresh-{{ sandbox_moodle_instance }} - dest: /var/www/moodledata-fresh-{{ sandbox_moodle_instance }}.tar.gz - owner: "{{ ansible_user }}" - group: "{{ ansible_user }}" - mode: u=rw,g=r,o=r - - - name: Rename moodledata as current {{ sandbox_item.version }} - ansible.builtin.command: - cmd: > - mv /var/www/moodledata-fresh-{{ sandbox_moodle_instance }} - /var/www/moodledata-current-{{ sandbox_moodle_instance }} - creates: /var/www/moodledata-current-{{ sandbox_moodle_instance }} - - - name: Turn moodledata into link {{ sandbox_item.version }} - ansible.builtin.file: - src: /var/www/moodledata-current-{{ sandbox_moodle_instance }} - dest: /var/www/moodledata-{{ sandbox_moodle_instance }} - state: link - - - name: Extract fresh moodledata {{ sandbox_item.version }} - ansible.builtin.unarchive: - remote_src: yes - src: /var/www/moodledata-fresh-{{ sandbox_moodle_instance }}.tar.gz - dest: /var/www - - - name: Set permissions for fresh moodledata {{ sandbox_item.version }} - ansible.builtin.file: - path: /var/www/moodledata-fresh-{{ sandbox_moodle_instance }} - state: directory - owner: "{{ ansible_user }}" - group: www-data - mode: u=rwX,g=rwX,o=rwX - -- name: Prepare for reset of database {{ sandbox_item.version }} - become: yes - become_user: postgres - block: - - name: Copy fresh database {{ sandbox_item.version }} - community.postgresql.postgresql_db: - name: moodle-{{ sandbox_item.version | replace(".", "") }}-fresh - state: present - template: moodle-{{ sandbox_item.version | replace(".", "") }} - - - name: Copy next database {{ sandbox_item.version }} - community.postgresql.postgresql_db: - name: moodle-{{ sandbox_item.version | replace(".", "") }}-next - state: present - template: moodle-{{ sandbox_item.version | replace(".", "") }} - -- name: Disable Moodle's maintenance mode {{ sandbox_item.version }} - ansible.builtin.command: - chdir: /var/www/html/moodle-{{ sandbox_item.version }} - cmd: php{{ sandbox_php_version }} admin/cli/maintenance.php --disable - changed_when: no # Set for passing Molecule idempotency test. diff --git a/tasks/reset_moodle.yml b/tasks/reset_moodle.yml index aab0c11..8208445 100644 --- a/tasks/reset_moodle.yml +++ b/tasks/reset_moodle.yml @@ -20,13 +20,21 @@ # @copyright 2023 Geoffrey Bernardo van Wyk (https://geoffreyvanwyk.dev) ## -- name: Set instance identifier for Moodle {{ sandbox_item.version }} +- name: Set variables [{{ sandbox_item.version }}] ansible.builtin.set_fact: + sandbox_database: >- + moodle-{{ sandbox_item.version | replace('.', '') }} + sandbox_database_fresh: "{{ sandbox_database }}-fresh" + sandbox_database_next: "{{ sandbox_database }}-next" + sandbox_database_old: "{{ sandbox_database }}-old" + sandbox_moodle_html: /var/www/html/moodle-{{ sandbox_item.version }} sandbox_moodle_instance: >- {{ sandbox_domain }}-moodle-{{ sandbox_item.version }} - -- name: Set PHP version - ansible.builtin.set_fact: + sandbox_moodledata: /var/www/moodledata-{{ sandbox_moodle_instance }} + sandbox_moodledata_fresh: "{{ sandbox_moodledata }}-fresh" + sandbox_moodledata_archive: "{{ sandbox_moodledata_fresh }}.tar.gz" + sandbox_moodledata_current: "{{ sandbox_moodledata }}-current" + sandbox_moodledata_old: "{{ sandbox_moodledata }}-old" sandbox_php_version: "{{ '8.1' if (sandbox_item.branch == 'MOODLE_402_STABLE') or (sandbox_item.branch == 'MOODLE_401_STABLE') @@ -34,83 +42,170 @@ (sandbox_item.branch == 'MOODLE_311_STABLE') else '7.4' }}" -- name: Enable Moodle's maintenance mode {{ sandbox_item.version }} - ansible.builtin.command: - chdir: /var/www/html/moodle-{{ sandbox_item.version }} - cmd: php{{ sandbox_php_version }} admin/cli/maintenance.php --enable - changed_when: no # Set for passing Molecule idempotency test. +# Additional database connections will prevent the copying of the database. +- name: Ensure no extra database connections [{{ sandbox_item.version }}] + block: + # Moodle maintenance mode is enabled to stop the scheduled tasks which might + # make connections to the database. + # yamllint disable-line rule:line-length + # @see {@link https://docs.moodle.org/403/en/Maintenance_mode#CLI_maintenance_mode} + - name: Enable Moodle's maintenance mode [{{ sandbox_item.version }}] + ansible.builtin.command: + chdir: "{{ sandbox_moodle_html }}" + cmd: php{{ sandbox_php_version }} admin/cli/maintenance.php --enable + # `changed_when` is actually always `yes` in this case, but it is set to + # `no` to pass Molecule's idempotency test. The other option of adding a + # tag `molecule-idempotency-notest` would not work, because with that tag + # Molecule would skip this task which will make the playbook fail for the + # very reason the task is here in the first place. + changed_when: no -- name: Rename current moodledata to old {{ sandbox_item.version }} - become: yes - ansible.builtin.command: - cmd: > - mv /var/www/moodledata-current-{{ sandbox_moodle_instance }} - /var/www/moodledata-old-{{ sandbox_moodle_instance }} - creates: /var/www/moodledata-old-{{ sandbox_moodle_instance }} + - name: Restart database to kill connections [{{ sandbox_item.version }}] + become: yes + ansible.builtin.sysvinit: + name: postgresql + state: restarted -- name: Rename fresh moodledata to current {{ sandbox_item.version }} - become: yes - ansible.builtin.command: - cmd: > - mv /var/www/moodledata-fresh-{{ sandbox_moodle_instance }} - /var/www/moodledata-current-{{ sandbox_moodle_instance }} - creates: /var/www/moodledata-current-{{ sandbox_moodle_instance }} +- name: Does archive of moodledata exists [{{ sandbox_item.version }}]? + ansible.builtin.stat: + path: "{{ sandbox_moodledata_archive }}" + register: sandbox_stat_moodledata_archive -- name: Rename "current" database to old {{ sandbox_item.version }} +- name: Reset Moodle [{{ sandbox_item.version }}] + when: sandbox_stat_moodledata_archive.stat.exists become: yes - become_user: postgres - community.postgresql.postgresql_db: - name: moodle-{{ sandbox_item.version | replace(".", "") }} - state: rename - target: moodle-{{ sandbox_item.version | replace(".", "") }}-old + block: + - name: Rename current moodledata to old [{{ sandbox_item.version }}] + ansible.builtin.command: + cmd: mv {{ sandbox_moodledata_current }} {{ sandbox_moodledata_old }} + creates: "{{ sandbox_moodledata_old }}" -- name: Rename next database to "current" {{ sandbox_item.version }} - become: yes - become_user: postgres - community.postgresql.postgresql_db: - name: moodle-{{ sandbox_item.version | replace(".", "") }}-next - state: rename - target: moodle-{{ sandbox_item.version | replace(".", "") }} + - name: Rename fresh moodledata to current [{{ sandbox_item.version }}] + ansible.builtin.command: + cmd: mv {{ sandbox_moodledata_fresh }} {{ sandbox_moodledata_current }} + creates: "{{ sandbox_moodledata_current }}" -- name: Remove old moodledata {{ sandbox_item.version }} - become: yes - ansible.builtin.file: - path: /var/www/moodledata-old-{{ sandbox_moodle_instance }} - state: absent + - name: Rename current database to old [{{ sandbox_item.version }}] + become_user: postgres + community.postgresql.postgresql_db: + name: "{{ sandbox_database }}" + state: rename + target: "{{ sandbox_database_old }}" -- name: Drop old database {{ sandbox_item.version }} - become: yes - become_user: postgres - community.postgresql.postgresql_db: - name: moodle-{{ sandbox_item.version | replace(".", "") }}-old - state: absent + - name: Rename next database to current [{{ sandbox_item.version }}] + become_user: postgres + community.postgresql.postgresql_db: + name: "{{ sandbox_database_next }}" + state: rename + target: "{{ sandbox_database }}" -- name: Extract fresh moodledata {{ sandbox_item.version }} +- name: Has Moodle been reset [{{ sandbox_item.version }}]? + ansible.builtin.stat: + path: "{{ sandbox_moodledata_old }}" + register: sandbox_stat_moodledata_old + +- name: Prepare for next reset [{{ sandbox_item.version }}] + when: sandbox_stat_moodledata_old.stat.exists become: yes - ansible.builtin.unarchive: - remote_src: yes - src: /var/www/moodledata-fresh-{{ sandbox_moodle_instance }}.tar.gz - dest: /var/www + block: + - name: Remove old moodledata [{{ sandbox_item.version }}] + ansible.builtin.file: + path: "{{ sandbox_moodledata_old }}" + state: absent + + - name: Extract fresh moodledata [{{ sandbox_item.version }}] + ansible.builtin.unarchive: + remote_src: yes + src: "{{ sandbox_moodledata_archive }}" + dest: /var/www + + - name: Set permissions for fresh moodledata [{{ sandbox_item.version }}] + ansible.builtin.file: + path: "{{ sandbox_moodledata_fresh }}" + state: directory + owner: "{{ ansible_user }}" + group: www-data + mode: u=rwX,g=rwX,o=rwX -- name: Set permissions for fresh moodledata {{ sandbox_item.version }} + - name: Drop old database [{{ sandbox_item.version }}] + become_user: postgres + community.postgresql.postgresql_db: + name: "{{ sandbox_database_old }}" + state: absent + + - name: Copy next database [{{ sandbox_item.version }}] + become_user: postgres + community.postgresql.postgresql_db: + name: "{{ sandbox_database_next }}" + state: present + template: "{{ sandbox_database_fresh }}" + +- name: Initialize moodledata for reset [{{ sandbox_item.version }}] + when: not sandbox_stat_moodledata_archive.stat.exists become: yes - ansible.builtin.file: - path: /var/www/moodledata-fresh-{{ sandbox_moodle_instance }} - state: directory - owner: "{{ ansible_user }}" - group: www-data - mode: u=rwX,g=rwX,o=rwX - -- name: Copy next database {{ sandbox_item.version }} + block: + - name: Rename moodledata as fresh [{{ sandbox_item.version }}] + ansible.builtin.command: + cmd: mv {{ sandbox_moodledata }} {{ sandbox_moodledata_fresh }} + creates: "{{ sandbox_moodledata_fresh }}" + + - name: Archive fresh moodledata [{{ sandbox_item.version }}] + community.general.archive: + path: "{{ sandbox_moodledata_fresh }}" + dest: "{{ sandbox_moodledata_archive }}" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: u=rw,g=r,o=r + + - name: Rename fresh moodledata to current [{{ sandbox_item.version }}] + ansible.builtin.command: + cmd: mv {{ sandbox_moodledata_fresh }} {{ sandbox_moodledata_current }} + creates: "{{ sandbox_moodledata_current }}" + + - name: Turn moodledata into link [{{ sandbox_item.version }}] + ansible.builtin.file: + src: "{{ sandbox_moodledata_current }}" + dest: "{{ sandbox_moodledata }}" + state: link + + - name: Extract fresh moodledata [{{ sandbox_item.version }}] + ansible.builtin.unarchive: + remote_src: yes + src: "{{ sandbox_moodledata_archive }}" + dest: /var/www + + - name: Set permissions for fresh moodledata [{{ sandbox_item.version }}] + ansible.builtin.file: + path: "{{ sandbox_moodledata_fresh }}" + state: directory + owner: "{{ ansible_user }}" + group: www-data + mode: u=rwX,g=rwX,o=rwX + +- name: Initialize database for reset [{{ sandbox_item.version }}] + when: not sandbox_stat_moodledata_archive.stat.exists become: yes become_user: postgres - community.postgresql.postgresql_db: - name: moodle-{{ sandbox_item.version | replace(".", "") }}-next - state: present - template: moodle-{{ sandbox_item.version | replace(".", "") }}-fresh + block: + - name: Copy fresh database [{{ sandbox_item.version }}] + community.postgresql.postgresql_db: + name: "{{ sandbox_database_fresh }}" + state: present + template: "{{ sandbox_database }}" + + - name: Copy next database [{{ sandbox_item.version }}] + community.postgresql.postgresql_db: + name: "{{ sandbox_database_next }}" + state: present + template: "{{ sandbox_database_fresh }}" - name: Disable Moodle's maintenance mode {{ sandbox_item.version }} ansible.builtin.command: - chdir: /var/www/html/moodle-{{ sandbox_item.version }} + chdir: "{{ sandbox_moodle_html }}" cmd: php{{ sandbox_php_version }} admin/cli/maintenance.php --disable - changed_when: no # Set for passing Molecule idempotency test. + # `changed_when` is actually always `yes` in this case, but it is set to + # `no` to pass Molecule's idempotency test. The other option of adding a + # tag `molecule-idempotency-notest` would not work, because with that tag + # Molecule would skip this task which would leave the Moodle instance in + # maintenance mode, which is not what we might want with future tests. + changed_when: no From 4ee1a3a1a686e61e2d3285c52590509812538c2a Mon Sep 17 00:00:00 2001 From: Geoffrey van Wyk Date: Thu, 23 Nov 2023 02:28:24 +0200 Subject: [PATCH 2/4] chore(lint): ``become_user`` should have a corresponding ``become`` at the play or task level --- tasks/reset_moodle.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasks/reset_moodle.yml b/tasks/reset_moodle.yml index 8208445..2cb7161 100644 --- a/tasks/reset_moodle.yml +++ b/tasks/reset_moodle.yml @@ -86,6 +86,7 @@ creates: "{{ sandbox_moodledata_current }}" - name: Rename current database to old [{{ sandbox_item.version }}] + become: yes become_user: postgres community.postgresql.postgresql_db: name: "{{ sandbox_database }}" @@ -93,6 +94,7 @@ target: "{{ sandbox_database_old }}" - name: Rename next database to current [{{ sandbox_item.version }}] + become: yes become_user: postgres community.postgresql.postgresql_db: name: "{{ sandbox_database_next }}" @@ -128,12 +130,14 @@ mode: u=rwX,g=rwX,o=rwX - name: Drop old database [{{ sandbox_item.version }}] + become: yes become_user: postgres community.postgresql.postgresql_db: name: "{{ sandbox_database_old }}" state: absent - name: Copy next database [{{ sandbox_item.version }}] + become: yes become_user: postgres community.postgresql.postgresql_db: name: "{{ sandbox_database_next }}" From 7ea94624dc5d7e7063b2ed9375a8593031cf8910 Mon Sep 17 00:00:00 2001 From: Geoffrey van Wyk Date: Thu, 23 Nov 2023 02:40:41 +0200 Subject: [PATCH 3/4] bugfix: Variable sandbox_database does not exist --- tasks/reset_moodle.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tasks/reset_moodle.yml b/tasks/reset_moodle.yml index 2cb7161..97a4056 100644 --- a/tasks/reset_moodle.yml +++ b/tasks/reset_moodle.yml @@ -20,21 +20,14 @@ # @copyright 2023 Geoffrey Bernardo van Wyk (https://geoffreyvanwyk.dev) ## -- name: Set variables [{{ sandbox_item.version }}] +- name: Set independent variables [{{ sandbox_item.version }}] ansible.builtin.set_fact: sandbox_database: >- moodle-{{ sandbox_item.version | replace('.', '') }} - sandbox_database_fresh: "{{ sandbox_database }}-fresh" - sandbox_database_next: "{{ sandbox_database }}-next" - sandbox_database_old: "{{ sandbox_database }}-old" sandbox_moodle_html: /var/www/html/moodle-{{ sandbox_item.version }} sandbox_moodle_instance: >- {{ sandbox_domain }}-moodle-{{ sandbox_item.version }} sandbox_moodledata: /var/www/moodledata-{{ sandbox_moodle_instance }} - sandbox_moodledata_fresh: "{{ sandbox_moodledata }}-fresh" - sandbox_moodledata_archive: "{{ sandbox_moodledata_fresh }}.tar.gz" - sandbox_moodledata_current: "{{ sandbox_moodledata }}-current" - sandbox_moodledata_old: "{{ sandbox_moodledata }}-old" sandbox_php_version: "{{ '8.1' if (sandbox_item.branch == 'MOODLE_402_STABLE') or (sandbox_item.branch == 'MOODLE_401_STABLE') @@ -42,6 +35,16 @@ (sandbox_item.branch == 'MOODLE_311_STABLE') else '7.4' }}" +- name: Set dependent variables [{{ sandbox_item.version }}] + ansible.builtin.set_fact: + sandbox_database_fresh: "{{ sandbox_database }}-fresh" + sandbox_database_next: "{{ sandbox_database }}-next" + sandbox_database_old: "{{ sandbox_database }}-old" + sandbox_moodledata_fresh: "{{ sandbox_moodledata }}-fresh" + sandbox_moodledata_archive: "{{ sandbox_moodledata_fresh }}.tar.gz" + sandbox_moodledata_current: "{{ sandbox_moodledata }}-current" + sandbox_moodledata_old: "{{ sandbox_moodledata }}-old" + # Additional database connections will prevent the copying of the database. - name: Ensure no extra database connections [{{ sandbox_item.version }}] block: From 2e3b828f333757711ca7233dff3fb1e37645f067 Mon Sep 17 00:00:00 2001 From: Geoffrey van Wyk Date: Thu, 23 Nov 2023 02:58:49 +0200 Subject: [PATCH 4/4] fix: Undefined variable sandbox_moodle_instance --- tasks/reset_moodle.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tasks/reset_moodle.yml b/tasks/reset_moodle.yml index 97a4056..32d3af0 100644 --- a/tasks/reset_moodle.yml +++ b/tasks/reset_moodle.yml @@ -25,9 +25,8 @@ sandbox_database: >- moodle-{{ sandbox_item.version | replace('.', '') }} sandbox_moodle_html: /var/www/html/moodle-{{ sandbox_item.version }} - sandbox_moodle_instance: >- - {{ sandbox_domain }}-moodle-{{ sandbox_item.version }} - sandbox_moodledata: /var/www/moodledata-{{ sandbox_moodle_instance }} + sandbox_moodledata: >- + /var/www/moodledata-{{ sandbox_domain }}-moodle-{{ sandbox_item.version }} sandbox_php_version: "{{ '8.1' if (sandbox_item.branch == 'MOODLE_402_STABLE') or (sandbox_item.branch == 'MOODLE_401_STABLE') @@ -41,7 +40,7 @@ sandbox_database_next: "{{ sandbox_database }}-next" sandbox_database_old: "{{ sandbox_database }}-old" sandbox_moodledata_fresh: "{{ sandbox_moodledata }}-fresh" - sandbox_moodledata_archive: "{{ sandbox_moodledata_fresh }}.tar.gz" + sandbox_moodledata_archive: "{{ sandbox_moodledata }}-fresh.tar.gz" sandbox_moodledata_current: "{{ sandbox_moodledata }}-current" sandbox_moodledata_old: "{{ sandbox_moodledata }}-old"