--- # roles/control_node_sanity/tasks/main.yml # Non-invasive control node checks for Ansible runtime health. - name: Collect kernel information ansible.builtin.command: uname -a register: sanity_uname changed_when: false - name: Compute repository root path ansible.builtin.set_fact: sanity_repo_root: "{{ playbook_dir | dirname | dirname }}" - name: Collect distribution metadata ansible.builtin.command: cat /etc/os-release register: sanity_os_release changed_when: false - name: Gather ansible core version details ansible.builtin.command: ansible --version register: sanity_ansible_version changed_when: false - name: Gather ansible-playbook version details ansible.builtin.command: ansible-playbook --version register: sanity_ansible_playbook_version changed_when: false - name: Gather python version details ansible.builtin.command: python3 --version register: sanity_python_version changed_when: false - name: Check if ansible-lint is available ansible.builtin.command: ansible-lint --version register: sanity_ansible_lint changed_when: false failed_when: false - name: Determine ansible.cfg source path ansible.builtin.command: ansible --version register: sanity_cfg_source changed_when: false args: chdir: "{{ sanity_repo_root }}" - name: Capture effective Ansible config overrides ansible.builtin.command: ansible-config dump --only-changed register: sanity_config_dump changed_when: false args: chdir: "{{ sanity_repo_root }}" - name: Validate inventory graph parses ansible.builtin.command: ansible-inventory -i inventory/hosts.ini --graph register: sanity_inventory_graph changed_when: false args: chdir: "{{ sanity_repo_root }}" - name: Validate onboarding playbook syntax ansible.builtin.command: >- ansible-playbook -i inventory/hosts.ini playbooks/onboarding/generic_host.yml --syntax-check register: sanity_syntax_generic_host changed_when: false args: chdir: "{{ sanity_repo_root }}" - name: Validate docker management playbook syntax ansible.builtin.command: >- ansible-playbook -i inventory/hosts.ini playbooks/docker/manage_containers.yml --syntax-check register: sanity_syntax_manage_containers changed_when: false args: chdir: "{{ sanity_repo_root }}" - name: Parse ansible version number from output ansible.builtin.set_fact: sanity_ansible_version_number: "{{ ansible_version.full | default('0.0.0') }}" - name: Normalize python version text ansible.builtin.set_fact: sanity_python_version_text: >- {{ (sanity_python_version.stdout | default('') | trim) if (sanity_python_version.stdout | default('') | trim | length > 0) else (sanity_python_version.stderr | default('') | trim) }} - name: Split python version parts ansible.builtin.set_fact: sanity_python_major: "{{ sanity_python_version_text | regex_search('([0-9]+)\\.([0-9]+)', '\\1') | first | default('0') | int }}" sanity_python_minor: "{{ sanity_python_version_text | regex_search('([0-9]+)\\.([0-9]+)', '\\2') | first | default('0') | int }}" - name: Set status flags ansible.builtin.set_fact: sanity_ansible_ok: "{{ sanity_ansible_version_number is version(control_node_sanity_min_ansible_version, '>=') }}" sanity_python_ok: >- {{ (sanity_python_major == control_node_sanity_expected_python_major) and (sanity_python_minor >= control_node_sanity_expected_python_minor_min) }} sanity_lint_ok: "{{ sanity_ansible_lint.rc == 0 }}" sanity_cfg_loaded: "{{ 'config file = ' in sanity_cfg_source.stdout and 'config file = None' not in sanity_cfg_source.stdout }}" - name: Optionally enforce ansible-lint availability ansible.builtin.assert: that: - sanity_lint_ok fail_msg: "ansible-lint is required but not installed on this control node" success_msg: "ansible-lint is installed" when: control_node_sanity_require_lint | bool - name: Assert minimum sanity gates ansible.builtin.assert: that: - sanity_ansible_ok - sanity_python_ok - sanity_cfg_loaded - sanity_inventory_graph.rc == 0 - sanity_syntax_generic_host.rc == 0 - sanity_syntax_manage_containers.rc == 0 fail_msg: "Control node sanity gates failed. Review summary output." success_msg: "Control node sanity gates passed" - name: Print control node sanity summary ansible.builtin.debug: msg: - "System: {{ sanity_uname.stdout }}" - "Ansible core: {{ sanity_ansible_version_number }} (min {{ control_node_sanity_min_ansible_version }})" - "Python: {{ sanity_python_version.stdout }}" - "Ansible config loaded: {{ sanity_cfg_loaded }}" - "Inventory parse: {{ sanity_inventory_graph.rc == 0 }}" - "Syntax generic_host.yml: {{ sanity_syntax_generic_host.rc == 0 }}" - "Syntax manage_containers.yml: {{ sanity_syntax_manage_containers.rc == 0 }}" - "ansible-lint installed: {{ sanity_lint_ok }}" - "Reality note: host_key_checking is {{ 'disabled' if ('HOST_KEY_CHECKING' in sanity_config_dump.stdout and ' = False' in sanity_config_dump.stdout) else 'not explicitly disabled' }}"