Search code examples
pythonansibleservice-discovery

How to log ansible_python_interpreter failed IPs using Ansible?


I'm not looking for a solution to fix the below python interpreter discovery failed error:

TASK [Gathering Facts]
fatal: [123.123.123.123]: FAILED! => {"changed": false, 
  "module_stderr": "/bin/sh: 1: /usr/bin/python: not found\n", 
  "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", 
  "rc": 127

Instead, what i need is to log IPs where python discovery failed.

Below is my plabook where i'm able to log failed, telnet and failed ssh from my ansible host. However, I wish to also log failed python discovery.

Below is my playbook.

- name: Play 3- check nodes
  hosts: localhost
  tasks:

   - name: Check all port numbers are accessible from current host
     include_tasks: /app/checkssh/innertelnet.yml
     with_items: "{{ groups['all_hosts'] }}"

cat innertelnet.yml

---
       - wait_for:
           host: "{{ item }}"
           port: 22
           state: started
           delay: 0
           timeout: 2
         ignore_errors: yes
         register: netstatoutput

       - raw: "echo telnet failed on IP {{ item }}"
         delegate_to: localhost
         when: netstatoutput.failed == 'True'

       - name: Check ssh connectivity
         ignore_errors: yes
         raw: "ssh -o BatchMode=yes root@{{ item }} echo success"
         register: sshcheck

       - raw: "echo ssh failed on IP {{ item }}"
         delegate_to: localhost
         when: not netstatoutput.failed and sshcheck is unreachable

For successful ssh connectivity how can i detect if python_interpreter was discovered by ansible on the target host ?

Thus, I'm looking for the below:

   - raw: "Python could not be discovered on IP {{ item }}"
     delegate_to: localhost
     when: <>

How to suppress the fatal error of discover_python_interpreter and log all the IPs using raw module where it is missing.


Solution

  • The only way to check Python interpreter discovery is to actually run a task on the remote host.

    The first thing you need to do is to disable automatic fact gathering, since this requires that Ansible is able to run the setup module on your target hosts:

    - hosts: all
      gather_facts: false
    

    With fact gathering disabled, you have more control over things. For example, we can do something like this:

    - hosts: all
      gather_facts: false
      tasks:
        - block:
          - ping:
            register: check
          rescue:
          - delegate_to: localhost
            when: >
                "No python interpreters found" in check.warnings|default([])|join("\n")
            debug:
              msg: "{{ inventory_hostname }} has no python interpreter"
    

    If I run this against two hosts, node0 without Python and node1 with Python, we see:

    PLAY [all] *********************************************************************
    
    TASK [ping] ********************************************************************
    fatal: [node0]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "module_stderr": "/bin/sh: /usr/bin/python: not found\n", "module_stdout": "", "msg": "The module failed to execute correctly, you probably need to set the interpreter.\nSee stdout/stderr for the exact error", "rc": 127}
    ok: [node1]
    
    TASK [debug] *******************************************************************
    ok: [node0 -> localhost] => {
        "msg": "node0 has no python interpreter"
    }
    
    PLAY RECAP *********************************************************************
    node0                      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0   
    node1                      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0