Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources

Advanced Module Usage in Ansible

Introduction

Ansible is a powerful automation tool used for configuration management, application deployment, and task automation. Modules are the building blocks in Ansible, providing functionality to perform various tasks. In this tutorial, we will dive into advanced usage of Ansible modules, covering topics such as custom modules, module arguments, and advanced module functionality.

Custom Modules

While Ansible provides a wide range of built-in modules, there might be cases where you need to create custom modules to meet specific requirements. Custom modules can be written in any language that can return JSON, but Python is the most commonly used language due to its simplicity and integration with Ansible.

Example: Creating a Custom Module

Let's create a simple custom module in Python that returns a greeting message.

    #!/usr/bin/python

    import json

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

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

        result = dict(
            changed=False,
            message=''
        )

        name = module.params['name']
        result['message'] = f"Hello, {name}!"

        module.exit_json(**result)

    from ansible.module_utils.basic import AnsibleModule
    if __name__ == '__main__':
        main()
                

Save this script as greet.py and make it executable. Now you can use this custom module in your playbooks.

Example Playbook

    - name: Use custom greet module
      hosts: localhost
      tasks:
        - name: Greet the user
          greet:
            name: "Ansible User"
          register: result

        - name: Print greeting message
          debug:
            msg: "{{ result.message }}"
                

Module Arguments

Modules in Ansible accept arguments that control their behavior. These arguments are defined using the argument_spec dictionary in the module. Arguments can have various types such as str, bool, list, etc. Here, we'll explore how to define and use module arguments.

Example: Module with Multiple Arguments

Let's extend our greet module to accept an optional argument for the greeting message.

    #!/usr/bin/python

    import json

    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
        )

        result = dict(
            changed=False,
            message=''
        )

        name = module.params['name']
        greeting = module.params['greeting']
        result['message'] = f"{greeting}, {name}!"

        module.exit_json(**result)

    from ansible.module_utils.basic import AnsibleModule
    if __name__ == '__main__':
        main()
                

Advanced Module Functionality

Modules can include advanced functionality such as handling check mode, returning complex results, and managing errors. Here, we'll discuss some of these advanced features.

Handling Check Mode

Check mode allows you to see what changes would be made without actually applying them. In our module, we can use supports_check_mode=True to support check mode. Inside the module, we can check if the module is in check mode using module.check_mode.

Example: Check Mode

    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
        )

        result = dict(
            changed=False,
            message=''
        )

        if module.check_mode:
            module.exit_json(**result)

        name = module.params['name']
        greeting = module.params['greeting']
        result['message'] = f"{greeting}, {name}!"

        module.exit_json(**result)
                

Returning Complex Results

Modules can return complex results as dictionaries. These results can then be accessed in playbooks using the register keyword.

Example: Complex Results

    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
        )

        result = dict(
            changed=False,
            message='',
            data=dict()
        )

        if module.check_mode:
            module.exit_json(**result)

        name = module.params['name']
        greeting = module.params['greeting']
        result['message'] = f"{greeting}, {name}!"
        result['data'] = {
            'name': name,
            'greeting': greeting
        }

        module.exit_json(**result)
                

Error Handling

Handling errors gracefully is important in module development. Ansible provides the fail_json method to exit the module with an error message.

Example: Error Handling

    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
        )

        result = dict(
            changed=False,
            message=''
        )

        try:
            name = module.params['name']
            greeting = module.params['greeting']
            result['message'] = f"{greeting}, {name}!"
        except Exception as e:
            module.fail_json(msg=str(e))

        module.exit_json(**result)
                

Conclusion

In this tutorial, we explored advanced usage of Ansible modules, including creating custom modules, using module arguments, handling check mode, returning complex results, and managing errors. By mastering these advanced techniques, you can create powerful and flexible automation solutions using Ansible.