Ansible plugins are pieces of code that augment Ansible's core functionality. They allow you to extend Ansible's capabilities in various ways, such as adding new connection methods, lookup methods, or even custom actions. This topic will cover the different types of plugins available in Ansible, how to create your own plugins, and practical examples to help you understand their usage.

Types of Ansible Plugins

Ansible supports several types of plugins, each serving a different purpose:

  1. Action Plugins: Modify the behavior of Ansible modules.
  2. Callback Plugins: Respond to events during playbook execution.
  3. Connection Plugins: Define how Ansible connects to hosts.
  4. Lookup Plugins: Retrieve data from external sources.
  5. Filter Plugins: Transform data within Jinja2 templates.
  6. Test Plugins: Provide custom tests for conditionals in Jinja2 templates.
  7. Vars Plugins: Load variables from external sources.
  8. Inventory Plugins: Dynamically generate inventory from external sources.

Creating a Custom Filter Plugin

Let's create a simple custom filter plugin that reverses a string. This example will help you understand the structure and implementation of a filter plugin.

Step-by-Step Guide

  1. Directory Structure: Create a directory structure for your custom plugin. For this example, we'll place our plugin in a directory named filter_plugins.

    my_ansible_project/
    ├── filter_plugins/
    │   └── reverse.py
    └── playbook.yml
    
  2. Plugin Code: In the reverse.py file, write the following code:

    # reverse.py
    class FilterModule(object):
        def filters(self):
            return {
                'reverse_string': self.reverse_string
            }
    
        def reverse_string(self, value):
            return value[::-1]
    

    Explanation:

    • FilterModule class: Defines the plugin.
    • filters method: Returns a dictionary mapping filter names to their corresponding methods.
    • reverse_string method: Implements the logic to reverse a string.
  3. Using the Plugin in a Playbook: Create a playbook playbook.yml to use the custom filter plugin.

    # playbook.yml
    - name: Test custom filter plugin
      hosts: localhost
      vars:
        my_string: "Hello, Ansible!"
      tasks:
        - name: Reverse the string
          debug:
            msg: "{{ my_string | reverse_string }}"
    

    Explanation:

    • vars: Defines a variable my_string.
    • tasks: Uses the debug module to print the reversed string using the custom filter reverse_string.
  4. Running the Playbook: Execute the playbook to see the custom filter in action.

    ansible-playbook playbook.yml
    

    Expected Output:

    TASK [Reverse the string] ****************************************************
    ok: [localhost] => {
        "msg": "!elbisnA ,olleH"
    }
    

Practical Exercises

Exercise 1: Create a Custom Lookup Plugin

Objective: Create a custom lookup plugin that reads data from a local JSON file.

  1. Directory Structure:

    my_ansible_project/
    ├── lookup_plugins/
    │   └── json_lookup.py
    ├── data.json
    └── playbook.yml
    
  2. Plugin Code:

    # json_lookup.py
    import json
    
    class LookupModule(object):
        def __init__(self, *args, **kwargs):
            pass
    
        def run(self, terms, variables=None, **kwargs):
            with open(terms[0], 'r') as f:
                data = json.load(f)
            return [data]
    
  3. JSON Data (data.json):

    {
        "name": "Ansible",
        "type": "Automation"
    }
    
  4. Playbook (playbook.yml):

    - name: Test custom lookup plugin
      hosts: localhost
      tasks:
        - name: Read data from JSON file
          debug:
            msg: "{{ lookup('json_lookup', 'data.json') }}"
    
  5. Run the Playbook:

    ansible-playbook playbook.yml
    

Expected Output:

TASK [Read data from JSON file] 
ok: [localhost] => {
    "msg": [
        {
            "name": "Ansible",
            "type": "Automation"
        }
    ]
}

Exercise 2: Create a Custom Callback Plugin

Objective: Create a custom callback plugin that logs task results to a file.

  1. Directory Structure:

    my_ansible_project/
    ├── callback_plugins/
    │   └── log_results.py
    └── playbook.yml
    
  2. Plugin Code:

    # log_results.py
    from ansible.plugins.callback import CallbackBase
    
    class CallbackModule(CallbackBase):
        def v2_runner_on_ok(self, result):
            with open('task_results.log', 'a') as f:
                f.write(f"Task {result.task_name} succeeded: {result._result}\n")
    
  3. Playbook (playbook.yml):

    - name: Test custom callback plugin
      hosts: localhost
      tasks:
        - name: Test task
          debug:
            msg: "This is a test message"
    
  4. Run the Playbook:

    ANSIBLE_STDOUT_CALLBACK=log_results ansible-playbook playbook.yml
    

Expected Output: Check the task_results.log file for the logged task results.

Summary

In this section, we covered the different types of Ansible plugins and how they can extend Ansible's functionality. We walked through creating a custom filter plugin and provided practical exercises for creating custom lookup and callback plugins. Understanding and utilizing plugins can significantly enhance your Ansible automation capabilities, allowing for more flexible and powerful playbooks.

© Copyright 2024. All rights reserved