From 948c8bfec22fdfd592c99fee83302fcf4a5566f5 Mon Sep 17 00:00:00 2001
From: Chris Croome <chris@webarchitects.co.uk>
Date: Sat, 29 Apr 2023 09:21:45 +0100
Subject: [PATCH] Update for multiple versions of PHP

---
 .ansible-lint                 |  24 ++++++--
 .gitlab-ci.yml                |  11 +++-
 .pre-commit-config.yaml       |  18 ++++++
 meta/main.yml                 |  14 ++++-
 molecule/default/molecule.yml |  11 +++-
 tasks/checks.yml              | 101 +++++++++++++++++++---------------
 tasks/cloudflare.yml          |   4 +-
 tasks/config.yml              |  24 ++++----
 tasks/local_facts.yml         |   4 +-
 tasks/main.yml                |   4 +-
 tasks/mc3.yml                 |   2 +-
 tasks/suexec.yml              |   2 +-
 tasks/webarch.yml             |   2 +-
 13 files changed, 146 insertions(+), 75 deletions(-)
 create mode 100644 .pre-commit-config.yaml

diff --git a/.ansible-lint b/.ansible-lint
index 3cbe21d..91a81ee 100644
--- a/.ansible-lint
+++ b/.ansible-lint
@@ -1,9 +1,23 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
-# https://docs.ansible.com/ansible-lint/rules/default_rules.html
+# https://ansible-lint.readthedocs.io/rules/
 skip_list:
-  # Lines should be no longer than 160 chars
-  - "204"
-  # Package installs should not use latest
-  - "403"
+  - fqcn[action-core]
+  - fqcn[action]
+  - jinja[spacing]
+  - key-order[task]
+  - name[casing]
+  - name[template]
+  - no-changed-when
+  - no-handler
+  - package-latest
 # vim: syntax=yaml
 ...
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1d636c3..0302f60 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,14 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
-image: registry.git.coop/webarch/containers/images/ansible:0.8.0
+image: registry.git.coop/webarch/containers/images/ansible:0.23.0
 variables:
   PY_COLORS: "1"
   ANSIBLE_FORCE_COLOR: "1"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..3663620
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,18 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
+---
+# https://yamllint.readthedocs.io/en/stable/integration.html
+# https://github.com/adrienverge/yamllint/tags
+repos:
+  - repo: https://github.com/adrienverge/yamllint.git
+    rev: v1.30.0
+    hooks:
+      - id: yamllint
+...
diff --git a/meta/main.yml b/meta/main.yml
index 9b34f4e..cbc12af 100644
--- a/meta/main.yml
+++ b/meta/main.yml
@@ -1,3 +1,12 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 galaxy_info:
   role_name: apache
@@ -6,10 +15,11 @@ galaxy_info:
   description: Ansible role for installing Apache on Debian
   company: Webarchitects Co-operative
   license: GNU General Public License v3.0 (GPLv3)
-  min_ansible_version: 2.9
+  min_ansible_version: "2.10.7"
   platforms:
-    - name: debian
+    - name: Debian
       versions:
+        - bookworm
         - bullseye
         - buster
         - stretch
diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml
index b27fbc3..612062e 100644
--- a/molecule/default/molecule.yml
+++ b/molecule/default/molecule.yml
@@ -1,9 +1,18 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 dependency:
   name: galaxy
 platforms:
   - name: instance
-    image: registry.git.coop/webarch/containers/images/ansible:0.8.0
+    image: registry.git.coop/webarch/containers/images/ansible:0.23.0
     pre_build_image: true
 provisioner:
   name: ansible
diff --git a/tasks/checks.yml b/tasks/checks.yml
index 8514337..190aa74 100644
--- a/tasks/checks.yml
+++ b/tasks/checks.yml
@@ -3,13 +3,13 @@
   block:
 
     - name: Check that at least one module is in apache_mods_enabled and that either mpm_event or mpm_prefork is enabled
