Ansible-navigator to automate tests

Hello,

I would like to use ansible-navigator to run playbook in EE, in order to test playbooks and collections.

I see that ansible-navigator run can run playbooks in EE: it starts the container, it runs the playbook, it exits the EE container, all in non interactive mode. This is good for test, I always start with the same initial conditions of a new fresh container. This is like it happens in AWX.

So I would like to use ansible-navigator run in this way.

First problem I encountered: AWX allows me to define a project requirements.yml. Ansible-navigator can’t.

This is not a problem, I try with a playbook:

- name: Install requirements on controller node
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Install collections
      community.general.ansible_galaxy_install:
        type: both
        requirements_file: requirements.yml

- name: Other play requiring requirements
  hosts: myhost
  ...

Unfortunately there is not a kind of meta to refresh the collection list runtime and the following play fails (ERROR! couldn't resolve module/action…). I should replay the playbook, but with ansible-navigator run I can’t.

Let suppose I can run the playbook again. Required collections has been installed at previous step and other plays can proceed. This is not true at all.

If I’m testing a collection I can have a play like:

- name: Role installation process
  hosts: linux
  vars:
    proxy_env:
      http_proxy: "{{ myrole_proxy }}"
      https_proxy: "{{ myrole_proxy }}"
      no_proxy: "{{ no_proxy | default(omit) }}"

  environment: "{{ proxy_env }}"

  roles:
    - mynamespace.mycollection.myrole

The result is

PLAY [Role installation process] **********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************************************************************
fatal: [linux_ubuntu24]: FAILED! => {"msg": "The field 'environment' has an invalid value, which includes an undefined variable. The error was: {'http_proxy': '{{ myrole_proxy }}', 'https_proxy': '{{ myrole_proxy }}', 'no_proxy': '{{ no_proxy | default(omit) }}'}: 'myrole_proxy' is undefined. 'myrole_proxy' is undefined. {'http_proxy': '{{ myrole_proxy }}', 'https_proxy': '{{ myrole_proxy }}', 'no_proxy': '{{ no_proxy | default(omit) }}'}: 'myrole_proxy' is undefined. 'myrole_proxy' is undefined. {'http_proxy': '{{ myrole_proxy }}', 'https_proxy': '{{ myrole_proxy }}', 'no_proxy': '{{ no_proxy | default(omit) }}'}: 'myrole_proxy' is undefined. 'myrole_proxy' is undefined. {'http_proxy': '{{ myrole_proxy }}', 'https_proxy': '{{ myrole_proxy }}', 'no_proxy': '{{ no_proxy | default(omit) }}'}: 'myrole_proxy' is undefined. 'myrole_proxy' is undefined"}

The first error could depends on community.general.ansible_galaxy_install.

The second error could depends on meta refresh_inventory. I install inventory with:

    - name: Setup inventory file
      ansible.builtin.copy:
        src: "group_vars_linux.yml"
        dest: "/etc/ansible/hosts/group_vars/linux.yml"
        owner: root
        group: root
        mode: '0644'
    - name: Refresh inventory
      ansible.builtin.meta: refresh_inventory

I defined myrole_proxy in /etc/ansible/hosts/group_vars/linux.yml and it seems that refresh_inventory does not take into account this var.

Again, if I run the playbook again, then it works as expected. But I have to run it three times…

Complete example

- name: Install requirements on controller node
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Install collections
      community.general.ansible_galaxy_install:
        type: both
        requirements_file: requirements.yml

- name: Prepare inventory hosts
  hosts: localhost
  tags: setup
  gather_facts: false
  tasks:
    - name: Setup inventory folder
      ansible.builtin.file:
        path: /etc/ansible/hosts/group_vars
        state: directory
        mode: '0755'
    - name: Setup inventory file
      ansible.builtin.copy:
        src: "../group_vars_linux.yml"
        dest: "/etc/ansible/hosts/group_vars/linux.yml"
        owner: root
        group: root
        mode: '0644'
    - name: Refresh inventory with new containers
      ansible.builtin.meta: refresh_inventory

- name: Role installation process
  hosts: linux
  vars:
    no_proxy: localhost,10.0.0.0/8
    proxy_env:
      http_proxy: "{{ myrole_proxy }}"
      https_proxy: "{{ myrole_proxy }}"
      no_proxy: "{{ no_proxy | default(omit) }}"
  environment: "{{ proxy_env }}"
  roles:
    - mynamespace.mycoll.myrole
# cat /etc/ansible/hosts/group_vars/linux.yml
---
myrole_proxy: http://10.1.2.3:3124

It’s difficult to notice these issues if you don’t try to run all in row.

A solution is to run ansible-navigator exec with a shell script with three ansible-playbook commands.

Obviously, another solution is to provide all inventory details and collection dependencies in EE at build time. In this way I should have an EE for every project, it’s not very good for me.

I wonder if there is a better solution running ansible-navigator run.

Do you have any hints?
Thank you very much
Kind Regards
Marco

Hello, all of this is quite confusing, but maybe the following points could help :

ansible-navigator is a kind of enhanced ansible-playbook command, that you use more a less like ansible-playbook, but which allows to specify an execution environment into which the playbook is executed.

In light of this, you don’t need to install anything with a requirements.yml file, as the collections and other dependencies are expected to be already present in the EE.

Second, I might be wrong, but my understanding is that the environment keyword is a task keyword, not a play keyword, so it’s not useful to define it at the beginning of a playbook.

Then, the usal way to provide an inventory to ansible-navigator is to specify it with the -i option, as for ansible-playbook.

So far you could launch a playbook like this :
ansible-navigator run my-playbook.yml --eei ghcr.io/ansible-community/community-ee-minimal:latest

And you can use :
ansible-navigator run my-playbook.yml --ee false -m stdout -i inventory
to mimic ansible-playbook command.

best regards, Johan

1 Like

@johan well put, thanks

1 Like