# Copyright 2020-2024 Chris Croome
#
# This file is part of the Webarchitects Icinga Ansible role.
#
# The Webarchitects Icinga 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 Icinga 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 Icinga Ansible role. If not, see <https://www.gnu.org/licenses/>.
---
# https://icinga.com/docs/icinga2/latest/doc/02-installation/#debianubunturaspbian-repositories
- name: Icinga Debian / Ubuntu apt repo configuration
  block:

    - name: Python3 Debian present for deb822 module
      ansible.builtin.apt:
        pkg: python3-debian
        state: present

    - name: Apt GPG configuration for supported Debian and Ubuntu distros
      block:

        - name: "Icinga GPG package present {{ icinga_archive_keyring_deb_url |  ansible.builtin.urlsplit('path') | ansible.builtin.regex_replace('^[/]') }}"
          ansible.builtin.apt:
            deb: "{{ icinga_archive_keyring_deb_url }}"
            state: present

        - name: Stat /usr/share/keyrings/icinga-archive-keyring.gpg
          ansible.builtin.stat:
            path: /usr/share/keyrings/icinga-archive-keyring.gpg
          register: icinga_archive_keyring_pub_key

        - name: "The GPG key provided by the Icinga GPG package is required {{ icinga_archive_keyring_deb_url |  ansible.builtin.urlsplit('path') | ansible.builtin.regex_replace('^[/]') }}"
          ansible.builtin.assert:
            that:
              - icinga_archive_keyring_pub_key.stat.exists | bool
            quiet: "{% if ansible_check_mode or ansible_verbosity >= 1 %}false{% else %}true{% endif %}"
            fail_msg: >-
              The GPG key provided by {{ icinga_archive_keyring_deb_url }} is required to configure the Icinga apt repo.

        - name: Configure the Icinga apt repo when the GPG public key is present
          block:

            - name: Stat Icinga repository sources file
              ansible.builtin.stat:
                path: /etc/apt/sources.list.d/icinga.sources
              register: icinga_sources_path

            - name: Read and backup Icinga repository sources file
              block:

                - name: Slurp /etc/apt/sources.list.d/icinga.sources
                  ansible.builtin.slurp:
                    src: /etc/apt/sources.list.d/icinga.sources
                  register: icinga_sources_contents_b64encoded

                - name: Decode the base64 encoded version of /etc/apt/sources.list.d/icinga.sources
                  ansible.builtin.set_fact:
                    icinga_sources_contents: "{{ icinga_sources_contents_b64encoded['content'] | ansible.builtin.b64decode | community.general.jc('ini') }}"

                - name: Print the contents of /etc/apt/sources.list.d/icinga.sources
                  ansible.builtin.debug:
                    var: icinga_sources_contents
                    verbosity: "{% if ansible_check_mode | bool %}0{% else %}1{% endif %}"

                - name: Set a fact for the prior Icinga repository sources file contents
                  ansible.builtin.set_fact:
                    icinga_sources_contents_prior: "{{ icinga_sources_contents }}"
                  when: icinga_sources_contents is defined

                - name: Check Icinga repository sources file present
                  ansible.builtin.deb822_repository:
                    allow_downgrade_to_insecure: false
                    allow_insecure: false
                    allow_weak: false
                    architectures: "{{ ansible_facts.ansible_local.dpkg.arch }}"
                    check_date: true
                    check_valid_until: true
                    components: main
                    enabled: true
                    name: icinga
                    pdiffs: true
                    signed_by: /usr/share/keyrings/icinga-archive-keyring.gpg
                    suites: "icinga-{{ ansible_facts.distribution_release }}"
                    types: deb
                    uris: "https://packages.icinga.com/{{ ansible_distribution | lower }}"
                  check_mode: true
                  changed_when: false
                  register: icinga_sources_check

                - name: Debug proposed icinga_sources_check.repo
                  ansible.builtin.debug:
                    var: icinga_sources_check.repo
                    verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}1{% else %}2{% endif %}"

                - name: Backup old Icinga sources file
                  ansible.builtin.command:
                    cmd: >-
                      mv
                      /etc/apt/sources.list.d/icinga.sources
                      /etc/apt/sources.list.d/.icinga.sources.{{ icinga_date_timestamp }}.ansible.save
                  args:
                    creates: "/etc/apt/sources.list.d/.icinga.sources.{{ icinga_date_timestamp }}.ansible.save"
                    removes: /etc/apt/sources.list.d/icinga.sources
                  vars:
                    icinga_date_timestamp: "{{ ansible_facts.date_time.iso8601_basic_short }}"
                  when: icinga_sources_contents_prior != icinga_sources_check.repo | string | community.general.jc('ini')

              when: icinga_sources_path.stat.exists | bool

            - name: Icinga repository sources file present
              ansible.builtin.deb822_repository:
                allow_downgrade_to_insecure: false
                allow_insecure: false
                allow_weak: false
                architectures: "{{ ansible_facts.ansible_local.dpkg.arch }}"
                check_date: true
                check_valid_until: true
                components: main
                enabled: true
                name: icinga
                pdiffs: true
                signed_by: /usr/share/keyrings/icinga-archive-keyring.gpg
                suites: "icinga-{{ ansible_facts.distribution_release }}"
                types: deb
                uris: "https://packages.icinga.com/{{ ansible_distribution | lower }}"
              register: icinga_sources

          when: icinga_archive_keyring_pub_key.stat.exists | bool

        - name: Legacy Icinga apt configuration absent
          ansible.builtin.file:
            path: "{{ icinga_legacy_apt_path }}"
            state: absent
          loop:
            - /etc/apt/keyrings/icinga.gpg
            - /etc/apt/sources.list.d/icinga.list
            - /usr/local/share/keyrings/icinga-archive-keyring.gpg
            - /usr/share/keyrings/icinga.gpg
          loop_control:
            loop_var: icinga_legacy_apt_path

      when: ansible_facts.distribution_release in icinga_distros

    - name: Apt GPG configuration for unsupported Debian and Ubuntu distros
      block:

        - name: EOL Distribution Versions
          ansible.builtin.fail:
            msg: "TODO see Required Actions for Users of EOL Distribution Versions https://icinga.com/blog/2024/08/26/icinga-package-repository-key-rotation-2024/"

        - name: Legacy Icinga apt configuration absent
          ansible.builtin.file:
            path: "{{ icinga_legacy_apt_path }}"
            state: absent
          loop:
            - /etc/apt/sources.list.d/icinga.list
            - /usr/share/keyrings/icinga.gpg
            - /usr/local/share/keyrings/icinga-archive-keyring.gpg
          loop_control:
            loop_var: icinga_legacy_apt_path

        - name: Apt Keyrings directory present
          ansible.builtin.file:
            path: /etc/apt/keyrings
            state: directory
            mode: "0755"
            owner: root
            group: root

        - name: Icinga gpg ascii armored key present
          ansible.builtin.get_url:
            url: "{{ icinga_gpg_url }}"
            checksum: "{{ icinga_gpg_checksum }}"
            dest: /root/icinga.asc
            mode: "0644"
            owner: root
            group: root
          register: icinga_tmp_asc_file

        - name: Stat Icinga2 gpg ascii armored file
          ansible.builtin.stat:
            path: /root/icinga.asc
          register: icinga_asc_file

        - name: Check gpg key when it exists
          block:

            - name: Stat Icinga gpg dearmored file
              ansible.builtin.stat:
                path: /etc/apt/keyrings/icinga.gpg
              register: icinga_gpg_file

            - name: Icinga gpg key dearmored
              ansible.builtin.shell: |-
                set -e -o pipefail
                gpg --dearmor < /root/icinga.asc > /etc/apt/keyrings/icinga.gpg
                chmod 644 /etc/apt/keyrings/icinga.gpg
              args:
                executable: "{{ ansible_local.bash.path }}"
              when: ( icinga_tmp_asc_file.changed | bool ) or ( not icinga_gpg_file.stat.exists | bool )

            - name: Stat Icinga gpg dearmored file
              ansible.builtin.stat:
                path: /etc/apt/keyrings/icinga.gpg
              register: icinga_gpg_file

            - name: Debug disto
              ansible.builtin.debug:
                var: ansible_distribution
                verbosity: 2

            - name: Debug disto version
              ansible.builtin.debug:
                var: ansible_distribution_version
                verbosity: 2

            - name: Icinga gpg key check command
              ansible.builtin.command: >
                gpg --with-colons
                {% if ansible_local.gpg.version is version('2.2.12', '<') %}
                --with-fingerprint --with-subkey-fingerprint
                {% else %}
                --show-keys
                {% endif %}
                /etc/apt/keyrings/icinga.gpg
              when: ( icinga_gpg_file.stat.exists | bool )
              check_mode: false
              changed_when: false
              register: icinga_gpg

            - name: Icinga gpg key check first fingerprint on Debian 10 and older
              ansible.builtin.assert:
                that:
                  - icinga_fpr in icinga_gpg.stdout
                quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
              when:
                - ansible_loop.first | bool
                - ansible_distribution == "Debian"
                - ansible_distribution_version is version('10', '<')
              loop: "{{ icinga_gpg_fingerprints }}"
              loop_control:
                extended: true
                loop_var: icinga_fpr

            - name: Icinga gpg key check first fingerprint on Ubuntu 18.04 and older
              ansible.builtin.assert:
                that:
                  - icinga_fpr in icinga_gpg.stdout
                quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
              when:
                - ansible_loop.first | bool
                - ansible_distribution == "Ubuntu"
                - ansible_distribution_version is version('18.04', '<=')
              loop: "{{ icinga_gpg_fingerprints }}"
              loop_control:
                extended: true
                loop_var: icinga_fpr

            - name: Icinga gpg key check all fingerprints
              ansible.builtin.assert:
                that:
                  - icinga_fpr in icinga_gpg.stdout
                quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
              when: >
                ( ( ansible_distribution == "Debian" ) and ( ansible_distribution_version is version('10', '>=') ) ) or
                ( ( ansible_distribution == "Ubuntu" ) and ( ansible_distribution_version is version('18.04', '>') ) )
              loop: "{{ icinga_gpg_fingerprints }}"
              loop_control:
                loop_var: icinga_fpr

          when: icinga_asc_file.stat.exists | bool

        - name: Icinga repo apt sources file present
          ansible.builtin.template:
            src: icinga.sources.j2
            dest: /etc/apt/sources.list.d/icinga.sources
            mode: "0644"
            owner: root
            group: root
          register: icinga_sources

      when: ansible_facts.distribution_release not in icinga_distros

    - name: Icinga apt prefs file present
      ansible.builtin.template:
        src: icinga.pref.j2
        dest: /etc/apt/preferences.d/icinga.pref
        mode: "0644"
        owner: root
        group: root
      register: icinga_prefs

    - name: Apt cache update  # noqa: no-handler
      ansible.builtin.apt:
        update_cache: true
      when: ( icinga_sources.changed | bool ) or ( icinga_prefs.changed | bool )

  when:
    - ( groups['icinga_master_nodes'] is defined ) or ( groups['icinga_agent_nodes'] is defined )
    - ( inventory_hostname in groups['icinga_master_nodes'] ) or ( inventory_hostname in groups['icinga_agent_nodes'] )
  tags:
    - icinga
    - icinga_apt
...