-      assert:
+      ansible.builtin.assert:
         that:
           - ( apache_mods_enabled is defined ) and ( apache_mods_enabled[0] is defined )
           - ( "mpm_prefork" in apache_mods_enabled ) or ( "mpm_event" in apache_mods_enabled )
 
     - name: Checks when mpm_event enabled
-      assert:
+      ansible.builtin.assert:
         that:
           - ( "mpm_prefork" not in apache_mods_enabled )
           - ( "mpm_event" not in apache_mods_disabled )
@@ -17,26 +17,26 @@
       when: ( "mpm_event" in apache_mods_enabled )
 
     - name: Checks when mpm_prefork enabled
-      assert:
+      ansible.builtin.assert:
         that:
           - ( "mpm_event" not in apache_mods_enabled )
           - ( "mpm_prefork" not in apache_mods_disabled )
       when: ( "mpm_prefork" in apache_mods_enabled )
 
     - name: Check that there are no duplicates in the mods arrays
-      assert:
+      ansible.builtin.assert:
         that:
           - apache_mods_enabled | unique | count == apache_mods_enabled | count
           - apache_mods_disabled | unique | count == apache_mods_disabled | count
 
     - name: Check that there are no duplicates in the conf arrays
-      assert:
+      ansible.builtin.assert:
         that:
           - apache_conf_enabled | unique | count == apache_conf_enabled | count
           - apache_conf_disabled | unique | count == apache_conf_disabled | count
 
     - name: Check that there are no duplicates in the sites arrays
-      assert:
+      ansible.builtin.assert:
         that:
           - apache_sites_enabled | unique | count == apache_sites_enabled | count
           - apache_sites_disabled | unique | count == apache_sites_disabled | count
@@ -45,17 +45,17 @@
       block:
 
         - name: Debug apache_mods_enabled array
-          debug:
+          ansible.builtin.debug:
             var: apache_mods_enabled
             verbosity: 2
 
         - name: Debug apache_mods_disabled array
-          debug:
+          ansible.builtin.debug:
             var: apache_mods_disabled
             verbosity: 2
 
         - name: Check that no mods are enabled and disabled
-          assert:
+          ansible.builtin.assert:
             that: mod not in apache_mods_disabled
           loop: "{{ apache_mods_enabled }}"
           loop_control:
@@ -63,7 +63,7 @@
             label: "{{ mod }}"
 
         - name: Check that no mods are disabled and enabled
-          assert:
+          ansible.builtin.assert:
             that: mod not in apache_mods_enabled
           loop: "{{ apache_mods_disabled }}"
           loop_control:
@@ -78,18 +78,18 @@
       block:
 
         - name: Debug apache_conf_enabled arrays
-          debug:
+          ansible.builtin.debug:
             var: apache_conf_enabled
             verbosity: 2
 
         - name: Debug apache_conf_disabled arrays
-          debug:
+          ansible.builtin.debug:
             var:
               - apache_conf_disabled
             verbosity: 2
 
         - name: Check that no conf are enabled and disabled
-          assert:
+          ansible.builtin.assert:
             that: conf not in apache_conf_disabled
           loop: "{{ apache_conf_enabled }}"
           loop_control:
@@ -97,7 +97,7 @@
             label: "{{ conf }}"
 
         - name: Check that no conf are disabled and enabled
-          assert:
+          ansible.builtin.assert:
             that: conf not in apache_conf_enabled
           loop: "{{ apache_conf_disabled }}"
           loop_control:
@@ -112,17 +112,17 @@
       block:
 
         - name: Debug apache_sites_enabled arrays
-          debug:
+          ansible.builtin.debug:
             var: apache_sites_enabled
             verbosity: 2
 
         - name: Debug apache_sites_disabled arrays
-          debug:
+          ansible.builtin.debug:
             var: apache_sites_disabled
             verbosity: 2
 
         - name: Check that no sites are enabled and disabled
