Creating a Custom Ansible Lookup Plugin in Python for Reading a File
By Luca Berton · Published 2024-01-01 · Category: installation
Create a custom Ansible lookup plugin in Python to extend capabilities for reading file contents on the Ansible controller, enhancing file retrieval.

Introduction
Ansible, a powerful automation tool, offers a wide range of built-in modules and plugins that simplify infrastructure management. However, there are scenarios where you may need to extend Ansible’s capabilities by creating custom plugins tailored to your specific needs. In this article, we will explore creating and using a custom Ansible file lookup plugin, which allows you to retrieve file contents from your Ansible controller’s file system during playbook execution.See also: Creating a Custom Ansible Lookup Plugin in Python for retrieving API token
What is a Lookup Plugin?
Ansible lookup plugins are used to retrieve data dynamically during playbook execution. They allow you to fetch information from various sources, such as databases, APIs, or external files, and use that data in your Ansible tasks.Links
- https://docs.ansible.com/ansible/latest/dev_guide/developing_plugins.html#lookup-plugins
- https://docs.ansible.com/ansible/latest/plugins/lookup.html#lookup-plugins
- https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-lookup-plugin-path
See also: Create Custom Ansible Modules: Python Module Development Guide
Unveiling the Custom File Lookup Plugin
Before delving into the details of the plugin, let’s take a closer look at the Python script provided at the beginning of this article. This script serves as an example of a custom Ansible file lookup plugin and consists of several essential components:1. Python 3 Headers
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type2. Documentation
DOCUMENTATION = r"""
name: file
author: Luca Berton <luca@ansiblepilot.com>
version_added: "0.1"
short_description: read file contents
description:
- This lookup returns the contents from a file on the Ansible controller's file system.
options:
_terms:
description: path(s) of files to read
required: True
option1:
description:
- Sample option that could modify plugin behaviour.
- This one can be set directly ``option1='x'`` or in ansible.cfg, but can also use vars or environment.
type: string
ini:
- section: file_lookup
key: option1
notes:
- if read in variable context, the file can be interpreted as YAML if the content is valid to the parser.
- this lookup does not understand globbing --- use the fileglob lookup instead.3. Imports
from ansible.errors import AnsibleError, AnsibleParserError
from ansible.plugins.lookup import LookupBase
from ansible.utils.display import Display4. Initialization
display = Display()5. Custom Lookup Module
class LookupModule(LookupBase):6. Custom Method (run)
def run(self, terms, variables=None, **kwargs):
# Plugin logic goes herePlease note that by design, Ansible Lookup plugins are historically usually used to pipe results into loops. Ansible expects a list as a return type. A common walkaround is to wrap our return value into a list, like:
return [ret]fileread.py Ansible lookup plugin looks like the:
# python 3 headers, required if submitting to Ansible
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: file
author: Luca Berton <luca@ansiblepilot.com>
version_added: "0.1"
short_description: read file contents
description:
- This lookup returns the contents from a file on the Ansible controller's file system.
options:
_terms:
description: path(s) of files to read
required: True
option1:
description:
- Sample option that could modify plugin behaviour.
- This one can be set directly ``option1='x'`` or in ansible.cfg, but can also use vars or environment.
type: string
ini:
- section: file_lookup
key: option1
notes:
- if read in variable context, the file can be interpreted as YAML if the content is valid to the parser.
- this lookup does not understand globbing --- use the fileglob lookup instead.
"""
from ansible.errors import AnsibleError, AnsibleParserError
from ansible.plugins.lookup import LookupBase
from ansible.utils.display import Display
display = Display()
class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs):
self.set_options(var_options=variables, direct=kwargs)
ret = []
for term in terms:
display.debug("File lookup term: %s" % term)
lookupfile = self.find_file_in_search_path(variables, 'files', term)
display.vvvv(u"File lookup using %s as file" % lookupfile)
try:
if lookupfile:
contents, show_data = self._loader._get_file_contents(lookupfile)
ret.append(contents.rstrip())
else:
raise AnsibleParserError()
except AnsibleParserError:
raise AnsibleError("could not locate file in lookup: %s" % term)
if self.get_option('option1') == 'do something':
pass
return retEnabling lookup plugins
Ansible automatically enables all available lookup plugins. To activate a custom lookup plugin, you can do so by placing it in one of the following locations:- Adjacent to Your Playbook:
- Inside a Collection:
plugins/lookup directory within that collection.
- Within a Standalone Role:
lookup_plugins directory within the role.
- Configured Directory Sources:
ansible.cfg configuration file, you can place the lookup plugin in one of those directories. The setting key is lookup_plugins under the [defaults] section or ANSIBLE_LOOKUP_PLUGINS environmental variable
Following these methods, you can activate and use custom lookup plugins in Ansible to extend its functionality according to your specific automation requirements.
See also: Executing Custom Lookup Plugins in the Ansible Automation Platform
Utilizing the Custom File Lookup Plugin
Now that we’ve examined the script’s components, let’s explore how to use this custom file lookup plugin effectively in Ansible playbooks. Here are the key steps:- Placing the Plugin File
- Using the Plugin in a Task
- name: Read File Contents
Ansible Playbook
The full Ansible Playbook code is the following:- exec.yml
---
- name: Exec lookup plugin
hosts: all
tasks:
- name: Read file from plugin
ansible.builtin.debug:
msg: "{{ lookup('fileread', 'example.txt') }}"- example.txt
sample textExecution
ansible-playbook -i inventory exec.yml
PLAY [Exec lookup plugin] *******************************************************************************
TASK [Gathering Facts] **********************************************************************************
ok: [demo.example.com]
TASK [Read file from plugin] ****************************************************************************
ok: [demo.example.com] => {
"msg": "sample text"
}
PLAY RECAP **********************************************************************************************
demo.example.com : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Conclusion
Creating custom lookup plugins in Ansible, such as the custom file lookup plugin discussed in this article, empowers you to extend Ansible’s functionality to meet your specific automation requirements. Whether you need to retrieve file contents, access data from external sources, or perform other dynamic operations, custom lookup plugins enable you to harness the full potential of Ansible in your infrastructure automation workflows. By understanding the structure of a lookup plugin and following the steps outlined in this article, you can streamline your automation tasks and achieve greater flexibility and control.Related Articles
Category: installation
Watch the video: Creating a Custom Ansible Lookup Plugin in Python for Reading a File — Video Tutorial