---
- name: "Combination test - test for (2 types of inputs) x
  (2 types of outputs) combination"
  hosts: all
  gather_facts: true  # test needs facts
  vars:
    __test_files_conf: /etc/rsyslog.d/30-output-files-files_test0.conf
    __test_forwards_conf_s_f: >-
      /etc/rsyslog.d/30-output-forwards-forwards_severity_and_facility.conf
    __test_tag: files_input
    __test_inputfiles_conf: /etc/rsyslog.d/90-input-files-{{ __test_tag }}.conf
    __test_basics_conf: /etc/rsyslog.d/90-input-basics-basic_input.conf
    __test_inputfiles_dir: /var/log/inputdirectory
    __default_system_log: /var/log/messages

  tasks:
    - name: Generate an input log dir {{ __test_inputfiles_dir }}
      file:
        path: "{{ __test_inputfiles_dir }}"
        state: directory
        mode: "0700"

    # TEST CASE 0
    - name: "TEST CASE 0; Ensure that the role runs with complicated flows
      - M x N combinations"
      vars:
        logging_outputs:
          - name: files_test0
            type: files
            severity: info
            exclude:
              - authpriv.none
              - auth.none
              - cron.none
              - mail.none
            path: "{{ __default_system_log }}"
          - name: files_test1
            type: files
            facility: authpriv,auth
            path: /var/log/secure
          - name: forwards_severity_and_facility
            type: forwards
            facility: local1
            severity: info
            target: host.domain
            tcp_port: 1514
          - name: forwards_facility_only
            type: forwards
            facility: local2
            target: host.domain
            tcp_port: 2514
        logging_inputs:
          - name: "{{ __test_tag }}"
            type: files
            input_log_path: "{{ __test_inputfiles_dir }}/*.log"
            # Not supported on EL 7
            endmsg_regex: "{{ omit
              if ansible_distribution in ['CentOS', 'RedHat'] and
              ansible_distribution_major_version is version('7', '==')
              else 'xyz' }}"
          - name: basic_input
            type: basics
            ratelimit_burst: 33333
          - name: basic_input
            type: basics
            ratelimit_burst: 44444
        logging_flows:
          - name: flow_0
            inputs: [basic_input]
            outputs:
              - files_test0
              - files_test1
              - forwards_severity_and_facility
              - forwards_facility_only
          - name: flow_1
            inputs: ["{{ __test_tag }}"]
            outputs: [files_test0, files_test1]
      include_role:
        name: linux-system-roles.logging
        public: true

    # notify Restart rsyslogd is executed at the end of this test task.
    # thus we have to force to invoke handlers
    - name: "Force all notified handlers to run at this point,
      not waiting for normal sync points"
      meta: flush_handlers

    - name: Ensure config file size and counts
      vars:
        __conf_count: 10
        __conf_size: less
        __conf_files:
          - "{{ __test_files_conf }}"
          - "{{ __test_forwards_conf_s_f }}"
          - "{{ __test_inputfiles_conf }}"
        __check_systemctl_status: true
      include_tasks: tasks/check_daemon_config_files.yml

    - name: Check if the files config exists
      stat:
        path: "{{ __test_files_conf }}"
      register: __result
      failed_when: not __result.stat.exists

    # yamllint disable rule:line-length
    - name: Check the filter and action in the files output config
      command: >-
        /bin/grep
        '\*.info;authpriv.none;auth.none;cron.none;mail.none.*{{ __default_system_log }}'
        {{ __test_files_conf }}
      changed_when: false
    # yamllint enable rule:line-length

    - name: Ensure logger message is logged in a file
      vars:
        __logging_index: 0
        __logging_file: "{{ __default_system_log }}"
      include_tasks: tasks/test_logger.yml

    - name: Generate a file to check severity_and_facility
      copy:
        dest: /tmp/__testfile__
        content: |
          #
          # Ansible managed
          #
          # system_role:logging
          ruleset(name="forwards_severity_and_facility") {
              local1.info action(name="forwards_severity_and_facility"
                  type="omfwd"
                  Target="host.domain"
                  Port="1514"
                  Protocol="tcp"
                  Template="RSYSLOG_ForwardFormat"
              )
          }
        mode: "0600"

    - name: Check severity_and_facility
      command: diff -B /tmp/__testfile__ '{{ __test_forwards_conf_s_f }}'
      changed_when: false

    - name: Check if the input files config exists
      stat:
        path: "{{ __test_inputfiles_conf }}"
      register: __result
      failed_when: not __result.stat.exists

    - name: Check the input call with tag={{ __test_tag }}
      lineinfile:
        path: "{{ __test_inputfiles_conf }}"
        line: "  {{ item }}"
        state: present
      check_mode: true
      register: _result
      failed_when: _result.changed
      loop:
        - type="imfile"
        - file="/var/log/inputdirectory/*.log"
        - tag="{{ __test_tag }}"

    # yamllint disable rule:line-length
    - name: "Create a test log file with a log message in
      {{ __test_inputfiles_dir }}"
      shell: |-
        set -euo pipefail
        echo '<167>Mar 20 01:00:00 11.22.33.44 tag msgnum:00000000:26:abcdefghijklmnopqrstuvwxyz' > {{ __test_inputfiles_dir }}/test.log
      changed_when: false

    - name: Check the fake test log message in {{ __default_system_log }}
      command: >-
        /bin/grep '{{ __test_tag }} .*abcdefghijklmnopqrstuvwxyz$' {{ __default_system_log }}
      changed_when: false
    # yamllint enable rule:line-length

    # yamllint disable rule:line-length
    - name: >-
        Create a test log file with a log message in the input
        which will not be logged due to the regex condition - input
        {{ __test_inputfiles_dir }}
      shell: |-
        set -euo pipefail
        echo '<167>Jul 22 01:00:00 11.22.33.44 tag msgnum:00000000:24:test message 0123456789' > {{ __test_inputfiles_dir }}/test.log
      changed_when: false

    - name: Check the fake second test log message is not in {{ __default_system_log }}
      command: >-
        /bin/grep '{{ __test_tag }} .*test message 0123456789$' {{ __default_system_log }}
      register: __result
      changed_when: false
      failed_when: __result.rc != 1
    # yamllint enable rule:line-length

    - name: Check ports managed by firewall and selinux
      include_tasks: tasks/check_firewall_selinux.yml

    - name: END TEST CASE 0; Clean up the deployed config
      vars:
        logging_purge_confs: true
        logging_inputs: []
        logging_outputs: []
        logging_flows: []
      include_role:
        name: linux-system-roles.logging
        public: true

    # notify Restart rsyslogd is executed at the end of this test task.
    # thus we have to force to invoke handlers
    - name: "Force all notified handlers to run at this point,
      not waiting for normal sync points"
      meta: flush_handlers

    - name: Check ports managed by firewall and selinux
      include_tasks: tasks/check_firewall_selinux.yml

    # TEST CASE 1
    - name: "TEST CASE 1; Ensure that the role runs with complicated flows
      - N x M combinations"
      vars:
        logging_outputs:
          - name: files_test0
            type: files
            severity: info
            exclude:
              - authpriv.none
              - auth.none
              - cron.none
              - mail.none
            path: "{{ __default_system_log }}"
          - name: files_test1
            type: files
            facility: authpriv,auth
            path: /var/log/secure
          - name: forwards_severity_and_facility
            type: forwards
            facility: local1
            severity: info
            target: host.domain
            tcp_port: 1514
          - name: forwards_facility_only
            type: forwards
            facility: local2
            target: host.domain
            tcp_port: 2514
        logging_inputs:
          - name: basic_input
            type: basics
            ratelimit_burst: 33333
          - name: "{{ __test_tag }}"
            type: files
            input_log_path: "{{ __test_inputfiles_dir }}/*.log"
        logging_flows:
          - name: flow_0
            inputs: [basic_input, "{{ __test_tag }}"]
            outputs: [files_test0]
          - name: flow_1
            inputs: [basic_input, "{{ __test_tag }}"]
            outputs: [files_test1]
          - name: flow_2
            inputs: [basic_input]
            outputs: [forwards_severity_and_facility]
          - name: flow_3
            inputs: [basic_input]
            outputs: [forwards_facility_only]
      include_role:
        name: linux-system-roles.logging
        public: true

    # notify Restart rsyslogd is executed at the end of this test task.
    # thus we have to force to invoke handlers
    - name: "Force all notified handlers to run at this point,
      not waiting for normal sync points"
      meta: flush_handlers

    - name: Ensure config file size and counts
      vars:
        __conf_count: 10
        __conf_size: less
        __conf_files:
          - "{{ __test_files_conf }}"
          - "{{ __test_forwards_conf_s_f }}"
          - "{{ __test_inputfiles_conf }}"
        __check_systemctl_status: true
      include_tasks: tasks/check_daemon_config_files.yml

    - name: Check the files config stat
      stat:
        path: "{{ __test_files_conf }}"
      register: __result
      failed_when: not __result.stat.exists

    # yamllint disable rule:line-length
    - name: Grep output to messages line
      command: >-
        /bin/grep
        '\*.info;authpriv.none;auth.none;cron.none;mail.none.*{{ __default_system_log }}'
        {{ __test_files_conf }}
      changed_when: false
    # yamllint enable rule:line-length

    - name: Ensure logger message is logged in a file
      vars:
        __logging_index: 1
        __logging_file: "{{ __default_system_log }}"
      include_tasks: tasks/test_logger.yml

    - name: Check the forwarding config stat
      stat:
        path: "{{ __test_forwards_conf_s_f }}"
      register: __result
      failed_when: not __result.stat.exists

    - name: Generate a file to check severity_and_facility
      copy:
        dest: /tmp/__testfile__
        content: |
          #
          # Ansible managed
          #
          # system_role:logging
          ruleset(name="forwards_severity_and_facility") {
              local1.info action(name="forwards_severity_and_facility"
                  type="omfwd"
                  Target="host.domain"
                  Port="1514"
                  Protocol="tcp"
                  Template="RSYSLOG_ForwardFormat"
              )
          }
        mode: "0600"

    - name: Check severity_and_facility
      command: diff -B /tmp/__testfile__ '{{ __test_forwards_conf_s_f }}'
      changed_when: false

    - name: Check the files config stat
      stat:
        path: "{{ __test_inputfiles_conf }}"
      register: __result
      failed_when: not __result.stat.exists

    - name: Check the input call with tag={{ __test_tag }}
      lineinfile:
        path: "{{ __test_inputfiles_conf }}"
        line: "  {{ item }}"
        state: present
      check_mode: true
      register: _result
      failed_when: _result.changed
      loop:
        - type="imfile"
        - file="/var/log/inputdirectory/*.log"
        - tag="{{ __test_tag }}"

    # yamllint disable rule:line-length
    - name: "Create a test log file with a log message in
      {{ __test_inputfiles_dir }}"
      shell: |-
        set -euo pipefail
        echo '<167>Dec 26 01:00:00 11.22.33.44 tag msgnum:00000001:26:ABCDEFGHIJKLMNOPQRSTUVWXYZ' >> {{ __test_inputfiles_dir }}/test.log
      changed_when: false

    - name: Check the fake test log message in {{ __default_system_log }}
      command: >-
        /bin/grep '{{ __test_tag }} .*ABCDEFGHIJKLMNOPQRSTUVWXYZ$' {{ __default_system_log }}
      changed_when: false
    # yamllint enable rule:line-length

    - name: Check ports managed by firewall and selinux
      include_tasks: tasks/check_firewall_selinux.yml

    - name: END TEST CASE 1; Clean up the deployed config
      vars:
        logging_purge_confs: true
        logging_inputs: []
        logging_outputs: []
        logging_flows: []
      include_role:
        name: linux-system-roles.logging
        public: true

    # notify Restart rsyslogd is executed at the end of this test task.
    # thus we have to force to invoke handlers
    - name: "Force all notified handlers to run at this point,
      not waiting for normal sync points"
      meta: flush_handlers

    - name: Check ports managed by firewall and selinux
      include_tasks: tasks/check_firewall_selinux.yml

    # TEST CASE 2
    - name: "TEST CASE 2; Absent state test -
      Running combination configured logging role twice"
      vars:
        logging_outputs:
          - name: files_test0
            type: files
            severity: info
            exclude:
              - authpriv.none
              - auth.none
              - cron.none
              - mail.none
            path: "{{ __default_system_log }}"
          - name: files_test1
            type: files
            facility: authpriv,auth
            path: /var/log/secure
          - name: forwards_severity_and_facility
            type: forwards
            facility: local1
            severity: info
            target: host.domain
            tcp_port: 1514
          - name: forwards_facility_only
            type: forwards
            facility: local2
            target: host.domain
            tcp_port: 2514
        logging_inputs:
          - name: basic_input
            type: basics
            ratelimit_burst: 33333
          - name: "{{ __test_tag }}"
            type: files
            input_log_path: "{{ __test_inputfiles_dir }}/*.log"
        logging_flows:
          - name: flow_0
            inputs: [basic_input]
            outputs:
              - files_test0
              - files_test1
              - forwards_severity_and_facility
              - forwards_facility_only
          - name: flow_1
            inputs: ["{{ __test_tag }}"]
            outputs: [files_test0, files_test1]
      include_role:
        name: linux-system-roles.logging
        public: true

    # notify Restart rsyslogd is executed at the end of this test task.
    # thus we have to force to invoke handlers
    - name: "Force all notified handlers to run at this point,
      not waiting for normal sync points"
      meta: flush_handlers

    - name: Ensure config file size and counts
      vars:
        __conf_count: 10
        __conf_size: less
        __conf_files:
          - "{{ __test_files_conf }}"
          - "{{ __test_forwards_conf_s_f }}"
          - "{{ __test_inputfiles_conf }}"
        __check_systemctl_status: true
      include_tasks: tasks/check_daemon_config_files.yml

    - name: Generate test config file to be overridden
      copy:
        dest: "{{ __test_basics_conf }}"
        content: |-
          # GENERATED BASICS CONFIG FILE
          module(load="imuxsock"    # provides support for local system logging
                                    # (e.g. via logger command)
                 SysSock.Use="off") # Turn off message reception via local log
                                    # socket
          module(load="imjournal"
                 StateFile="/var/lib/rsyslog/imjournal.state"
                 RateLimit.Burst="20000"
                 RateLimit.Interval="600"
                 PersistStateInterval="10")
          if
            ($inputname == "imjournal")
            then {
              call files_test0
          }
        mode: "0644"

    - name: Check ports managed by firewall and selinux
      include_tasks: tasks/check_firewall_selinux.yml

    - name: Deploy reduced config to output into local files
      vars:
        logging_outputs:
          - name: files_test0
            type: files
            severity: info
            exclude:
              - authpriv.none
              - auth.none
              - cron.none
              - mail.none
            path: "{{ __default_system_log }}"
          - name: files_test1
            type: files
            facility: authpriv,auth
            path: /var/log/secure
            state: absent
          - name: forwards_severity_and_facility
            type: forwards
            facility: local1
            severity: info
            target: host.domain
            tcp_port: 1514
            state: absent
          - name: forwards_facility_only
            type: forwards
            facility: local2
            target: host.domain
            tcp_port: 2514
            state: absent
        logging_inputs:
          - name: basic_input
            type: basics
            ratelimit_burst: 33333
          - name: "{{ __test_tag }}"
            type: files
            input_log_path: "{{ __test_inputfiles_dir }}/*.log"
            state: absent
        logging_flows:
          - name: flow_0
            inputs: [basic_input]
            outputs: [files_test0]
      include_role:
        name: linux-system-roles.logging
        public: true

    # notify Restart rsyslogd is executed at the end of this test task.
    # thus we have to force to invoke handlers
    - name: "Force all notified handlers to run at this point,
      not waiting for normal sync points"
      meta: flush_handlers

    - name: Ensure config file size and counts
      vars:
        __conf_count: 6
        __conf_size: less
        __conf_files:
          - "{{ __test_basics_conf }}"
        __check_systemctl_status: true
      include_tasks: tasks/check_daemon_config_files.yml

    - name: Check conf was updated {{ __test_basics_conf }}
      command: >-
        /bin/grep
        "# GENERATED BASICS CONFIG FILE"
        {{ __test_basics_conf }}
      register: __result
      changed_when: false
      failed_when: "__result is not failed"

    - name: Check rsyslog errors
      command: systemctl status rsyslog
      register: __result
      changed_when: false
      failed_when: "'error' in __result.stdout or __result is failed"

    - name: Check ports managed by firewall and selinux
      include_tasks: tasks/check_firewall_selinux.yml

    - name: END TEST CASE 2; Clean up the deployed config
      vars:
        logging_purge_confs: true
        logging_inputs: []
        logging_outputs: []
        logging_flows: []
      include_role:
        name: linux-system-roles.logging
        public: true

    - name: Cleaning up __testfile__
      file:
        path: "/tmp/__testfile__"
        state: absent

    - name: Check ports managed by firewall and selinux
      include_tasks: tasks/check_firewall_selinux.yml

    # notify Restart rsyslogd is executed at the end of this test task.
    # thus we have to force to invoke handlers
    - name: "Force all notified handlers to run at this point,
      not waiting for normal sync points"
      meta: flush_handlers

    - name: Assert {{ __default_system_log }}
      include_tasks: tasks/assert_varlogmessages.yml
