ansible-lint icon indicating copy to clipboard operation
ansible-lint copied to clipboard

"couldn't resolve module/action" for local module used in role

Open jwodder opened this issue 2 years ago • 7 comments

I have an Ansible playbook laid out as follows:

./
├── hosts
├── library/
│   └── nop.py
├── playbook.yml
└── roles/
    └── myrole/
        └── tasks/
            └── main.yml

Contents of library/nop.py:

#!/usr/bin/python3
from ansible.module_utils.basic import AnsibleModule

DOCUMENTATION = r"""
---
module: nop
short_description: Does nothing
options:
"""


def run_module():
    module = AnsibleModule(argument_spec={}, supports_check_mode=True)
    module.exit_json(changed=False)


def main():
    run_module()


if __name__ == "__main__":
    main()

Contents of playbook.yml:

---
- name: Play
  hosts: all
  roles:
    - myrole

Contents of roles/myrole/tasks/main.yml:

---
- name: Do nothing
  nop:

Running ansible-lint on this directory gives the error:

WARNING  Listing 1 violation(s) that are fatal
syntax-check[specific]: couldn't resolve module/action 'nop'. This often indicates a misspelling, missing collection, or incorrect module path.
roles/myrole/tasks/main.yml:2:3


                  Rule Violation Summary                   
 count tag                    profile rule associated tags 
     1 syntax-check[specific] min     core, unskippable    

Failed: 1 failure(s), 0 warning(s) on 5 files.

However, if the nop module is invoked as a task directly in playbook.yml instead, ansible-lint is fine with it.

OS / ENVIRONMENT
ansible-lint 6.20.3 using ansible-core:2.15.5 ansible-compat:4.1.10 ruamel-yaml:0.17.35 ruamel-yaml-clib:0.2.8
  • ansible installation method: pip
  • ansible-lint installation method: pip

jwodder avatar Oct 16 '23 19:10 jwodder

My understanding is that the reason this works when using ansible-playbook is that when it loads the playbook file, the "adjacent" library and collections/ansible_collections directories are added implicitly relative to the location of the playbook file. Then when the playbook loads a role, those directories are already in the search paths, so the role is able to use the custom modules (and other plugins).

But when you run ansible-lint (with no parameters) such that it heuristically scans all the files in the current directory, it seems to sometimes - but not always? - load roles without first loading a playbook, meaning that the playbook-adjacent directories may or may not have been added to ansible's search paths.

I've been finding this behaviour to be inconsistent/unpredictable. For example, in my production ansible playbooks, I currently have two different roles that both use a custom module from my toplevel library directory. Right now ansible-lint is giving me this error on one of the roles but not the other - I've been pulling my hair out a bit on this since it's the same module in both roles, and I can't figure out why one gives an error when the other doesn't.

kepstin avatar Nov 30 '23 21:11 kepstin

anyone got simple workaround?

mshonichev avatar Dec 13 '23 14:12 mshonichev

I am running into the same error, however, only whilst using ansible-lint@main as a GitHub workflow action. Running ansible-lint locally did not fail, yet.

The used version locally is:

❯ ansible-lint --version
ansible-lint 6.22.1 using ansible-core:2.16.2 ansible-compat:4.1.10 ruamel-yaml:0.17.40 ruamel-yaml-clib:0.2.7

Edit:

Maybe my issue is not related. Adding the module/collection in requirements.yml solved the issue.

depate avatar Jan 04 '24 12:01 depate

I see this error when importing a role into the Ansible Galaxy. The importer ignores this problem.

https://galaxy.ansible.com/ui/standalone/roles/vbotka/ansible_lint/import_log/

===== LOADING ROLE ===== 
Importing with galaxy-importer 0.4.19 
Determined role name to be ansible_lint 
Linting role ansible_lint via ansible-lint... 
ansible-lint/tasks/packages.yml:9:7: syntax-check[specific]: couldn't resolve module/action 'community.general.pkgng'. This often indicates a misspelling, missing collection, or incorrect module path. 
...ansible-lint run complete 
Legacy role loading complete 

I see this problem on all my roles that use any collection. For example,

https://galaxy.ansible.com/ui/standalone/roles/vbotka/linux_postinstall/import_log/

Other "heavy-duty" roles suffer from this too. For example,

https://galaxy.ansible.com/ui/standalone/roles/mrlesmithjr/netplan/import_log/

vbotka avatar Feb 03 '24 15:02 vbotka

I am running into the same error, however, only whilst using ansible-lint@main as a GitHub workflow action. Running ansible-lint locally did not fail, yet.

The used version locally is:

❯ ansible-lint --version
ansible-lint 6.22.1 using ansible-core:2.16.2 ansible-compat:4.1.10 ruamel-yaml:0.17.40 ruamel-yaml-clib:0.2.7

Edit:

Maybe my issue is not related. Adding the module/collection in requirements.yml solved the issue.

Worked for me adding requirements.yml in the root folder.

[!NOTE]
For some reason it does not work with requirements.yaml. Seems like is not supported in the documentation.

plusiv avatar Apr 03 '24 06:04 plusiv

requirements.yml in the root folder does not help

shell> cat requirements.yml 
---
collections:
  - name: community.general
    source: https://galaxy.ansible.com

Galaxy reports the same error:

===== LOADING ROLE ===== 
Importing with galaxy-importer 0.4.20 
Determined role name to be ansible_lint 
Linting role ansible_lint via ansible-lint... 
ansible-lint/tasks/packages.yml:9:7: syntax-check[specific]: couldn't resolve module/action 'community.general.pkgng'. This often indicates a misspelling, missing collection, or incorrect module path. 
...ansible-lint run complete 
Legacy role loading complete

See: https://galaxy.ansible.com/ui/standalone/roles/vbotka/ansible_lint/import_log/

vbotka avatar Apr 04 '24 09:04 vbotka

A workaround which addresses the related issue described in #4042 (closed as duplicate of this issue) is to set the ANSIBLE_LIBRARY environment variable appropriately.

For example, given a role laid out like this:

.
├── defaults
│   └── main.yml
├── library
│   └── mongodb_replicaset_members.py
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
└── vars
    └── main.yml

Running ansible-lint in the top directory fails with:

syntax-check[unknown-module]: couldn't resolve module/action 'mongodb_replicaset_members'. This often indicates a misspelling, missing collection, or incorrect module path.

However, running ANSIBLE_LIBRARY=library ansible-lint succeeds.

Tested with:

$ ansible-lint --version
ansible-lint 24.2.1 using ansible-core:2.16.5 ansible-compat:4.1.11 ruamel-yaml:0.18.6 ruamel-yaml-clib:0.2.8

anl avatar Apr 05 '24 18:04 anl

Closing as this bug no longer happens with the code from main. Wait for the next release as I know one notable fix what merged but not released.

ssbarnea avatar May 07 '24 12:05 ssbarnea