---
- name: "Ensure that the role runs with parameters from
  imfile to two elasticsearch outputs"
  hosts: all
  vars:
    __test_inputfiles_dir: /var/log/inputdirectory
    __test_inputfiles_conf: >-
      /etc/rsyslog.d/90-input-files-files_input.conf
    __test_outputfiles_conf: >-
      /etc/rsyslog.d/31-output-elasticsearch-elasticsearch_output.conf
    __test_ca_cert_name: es-ca.crt
    __test_cert_name: es-cert.pem
    __test_key_name: es-key.pem
    __test_ca_cert_target: /etc/rsyslog.d/es-ca-target.crt
    __test_cert_target: /etc/rsyslog.d/es-cert-target.pem
    __test_key_target: /etc/rsyslog.d/es-key-target.pem
    __test_el: elasticsearch_output
    __expected_err1: "Error: you specified tls: true; you must
      specify all 3 of ca_cert, cert, private_key, or all 3 of
      ca_cert_src, cert_src, private_key_src, or set tls:
      false in the configuration named elasticsearch_output"
    __certdir: /etc/pki/tls/certs/
    __keydir: /etc/pki/tls/private/
    __default_system_log: /var/log/messages
  tasks:
    - name: Run test
      block:
        - name: Create tempdir for test files
          tempfile:
            state: directory
            prefix: logging_test_
          delegate_to: localhost
          register: _tmpdir

        - name: Set __test_ca_cert path
          set_fact:
            __test_ca_cert: "{{ _tmpdir.path }}/{{ __test_ca_cert_name }}"

        - name: Set __test_cert path
          set_fact:
            __test_cert: "{{ _tmpdir.path }}/{{ __test_cert_name }}"

        - name: Set __test_key path
          set_fact:
            __test_key: "{{ _tmpdir.path }}/{{ __test_key_name }}"

        - name: "Local certs are copied to the target host with
          the default configuration path."
          copy:
            dest: "{{ item }}"
            content:
              This is a fake {{ item }}.
            mode: '0400'
          delegate_to: localhost
          loop:
            - "{{ __test_ca_cert }}"
            - "{{ __test_cert }}"
            - "{{ __test_key }}"

        # TEST CASE 0
        - name: "TEST CASE 0; local certs are copied to the target host
          with the default configuration path"
          vars:
            logging_outputs:
              - name: "{{ __test_el }}"
                type: elasticsearch
                server_host: logging-es
                server_port: 9200
                index_prefix: project.
                input_type: ovirt
                retryfailures: true
                ca_cert_src: "{{ __test_ca_cert }}"
                cert_src: "{{ __test_cert }}"
                private_key_src: "{{ __test_key }}"
            logging_inputs:
              - name: files_input
                type: files
                input_log_path: "{{ __test_inputfiles_dir }}/*.log"
            logging_flows:
              - name: flow_0
                inputs: [files_input]
                outputs: "[{{ __test_el }}]"
          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: 9
            __conf_size: less
            __conf_files:
              - "{{ __test_inputfiles_conf }}"
              - "{{ __test_outputfiles_conf }}"
            __check_systemctl_status: true
          include_tasks: tasks/check_daemon_config_files.yml

        - name: Check if the output files config exists
          stat:
            path: "{{ __test_outputfiles_conf }}"

        - name: Check if the copied key/certs files exist
          stat:
            path: "{{ item }}"
          loop:
            - "/etc/rsyslog.d/{{ __test_ca_cert | basename }}"
            - "/etc/rsyslog.d/{{ __test_cert | basename }}"
            - "/etc/rsyslog.d/{{ __test_key | basename }}"

        - name: Check certs in {{ __test_outputfiles_conf }}
          command: >-
            /bin/grep
            'tls.{{ item.key }}="{{ __certdir }}{{ item.value | basename }}"'
            {{ __test_outputfiles_conf }}
          with_dict:
            - cacert: "{{ __test_ca_cert }}"
            - mycert: "{{ __test_cert }}"
          changed_when: false

        - name: Check key in {{ __test_outputfiles_conf }}
          command: >-
            /bin/grep
            'tls.myprivkey="{{ __keydir }}{{ __test_key | basename }}"'
            {{ __test_outputfiles_conf }}
          changed_when: false

        - name: Check retryfailures in {{ __test_outputfiles_conf }}
          command: /bin/grep 'retryfailures="on"' {{ __test_outputfiles_conf }}
          changed_when: false

        - name: Check retryruleset in {{ __test_outputfiles_conf }}
          command: >-
            grep 'retryruleset="{{ __test_el }}"'
              {{ __test_outputfiles_conf }}
          changed_when: false

        - 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

        # 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: Clean up fake pki files
          file:
            path: "{{ item }}"
            state: absent
          loop:
            - "{{ __keydir }}es-key.pem"
            - "{{ __certdir }}es-cert.pem"
            - "{{ __certdir }}es-ca.crt"

        # TEST CASE 1
        - name: "TEST CASE 1; Elasticsearch config -
          local certs are copied to the target host with the specified path"
          vars:
            logging_outputs:
              - name: elasticsearch_output
                type: elasticsearch
                server_host: logging-es
                server_port: 9200
                index_prefix: project.
                input_type: ovirt
                retryfailures: false
                ca_cert_src: "{{ __test_ca_cert }}"
                cert_src: "{{ __test_cert }}"
                private_key_src: "{{ __test_key }}"
                ca_cert: "{{ __test_ca_cert_target }}"
                cert: "{{ __test_cert_target }}"
                private_key: "{{ __test_key_target }}"
            logging_inputs:
              - name: files_input
                type: files
                input_log_path: "{{ __test_inputfiles_dir }}/*.log"
            logging_flows:
              - name: flow_0
                inputs: [files_input]
                outputs: [elasticsearch_output]
          include_role:
            name: linux-system-roles.logging

        # 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: 9
            __conf_size: less
            __conf_files:
              - "{{ __test_inputfiles_conf }}"
              - "{{ __test_outputfiles_conf }}"
            __check_systemctl_status: true
          include_tasks: tasks/check_daemon_config_files.yml

        - name: Check if the output files config exists
          stat:
            path: "{{ __test_outputfiles_conf }}"

        - name: Check if the copied key/certs files exist
          stat:
            path: "{{ item }}"
          loop:
            - "{{ __test_ca_cert_target }}"
            - "{{ __test_cert_target }}"
            - "{{ __test_key_target }}"

        - name: Check key/certs in {{ __test_outputfiles_conf }}
          command: >-
            /bin/grep 'tls.{{ item.key }}="{{ item.value }}"'
            {{ __test_outputfiles_conf }}
          with_dict:
            - cacert: "{{ __test_ca_cert_target }}"
            - mycert: "{{ __test_cert_target }}"
            - myprivkey: "{{ __test_key_target }}"
          changed_when: false

        - 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

        # 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: Clean up fake pki files
          file:
            path: "{{ item }}"
            state: absent
          loop:
            - "{{ __test_ca_cert_target }}"
            - "{{ __test_cert_target }}"
            - "{{ __test_key_target }}"

        # TEST CASE 2
        - name: "TEST CASE 2; Elasticsearch config -
          local certs are not copied to the target host as tls is false"
          vars:
            logging_outputs:
              - name: elasticsearch_output
                type: elasticsearch
                server_host: logging-es
                server_port: 9200
                index_prefix: project.
                input_type: ovirt
                retryfailures: false
                tls: false
                ca_cert_src: "{{ __test_ca_cert }}"
                cert_src: "{{ __test_cert }}"
                private_key_src: "{{ __test_key }}"
            logging_inputs:
              - name: files_input
                type: files
                input_log_path: "{{ __test_inputfiles_dir }}/*.log"
            logging_flows:
              - name: flow_0
                inputs: [files_input]
                outputs: [elasticsearch_output]
          include_role:
            name: linux-system-roles.logging

        # 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: 9
            __conf_size: less
            __conf_files:
              - "{{ __test_inputfiles_conf }}"
              - "{{ __test_outputfiles_conf }}"
            __check_systemctl_status: true
          include_tasks: tasks/check_daemon_config_files.yml

        - name: Check if the output files config exists
          stat:
            path: "{{ __test_outputfiles_conf }}"

        - name: Check if the copied key/certs files do not exist
          stat:
            path: "{{ item }}"
          register: __result
          failed_when: __result.stat.exists
          loop:
            - "{{ __test_ca_cert_target }}"
            - "{{ __test_cert_target }}"
            - "{{ __test_key_target }}"

        - name: Check key/certs not in {{ __test_outputfiles_conf }}
          command: >-
            /bin/grep 'tls.{{ item.key }}="{{ item.value }}"'
            {{ __test_outputfiles_conf }}
          with_dict:
            - cacert: "{{ __test_ca_cert_target }}"
            - mycert: "{{ __test_cert_target }}"
            - myprivkey: "{{ __test_key_target }}"
          register: __result
          changed_when: false
          failed_when: __result.rc != 1

        - 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

        # 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

        # TEST CASE 3
        - name: Test case 3
          block:
            - name: "TEST CASE 3; Error case for Elasticsearch config -
              cert and ca_cert_src are missing"
              vars:
                logging_outputs:
                  - name: elasticsearch_output
                    type: elasticsearch
                    server_host: logging-es
                    server_port: 9200
                    index_prefix: project.
                    input_type: ovirt
                    retryfailures: false
                    ca_cert: /etc/rsyslog.d/ca_cert.crt
                    private_key: /etc/rsyslog.d/key.pem
                    cert_src: "{{ __test_cert }}"
                    private_key_src: "{{ __test_key }}"
                logging_inputs:
                  - name: files_input
                    type: files
                    input_log_path: "{{ __test_inputfiles_dir }}/*.log"
                logging_flows:
                  - name: flow_0
                    inputs: [files_input]
                    outputs: [elasticsearch_output, elasticsearch_output_ops]
              include_role:
                name: linux-system-roles.logging

            - name: Unreachable task
              fail:
                msg: UNREACH

          rescue:
            - name: Report error
              debug:
                msg: "Caught an expected error - {{ ansible_failed_result }}"
            - name: Assert...
              assert:
                that: ansible_failed_result.msg is match(__expected_err1)

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

        # 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: Clean up fake pki files
          file:
            path: "{{ item }}"
            state: absent
          loop:
            - /etc/rsyslog.d/ca_cert.crt
            - /etc/rsyslog.d/key.pem

        # TEST CASE 4
        - name: Test case 4
          block:
            - name: "TEST CASE 4; Error case for Elasticsearch config -
              although tls is true, no cert data are given."
              vars:
                logging_outputs:
                  - name: elasticsearch_output
                    type: elasticsearch
                    server_host: logging-es
                    server_port: 9200
                    index_prefix: project.
                    input_type: ovirt
                    retryfailures: false
                    tls: true
                logging_inputs:
                  - name: files_input
                    type: files
                    input_log_path: "{{ __test_inputfiles_dir }}/*.log"
                logging_flows:
                  - name: flow_0
                    inputs: [files_input]
                    outputs: [elasticsearch_output, elasticsearch_output_ops]
              include_role:
                name: linux-system-roles.logging

            - name: Unreachable task
              fail:
                msg: UNREACH

          rescue:
            - name: Report error
              debug:
                msg: "Caught an expected error - {{ ansible_failed_result }}"
            - name: Assert...
              assert:
                that: ansible_failed_result.msg is match(__expected_err1)

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

        # 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
      always:
        - name: Remove tempdir
          file:
            path: "{{ _tmpdir.path }}"
            state: absent
          delegate_to: localhost
