Role uses module that another role installs - how to handle?

Hi. I have an issue I don’t know how to handle; I’m creating a load of roles to configure my Arch Linux system - the main file looks like this:

---
- name: Configure Arch Linux on ThinkPad E16 Laptop
  hosts: control
  vars_files:
    - vars/main.yml 

  roles: 
    - roles/base_packages
    - ssh_client_config
    - roles/git
    - roles/vim
    - roles/networkmanager
...
    - roles/alsa
    - roles/aur_builder
    - roles/brave
  handlers:
    - include: handlers/main.yml

The roles/aur_builder creates a user with sudo privileges on pacman, checks if the package is already installed (shell) and git clones the ansible-aur repository to /tmp if not and then does a makepkg to install it.

That all works fine - so the next role is the first one to use the new aur module:

- name: Install the Brave browser
  become: true
  become_user: aur_builder
  aur:
    name: brave-bin
    use: makepkg
    aur_only: true
    state: present

This also works fine - the problem is when I run it from scratch on a unconfigured system, because the aur module is not installed.

[andy@work-pc archlinux]$ ansible-playbook configure.yml --ask-vault-pass 
Vault password: 
ERROR! couldn't resolve module/action 'aur'. This often indicates a misspelling, missing collection, or incorrect module path.

The error appears to be in '/home/andy/ansible/archlinux/roles/brave/tasks/main.yml': line 1, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:


- name: Install the Brave browser
  ^ here

How can I handle this situation? I have no idea! Thanks.

You have probably installed the Ansible Collection - kewlfft.aur.

Have you tried the FQCN (Fully Qualified Collection Name) name?
As described in the example?

# This task uses the module's short name instead of its FQCN (Fully Qualified Collection Name).
# Use the short name if the module was installed as a local custom module.
# Otherwise, if it was installed through the `kewlfft.aur` collection, this task will fail.

# This task uses the `aur` module's FQCN.
- name: Install trizen using makepkg if it isn't installed already
  kewlfft.aur.aur:
    name: trizen
    use: makepkg
    state: present
  become: yes
  become_user: aur_builder

Ansible “compiles” a play before it starts to run it. All modules a play uses have to exist already.

So you’ll need to split your play into two plays. The first one can put everything in place that the second one needs to run.

---
- name: Configure Arch Linux on ThinkPad E16 Laptop - Phase 1
  hosts: control
  vars_files:
    - vars/main.yml 
  roles: 
    - roles/base_packages
    - ssh_client_config
    - roles/git
    - roles/vim
    - roles/networkmanager
    # […]
    - roles/alsa
    - roles/aur_builder
  handlers:
    - include: handlers/main.yml

- name: Configure Arch Linux on ThinkPad E16 Laptop - Phase 2
  hosts: control
  vars_files:
    - vars/main.yml 
  roles: 
    - roles/brave
  handlers:
    - include: handlers/main.yml
1 Like

Thanks - but when I try what you suggest and put all that in one file I seem to run into the same issue when running configure.yml. Or do I need to put phase 1 into its own file (configure_phase1.yml) and phase 2 into its own file (configure_phase2.yml) and run them completely separately?

Load your role with ansible.builtin.include_role
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/include_role_module.html

Then the requirements of that role will not be checked at the beginning

Installing a module while ansible-playbook is running and then using it is not a supported scenario. You may be able to get it working by being clever, but there’s no guarantee that it will continue working in the future.

Instead, you should built your process so that all of the Ansible content that you depend on is installed before you run ansible-playbook against a playbook that requires it. There are many ways you can approach this, such as calling ansible-galaxy directly to install the dependencies, or moving your existing steps into a bootstrap playbook and using a separate invocation of ansible-playbook.

3 Likes

@benjamin.schweizer - thanks! I think this is the solution I’ll go with for now. As a test I created:

[andy@work-pc archlinux]$ cat site.yml -p
---
- name: Configure Arch Linux on ThinkPad E16
  hosts: control
  vars_files:
    - vars/main.yml 
  roles: 
    - roles/aur_builder
  handlers:
    - include: handlers/main.yml

  tasks:
    # tasks that use aur module:
    - name: Install Brave
      include_role:
        name: brave

I uninstalled brave-bin and ansible-aur; deleted the cloned git repo from /tmp and ran. And it worked!!

Although I do take your point @flowerysong - I think my longer term plan will be to create a play for the initial installation that I run from a LiveUSB which includes the aur_builder role. That way when I reboot into my fresh OS I can run the configure part normally again.

Thanks for everyone’s help!