SyntaxError: future feature annotations is not defined
В чём суть. EL8 поставляется с Python 3.6. Модули Ansible 2.17 внутри используют синтаксис
from __future__ import annotations, который появился только в Python 3.7. Отсюда несовместимость. Причём упадут все модули - package_facts, package, yum, dnf, command, setup и другие. Механизм один и тот же: Ansible упаковывает любой модуль через AnsiballZ-фреймворк и запускает его локальным Python-интерпретатором на хосте.Единственный модуль который не использует Python на хосте вообще — raw. Он передаёт команду напрямую через SSH. Его и будем использовать для фиксов.
Сначала определяем ОС через raw:
- name: "Detect OS family via raw"
ansible.builtin.raw: |
if [ -f /etc/redhat-release ]; then
major=$(rpm -E '%{rhel}' 2>/dev/null || grep -oP '\d+' /etc/redhat-release | head -1)
echo "RedHat:${major}"
else
echo "other"
fi
register: os_detection
changed_when: false
Выставляем флаг:
- name: "Set EL8 flag"
ansible.builtin.set_fact:
is_el8: "{{ os_detection.stdout | trim is search('^RedHat:8') }}"
ansible.builtin.setup запускаем только для не-EL8:
name: "Populate ansible facts"
ansible.builtin.setup:
when: not is_el8
Для EL8 собираем нужные факты через raw:
- name: "Populate ansible facts via raw (EL8)"
# We already now that's 8 major version via is_el8 var
ansible.builtin.raw: |
python3 -c "
import platform, json, subprocess
print(json.dumps({
'ansible_distribution': open('/etc/system-release').read().split()[0],
'ansible_distribution_major_version': '8',
'ansible_os_family': 'RedHat',
'ansible_architecture': platform.machine(),
'ansible_hostname': platform.node(),
}))
" 2>/dev/null
register: raw_facts
changed_when: false
when: is_el8
- name: "Set ansible facts from raw (EL8)"
ansible.builtin.set_fact:
ansible_distribution: "{{ (raw_facts.stdout | trim | from_json).ansible_distribution }}"
ansible_distribution_major_version: "{{ (raw_facts.stdout | trim | from_json).ansible_distribution_major_version }}"
ansible_os_family: "{{ (raw_facts.stdout | trim | from_json).ansible_os_family }}"
ansible_architecture: "{{ (raw_facts.stdout | trim | from_json).ansible_architecture }}"
ansible_hostname: "{{ (raw_facts.stdout | trim | from_json).ansible_hostname }}"
when: is_el8
Все операции с пакетами для EL8 делаем тоже через raw:
- name: "Install package (EL8)"
ansible.builtin.raw: dnf -y install <package_name>
when: is_el8
- name: "Gather package list (EL8)"
ansible.builtin.raw: rpm -qa --qf '%{NAME}\n'
register: rpm_list
changed_when: false
when: is_el8
Можно конечно установить/скомпилировать свежий Python, но иногда нужно работать с тем что есть.
#ansible