Ansible's own extension terminology

Ansible’s own extension terminology #

I saved this terminology for the appendix because this book is mostly about sample code and showing how you might solve specific problems, and a first-principles understanding of how to name what is not the first milestone to achieving that goal.

However, it is useful to know the terms that the Ansible development team uses, and frankly the official documentation is not as clear on this point as it could be, so it’s worth describing it for reference in case you need it.

Ansible recognizes two types of extension: modules and plugins:

Modules #

Modules are standalone scripts that conform to a specific interface which Ansible can call, and which are expected to return JSON objects. Modules can be written in any language.

If you want to build a new task that Ansible can perform, peer with the template or shell or any other built-in actions, you might start by building a module.

Modules execute on the target system, and they don’t have access to any Ansible context like variables or facts, unless that context is passed in as an argument. For example, a custom argument will not be able to read the built-in Ansible fact {{ ansible_hostname }}, but it could accept a hostname: parameter that is passed when the task is invoked like this:

- name: Use a custom module
  custom_module_name:
    hostname: "{{ ansible_hostname }}"

Ansible has documentation for writing custom modules.

Plugins #

Plugins have deeper integration into Ansible, and can be used for more things. A plugin might implement logging to a SEIM product, or allow connecting to a device that does not have a POSIX shell available such as some switches and routers.

Plugins execute on the Ansible controller, and they have access to all facts and variables. Plugins must be written in Python.

Plugins can also be used to implement tasks that Ansible can perform, like modules can, as long as that task can run on the Ansible controller. So a task that queries a remote service that the Ansible controller has access to and returns a value could be implemented as an action, but creating a file on the target machine with the results of that query is not possible in an action by itself.

Ansible has documentation for writing custom plugins.

TODO

Add comprehensive list of things plugins can implement

Using modules and plugins together #

Readers may see some missing functionality in the description above: what if a task must both modify the target host and read Ansible context like facts and variables? Indeed, how does the template task do its work, since it can read facts/variables and write hydrated templates to the target host?

It turns out that action plugins, running on the Ansible controller and with full access to facts/variables, can call modules, running on the target server and able to change it.

TODO

Add example of using modules and plugins together

Inventory scripts #

Ansible inventories can be implemented as flat files or plugins, but they can also be shell scripts that support a couple of options and return data in a specific format.

TODO

Improve prose for inventory scripts

Terminology confusion in the Ansible documentation #

The Ansible documentation is not very consistent about what it calls these concepts.

For instance, Ansible calls its built-in actions “modules” even though at least some of them are implemented using action plugins and are not modules at all, or a plugin that calls a module.

Because modules execute on the target host, and most tasks are about configuring the target host, many actions/tasks that Ansible can perform (like template or shell, etc) are called “modules” by the Ansible documentation. In fact, this is true even in the URL: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/template_module.html

Oddly, the API for building plugins requires that you export a class called a module, e.g. action plugins must export an ActionModule, and lookup plugins must export a LookupModule, etc.

Finally, an Ansible module is not the same as a Python module, although it could be. An Ansible module might not be written in Python at all, or it might be written as a whole Python package consisting of sub-modules.

With this in mind, I have a few recommendations to keep things clear. There are of course just rules of thumb.

  • When referring to something that Ansible can do, like template or shell or set_fact, use the term “action” or “task”, not “module” or “plugin”.
  • When referring to something that extends Ansible with custom code, use the term “Ansible extension”. This is intentionally very broad, covering not just modules and plugins but also inventory scripts.

Further reference #