-          assert:
+          ansible.builtin.assert:
             that: site not in apache_sites_disabled
           loop: "{{ apache_sites_enabled }}"
           loop_control:
@@ -130,7 +130,7 @@
             label: "{{ site }}"
 
         - name: Check that no sites are disabled and enabled
-          assert:
+          ansible.builtin.assert:
             that: site not in apache_sites_enabled
           loop: "{{ apache_sites_disabled }}"
           loop_control:
@@ -145,22 +145,22 @@
   block:
 
     - name: Check the Apache version
-      command: apache2ctl -v
+      ansible.builtin.command: apache2ctl -v
       check_mode: false
       changed_when: false
       register: apache_version_check
 
     - name: Debug Apache version check
-      debug:
+      ansible.builtin.debug:
         msg: "{{ apache_version_check.stdout_lines[0] }}"
         verbosity: 2
 
     - name: Set a fact for the Apache version
-      set_fact:
+      ansible.builtin.set_fact:
         apache_version: "{{ apache_version_check.stdout_lines[0].split(' ')[2] | regex_replace('^Apache[/]') }}"
 
     - name: Debug Apache version
-      debug:
+      ansible.builtin.debug:
         var: apache_version
         verbosity: 1
 
@@ -168,51 +168,62 @@
       block:
 
         - name: Set facts for TLS versions
-          set_fact:
+          ansible.builtin.set_fact:
             apache_tls1_3: true
           when: apache_version is version('2.4.41', '>=')
 
         - name: Debug TLS 1.3 variable
-          debug:
+          ansible.builtin.debug:
             var: apache_tls1_3
             verbosity: 1
 
       when: apache_version is version('2.4.41', '>=')
 
     - name: Check if phpquery is installed
-      command: which phpquery
+      ansible.builtin.command: which phpquery
       check_mode: false
       changed_when: false
       register: apache_which_phpquery
       failed_when: apache_which_phpquery.rc is not regex('^0|1$')
 
     - name: Set the apache_php variable to true or false
-      set_fact:
+      ansible.builtin.set_fact:
         apache_php: "{% if apache_which_phpquery.rc == 0 %}true{% else %}false{% endif %}"
 
     - name: Check PHP version
       block:
 
-        - name: Run phpquery to get the PHP version NOTE that currently having only one PHP version installed is supported
-          command: phpquery -V
+        - name: Run phpquery to get the PHP versions
+          ansible.builtin.command: phpquery -V
           args:
             strip_empty_ends: true
           check_mode: false
           changed_when: false
-          register: apache_phpquery_version
-          failed_when: apache_which_phpquery.stdout_lines | count >= 2
+          register: apache_phpquery_versions
 
-        - name: Set a fact for the PHP version
-          set_fact:
-            apache_php_version: "{{ apache_phpquery_version.stdout | trim }}"
+        - name: Set a fact for the PHP versions
+          ansible.builtin.set_fact:
+            apache_php_versions: "{{ apache_phpquery_versions.stdout_lines }}"
 
-        - name: Set a fact for the PHP FPM module and conf names
-          set_fact:
+        - name: Run update-alternatives to find the default version of PHP
+          ansible.builtin.command: update-alternatives --query php
+          args:
+            strip_empty_ends: true
+          check_mode: false
+          changed_when: false
+          register: apache_update_alternatives_query_php
+
+        - name: Set a fact for the default version of PHP
+          ansible.builtin.ansible.builtin.set_fact:
+            apache_php_version: "{{ apache_update_alternatives_query_php.stdout | string | community.general.jc('update_alt_q') | community.general.json_query('default') | regex_replace('^/usr/bin/php') }}"
+
+        - name: Set facts for the PHP FPM module and conf names
+          ansible.builtin.set_fact:
             apache_phpfpm_mod: "php{{ apache_php_version }}"
             apache_phpfpm_conf: "php{{ apache_php_version }}-fpm"
 
         - name: Debug PHP FPM module and conf names
