cloud-init icon indicating copy to clipboard operation
cloud-init copied to clipboard

Ansible module doesn't find collections installed by the playbook

Open jjo93sa opened this issue 8 months ago • 2 comments

Bug report

We have a playbook that looks something like this:

- name: Example customization playbook
  hosts: 127.0.0.1
  connection: local
  gather_facts: true
  tasks:
    - name: Install roles and collections
      community.general.ansible_galaxy_install:
        type: both
        requirements_file: ./requirements.yml

    - name: Execute a role from collection installed from requirements.yml
      ansible.builtin.include_role:
        name: my_namespace.my_collection.role1

And we invoke that like this:

    ansible:
      install_method: pip
      package_name: ansible
      run_user: my_user
      pull:
        url: "<url>"
        playbook_name: "custom.yml"

Debug logs show that the collection is installed in the first task. However, it appears that ansible-pull can't find the role:

TASK [Execute a role] **********************************************************
        ERROR! the role 'my_namespace.my_collection.role1' was not found in /home/my_user/.ansible/pull/test/roles:/home/my_user/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:/home/my_user/.ansible/pull/test

Indeed, ansible-pull doesn't seem to be looking in the collection install path (although it is clearly able to use the Community collection?). Executing ansible --version as a task in the playbook shows:

                "stdout_lines": [
                    "ansible [core 2.17.0]",
                    "  config file = None",
                    "  configured module search path = ['/home/imy_user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']",
                    "  ansible python module location = /home/my_user/.local/lib/python3.10/site-packages/ansible",
                    "  ansible collection location = /home/my_user/.ansible/collections:/usr/share/ansible/collections",
                    "  executable location = /home/my_user/.local/bin/ansible",
                    "  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)",
                    "  jinja version = 3.0.3",
                    "  libyaml = True"
                ]

And the collection is indeed installed to the first location in the "ansible collection location" path.

Things we've tried to solve the problem, but haven't:

  • Using an ansible.cfg file in the repository cloned to force the collection installation location, but it has made no difference.
  • Splitting the playbook into two plays, one to install the collection, the second to execute the role, but this hasn't helped
  • Both import_role vs include_role
  • Executing the role from "roles:" rather than as part of a task

Manually logging into the instance and running the custom.yml playbook completes as expected - showing both that the collection is installed and that the "system" Ansible can find it.

We don't know a priori if a requirements.yml file exists, which makes using the "galaxy/actions" more problematic, and it isn't clear from the documentation if installing from a requirements.yml file works:

  galaxy:
    actions:
      - ["ansible-galaxy", "install", "-r", "./requirements.yml"]

TL;DR It doesn't seem possible to use roles from within a collection installed as part of the playbook executed by the Ansible module.

Steps to reproduce the problem

See sample playbook and cloud-init config above

Environment details

  • Operating System Distribution: Ubuntu 20.04 and 22.04

  • Cloud-init version:

Ubuntu 20.04 - /usr/bin/cloud-init 24.1.3-0ubuntu1~20.04.1
Ubuntu 22.04 - /usr/bin/cloud-init 24.1.3-0ubuntu1~22.04.1
  • Cloud provider, platform or installer type: Openstack with Terraform launching Ubuntu cloud images

cloud-init logs

The relevant section appears to be:

2024-06-18 07:51:22,085 - util.py[WARNING]: Running module ansible (<module 'cloudinit.config.cc_ansible' from '/usr/lib/python3/dist-packages/cloudinit/config/cc_ansible.py'>) failed
2024-06-18 07:51:22,085 - util.py[DEBUG]: Running module ansible (<module 'cloudinit.config.cc_ansible' from '/usr/lib/python3/dist-packages/cloudinit/config/cc_ansible.py'>) failed
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/cloudinit/config/modules.py", line 286, in _run_modules
    ran, _r = cc.run(
  File "/usr/lib/python3/dist-packages/cloudinit/cloud.py", line 60, in run
    return self._runners.run(name, functor, args, freq, clear_on_fail)
  File "/usr/lib/python3/dist-packages/cloudinit/helpers.py", line 156, in run
    results = functor(**args)
  File "/usr/lib/python3/dist-packages/cloudinit/config/cc_ansible.py", line 202, in handle
    run_ansible_pull(ansible, deepcopy(pull_cfg))
  File "/usr/lib/python3/dist-packages/cloudinit/config/cc_ansible.py", line 258, in run_ansible_pull
    stdout = pull.pull(
  File "/usr/lib/python3/dist-packages/cloudinit/config/cc_ansible.py", line 90, in pull
    stdout, _ = self.do_as([*self.cmd_pull, *args])
  File "/usr/lib/python3/dist-packages/cloudinit/config/cc_ansible.py", line 100, in do_as
    return self.distro.do_as(command, self.run_user, **kwargs)
  File "/usr/lib/python3/dist-packages/cloudinit/distros/__init__.py", line 1225, in do_as
    return subp.subp(
  File "/usr/lib/python3/dist-packages/cloudinit/subp.py", line 298, in subp
    raise ProcessExecutionError(
cloudinit.subp.ProcessExecutionError: Unexpected error while running command.
Command: ['su', '-', 'my_user', '-c', 'env PATH=$PATH ansible-pull --url=https://<url> custom.yml']
Exit code: 1
Reason: -
Stdout: Starting Ansible Pull at 2024-06-18 07:51:15
        /home/ipuuser/.local/bin/ansible-pull --url=<url> custom.yml
        [WARNING]: Could not match supplied host pattern, ignoring: test
        localhost | CHANGED => {
            "after": "bd5cab726a44c0640f65b6607770bd29ffae3bb8",
            "before": null,
            "changed": true
        }
        [WARNING]: No inventory was parsed, only implicit localhost is available
        [WARNING]: provided hosts list is empty, only localhost is available. Note that
        the implicit localhost does not match 'all'
        [WARNING]: Could not match supplied host pattern, ignoring: test1
        ERROR! the role 'my_namespace.my_collection.role1' was not found in /home/my_user/.ansible/pull/test1/roles:/home/my_user/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:/home/my_user/.ansible/pull/test1
        
        The error appears to be in '/home/my_user/.ansible/pull/test/custom.yml': line 54, column 15, but may
        be elsewhere in the file depending on the exact syntax problem.
        
        The offending line appears to be:
        
              ansible.builtin.include_role:
                name: my_namespace.my_collection.role1
                      ^ here
Stderr: 

jjo93sa avatar Jun 18 '24 09:06 jjo93sa