Developing particular plugin types
Action plugins
It allows the user to integrate local processing as well as local data with the module functionality. A user can create an action plugin by creating a new class with the Base class as the parent:
from Ansible.plugins.action import ActionBase
class ActionModule(ActionBase):
pass
Then from there, using the _execute_module method, start executing the module to call the original module. Once the module is successfully executed, the user can modify the module return data.
module_return = self._execute_module(module_name='<NAME_OF_MODULE>',
module_args=module_args,
task_vars=task_vars, tmp=tmp)
Cache plugins
They store gathered facts as well as data retrieved by the inventory plugins. To use the self.set_options() and self.get_option(<option_name>) the user needs to import cache plugins using the cache_loader. If the user imports a cache plugin directly into the code base, then the user can only access options via Ansible.constants and can break the cache plugin's ability to be used by an inventory plugin.
from ansible.plugins.loader import cache_loader
[...]
plugin = cache_loader.get('custom_cache', **cache_kwargs)
Cache plugins have two base classes: BaseCacheModule, which is for database-backed caches, and BaseCacheFileModule, which is for file-backed caches.
If the user wants to create a cache plugin, then the user needs to start by creating a new CacheModule class with an appropriate base class. If the user is creating a plugin using an _init_ method, then the user should initialize the base class with any provided args and kwargs so that it's compatible with the inventory plugin cache options. The base class makes a call to self.set_options(direct=kwargs). The self.get_option(<option_name>) should be used for accessing the cache options once the base class _init_ method has been called.
Options such as _uri, _prefix, and _timeout should be taken by new cache plugins to be consistent with the existing cache plugins.
from ansible.plugins.cache import BaseCacheModule
class CacheModule(BaseCacheModule):
def __init__(self, *args, **kwargs):
super(CacheModule, self).__init__(*args, **kwargs)
self._connection = self.get_option('_uri')
self._prefix = self.get_option('_prefix')
self._timeout = self.get_option('_timeout')
If in case the user uses the BaseCacheModule, then the user must implement the methods get, contains, keys, set, delete, flush, and copy. A boolean value which indicates whether the key exists or not should be returned by the contains method. The get method doesn't raise a KeyError in case the cache has expired.
If in case the user uses the BaseFileCacheModule, then the user must implement _load and _dump methods as they will be called from the base class methods get and set.
Connection plugins
It allows Ansible to connect with the target hosts allowing it to execute tasks on them. Though Ansible comes with many connection plugins, at a time, only one can be used per host. Native ssh, paramiko SSH, and local connection types are some of the most commonly used connection plugins. All of these have the ability to be used in playbooks and /usr/bin/ansible to connect to remote machines.
Since the ansible version 2.1, the smart connection plugins have been introduced. The smart connection type allows the Ansible to automatically select either paramiko or the openssh connection plugin, depending on the system's capabilities.
If the user wants to create a new connection plugin, then copy the format of one of the existing connection plugins and just drop it into the connection directory onto the local plugin path.
Filter plugins
They are used to manipulate the data. It is a feature of Jinja2 and is also available for use in Jinja2 templates, which are used by the template module. All the plugins can be extended easily, but the user can have several per file rather than having a file for each. Almost all of the filter plugins shipped with the Ansible reside in core.py.
These plugins don't use the standard configuration and documentation system.
Ansible evaluates variables only when they are required; therefore, the filter plugins should propagate the exceptions jinja2.exceptions.UndefinedError and AnsibleUndefinedVariable to make sure that the undefined variables are only fatal when necessary.
try:
cause_an_exception(with_undefined_variable)
except jinja2.exceptions.UndefinedError as e:
raise AnsibleUndefinedVariable("Something happened, this was the original exception: %s" % to_native(e))
except Exception as e:
raise AnsibleFilterError("Something happened, this was the original exception: %s" % to_native(e))
Inventory Plugins
They parse inventory sources. They also form a representation of the inventory in an in-memory style. They were added in the Ansible version 2.4.
Test plugins
They are used to verify the data. It is a feature of Jinja2 and is also available for use in Jinja2 templates, which are used by the template module. All the plugins can be easily extended, but the user can have several per file rather than having a file for each one. Almost all of the filter plugins shipped with the Ansible reside in core.py. They are very useful in conjunction with filter plugins such as map and select. They are also available for conditional directives such as when.
They don't use the standard configuration and documentation system.
Ansible evaluates the variables only when they are required, therefore the test plugins should propagate the exceptions jinja2.exceptions.UndefinedError as well as AnsibleUndefinedVariable to make sure that the undefined variables are only fatal when necessary.
try:
cause_an_exception(with_undefined_variable)
except jinja2.exceptions.UndefinedError as e:
raise AnsibleUndefinedVariable("Something happened, this was the original exception: %s" % to_native(e))
except Exception as e:
raise AnsibleFilterError("Something happened, this was the original exception: %s" % to_native(e))
Vars plugins
They inject additional variable data into the ansible runs which didn't come from an inventory source, playbook, or command line. 'Host_vars" and "group_vars" are some of the playbook constructs that work using vars plugins.
Though they were partially implemented in Ansible 2.0, they were rewritten so that they could be fully implemented in Ansible 2.4. They are supported from ansible 2.10 & newer.
Since ansible 2.4, they are executed as and when needed when preparing to execute a task. This helps reduce the extra cost of the 'always execute' behavior in the older versions. Since ansible 2.10, their execution can be toggled by the user to run either while preparing to execute or after importing an inventory source.
A user can create vars plugins using the REQUIRES_ENABLED class variable that is by default not enabled. In case the vars plugin resides in a collection, then it can't be enabled by default. The user must use REQUIRES_ENABLED in all the collections-based vars plugins.
To make users enable the plugin, set the class variable REQUIRES_ENABLED:
class VarsModule(BaseVarsPlugin):
REQUIRES_ENABLED = True
Also see, How to Check Python Version in CMD
Frequently Asked Questions
Which language should be used for writing plugins?
The plugins should be written in Python.
Why should the user convert the strings returned by the plugin into Python's Unicode type?
It is necessary to convert any strings returned by the plugin into Python's Unicode type so that these strings can run through Jinja2.
Mention any commonly used connection plugin.
One of the commonly used connection plugins is paramiko SSH.
Conclusion
In this article, we have extensively discussed Ansible-Developing Plugins.
After reading about the Ansible-Developing Plugins, are you not feeling excited to read/explore more articles on Development? Don't worry; Coding Ninjas has you covered. To learn about system design strategies, how to start learning full-stack web development and what are top web development languages.
If you want to enhance your skills in Data Structures and Algorithms, Competitive Programming, JavaScript, etc., you should check out our Guided path column at Coding Ninjas Studio. We at Coding Ninjas Studio organise many contests in which you can participate. You can also prepare for the contests and test your coding skills by taking the mock test series available. In case you have just started the learning process, and your dream is to crack major tech giants like Amazon, Microsoft, etc., then you should check out the most frequently asked problems and the interview experiences of your seniors that will surely help you in landing a job in your dream company.
Do upvote if you find the blogs helpful.
Happy Learning!
