ansibleansible-module

Is it possible to use an Ansible Core Module within a Custom Module?


There is also this related question "Access predefined ansible modules in custom module" but unfortunately without an helpful answer.

In general, I would like to create a Custom Module which uses some Core Modules.

If I e.g. want to use the Core Module file, I could of course look at the main function and extract the parts needed by importing the functions required.

So to create / remove a file this would require to use something like

from ansible.modules.file import check_owner_exists, check_group_exists, keep_backward_compatibility_on_timestamps, ensure_file_attributes, ensure_absent

Then copy the required code and use it accordingly.

This seems like a huge workaround for something as simple as importing a core module in a custom module.

Are there any better ways to call the file module in a custom module?


Solution

  • As @U880D already pointed out, it is not possible call a module from another module.

    The way around this is to use an action plugin (https://docs.ansible.com/ansible/latest/dev_guide/developing_plugins.html#developing-actions. The most prominent example is probably the template module:

    In the hope it simplifies life for others, here is what I ended up using.

    So to run the file module inside our own "module" we create library/custom_file.py (the "module" file containing only the documentation) with content

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    # Copyright: ...
    # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
    
    DOCUMENTATION = r"""
    ---
    <...>
    """
    EXAMPLES = r"""
    ---
    <...>
    """
    RETURN = r"""
    ---
    <...>
    """
    

    and action_plugins/custom_file.py with

    #!/usr/bin/env python3
    
    from ansible.plugins.action import ActionBase
    
    class ActionModule(ActionBase):
        def run(self, tmp=None, task_vars=None):
            result = super(ActionModule, self).run(tmp, task_vars)
    
            result.update(self._execute_module(
                module_name="file", module_args=file_args, task_vars=task_vars, tmp=tmp
            ))
    
            return result
    

    now we can use this "module" in our playbook test.yml

    - name: Test my new module
      gather_facts: false
      hosts: localhost
      tasks:
        - name: Run custom file module
          custom_file:
            path: /etc/foo.conf
            owner: foo
            group: foo
            mode: '0644'