Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources

Ansible Custom Modules

Introduction

Ansible is a powerful automation tool that allows users to manage and configure systems. While Ansible comes with a vast array of built-in modules, there may be situations where you need to create custom modules to perform specific tasks that are not covered by the built-in modules. This tutorial will guide you through creating your own custom modules in Ansible.

Prerequisites

Before you begin, ensure that you have the following:

  • Ansible installed on your system.
  • Basic understanding of Python programming.
  • Basic knowledge of YAML and Ansible playbooks.

Creating a Basic Custom Module

To create a custom module, you'll need to write a Python script that follows certain conventions. Let's start by creating a simple custom module that returns a message.

Step 1: Create the Python Script

Create a new file named my_custom_module.py and add the following code:

#!/usr/bin/python

from ansible.module_utils.basic import AnsibleModule

def main():
    module_args = dict(
        name=dict(type='str', required=True)
    )

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    name = module.params['name']
    result = dict(
        changed=False,
        message='Hello, {}'.format(name)
    )

    module.exit_json(**result)

if __name__ == '__main__':
    main()
                

Step 2: Make the Script Executable

Ensure that the script is executable by running the following command:

$ chmod +x my_custom_module.py

Step 3: Create a Playbook to Use the Custom Module

Create a new playbook file named custom_module_playbook.yml and add the following content:

- name: Test custom module
  hosts: localhost
  tasks:
    - name: Run custom module
      my_custom_module:
        name: World
      register: result

    - name: Print result
      debug:
        var: result.message
                

Step 4: Run the Playbook

Run the playbook using the following command:

$ ansible-playbook custom_module_playbook.yml

You should see output similar to the following:

PLAY [Test custom module] ***********************************************

TASK [Gathering Facts] *******************************************************
ok: [localhost]

TASK [Run custom module] *****************************************************
ok: [localhost]

TASK [Print result] **********************************************************
ok: [localhost] => {
    "result.message": "Hello, World"
}

PLAY RECAP *******************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0
                

Handling Module Parameters

Custom modules can accept various parameters to perform different tasks. Let's enhance our module to accept two parameters: name and greeting.

Step 1: Update the Python Script

Modify the my_custom_module.py script as follows:

#!/usr/bin/python

from ansible.module_utils.basic import AnsibleModule

def main():
    module_args = dict(
        name=dict(type='str', required=True),
        greeting=dict(type='str', required=False, default='Hello')
    )

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    name = module.params['name']
    greeting = module.params['greeting']
    result = dict(
        changed=False,
        message='{}, {}'.format(greeting, name)
    )

    module.exit_json(**result)

if __name__ == '__main__':
    main()
                

Step 2: Update the Playbook

Update the custom_module_playbook.yml to use the new parameter:

- name: Test custom module
  hosts: localhost
  tasks:
    - name: Run custom module
      my_custom_module:
        name: World
        greeting: Hi
      register: result

    - name: Print result
      debug:
        var: result.message
                

Step 3: Run the Playbook

Run the playbook again using the same command:

$ ansible-playbook custom_module_playbook.yml

You should see output similar to the following:

PLAY [Test custom module] ***********************************************

TASK [Gathering Facts] *******************************************************
ok: [localhost]

TASK [Run custom module] *****************************************************
ok: [localhost]

TASK [Print result] **********************************************************
ok: [localhost] => {
    "result.message": "Hi, World"
}

PLAY RECAP *******************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0
                

Advanced Features

Custom modules can perform more complex tasks, handle errors, and support check mode. In this section, we'll cover these advanced features.

Error Handling

To handle errors, use the module.fail_json() method. Modify the script to fail if the name parameter is "error":

#!/usr/bin/python

from ansible.module_utils.basic import AnsibleModule

def main():
    module_args = dict(
        name=dict(type='str', required=True),
        greeting=dict(type='str', required=False, default='Hello')
    )

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    name = module.params['name']
    greeting = module.params['greeting']
    
    if name == 'error':
        module.fail_json(msg='An error occurred!')

    result = dict(
        changed=False,
        message='{}, {}'.format(greeting, name)
    )

    module.exit_json(**result)

if __name__ == '__main__':
    main()
                

Supporting Check Mode

Check mode allows you to see what changes would be made without actually making them. Ensure your module supports check mode by checking module.check_mode:

#!/usr/bin/python

from ansible.module_utils.basic import AnsibleModule

def main():
    module_args = dict(
        name=dict(type='str', required=True),
        greeting=dict(type='str', required=False, default='Hello')
    )

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    name = module.params['name']
    greeting = module.params['greeting']
    
    if name == 'error':
        module.fail_json(msg='An error occurred!')

    result = dict(
        changed=False,
        message='{}, {}'.format(greeting, name)
    )

    if module.check_mode:
        module.exit_json(**result)
    
    # Perform any actions here

    module.exit_json(**result)

if __name__ == '__main__':
    main()
                

Conclusion

In this tutorial, we've covered the basics of creating custom modules in Ansible. We started with a simple module and gradually added more features, including handling parameters, error handling, and supporting check mode. With this knowledge, you can create custom modules tailored to your specific needs and extend Ansible's functionality even further.