-          debug:
+          ansible.builtin.debug:
             msg:
               - "apache_phpfpm_mod: {{ apache_phpfpm_mod }}"
               - "apache_phpfpm_conf: {{ apache_phpfpm_conf }}"
@@ -221,47 +232,47 @@
       when: ( apache_php is defined ) and ( apache_php )
 
     - name: Check the enabled MPM
-      command: a2query -M
+      ansible.builtin.command: a2query -M
       check_mode: false
       changed_when: false
       register: apache_mpm_check
 
     - name: Debug the enabled MPM
-      debug:
+      ansible.builtin.debug:
         msg: "{{ apache_mpm_check.stdout }}"
         verbosity: 2
 
     - name: Set a fact for the enabled MPM
-      set_fact:
+      ansible.builtin.set_fact:
         apache_mpm_loaded: "mpm_{{ apache_mpm_check.stdout | trim }}"
       when: apache_mpm_check.stdout != "invalid"
 
     - name: Set a fact for the enabled MPM
-      set_fact:
+      ansible.builtin.set_fact:
         apache_mpm_loaded: ""
       when: apache_mpm_check.stdout == "invalid"
 
     - name: Debug the enabled MPM
-      debug:
+      ansible.builtin.debug:
         var: apache_mpm_loaded
         verbosity: 2
       when: apache_mpm_loaded is defined
 
     - name: "Check if a Let's Encrypt HTTPS cert is present for {{ inventory_hostname }}"
-      stat:
+      ansible.builtin.stat:
         path: "/etc/ssl/le/{{ inventory_hostname }}.cert.pem"
       check_mode: false
       register: apache_cert
       when: ( "md" not in apache_mods_enabled )
 
     - name: Include mod checks
-      include_tasks: a2mod_checks.yml
+      ansible.builtin.include_tasks: a2mod_checks.yml
 
     - name: Include conf checks
-      include_tasks: a2conf_checks.yml
+      ansible.builtin.include_tasks: a2conf_checks.yml
 
     - name: Include site checks
-      include_tasks: a2site_checks.yml
+      ansible.builtin.include_tasks: a2site_checks.yml
 
   tags:
     - apache
diff --git a/tasks/cloudflare.yml b/tasks/cloudflare.yml
index 4760d13..2c0bf16 100644
--- a/tasks/cloudflare.yml
+++ b/tasks/cloudflare.yml
@@ -8,7 +8,7 @@
         dest: "/root/cloudflare_ips_v4.txt"
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
         force: true
 
     - name: Slurp Cloudflare IPv4 list
@@ -31,7 +31,7 @@
         dest: /etc/apache2/conf-available/cloudflare.conf
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
 
   tags:
     - apache
diff --git a/tasks/config.yml b/tasks/config.yml
index d8e3e60..ed56fb9 100644
--- a/tasks/config.yml
+++ b/tasks/config.yml
@@ -8,7 +8,7 @@
         state: directory
         owner: root
         group: root
-        mode: 0755
+        mode: "0755"
       loop:
         - "{{ apache_document_root }}"
         - "{{ apache_document_root }}/.well-known/acme-challenge"
@@ -22,7 +22,7 @@
         dest: "/etc/apache2/{{ file }}"
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
       loop:
         - apache2.conf
         - ports.conf
@@ -36,7 +36,7 @@
         dest: "/etc/apache2/mods-available/{{ file }}"
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
       loop:
         - http2.conf
         - md.conf
@@ -52,7 +52,7 @@
         dest: "/etc/apache2/conf-available/{{ file }}"
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
       loop:
         - le.conf
         - version-control.conf
@@ -66,7 +66,7 @@
         dest: /etc/apache2/sites-available/000-default.conf
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
       when: ( apache_sites_enabled is defined ) and ( "000-default" in apache_sites_enabled )
 
     - name: Conditional update default-ssl.conf
