Inquiry on Defining Default Fact Module for Custom Ansible Collections

Hi All,

I’m an Ansible Collections developer. I have a problem when defining the default fact module for our collections.

Our Ansible collections (e.g., FortiOS Ansible Collection, FortiManager Ansible Collection) use a self-defined httpapi plugin and don’t have a default fact module. It worked well before Ansible Core 2.18.2. For example, in the FortiManager Ansible Collection, I specify our custom httpapi plugin in the host file with the following configuration, and it can run our playbooks without error before Ansible-core 2.18.2:

ansible_network_os=fortinet.fortimanager.fortimanager
ansible_connection=httpapi

After the Ansible-core 2.18.2, when using our Ansible Collections, I received “No fact modules available and we could not find a fact module for your network OS (fortinet.fortimanager.fortimanager), try setting one via the FACTS_MODULES configuration.”

TASK [Gathering Facts] *************************************************************************************************
task path: <masked_path>/debug_fortimanager/ansible_collections/fortinet/scripts/debug/292/fmg_dvmdb_device_get.yml:1
redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
The full traceback is:
NoneType: None
fatal: [fortimanager746]: FAILED! => {
    "changed": false,
    "msg": "No fact modules available and we could not find a fact module for your network OS (fortinet.fortimanager.fortimanager), try setting one via the `FACTS_MODULES` configuration."
}

PLAY RECAP *************************************************************************************************************
fortimanager746            : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

In the ansible-core 2.18.2 changelog, it says “gather_facts action will now issues errors and warnings as appropriate if a network OS is detected but no facts modules are defined for it.”

The issue seems to be that Ansible cannot locate a default facts module for our network OS. My question is how to define a default fact module in the custom collection?

I attempted the following approach: creating a file “/plugins/modules/{collection_name}_facts.py”, and in the “/meta/runtime.yml”, adding

plugin_routing:
    facts:
        redirect: fortinet.{collection_name}.{collection_name}_facts

However, it is not working under my testing.

There is a workaround: adding “ansible_facts_modules=setup” in the host file or adding “gather_facts: false” in the playbook. But we prefer not to do it since it requires the user to make the changes in their files.

Is there a way for us to correctly define a default facts module for custom collection, so users do not need to make any additional configuration changes?

Thank you very much for your time and support!

A collection cannot define such a thing on its own at this time. There is a hardcoded list in core for fact modules that existed for ansible 2.9.

Users can however configure facts modules to execute in ansible.cfg, but at that point, it makes the playbooks config dependent, which is not recommended. So I’d recommend users just be explicit and call the module when they need it.

2 Likes

Thanks for the prompt response and suggestion.

@sivel @Xinwei in a related context question, given that the user would need to provide the fact module, what or where is the canonical way to notify the user of information like this? Outside of simply stating it in the role README, wanted to see if there was a more elegant way to indicate that users need to gather facts, and to do so, they must provide the fact module.

@sivel and @bcoca would a patch to this area be accepted? ansible/lib/ansible/config/base.yml at v2.18.5 · ansible/ansible · GitHub