# ripped and ported from https://github.com/ansible/ansible/pull/50163/files, when interpreter discovery was added to ansible
---

- name: integration/interpreter_discovery/ansible_2_8_tests.yml
  hosts: test-targets
  gather_facts: true
  vars:
    DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_lt_2_12:
      centos:
        '6': /usr/bin/python
        '7': /usr/bin/python
        '8': /usr/libexec/platform-python
      debian:
        '9': /usr/bin/python
        '10': /usr/bin/python3
        '11': /usr/bin/python
        'NA': /usr/bin/python  # Debian 11, Ansible <= 7 (ansible-core <= 2.14)
        'bullseye/sid': /usr/bin/python  # Debian 11, Ansible 8 - 9 (ansible-core 2.15 - 2.16)
      ubuntu:
        '16': /usr/bin/python3
        '18': /usr/bin/python3
        '20': /usr/bin/python3

    DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_2_12_to_2_16:
      centos:
        '6': /usr/bin/python
        '7': /usr/bin/python
        '8': /usr/libexec/platform-python
      debian:
        '9': /usr/bin/python
        '10': /usr/bin/python3
        '11': /usr/bin/python3.9
        'NA': /usr/bin/python3.9  # Debian 11, Ansible <= 7 (ansible-core <= 2.14)
        'bullseye/sid': /usr/bin/python3.9  # Debian 11, Ansible 8 - 9 (ansible-core 2.15 - 2.16)
      ubuntu:
        '16': /usr/bin/python3
        '18': /usr/bin/python3
        '20': /usr/bin/python3

    DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_ge_2_17:
      debian:
        '10': /usr/bin/python3.7
        '11': /usr/bin/python3.9
        'bullseye/sid': /usr/bin/python3.9
      ubuntu:
        '20': /usr/bin/python3.8

    discovered_interpreter_expected: >-
      {%- if ansible_version_major_minor is version('2.12', '<', strict=True) -%}
      {{ DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_lt_2_12[distro][distro_major] }}
      {%- elif ansible_version_major_minor is version('2.17', '<', strict=True) -%}
      {{ DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_2_12_to_2_16[distro][distro_major] }}
      {%- else -%}
      {{ DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_ge_2_17[distro][distro_major] }}
      {%- endif -%}
  tasks:
    - name: can only run these tests on ansible >= 2.8.0
      block:
        - name: ensure we can override ansible_python_interpreter
          vars:
            ansible_python_interpreter: overriddenpython
          assert:
            that:
            - ansible_python_interpreter == 'overriddenpython'
            fail_msg: "'ansible_python_interpreter' appears to be set at a high precedence to {{ ansible_python_interpreter }},
                      which breaks this test."

        - name: snag some facts to validate for later
          set_fact:
            distro: '{{ ansible_facts.distribution | lower }}'
            distro_major: '{{ ansible_facts.distribution_major_version }}'
            system: '{{ ansible_facts.system }}'

        - name: test that python discovery is working and that fact persistence makes it only run once
          block:
          - name: clear facts to force interpreter discovery to run
            meta: clear_facts

          - name: trigger discovery with auto
            vars:
              ansible_python_interpreter: auto
            ping:
            register: auto_out

          - name: get the interpreter being used on the target to execute modules
            vars:
              ansible_python_interpreter: auto
            test_echo_module:
              facts_copy: "{{ ansible_facts }}"
            register: echoout

          # can't test this assertion:
          # - echoout.ansible_facts is not defined or echoout.ansible_facts.discovered_interpreter_python is not defined
          # because Mitogen's ansible_python_interpreter is a connection-layer configurable that
          # "must be extracted during each task execution to form the complete connection-layer configuration".
          # Discovery won't be reran though; the ansible_python_interpreter is read from the cache if already discovered
          - name: assert discovered python matches invoked python
            assert:
              that:
              - auto_out.ansible_facts.discovered_interpreter_python is defined
              - auto_out.ansible_facts.discovered_interpreter_python == echoout.discovered_python.as_seen
              - echoout.discovered_python.sys.executable.as_seen == echoout.running_python.sys.executable.as_seen
              fail_msg:
                - "auto_out: {{ auto_out }}"
                - "echoout: {{ echoout }}"
            when:
              # On macOS 11 (Darwin 20) CI runners the Python 2.7 binary always
              # reports the same path. I can't reach via symlinks.
              # >>> sys.executable
              # /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
              - is_mitogen
                or echoout.running_python.sys.version_info.major != 2
                or not (echoout.running_python.sys.platform == "darwin"
                        and echoout.running_python.platform.release.major == 20)


        - name: test that auto_legacy gives a dep warning when /usr/bin/python present but != auto result
          block:
          - name: clear facts to force interpreter discovery to run
            meta: clear_facts

          - name: trigger discovery with auto_legacy
            vars:
              ansible_python_interpreter: auto_legacy
            ping:
            register: legacy

          - name: check for dep warning (only on platforms where auto result is not /usr/bin/python and legacy is) for ansible 2.8-2.11
            # from ansible 2.12 on this changed
            #  - https://docs.ansible.com/ansible/devel/porting_guides/porting_guide_5.html#python-interpreter-discovery
            #  - https://docs.ansible.com/ansible/latest/reference_appendices/interpreter_discovery.html
            # default discovery method is now auto and will default to python3
            # and the message changed from a deprecation warning to a real warning that can not be suppressed by
            # using deprecation_warnings=False
            assert:
              that:
              - legacy.deprecations | default([]) | length > 0
              fail_msg: |
                legacy={{ legacy }}
            # only check for a dep warning if legacy returned /usr/bin/python and auto didn't
            when:
              - legacy.ansible_facts.discovered_interpreter_python == '/usr/bin/python'
              - auto_out.ansible_facts.discovered_interpreter_python != '/usr/bin/python'
              - ansible_version_major_minor is version('2.12', '<', strict=True)

          - name: check for warning (only on platforms where auto result is not /usr/bin/python and legacy is) from ansible 2.12 on
            assert:
              that:
              - legacy.warnings | default([]) | length > 0
              fail_msg: |
                legacy={{ legacy }}
            # only check for a warning if legacy returned /usr/bin/python and auto didn't
            when:
              - legacy.ansible_facts.discovered_interpreter_python == '/usr/bin/python'
              -  auto_out.ansible_facts.discovered_interpreter_python != '/usr/bin/python'
              -  ansible_version_major_minor is version('2.12', '>=', strict=True)

        - name: test that auto_silent never warns and got the same answer as auto
          block:
          - name: clear facts to force interpreter discovery to run
            meta: clear_facts

          - name: initial task to trigger discovery
            vars:
              ansible_python_interpreter: auto_silent
            ping:
            register: auto_silent_out

          - assert:
              that:
              - auto_silent_out.warnings is not defined
              - auto_silent_out.ansible_facts.discovered_interpreter_python == auto_out.ansible_facts.discovered_interpreter_python
              fail_msg: |
                auto_silent_out={{ auto_silent_out }}


        - name: test that auto_legacy_silent never warns and got the same answer as auto_legacy
          block:
          - name: clear facts to force interpreter discovery to run
            meta: clear_facts

          - name: trigger discovery with auto_legacy_silent
            vars:
              ansible_python_interpreter: auto_legacy_silent
            ping:
            register: legacy_silent

          - assert:
              that:
                - legacy_silent.warnings is not defined
                - legacy_silent.ansible_facts.discovered_interpreter_python == legacy.ansible_facts.discovered_interpreter_python
              fail_msg: |
                legacy_silent={{ legacy_silent }}

        - name: ensure modules can't set discovered_interpreter_X or ansible_X_interpreter
          block:
          - test_echo_module:
              facts_copy: "{{ ansible_facts }}"
              facts_to_override:
                ansible_discovered_interpreter_bogus: from module
                discovered_interpreter_bogus: from_module
                ansible_bogus_interpreter: from_module
                test_fact: from_module
            register: echoout

          - assert:
              that:
              - test_fact == 'from_module'
              - discovered_interpreter_bogus | default('nope') == 'nope'
              - ansible_bogus_interpreter | default('nope') == 'nope'
              # this one will exist in facts, but with its prefix removed
              - ansible_facts['ansible_bogus_interpreter'] | default('nope') == 'nope'
              - ansible_facts['discovered_interpreter_bogus'] | default('nope') == 'nope'

          - name: Check discovered interpreter matches expected
            assert:
              that:
                - auto_out.ansible_facts.discovered_interpreter_python == discovered_interpreter_expected
              fail_msg: |
                distro={{ distro }}
                distro_major= {{ distro_major }}
                system={{ system }}
                auto_out={{ auto_out }}
                discovered_interpreter_expected={{ discovered_interpreter_expected }}
                ansible_version.full={{ ansible_version.full }}
            when:
              - system in ['Linux']

          always:
          - meta: clear_facts
      when:
        - ansible_version_major_minor is version('2.8', '>=', strict=True)
  tags:
    - ansible_2_8_tests