@@ -75,7 +75,7 @@
         dest: /etc/apache2/sites-available/default-ssl.conf
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
       when: ( apache_sites_enabled is defined ) and ( "default-ssl" in apache_sites_enabled )
 
     - name: Apache localhost site available
@@ -84,7 +84,7 @@
         dest: "/etc/apache2/sites-available/localhost.conf"
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
 
     - name: Conditionally include Webarchitects config
       include_tasks: webarch.yml
@@ -100,7 +100,7 @@
         state: directory
         owner: root
         group: root
-        mode: 0755
+        mode: "0755"
       loop:
         - /var/www/localhost
         - /etc/apache2/localhost.d
@@ -114,7 +114,7 @@
         dest: /var/www/html/robots.deny.txt
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
 
     - name: Expires and robots conf available
       template:
@@ -122,7 +122,7 @@
         dest: "/etc/apache2/conf-available/{{ file }}"
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
       loop:
         - robots-deny.conf
         - robots-deny-nextcloud.conf
@@ -139,7 +139,7 @@
         dest: /etc/apache2/mods-available/mpm_prefork.conf
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
       when: ( "mpm_itk" in apache_mods_enabled ) or ( "mpm_prefork" in apache_mods_enabled )
 
     - name: Apache ratelimit conf present
@@ -148,7 +148,7 @@
         dest: /etc/apache2/mods-available/ratelimit.conf
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
       when: '"ratelimit" in apache_mods_enabled'
 
     - name: Cloudflare config available
diff --git a/tasks/local_facts.yml b/tasks/local_facts.yml
index 76ace4b..7f2ccff 100644
--- a/tasks/local_facts.yml
+++ b/tasks/local_facts.yml
@@ -13,7 +13,7 @@
         path: /etc/ansible/facts.d
         recurse: true
         state: directory
-        mode: 0700
+        mode: "0700"
         owner: root
         group: root
 
@@ -21,7 +21,7 @@
       ansible.builtin.template:
         src: a2query.fact.j2
         dest: /etc/ansible/facts.d/a2query.fact
-        mode: 0700
+        mode: "0700"
         owner: root
         group: root
       register: apache_a2query_facts
diff --git a/tasks/main.yml b/tasks/main.yml
index b302f19..dfd287f 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -38,7 +38,7 @@
       file:
         path: "{{ apache_document_root }}"
         state: directory
-        mode: 0755
+        mode: "0755"
         owner: root
         group: root
 
@@ -66,7 +66,7 @@
       template:
         src: templates/envvars.j2
         dest: /etc/apache2/envvars
-        mode: 0755
+        mode: "0755"
         owner: root
         group: root
 
diff --git a/tasks/mc3.yml b/tasks/mc3.yml
index c0ee99c..16aa83a 100644
--- a/tasks/mc3.yml
+++ b/tasks/mc3.yml
@@ -22,7 +22,7 @@
         dest: /etc/apache2/conf-available/mc3.conf
         owner: root
         group: root
-        mode: 0644
+        mode: "0644"
 
   tags:
     - apache
diff --git a/tasks/suexec.yml b/tasks/suexec.yml
index 128b074..2ab1fc5 100644
--- a/tasks/suexec.yml
+++ b/tasks/suexec.yml
@@ -12,7 +12,7 @@
       file:
         path: /etc/apache2/suexec
         state: directory
-        mode: 0700
+        mode: "0700"
 
   tags:
     - apache
diff --git a/tasks/webarch.yml b/tasks/webarch.yml
index d26f415..65ac24d 100644
--- a/tasks/webarch.yml
+++ b/tasks/webarch.yml
@@ -28,7 +28,7 @@
         dest: /etc/apache2/conf-available/webarch.conf
         trim_blocks: false
         lstrip_blocks: true
-        mode: 0644
+        mode: "0644"
         owner: root
         group: root
 
-- 
GitLab