os specific pre_task in ansible

Viewed 739

I would like to run a set of raw commands (to install python) if a given operating system on the target host is OpenBSD

I have to run these checks as pre_tasks (because to run anything as a task Python must already be present on the target system)

What I do not understand is, whether any OS characteristics variables are available in pre_task stage (like ansible_os_family)

- name: Check for Python 
      raw: test -e /usr/bin/python
      changed_when: false
      failed_when: false
      register: check_python


- name: Install Python on OpenBSD
      # raw: test -e /usr/bin/apt && (apt -y update && apt install -y python-minimal) || (yum -y install python libselinux-python)
      raw: pkg_add -r python%3  
      when: check_python.rc != 0
      when: ansible_os_family == "OpenBSD" # <-- problem here

I seem to get a problem when trying to use ansible_os_family

Is there a way to enable the pre_tasks without me writing my own os family checks?

PS. I used the above python installation code, following recommendation here: [1] https://relativkreativ.at/articles/how-to-install-python-with-ansible

2 Answers

Following your latest comments, as said earlier by @Vladimir and myself, you will not be able to use ansible's facts variables to detect the OS on hosts without python since it is impossible to gather facts (i.e. play the setup module). You need to do that job on your own for this first step.

I don't have a BSD system I can access. So the below is totally untested for your platform. But I believe it should work, or at least put you on track. Check the content of /etc/os-release on your system to adapt the regex if needed. The one I wrote gave a correct result on Ubuntu, Debian, Centos, RHEL and on RedHat UBI and Alpine docker images.

---
- name: Fix hosts with no python at all
  hosts: all
  gather_facts: false

  tasks:
    - name: Perform a dirty OS detection if python is not installed
      raw: |-
        if which python > /dev/null || which python3 > /dev/null; then
          echo installed
        else
          sed -n "s/^NAME=\"\(.*\)\"/\\1/p" /etc/os-release
        fi
      changed_when: false
      register: dirty_detect

    - name: Print message when already installed
      debug:
        msg: Host {{ inventory_hostname }} already has python. Next will skip.
      when: dirty_detect.stdout_lines[0] == 'installed'

    - name: Install python on openbsd if needed
      raw: |-
        pkg_add -r python%3
      become: true
      when: dirty_detect.stdout_lines[0] == 'OpenBSD'

    - name: Install python on Ubuntu if needed
      raw: |-
        apt install -y python3
      become: true
      when: dirty_detect.stdout_lines[0] == 'Ubuntu'

- name: Back to normal life with ansible
  hosts: all

  tasks:
    - name: Now we gathered facts and we can use all facts vars
      debug:
        msg: Host {{ inventory_hostname }} is running {{ ansible_os_familly }}

    - name: We might have left hosts with python 2.7 only above, make sure python3 is installed
      package:
        name: python3
      become: true

Q: "Is there a way to enable the pre_tasks without me writing my own os family checks?"

A: No. It is not. Python is needed to collect the facts.


See the verbose output. For example the output of connecting FreeBSD 12 remote host from the Ubuntu controller

shell> ansible --version
ansible 2.9.6
...
python version = 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0]

shell> ansible test_01 -m setup -vvv

ESTABLISH SSH CONNECTION FOR USER: admin SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="admin"' -o ConnectTimeout=30 -o ControlPath=/export/home/admin.config/.ansible/cp/5a3ab05cf7 test_01 '/bin/sh -c '"'"'/usr/local/bin/python3.7 && sleep 0'"'"''

Without Python installed the module will crash

(127, b'', b'/bin/sh: /usr/bin/python: not found\n') Failed to connect to the host via ssh: /bin/sh: /usr/bin/python: not found [WARNING]: No python interpreters found for host test_01 (tried ['/usr/bin/python', 'python3.7', 'python3.6', 'python3.5', 'python2.7', 'python2.6', '/usr/libexec/platform- python', '/usr/bin/python3', 'python']) test_01 | 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 }

Related