Core module program flow and glossary (#15355)
* Reformat glossary as a sphinx glossary so that :term: will work. * Add a document decribing program flow for executing modules * Feedback from @docschick * More feedback from docschick for the Program Flow: Modules doc * Changes to address docschick's feedback on the glossary * Add note section for async plugin * make singular
This commit is contained in:
parent
40d0bb7aef
commit
8d60b298a4
4 changed files with 874 additions and 404 deletions
|
@ -10,6 +10,7 @@ Learn how to build modules of your own in any language, and also how to extend A
|
||||||
developing_inventory
|
developing_inventory
|
||||||
developing_modules
|
developing_modules
|
||||||
developing_plugins
|
developing_plugins
|
||||||
|
developing_core
|
||||||
developing_test_pr
|
developing_test_pr
|
||||||
developing_releases
|
developing_releases
|
||||||
|
|
||||||
|
|
401
docsite/rst/developing_program_flow_modules.rst
Normal file
401
docsite/rst/developing_program_flow_modules.rst
Normal file
|
@ -0,0 +1,401 @@
|
||||||
|
.. _flow_modules:
|
||||||
|
|
||||||
|
=======
|
||||||
|
Modules
|
||||||
|
=======
|
||||||
|
|
||||||
|
This in-depth dive helps you understand Ansible's program flow to execute
|
||||||
|
modules. It is written for people working on the portions of the Core Ansible
|
||||||
|
Engine that execute a module. Those writing Ansible Modules may also find this
|
||||||
|
in-depth dive to be of interest, but individuals simply using Ansible Modules
|
||||||
|
will not likely find this to be helpful.
|
||||||
|
|
||||||
|
.. _flow_types_of_modules:
|
||||||
|
|
||||||
|
Types of Modules
|
||||||
|
================
|
||||||
|
|
||||||
|
Ansible supports several different types of modules in its code base. Some of
|
||||||
|
these are for backwards compatibility and others are to enable flexibility.
|
||||||
|
|
||||||
|
.. _flow_action_plugins:
|
||||||
|
|
||||||
|
Action Plugins
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Action Plugins look like modules to end users who are writing :term:`playbooks` but
|
||||||
|
they're distinct entities for the purposes of this paper. Action Plugins
|
||||||
|
always execute on the controller and are sometimes able to do all work there
|
||||||
|
(for instance, the debug Action Plugin which prints some text for the user to
|
||||||
|
see or the assert Action Plugin which can test whether several values in
|
||||||
|
a playbook satisfy certain criteria.)
|
||||||
|
|
||||||
|
More often, Action Plugins set up some values on the controller, then invoke an
|
||||||
|
actual module on the managed node that does something with these values. An
|
||||||
|
easy to understand version of this is the :ref:`template Action Plugin
|
||||||
|
<template>`. The :ref:`template Action Plugin <template>` takes values from
|
||||||
|
the user to construct a file in a temporary location on the controller using
|
||||||
|
variables from the playbook environment. It then transfers the temporary file
|
||||||
|
to a temporary file on the remote system. After that, it invokes the
|
||||||
|
:ref:`copy module <copy>` which operates on the remote system to move the file
|
||||||
|
into its final location, sets file permissions, and so on.
|
||||||
|
|
||||||
|
.. _flow_new_style_modules:
|
||||||
|
|
||||||
|
New-style Modules
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
All of the modules that ship with Ansible fall into this category.
|
||||||
|
|
||||||
|
New-style modules have the arguments to the module embedded inside of them in
|
||||||
|
some manner. Non-new-style modules must copy a separate file over to the
|
||||||
|
managed node, which is less efficient as it requires two over-the-wire
|
||||||
|
connections instead of only one.
|
||||||
|
|
||||||
|
.. _flow_python_modules:
|
||||||
|
|
||||||
|
Python
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
New-style Python modules use the :ref:`ziploader` framework for constructing
|
||||||
|
modules. All official modules (shipped with Ansible) use either this or the
|
||||||
|
:ref:`powershell module framework <flow_powershell_modules>`.
|
||||||
|
|
||||||
|
These modules use imports from :code:`ansible.module_utils` in order to pull in
|
||||||
|
boilerplate module code, such as argument parsing, formatting of return
|
||||||
|
values as :term:`JSON`, and various file operations.
|
||||||
|
|
||||||
|
.. note:: In Ansible, up to version 2.0.x, the official Python modules used the
|
||||||
|
:ref:`module_replacer` framework. For module authors, :ref:`ziploader` is
|
||||||
|
largely a superset of :ref:`module_replacer` functionality, so you usually
|
||||||
|
do not need to know about one versus the other.
|
||||||
|
|
||||||
|
.. _flow_powershell_modules:
|
||||||
|
|
||||||
|
Powershell
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
New-style powershell modules use the :ref:`module_replacer` framework for
|
||||||
|
constructing modules. These modules get a library of powershell code embedded
|
||||||
|
in them before being sent to the managed node.
|
||||||
|
|
||||||
|
.. _flow_josnargs_modules:
|
||||||
|
|
||||||
|
JSONARGS
|
||||||
|
^^^^^^^^
|
||||||
|
|
||||||
|
Scripts can arrange for an argument string to be placed within them by placing
|
||||||
|
the string ``<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>`` somewhere inside of the
|
||||||
|
file. The module typically sets a variable to that value like this::
|
||||||
|
|
||||||
|
json_arguments = """<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>"""
|
||||||
|
|
||||||
|
Which is expanded as::
|
||||||
|
|
||||||
|
json_arguments = """{"param1": "test's quotes", "param2": "\"To be or not to be\" - Hamlet"}"""
|
||||||
|
|
||||||
|
.. note:: Ansible outputs a :term:`JSON` string with bare quotes. Double quotes are
|
||||||
|
used to quote string values, double quotes inside of string values are
|
||||||
|
backslash escaped, and single quotes may appear unescaped inside of
|
||||||
|
a string value. To use JSONARGS, your scripting language must have a way
|
||||||
|
to handle this type of string. The example uses Python's triple quoted
|
||||||
|
strings to do this. Other scripting languages may have a similar quote
|
||||||
|
character that won't be confused by any quotes in the JSON or it may
|
||||||
|
allow you to define your own start-of-quote and end-of-quote characters.
|
||||||
|
If the language doesn't give you any of these then you'll need to write
|
||||||
|
a :ref:`non-native JSON module <flow_want_json_modules>` or
|
||||||
|
:ref:`Old-style module <flow_old_style_modules>` instead.
|
||||||
|
|
||||||
|
The module typically parses the contents of ``json_arguments`` using a JSON
|
||||||
|
library and then use them as native variables throughout the rest of its code.
|
||||||
|
|
||||||
|
.. _flow_want_json_modules:
|
||||||
|
|
||||||
|
Non-native want JSON modules
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
If a module has the string ``WANT_JSON`` in it anywhere, Ansible treats
|
||||||
|
it as a non-native module that accepts a filename as its only command line
|
||||||
|
parameter. The filename is for a temporary file containing a :term:`JSON`
|
||||||
|
string containing the module's parameters. The module needs to open the file,
|
||||||
|
read and parse the parameters, operate on the data, and print its return data
|
||||||
|
as a JSON encoded dictionary to stdout before exiting.
|
||||||
|
|
||||||
|
These types of modules are self-contained entities. As of Ansible 2.1, Ansible
|
||||||
|
only modifies them to change a shebang line if present.
|
||||||
|
|
||||||
|
.. seealso:: Examples of Non-native modules written in ruby are in the `Ansible
|
||||||
|
for Rubyists <https://github.com/ansible/ansible-for-rubyists>`_ repository.
|
||||||
|
|
||||||
|
.. _flow_old_style_modules:
|
||||||
|
|
||||||
|
Old-style Modules
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Old-style modules are similar to
|
||||||
|
:ref:`want JSON modules <flow_want_json_modules>`, except that the file that
|
||||||
|
they take contains ``key=value`` pairs for their parameters instead of
|
||||||
|
:term:`JSON`.
|
||||||
|
|
||||||
|
Ansible decides that a module is old-style when it doesn't have any of the
|
||||||
|
markers that would show that it is one of the other types.
|
||||||
|
|
||||||
|
.. _flow_how_modules_are_executed:
|
||||||
|
|
||||||
|
How modules are executed
|
||||||
|
========================
|
||||||
|
|
||||||
|
When a user uses :program:`ansible` or :program:`ansible-playbook`, they
|
||||||
|
specify a task to execute. The task is usually the name of a module along
|
||||||
|
with several parameters to be passed to the module. Ansible takes these
|
||||||
|
values and processes them in various ways before they are finally executed on
|
||||||
|
the remote machine.
|
||||||
|
|
||||||
|
.. _flow_executor_task_executor:
|
||||||
|
|
||||||
|
executor/task_executor
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The TaskExecutor receives the module name and parameters that were parsed from
|
||||||
|
the :term:`playbook <playbooks>` (or from the command line in the case of
|
||||||
|
:command:`/usr/bin/ansible`). It uses the name to decide whether it's looking
|
||||||
|
at a module or an :ref:`Action Plugin <flow_action_plugins>`. If it's
|
||||||
|
a module, it loads the :ref:`Normal Action Plugin <flow_normal_action_plugin>`
|
||||||
|
and passes the name, variables, and other information about the task and play
|
||||||
|
to that Action Plugin for further processing.
|
||||||
|
|
||||||
|
.. _flow_normal_action_plugin:
|
||||||
|
|
||||||
|
Normal Action Plugin
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The ``normal`` Action Plugin executes the module on the remote host. It is
|
||||||
|
the primary coordinator of much of the work to actually execute the module on
|
||||||
|
the managed machine.
|
||||||
|
|
||||||
|
* It takes care of creating a connection to the managed machine by
|
||||||
|
instantiating a Connection class according to the inventory configuration for
|
||||||
|
that host.
|
||||||
|
* It adds any internal Ansible variables to the module's parameters (for
|
||||||
|
instance, the ones that pass along ``no_log`` to the module).
|
||||||
|
* It takes care of creating any temporary files on the remote machine and
|
||||||
|
cleans up afterwards.
|
||||||
|
* It does the actual work of pushing the module and module parameters to the
|
||||||
|
remote host, although the :ref:`module_common <flow_executor_module_common>`
|
||||||
|
code described next does the work of deciding which format those will take.
|
||||||
|
* It handles any special cases regarding modules (for instance, various
|
||||||
|
complications around Windows modules that must have the same names as Python
|
||||||
|
modules, so that internal calling of modules from other Action Plugins work.)
|
||||||
|
|
||||||
|
Much of this functionality comes from the :class:`BaseAction` class,
|
||||||
|
which lives in :file:`plugins/action/__init__.py`. It makes use of Connection
|
||||||
|
and Shell objects to do its work.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
When :term:`tasks <tasks>` are run with the ``async:`` parameter, Ansible
|
||||||
|
uses the ``async`` Action Plugin instead of the ``normal`` Action Plugin
|
||||||
|
to invoke it. That program flow is currently not documented. Read the
|
||||||
|
source for information on how that works.
|
||||||
|
|
||||||
|
.. _flow_executor_module_common:
|
||||||
|
|
||||||
|
executor/module_common.py
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Code in :file:`executor/module_common.py` takes care of assembling the module
|
||||||
|
to be shipped to the managed node. The module is first read in, then examined
|
||||||
|
to determine its type. :ref:`PowerShell <flow_powershell_modules>` and
|
||||||
|
:ref:`JSON-args modules <flow_jsonargs_modules>` are passed through
|
||||||
|
:ref:`Module Replacer <module_replacer>`. New-style
|
||||||
|
:ref:`Python modules <flow_python_modules>` are assembled by :ref:`ziploader`.
|
||||||
|
:ref:`Non-native-want-JSON <flow_want_json_modules>` and
|
||||||
|
:ref:`Old-Style modules <flow_old_style_modules>` aren't touched by either of
|
||||||
|
these and pass through unchanged. After the assembling step, one final
|
||||||
|
modification is made to all modules that have a shebang line. Ansible checks
|
||||||
|
whether the interpreter in the shebang line has a specific path configured via
|
||||||
|
an ``ansible_$X_interpreter`` inventory variable. If it does, Ansible
|
||||||
|
substitutes that path for the interpreter path given in the module. After
|
||||||
|
this Ansible returns the complete module data and the module type to the
|
||||||
|
:ref:`Normal Action <_flow_normal_action_plugin>` which continues execution of
|
||||||
|
the module.
|
||||||
|
|
||||||
|
Next we'll go into some details of the two assembler frameworks.
|
||||||
|
|
||||||
|
.. _module_replacer:
|
||||||
|
|
||||||
|
Module Replacer
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The Module Replacer is essentially a preprocessor (like the C Preprocessor for
|
||||||
|
those familiar with that language). It does straight substitutions of
|
||||||
|
specific substring patterns in the module file. There are two types of
|
||||||
|
substitutions:
|
||||||
|
|
||||||
|
* Replacements that only happen in the module file. These are public
|
||||||
|
replacement strings that modules can utilize to get helpful boilerplate or
|
||||||
|
access to arguments.
|
||||||
|
|
||||||
|
- :code:`from ansible.module_utils.MOD_LIB_NAME import *` is replaced with the
|
||||||
|
contents of the :file:`ansible/module_utils/MOD_LIB_NAME.py` These should
|
||||||
|
only be used with :ref:`new-style Python modules <flow_python_modules>`.
|
||||||
|
- :code:`#<<INCLUDE_ANSIBLE_MODULE_COMMON>>` is equivalent to
|
||||||
|
:code:`from ansible.module_utils.basic import *` and should also only apply
|
||||||
|
to new-style Python modules.
|
||||||
|
- :code:`# POWERSHELL_COMMON` substitutes the contents of
|
||||||
|
:file:`ansible/module_utils/powershell.ps1`. It should only be used with
|
||||||
|
:ref:`new-style Powershell modules <flow_powershell_modules>`.
|
||||||
|
|
||||||
|
* Replacements that are used by ``ansible.module_utils`` code. These are internal
|
||||||
|
replacement patterns. They may be used internally, in the above public
|
||||||
|
replacements, but shouldn't be used directly by modules.
|
||||||
|
|
||||||
|
- :code:`"<<ANSIBLE_VERSION>>"` is substituted with the Ansible version. In
|
||||||
|
a new-style Python module, it's better to use ``from ansible import
|
||||||
|
__version__`` and then use ``__version__`` instead.
|
||||||
|
- :code:`"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>"` is substituted with
|
||||||
|
a string which is the Python ``repr`` of the :term:`JSON` encoded module
|
||||||
|
parameters. Using ``repr`` on the JSON string makes it safe to embed in
|
||||||
|
a Python file. In :ref:`new-style Python modules <flow_python_modules>`
|
||||||
|
under :ref:`ziploader` this is passed in via an environment variable
|
||||||
|
instead.
|
||||||
|
- :code:`<<SELINUX_SPECIAL_FILESYSTEMS>>` substitutes a string which is
|
||||||
|
a comma separated list of file systems which have a file system dependent
|
||||||
|
security context in SELinux. In new-style Python modules, this is found
|
||||||
|
by looking up ``SELINUX_SPECIAL_FS`` from the
|
||||||
|
:envvar:`ANSIBLE_MODULE_CONSTANTS` environment variable. See the
|
||||||
|
:ref:`ziploader` documentation for details.
|
||||||
|
- :code:`<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>` substitutes the module
|
||||||
|
parameters as a JSON string. Care must be taken to properly quote the
|
||||||
|
string as JSON data may contain quotes. This pattern is not substituted
|
||||||
|
in new-style Python modules as they can get the module parameters via the
|
||||||
|
environment variable.
|
||||||
|
- the string :code:`syslog.LOG_USER` is replaced wherever it occurs with the
|
||||||
|
value of ``syslog_facility`` from the :file:`ansible.cfg` or any
|
||||||
|
``ansible_syslog_facility`` inventory variable that applies to this host. In
|
||||||
|
new-style Python modules, you can get the value of the ``syslog_facility``
|
||||||
|
by looking up ``SYSLOG_FACILITY`` in the :envvar:`ANSIBLE_MODULE_CONSTANTS`
|
||||||
|
environment variable. See the :ref:`ziploader` documentation for details.
|
||||||
|
|
||||||
|
.. _ziploader:
|
||||||
|
|
||||||
|
ziploader
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
Ziploader differs from :ref:`module_replacer` in that it uses real Python
|
||||||
|
imports of things in module_utils instead of merely preprocessing the module.
|
||||||
|
It does this by constructing a zipfile--which includes the module file, files
|
||||||
|
in :file:`ansible/module_utils` that are imported by the module, and some
|
||||||
|
boilerplate to pass in the constants. The zipfile is then Base64 encoded and
|
||||||
|
wrapped in a small Python script which unzips the file on the managed node and
|
||||||
|
then invokes Python on the file. (Ansible wraps the zipfile in the Python
|
||||||
|
script so that pipelining will work.)
|
||||||
|
|
||||||
|
In ziploader, any imports of Python modules from the ``ansible.module_utils``
|
||||||
|
package trigger inclusion of that Python file into the zipfile. Instances of
|
||||||
|
:code:`#<<INCLUDE_ANSIBLE_MODULE_COMMON>>` in the module are turned into
|
||||||
|
:code:`from ansible.module_utils.basic import *` and
|
||||||
|
:file:`ansible/module-utils/basic.py` is then included in the zipfile. Files
|
||||||
|
that are included from module_utils are themselves scanned for imports of other
|
||||||
|
Python modules from module_utils to be included in the zipfile as well.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
At present, there are two caveats to how ziploader determines other files
|
||||||
|
to import:
|
||||||
|
|
||||||
|
* Ziploader cannot determine whether an import should be included if it is
|
||||||
|
a relative import. Always use an absolute import that has
|
||||||
|
``ansible.module_utils`` in it to allow ziploader to determine that the
|
||||||
|
file should be included.
|
||||||
|
* Ziploader does not include Python packages (directories with
|
||||||
|
:file:`__init__.py`` in them). Ziploader only works on :file:`*.py`
|
||||||
|
files that are directly in the :file:`ansible/module_utils` directory.
|
||||||
|
|
||||||
|
.. _flow_passing_module_args:
|
||||||
|
|
||||||
|
Passing args
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
In :ref:`module_replacer`, module arguments are turned into a JSON-ified
|
||||||
|
string and substituted into the combined module file. In :ref:`ziploader`,
|
||||||
|
the JSON-ified string is placed in the the :envvar:`ANSIBLE_MODULE_ARGS`
|
||||||
|
environment variable. When :code:`ansible.module_utils.basic` is imported,
|
||||||
|
it places this string in the global variable
|
||||||
|
``ansible.module_utils.basic.MODULE_COMPLEX_ARGS`` and removes it from the
|
||||||
|
environment. Modules should not access this variable directly. Instead, they
|
||||||
|
should instantiate an :class:`AnsibleModule()` and use
|
||||||
|
:meth:`AnsibleModule.params` to access the parsed version of the arguments.
|
||||||
|
|
||||||
|
.. _flow_passing_module_constants:
|
||||||
|
|
||||||
|
Passing constants
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Currently, there are three constants passed from the controller to the modules:
|
||||||
|
``ANSIBLE_VERSION``, ``SELINUX_SPECIAL_FS``, and ``SYSLOG_FACILITY``. In
|
||||||
|
:ref:`module_replacer`, ``ANSIBLE_VERSION`` and ``SELINUX_SPECIAL_FS`` were
|
||||||
|
substituted into the global variables
|
||||||
|
:code:`ansible.module_utils.basic.ANSIBLE_VERSION` and
|
||||||
|
:code:`ansible.module_utils.basic.SELINUX_SPECIAL_FS`. ``SYSLOG_FACILITY`` didn't
|
||||||
|
get placed into a variable. Instead, any occurrences of the string
|
||||||
|
``syslog.LOG_USER`` in the combined module file were replaced with ``syslog.``
|
||||||
|
followed by the string contained in ``SYSLOG_FACILITY``. All of these have
|
||||||
|
changed in :ref:`ziploader`.
|
||||||
|
|
||||||
|
The Ansible verison can now be used by a module by importing ``__version__``
|
||||||
|
from ansible::
|
||||||
|
|
||||||
|
from ansible import __version__
|
||||||
|
module.exit_json({'msg': 'module invoked by ansible %s' % __version__})
|
||||||
|
|
||||||
|
For now, :code:`ANSIBLE_VERSION` is also available at its old location inside of
|
||||||
|
``ansible.module_utils.basic``, but that will eventually be removed.
|
||||||
|
|
||||||
|
``SELINUX_SPECIAL_FS`` and ``SYSLOG_FACILITY`` have changed much more.
|
||||||
|
:ref:`ziploader` passes these as another JSON-ified string inside of the
|
||||||
|
:envvar:`ANSIBLE_MODULE_CONSTANTS` environment variable. When
|
||||||
|
``ansible.module_utils.basic`` is imported, it places this string in the global
|
||||||
|
variable :code:`ansible.module_utils.basic.MODULE_CONSTANTS` and removes it from
|
||||||
|
the environment. The constants are parsed when an :class:`AnsibleModule` is
|
||||||
|
instantiated. Modules shouldn't access any of those directly. Instead, they
|
||||||
|
should instantiate an :class:`AnsibleModule` and use
|
||||||
|
:attr:`AnsibleModule.constants` to access the parsed version of these values.
|
||||||
|
|
||||||
|
Unlike the ``ANSIBLE_ARGS`` and ``ANSIBLE_VERSION``, where some efforts were
|
||||||
|
made to keep the old backwards compatible globals available, these two
|
||||||
|
constants are not available at their old names. This is a combination of the
|
||||||
|
degree to which these are internal to the needs of ``module_utils.basic`` and,
|
||||||
|
in the case of ``SYSLOG_FACILITY``, how hacky and unsafe the previous
|
||||||
|
implementation was.
|
||||||
|
|
||||||
|
Porting code from the :ref:`module_replacer` method of getting
|
||||||
|
``SYSLOG_FACILITY`` to the new one is a little more tricky than the other
|
||||||
|
constants and args, due to just how hacky the old way was. Here's an example
|
||||||
|
of using it in the new way::
|
||||||
|
|
||||||
|
import syslog
|
||||||
|
facility_name = module.constants.get('SYSLOG_FACILITY')
|
||||||
|
facility = getattr(syslog, facility_name)
|
||||||
|
syslog.openlog(str(module), 0, facility)
|
||||||
|
|
||||||
|
.. _flow_special_considerations:
|
||||||
|
|
||||||
|
Special Considerations
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
.. _flow_pipelining:
|
||||||
|
|
||||||
|
Pipelining
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
Ansible can transfer a module to a remote machine in one of two ways:
|
||||||
|
|
||||||
|
* it can write out the module to a temporary file on the remote host and then
|
||||||
|
use a second connection to the remote host to execute it with the
|
||||||
|
interpreter that the module needs
|
||||||
|
* or it can use what's known as pipelining to execute the module by piping it
|
||||||
|
into the remote interpreter's stdin.
|
||||||
|
|
||||||
|
Pipelining only works with modules written in Python at this time because
|
||||||
|
Ansible only knows that Python supports this mode of operation. Supporting
|
||||||
|
pipelining means that whatever format the module payload takes before being
|
||||||
|
sent over the wire must be executable by Python via stdin.
|
|
@ -7,409 +7,477 @@ Consult the documentation home page for the full documentation and to see the te
|
||||||
to check your knowledge of Ansible's components and understand how they fit together. It's something you might wish to read for review or
|
to check your knowledge of Ansible's components and understand how they fit together. It's something you might wish to read for review or
|
||||||
when a term comes up on the mailing list.
|
when a term comes up on the mailing list.
|
||||||
|
|
||||||
Action
|
.. glossary::
|
||||||
++++++
|
|
||||||
|
|
||||||
An action is a part of a task that specifies which of the modules to run and the arguments to pass to that module. Each task can have only one action, but it may also have other parameters.
|
Action
|
||||||
|
An action is a part of a task that specifies which of the modules to
|
||||||
|
run and which arguments to pass to that module. Each task can have
|
||||||
|
only one action, but it may also have other parameters.
|
||||||
|
|
||||||
Ad Hoc
|
Ad Hoc
|
||||||
++++++
|
Refers to running Ansible to perform some quick command, using
|
||||||
|
:command:`/usr/bin/ansible`, rather than the :term:`orchestration`
|
||||||
Refers to running Ansible to perform some quick command, using /usr/bin/ansible, rather than the orchestration language, which is
|
language, which is :command:`/usr/bin/ansible-playbook`. An example
|
||||||
/usr/bin/ansible-playbook. An example of an ad-hoc command might be rebooting 50 machines in your infrastructure. Anything
|
of an ad hoc command might be rebooting 50 machines in your
|
||||||
you can do ad-hoc can be accomplished by writing a playbook, and playbooks can also glue lots of other operations together.
|
infrastructure. Anything you can do ad hoc can be accomplished by
|
||||||
|
writing a :term:`playbook <playbooks>` and playbooks can also glue
|
||||||
|
lots of other operations together.
|
||||||
|
|
||||||
Async
|
Async
|
||||||
+++++
|
Refers to a task that is configured to run in the background rather
|
||||||
|
than waiting for completion. If you have a long process that would
|
||||||
Refers to a task that is configured to run in the background rather than waiting for completion. If you have a long process
|
run longer than the SSH timeout, it would make sense to launch that
|
||||||
that would run longer than the SSH timeout, it would make sense to launch that task in async mode. Async modes can poll
|
task in async mode. Async modes can poll for completion every so many
|
||||||
for completion every so many seconds, or can be configured to "fire and forget" in which case Ansible will not even
|
seconds or can be configured to "fire and forget", in which case
|
||||||
check on the task again, it will just kick it off and proceed to future steps. Async modes work with both /usr/bin/ansible
|
Ansible will not even check on the task again; it will just kick it
|
||||||
and /usr/bin/ansible-playbook.
|
off and proceed to future steps. Async modes work with both
|
||||||
|
:command:`/usr/bin/ansible` and :command:`/usr/bin/ansible-playbook`.
|
||||||
|
|
||||||
Callback Plugin
|
Callback Plugin
|
||||||
+++++++++++++++
|
Refers to some user-written code that can intercept results from
|
||||||
|
Ansible and do something with them. Some supplied examples in the
|
||||||
Refers to some user-written code that can intercept results from Ansible and do something with them. Some supplied examples
|
GitHub project perform custom logging, send email, or even play sound
|
||||||
in the GitHub project perform custom logging, send email, or even play sound effects.
|
effects.
|
||||||
|
|
||||||
Check Mode
|
Check Mode
|
||||||
++++++++++
|
Refers to running Ansible with the ``--check`` option, which does not
|
||||||
|
make any changes on the remote systems, but only outputs the changes
|
||||||
|
that might occur if the command ran without this flag. This is
|
||||||
|
analogous to so-called "dry run" modes in other systems, though the
|
||||||
|
user should be warned that this does not take into account unexpected
|
||||||
|
command failures or cascade effects (which is true of similar modes in
|
||||||
|
other systems). Use this to get an idea of what might happen, but do
|
||||||
|
not substitute it for a good staging environment.
|
||||||
|
|
||||||
Refers to running Ansible with the ``--check`` option, which does not make any changes on the remote systems, but only outputs the changes that
|
Connection Plugin
|
||||||
might occur if the command ran without this flag. This is analogous to so-called "dry run" modes in other systems, though the user should
|
By default, Ansible talks to remote machines through pluggable
|
||||||
be warned that this does not take into account unexpected command failures or cascade effects (which is true of similar modes in other
|
libraries. Ansible supports native OpenSSH (:term:`SSH (Native)`) or
|
||||||
systems). Use this to get an idea of what might happen, but it is not a substitute for a good staging environment.
|
a Python implementation called :term:`paramiko`. OpenSSH is preferred
|
||||||
|
if you are using a recent version, and also enables some features like
|
||||||
Connection Type, Connection Plugin
|
Kerberos and jump hosts. This is covered in the :ref:`getting
|
||||||
++++++++++++++++++++++++++++++++++
|
started section <remote_connection_information>`. There are also
|
||||||
|
other connection types like ``accelerate`` mode, which must be
|
||||||
By default, Ansible talks to remote machines through pluggable libraries. Ansible supports native OpenSSH ('ssh'), or a Python
|
bootstrapped over one of the SSH-based connection types but is very
|
||||||
implementation called 'paramiko'. OpenSSH is preferred if you are using a recent version, and also enables some features
|
fast, and local mode, which acts on the local system. Users can also
|
||||||
like Kerberos and jump hosts. This is covered in the getting started section.
|
write their own connection plugins.
|
||||||
There are also other connection types like 'accelerate' mode, which must be bootstrapped
|
|
||||||
over one of the SSH-based connection types but is very fast, and local mode, which acts on the local system.
|
|
||||||
Users can also write their own connection plugins.
|
|
||||||
|
|
||||||
Conditionals
|
Conditionals
|
||||||
++++++++++++
|
A conditional is an expression that evaluates to true or false that
|
||||||
|
decides whether a given task is executed on a given machine or not.
|
||||||
A conditional is an expression that evaluates to true or false that decides whether a given task will be executed on a given
|
Ansible's conditionals are powered by the 'when' statement, which are
|
||||||
machine or not. Ansible's conditionals are powered by the 'when' statement, and are
|
discussed in the :doc:`playbook documentation <playbooks>`.
|
||||||
discussed in the playbook documentation.
|
|
||||||
|
|
||||||
Diff Mode
|
Diff Mode
|
||||||
+++++++++
|
A ``--diff`` flag can be passed to Ansible to show how template files
|
||||||
|
change when they are overwritten or how they might change when used
|
||||||
A ``--diff`` flag can be passed to Ansible to show how template files change when they are overwritten, or how they might change when used
|
|
||||||
with ``--check`` mode. These diffs come out in unified diff format.
|
with ``--check`` mode. These diffs come out in unified diff format.
|
||||||
|
|
||||||
Facts
|
Executor
|
||||||
+++++
|
A core software component of Ansible that is the power behind
|
||||||
|
:command:`/usr/bin/ansible` directly -- and corresponds to the
|
||||||
|
invocation of each task in a :term:`playbook <playbooks>`. The
|
||||||
|
Executor is something Ansible developers may talk about, but it's not
|
||||||
|
really user land vocabulary.
|
||||||
|
|
||||||
Facts are simply things that are discovered about remote nodes. While they can be used in playbooks and templates just like variables, facts
|
Facts
|
||||||
are things that are inferred, rather than set. Facts are automatically discovered by Ansible when running plays by executing the internal 'setup'
|
Facts are simply things that are discovered about remote nodes. While
|
||||||
module on the remote nodes. You never have to call the setup module explicitly, it just runs, but it can be disabled to save time if it is
|
they can be used in :term:`playbooks` and templates just like
|
||||||
not needed or you can tell ansible to collect only a subset of the full facts via the `gather_subset:` option. For the convenience of users who are switching from other configuration management systems, the fact module will also pull in facts from the 'ohai' and 'facter' tools if they are installed, which are fact libraries from Chef and Puppet, respectively. (These may also be disabled via `gather_subset:`)
|
variables, facts are things that are inferred, rather than set. Facts
|
||||||
|
are automatically discovered by Ansible when running plays by
|
||||||
|
executing the internal :ref:`setup module <setup>` on the remote nodes. You
|
||||||
|
never have to call the setup module explicitly, it just runs, but it
|
||||||
|
can be disabled to save time if it is not needed or you can tell
|
||||||
|
ansible to collect only a subset of the full facts via the
|
||||||
|
``gather_subset:`` option. For the convenience of users who are
|
||||||
|
switching from other configuration management systems, the fact module
|
||||||
|
will also pull in facts from the :program:`ohai` and :program:`facter`
|
||||||
|
tools if they are installed. These are fact libraries from Chef and
|
||||||
|
Puppet, respectively. (These may also be disabled via
|
||||||
|
``gather_subset:``)
|
||||||
|
|
||||||
Filter Plugin
|
Filter Plugin
|
||||||
+++++++++++++
|
A filter plugin is something that most users will never need to
|
||||||
|
understand. These allow for the creation of new :term:`Jinja2`
|
||||||
A filter plugin is something that most users will never need to understand. These allow for the creation of new Jinja2 filters, which
|
filters, which are more or less only of use to people who know what
|
||||||
are more or less only of use to people who know what Jinja2 filters are. If you need them, you can learn how to write them in the API
|
Jinja2 filters are. If you need them, you can learn how to write them
|
||||||
docs section.
|
in the :ref:`API docs section <developing_filter_plugins>`.
|
||||||
|
|
||||||
Forks
|
Forks
|
||||||
+++++
|
Ansible talks to remote nodes in parallel and the level of parallelism
|
||||||
|
can be set either by passing ``--forks`` or editing the default in
|
||||||
Ansible talks to remote nodes in parallel and the level of parallelism can be set either by passing ``--forks``, or editing the default in a configuration
|
a configuration file. The default is a very conservative five (5)
|
||||||
file. The default is a very conservative 5 forks, though if you have a lot of RAM, you can easily set this to a value like 50 for increased
|
forks, though if you have a lot of RAM, you can easily set this to
|
||||||
parallelism.
|
a value like 50 for increased parallelism.
|
||||||
|
|
||||||
Gather Facts (Boolean)
|
Gather Facts (Boolean)
|
||||||
++++++++++++++++++++++
|
:term:`Facts` are mentioned above. Sometimes when running a multi-play
|
||||||
|
:term:`playbook <playbooks>`, it is desirable to have some plays that
|
||||||
Facts are mentioned above. Sometimes when running a multi-play playbook, it is desirable to have some plays that don't bother with fact
|
don't bother with fact computation if they aren't going to need to
|
||||||
computation if they aren't going to need to utilize any of these values. Setting `gather_facts: False` on a playbook allows this implicit
|
utilize any of these values. Setting ``gather_facts: False`` on
|
||||||
fact gathering to be skipped.
|
a playbook allows this implicit fact gathering to be skipped.
|
||||||
|
|
||||||
Globbing
|
Globbing
|
||||||
++++++++
|
Globbing is a way to select lots of hosts based on wildcards, rather
|
||||||
|
than the name of the host specifically, or the name of the group they
|
||||||
Globbing is a way to select lots of hosts based on wildcards, rather than the name of the host specifically, or the name of the group
|
are in. For instance, it is possible to select ``ww*`` to match all
|
||||||
they are in. For instance, it is possible to select "www*" to match all hosts starting with "www". This concept is pulled directly
|
hosts starting with ``www``. This concept is pulled directly from
|
||||||
from Func, one of Michael's earlier projects. In addition to basic globbing, various set operations are also possible, such as
|
:program:`Func`, one of Michael DeHaan's (an Ansible Founder) earlier
|
||||||
'hosts in this group and not in another group', and so on.
|
projects. In addition to basic globbing, various set operations are
|
||||||
|
also possible, such as 'hosts in this group and not in another group',
|
||||||
|
and so on.
|
||||||
|
|
||||||
Group
|
Group
|
||||||
+++++
|
A group consists of several hosts assigned to a pool that can be
|
||||||
|
conveniently targeted together, as well as given variables that they
|
||||||
A group consists of several hosts assigned to a pool that can be conveniently targeted together, and also given variables that they share in
|
share in common.
|
||||||
common.
|
|
||||||
|
|
||||||
Group Vars
|
Group Vars
|
||||||
++++++++++
|
The :file:`group_vars/` files are files that live in a directory
|
||||||
|
alongside an inventory file, with an optional filename named after
|
||||||
The "group_vars/" files are files that live in a directory alongside an inventory file, with an optional filename named after each group.
|
each group. This is a convenient place to put variables that are
|
||||||
This is a convenient place to put variables that will be provided to a given group, especially complex data structures, so that these
|
provided to a given group, especially complex data structures, so that
|
||||||
variables do not have to be embedded in the inventory file or playbook.
|
these variables do not have to be embedded in the :term:`inventory`
|
||||||
|
file or :term:`playbook <playbooks>`.
|
||||||
|
|
||||||
Handlers
|
Handlers
|
||||||
++++++++
|
Handlers are just like regular tasks in an Ansible
|
||||||
|
:term:`playbook <playbooks>` (see :term:`Tasks`) but are only run if
|
||||||
Handlers are just like regular tasks in an Ansible playbook (see Tasks), but are only run if the Task contains a "notify" directive and
|
the Task contains a ``notify`` directive and also indicates that it
|
||||||
also indicates that it changed something. For example, if a config file is changed then the task referencing the config file templating
|
changed something. For example, if a config file is changed, then the
|
||||||
operation may notify a service restart handler. This means services can be bounced only if they need to be restarted.
|
task referencing the config file templating operation may notify
|
||||||
Handlers can be used for things other than service restarts, but service restarts are the most common usage.
|
a service restart handler. This means services can be bounced only if
|
||||||
|
they need to be restarted. Handlers can be used for things other than
|
||||||
|
service restarts, but service restarts are the most common usage.
|
||||||
|
|
||||||
Host
|
Host
|
||||||
++++
|
A host is simply a remote machine that Ansible manages. They can have
|
||||||
|
individual variables assigned to them, and can also be organized in
|
||||||
A host is simply a remote machine that Ansible manages. They can have individual variables assigned to them, and can also be organized
|
groups. All hosts have a name they can be reached at (which is either
|
||||||
in groups. All hosts have a name they can be reached at (which is either an IP address or a domain name) and optionally a port number
|
an IP address or a domain name) and, optionally, a port number, if they
|
||||||
if they are not to be accessed on the default SSH port.
|
are not to be accessed on the default SSH port.
|
||||||
|
|
||||||
Host Specifier
|
Host Specifier
|
||||||
++++++++++++++
|
Each :term:`Play <plays>` in Ansible maps a series of :term:`tasks` (which define the role,
|
||||||
|
purpose, or orders of a system) to a set of systems.
|
||||||
|
|
||||||
Each Play in Ansible maps a series of tasks (which define the role, purpose, or orders of a system) to a set of systems.
|
This ``hosts:`` directive in each play is often called the hosts specifier.
|
||||||
|
|
||||||
This "hosts:" directive in each play is often called the hosts specifier.
|
It may select one system, many systems, one or more groups, or even
|
||||||
|
some hosts that are in one group and explicitly not in another.
|
||||||
It may select one system, many systems, one or more groups, or even some hosts that are in one group and explicitly not in another.
|
|
||||||
|
|
||||||
Host Vars
|
Host Vars
|
||||||
+++++++++
|
Just like :term:`Group Vars`, a directory alongside the inventory file named
|
||||||
|
:file:`host_vars/` can contain a file named after each hostname in the
|
||||||
Just like "Group Vars", a directory alongside the inventory file named "host_vars/" can contain a file named after each hostname in
|
inventory file, in :term:`YAML` format. This provides a convenient place to
|
||||||
the inventory file, in YAML format. This provides a convenient place to assign variables to the host without having to embed
|
assign variables to the host without having to embed them in the
|
||||||
them in the inventory file. The Host Vars file can also be used to define complex data structures that can't be represented in the
|
:term:`inventory` file. The Host Vars file can also be used to define complex
|
||||||
inventory file.
|
data structures that can't be represented in the inventory file.
|
||||||
|
|
||||||
Idempotency
|
Idempotency
|
||||||
+++++++++++
|
The concept that change commands should only be applied when they need
|
||||||
|
to be applied, and that it is better to describe the desired state of
|
||||||
The concept that change commands should only be applied when they need to be applied, and that it is better to describe the desired
|
a system than the process of how to get to that state. As an analogy,
|
||||||
state of a system than the process of how to get to that state. As an analogy, the path from North Carolina in the United States to
|
the path from North Carolina in the United States to California
|
||||||
California involves driving a very long way West, but if I were instead in Anchorage, Alaska, driving a long way west is no longer
|
involves driving a very long way West but if I were instead in
|
||||||
the right way to get to California. Ansible's Resources like you to say "put me in California" and then decide how to get there. If
|
Anchorage, Alaska, driving a long way west is no longer the right way
|
||||||
you were already in California, nothing needs to happen, and it will let you know it didn't need to change anything.
|
to get to California. Ansible's Resources like you to say "put me in
|
||||||
|
California" and then decide how to get there. If you were already in
|
||||||
|
California, nothing needs to happen, and it will let you know it
|
||||||
|
didn't need to change anything.
|
||||||
|
|
||||||
Includes
|
Includes
|
||||||
++++++++
|
The idea that :term:`playbook <playbooks>` files (which are nothing
|
||||||
|
more than lists of :term:`plays`) can include other lists of plays,
|
||||||
The idea that playbook files (which are nothing more than lists of plays) can include other lists of plays, and task lists
|
and task lists can externalize lists of :term:`tasks` in other files,
|
||||||
can externalize lists of tasks in other files, and similarly with handlers. Includes can be parameterized, which means that the
|
and similarly with :term:`handlers`. Includes can be parameterized,
|
||||||
loaded file can pass variables. For instance, an included play for setting up a WordPress blog may take a parameter called "user"
|
which means that the loaded file can pass variables. For instance, an
|
||||||
and that play could be included more than once to create a blog for both "alice" and "bob".
|
included play for setting up a WordPress blog may take a parameter
|
||||||
|
called ``user`` and that play could be included more than once to
|
||||||
|
create a blog for both ``alice`` and ``bob``.
|
||||||
|
|
||||||
Inventory
|
Inventory
|
||||||
+++++++++
|
A file (by default, Ansible uses a simple INI format) that describes
|
||||||
|
:term:`Hosts <Host>` and :term:`Groups <Group>` in Ansible. Inventory
|
||||||
A file (by default, Ansible uses a simple INI format) that describes Hosts and Groups in Ansible. Inventory can also be provided
|
can also be provided via an :term:`Inventory Script` (sometimes called
|
||||||
via an "Inventory Script" (sometimes called an "External Inventory Script").
|
an "External Inventory Script").
|
||||||
|
|
||||||
Inventory Script
|
Inventory Script
|
||||||
++++++++++++++++
|
A very simple program (or a complicated one) that looks up
|
||||||
|
:term:`hosts <Host>`, :term:`group` membership for hosts, and variable
|
||||||
A very simple program (or a complicated one) that looks up hosts, group membership for hosts, and variable information from an external
|
information from an external resource -- whether that be a SQL
|
||||||
resource -- whether that be a SQL database, a CMDB solution, or something like LDAP. This concept was adapted from Puppet (where it is
|
database, a CMDB solution, or something like LDAP. This concept was
|
||||||
called an "External Nodes Classifier") and works more or less exactly the same way.
|
adapted from Puppet (where it is called an "External Nodes
|
||||||
|
Classifier") and works more or less exactly the same way.
|
||||||
|
|
||||||
Jinja2
|
Jinja2
|
||||||
++++++
|
Jinja2 is the preferred templating language of Ansible's template
|
||||||
|
module. It is a very simple Python template language that is
|
||||||
Jinja2 is the preferred templating language of Ansible's template module. It is a very simple Python template language that is generally
|
generally readable and easy to write.
|
||||||
readable and easy to write.
|
|
||||||
|
|
||||||
JSON
|
JSON
|
||||||
++++
|
Ansible uses JSON for return data from remote modules. This allows
|
||||||
|
modules to be written in any language, not just Python.
|
||||||
Ansible uses JSON for return data from remote modules. This allows modules to be written in any language, not just Python.
|
|
||||||
|
|
||||||
Lazy Evaluation
|
Lazy Evaluation
|
||||||
+++++++++++++++
|
In general, Ansible evaluates any variables in
|
||||||
|
:term:`playbook <playbooks>` content at the last possible second,
|
||||||
In general, Ansible evaluates any variables in playbook content at the last possible second, which means that if you define a data structure
|
which means that if you define a data structure that data structure
|
||||||
that data structure itself can define variable values within it, and everything "just works" as you would expect. This also means variable
|
itself can define variable values within it, and everything "just
|
||||||
strings can include other variables inside of those strings.
|
works" as you would expect. This also means variable strings can
|
||||||
|
include other variables inside of those strings.
|
||||||
|
|
||||||
Library
|
Library
|
||||||
+++++++
|
A collection of modules made available to :command:`/usr/bin/ansible`
|
||||||
|
or an Ansible :term:`playbook <playbooks>`.
|
||||||
A collection of modules made available to /usr/bin/ansible or an Ansible playbook.
|
|
||||||
|
|
||||||
Limit Groups
|
Limit Groups
|
||||||
++++++++++++
|
By passing ``--limit somegroup`` to :command:`ansible` or
|
||||||
|
:command:`ansible-playbook`, the commands can be limited to a subset
|
||||||
By passing ``--limit somegroup`` to ansible or ansible-playbook, the commands can be limited to a subset of hosts. For instance,
|
of :term:`hosts <Host>`. For instance, this can be used to run
|
||||||
this can be used to run a playbook that normally targets an entire set of servers to one particular server.
|
a :term:`playbook <playbooks>` that normally targets an entire set of
|
||||||
|
servers to one particular server.
|
||||||
|
|
||||||
Local Action
|
Local Action
|
||||||
++++++++++++
|
A local_action directive in a :term:`playbook <playbooks>` targeting
|
||||||
|
remote machines means that the given step will actually occur on the
|
||||||
A local_action directive in a playbook targeting remote machines means that the given step will actually occur on the local
|
local machine, but that the variable ``{{ ansible_hostname }}`` can be
|
||||||
machine, but that the variable '{{ ansible_hostname }}' can be passed in to reference the remote hostname being referred to in
|
passed in to reference the remote hostname being referred to in that
|
||||||
that step. This can be used to trigger, for example, an rsync operation.
|
step. This can be used to trigger, for example, an rsync operation.
|
||||||
|
|
||||||
Local Connection
|
Local Connection
|
||||||
++++++++++++++++
|
By using ``connection: local`` in a :term:`playbook <playbooks>`, or
|
||||||
|
passing ``-c local`` to :command:`/usr/bin/ansible`, this indicates
|
||||||
By using "connection: local" in a playbook, or passing "-c local" to /usr/bin/ansible, this indicates that we are managing the local
|
that we are managing the local host and not a remote machine.
|
||||||
host and not a remote machine.
|
|
||||||
|
|
||||||
Lookup Plugin
|
Lookup Plugin
|
||||||
+++++++++++++
|
A lookup plugin is a way to get data into Ansible from the outside
|
||||||
|
world. These are how such things as ``with_items``, a basic looping
|
||||||
A lookup plugin is a way to get data into Ansible from the outside world. These are how such things as "with_items", a basic looping plugin, are implemented,
|
plugin, are implemented. There are also lookup plugins like
|
||||||
but there are also lookup plugins like "with_file" which loads data from a file, and even ones for querying environment variables,
|
``with_file`` which load data from a file and ones for querying
|
||||||
DNS text records, or key value stores. Lookup plugins can also be accessed in templates, e.g., ``{{ lookup('file','/path/to/file') }}``.
|
environment variables, DNS text records, or key value stores. Lookup
|
||||||
|
plugins can also be accessed in templates, e.g.,
|
||||||
|
``{{ lookup('file','/path/to/file') }}``.
|
||||||
|
|
||||||
Loops
|
Loops
|
||||||
+++++
|
Generally, Ansible is not a programming language. It prefers to be
|
||||||
|
more declarative, though various constructs like ``with_items`` allow
|
||||||
Generally, Ansible is not a programming language. It prefers to be more declarative, though various constructs like "with_items"
|
a particular task to be repeated for multiple items in a list.
|
||||||
allow a particular task to be repeated for multiple items in a list. Certain modules, like yum and apt, are actually optimized
|
Certain modules, like :ref:`yum <yum>` and :ref:`apt <apt>`, are actually
|
||||||
for this, and can install all packages given in those lists within a single transaction, dramatically speeding up total
|
optimized for this, and can install all packages given in those lists
|
||||||
time to configuration.
|
within a single transaction, dramatically speeding up total time to
|
||||||
|
configuration.
|
||||||
|
|
||||||
Modules
|
Modules
|
||||||
+++++++
|
Modules are the units of work that Ansible ships out to remote
|
||||||
|
machines. Modules are kicked off by either
|
||||||
Modules are the units of work that Ansible ships out to remote machines. Modules are kicked off by either /usr/bin/ansible or
|
:command:`/usr/bin/ansible` or :command:`/usr/bin/ansible-playbook`
|
||||||
/usr/bin/ansible-playbook (where multiple tasks use lots of different modules in conjunction). Modules can be implemented in any
|
(where multiple tasks use lots of different modules in conjunction).
|
||||||
language, including Perl, Bash, or Ruby -- but can leverage some useful communal library code if written in Python. Modules just
|
Modules can be implemented in any language, including Perl, Bash, or
|
||||||
have to return JSON or simple key=value pairs. Once modules are executed on remote machines, they are removed, so no long running
|
Ruby -- but can leverage some useful communal library code if written
|
||||||
daemons are used. Ansible refers to the collection of available modules as a 'library'.
|
in Python. Modules just have to return :term:`JSON`. Once modules are
|
||||||
|
executed on remote machines, they are removed, so no long running
|
||||||
|
daemons are used. Ansible refers to the collection of available
|
||||||
|
modules as a :term:`library`.
|
||||||
|
|
||||||
Multi-Tier
|
Multi-Tier
|
||||||
++++++++++
|
The concept that IT systems are not managed one system at a time, but
|
||||||
|
by interactions between multiple systems and groups of systems in
|
||||||
The concept that IT systems are not managed one system at a time, but by interactions between multiple systems, and groups of systems, in
|
well defined orders. For instance, a web server may need to be
|
||||||
well defined orders. For instance, a web server may need to be updated before a database server, and pieces on the web server may need
|
updated before a database server and pieces on the web server may
|
||||||
to be updated after *THAT* database server, and various load balancers and monitoring servers may need to be contacted. Ansible models
|
need to be updated after *THAT* database server and various load
|
||||||
entire IT topologies and workflows rather than looking at configuration from a "one system at a time" perspective.
|
balancers and monitoring servers may need to be contacted. Ansible
|
||||||
|
models entire IT topologies and workflows rather than looking at
|
||||||
|
configuration from a "one system at a time" perspective.
|
||||||
|
|
||||||
Notify
|
Notify
|
||||||
++++++
|
The act of a :term:`task <tasks>` registering a change event and
|
||||||
|
informing a :term:`handler <handlers>` task that another
|
||||||
The act of a task registering a change event and informing a handler task that another action needs to be run at the end of the play.
|
:term:`action` needs to be run at the end of the :term:`play <plays>`. If
|
||||||
If a handler is notified by multiple tasks, it will still be run only once. Handlers are run in the order they are listed, not
|
a handler is notified by multiple tasks, it will still be run only
|
||||||
in the order that they are notified.
|
once. Handlers are run in the order they are listed, not in the order
|
||||||
|
that they are notified.
|
||||||
|
|
||||||
Orchestration
|
Orchestration
|
||||||
+++++++++++++
|
Many software automation systems use this word to mean different
|
||||||
|
things. Ansible uses it as a conductor would conduct an orchestra.
|
||||||
Many software automation systems use this word to mean different things. Ansible uses it as a conductor would conduct an orchestra.
|
A datacenter or cloud architecture is full of many systems, playing
|
||||||
A datacenter or cloud architecture is full of many systems, playing many parts -- web servers, database servers, maybe load balancers,
|
many parts -- web servers, database servers, maybe load balancers,
|
||||||
monitoring systems, continuous integration systems, etc. In performing any process, it is necessary to touch systems in particular orders,
|
monitoring systems, continuous integration systems, etc. In
|
||||||
often to simulate rolling updates or to deploy software correctly. Some system may perform some steps, then others, then previous systems
|
performing any process, it is necessary to touch systems in particular
|
||||||
already processed may need to perform more steps. Along the way, emails may need to be sent or web services contacted. Ansible
|
orders, often to simulate rolling updates or to deploy software
|
||||||
orchestration is all about modeling that kind of process.
|
correctly. Some system may perform some steps, then others, then
|
||||||
|
previous systems already processed may need to perform more steps.
|
||||||
|
Along the way, emails may need to be sent or web services contacted.
|
||||||
|
Ansible orchestration is all about modeling that kind of process.
|
||||||
|
|
||||||
paramiko
|
paramiko
|
||||||
++++++++
|
By default, Ansible manages machines over SSH. The library that
|
||||||
|
Ansible uses by default to do this is a Python-powered library called
|
||||||
By default, Ansible manages machines over SSH. The library that Ansible uses by default to do this is a Python-powered library called
|
paramiko. The paramiko library is generally fast and easy to manage,
|
||||||
paramiko. The paramiko library is generally fast and easy to manage, though users desiring Kerberos or Jump Host support may wish to switch
|
though users desiring Kerberos or Jump Host support may wish to switch
|
||||||
to a native SSH binary such as OpenSSH by specifying the connection type in their playbook, or using the "-c ssh" flag.
|
to a native SSH binary such as OpenSSH by specifying the connection
|
||||||
|
type in their :term:`playbooks`, or using the ``-c ssh`` flag.
|
||||||
|
|
||||||
Playbooks
|
Playbooks
|
||||||
+++++++++
|
Playbooks are the language by which Ansible orchestrates, configures,
|
||||||
|
administers, or deploys systems. They are called playbooks partially
|
||||||
Playbooks are the language by which Ansible orchestrates, configures, administers, or deploys systems. They are called playbooks partially because it's a sports analogy, and it's supposed to be fun using them. They aren't workbooks :)
|
because it's a sports analogy, and it's supposed to be fun using them.
|
||||||
|
They aren't workbooks :)
|
||||||
|
|
||||||
Plays
|
Plays
|
||||||
+++++
|
A :term:`playbook <playbooks>` is a list of plays. A play is
|
||||||
|
minimally a mapping between a set of :term:`hosts <Host>` selected by a host
|
||||||
A playbook is a list of plays. A play is minimally a mapping between a set of hosts selected by a host specifier (usually chosen by groups, but sometimes by hostname
|
specifier (usually chosen by :term:`groups <Group>` but sometimes by
|
||||||
globs) and the tasks which run on those hosts to define the role that those systems will perform. There
|
hostname :term:`globs <Globbing>`) and the :term:`tasks` which run on those
|
||||||
can be one or many plays in a playbook.
|
hosts to define the role that those systems will perform. There can be
|
||||||
|
one or many plays in a playbook.
|
||||||
|
|
||||||
Pull Mode
|
Pull Mode
|
||||||
+++++++++
|
By default, Ansible runs in :term:`push mode`, which allows it very
|
||||||
|
fine-grained control over when it talks to each system. Pull mode is
|
||||||
|
provided for when you would rather have nodes check in every N minutes
|
||||||
|
on a particular schedule. It uses a program called
|
||||||
|
:command:`ansible-pull` and can also be set up (or reconfigured) using
|
||||||
|
a push-mode :term:`playbook <playbooks>`. Most Ansible users use push
|
||||||
|
mode, but pull mode is included for variety and the sake of having
|
||||||
|
choices.
|
||||||
|
|
||||||
By default, Ansible runs in push mode, which allows it very fine-grained control over when it talks to each system. Pull mode is
|
:command:`ansible-pull` works by checking configuration orders out of
|
||||||
provided for when you would rather have nodes check in every N minutes on a particular schedule. It uses a program called ansible-pull and can also be set up (or reconfigured) using a push-mode playbook. Most Ansible users use push mode, but pull mode is included for variety and the sake
|
git on a crontab and then managing the machine locally, using the
|
||||||
of having choices.
|
:term:`local connection` plugin.
|
||||||
|
|
||||||
ansible-pull works by checking configuration orders out of git on a crontab and then managing the machine locally, using the local
|
|
||||||
connection plugin.
|
|
||||||
|
|
||||||
Push Mode
|
Push Mode
|
||||||
+++++++++
|
Push mode is the default mode of Ansible. In fact, it's not really
|
||||||
|
a mode at all -- it's just how Ansible works when you aren't thinking
|
||||||
Push mode is the default mode of Ansible. In fact, it's not really a mode at all -- it's just how Ansible works when you aren't
|
about it. Push mode allows Ansible to be fine-grained and conduct
|
||||||
thinking about it. Push mode allows Ansible to be fine-grained and conduct nodes through complex orchestration processes without
|
nodes through complex orchestration processes without waiting for them
|
||||||
waiting for them to check in.
|
to check in.
|
||||||
|
|
||||||
Register Variable
|
Register Variable
|
||||||
+++++++++++++++++
|
The result of running any :term:`task <tasks>` in Ansible can be
|
||||||
|
stored in a variable for use in a template or a conditional statement.
|
||||||
The result of running any task in Ansible can be stored in a variable for use in a template or a conditional statement.
|
The keyword used to define the variable is called ``register``, taking
|
||||||
The keyword used to define the variable is called 'register', taking its name from the idea of registers in assembly
|
its name from the idea of registers in assembly programming (though
|
||||||
programming (though Ansible will never feel like assembly programming). There are an infinite number of variable names
|
Ansible will never feel like assembly programming). There are an
|
||||||
you can use for registration.
|
infinite number of variable names you can use for registration.
|
||||||
|
|
||||||
Resource Model
|
Resource Model
|
||||||
++++++++++++++
|
Ansible modules work in terms of resources. For instance, the
|
||||||
|
:ref:`file module <file>` will select a particular file and ensure
|
||||||
Ansible modules work in terms of resources. For instance, the file module will select a particular file
|
that the attributes of that resource match a particular model. As an
|
||||||
and ensure that the attributes of that resource match a particular model. As an example, we might wish to change the owner of /etc/motd
|
example, we might wish to change the owner of :file:`/etc/motd` to
|
||||||
to 'root' if it is not already set to root, or set its mode to '0644' if it is not already set to '0644'. The resource models
|
``root`` if it is not already set to ``root``, or set its mode to
|
||||||
are 'idempotent' meaning change commands are not run unless needed, and Ansible will bring the system back to a desired
|
``0644`` if it is not already set to ``0644``. The resource models
|
||||||
state regardless of the actual state -- rather than you having to tell it how to get to the state.
|
are :term:`idempotent <idempotency>` meaning change commands are not
|
||||||
|
run unless needed, and Ansible will bring the system back to a desired
|
||||||
|
state regardless of the actual state -- rather than you having to tell
|
||||||
|
it how to get to the state.
|
||||||
|
|
||||||
Roles
|
Roles
|
||||||
+++++
|
Roles are units of organization in Ansible. Assigning a role to
|
||||||
|
a group of :term:`hosts <Host>` (or a set of :term:`groups <group>`,
|
||||||
Roles are units of organization in Ansible. Assigning a role to a group of hosts (or a set of groups, or host patterns, etc.) implies that they should implement a specific behavior. A role
|
or :term:`host patterns <Globbing>`, etc.) implies that they should
|
||||||
may include applying certain variable values, certain tasks, and certain handlers -- or just one or more of these things. Because of the file structure associated with a role, roles become
|
implement a specific behavior. A role may include applying certain
|
||||||
redistributable units that allow you to share behavior among playbooks -- or even with other users.
|
variable values, certain :term:`tasks`, and certain :term:`handlers`
|
||||||
|
-- or just one or more of these things. Because of the file structure
|
||||||
|
associated with a role, roles become redistributable units that allow
|
||||||
|
you to share behavior among :term:`playbooks` -- or even with other users.
|
||||||
|
|
||||||
Rolling Update
|
Rolling Update
|
||||||
++++++++++++++
|
The act of addressing a number of nodes in a group N at a time to
|
||||||
|
avoid updating them all at once and bringing the system offline. For
|
||||||
The act of addressing a number of nodes in a group N at a time to avoid updating them all at once and bringing the system
|
instance, in a web topology of 500 nodes handling very large volume,
|
||||||
offline. For instance, in a web topology of 500 nodes handling very large volume, it may be reasonable to update 10 or 20
|
it may be reasonable to update 10 or 20 machines at a time, moving on
|
||||||
machines at a time, moving on to the next 10 or 20 when done. The "serial:" keyword in an Ansible playbook controls the
|
to the next 10 or 20 when done. The ``serial:`` keyword in an Ansible
|
||||||
size of the rolling update pool. The default is to address the batch size all at once, so this is something that you must
|
:term:`playbooks` control the size of the rolling update pool. The
|
||||||
opt-in to. OS configuration (such as making sure config files are correct) does not typically have to use the rolling update
|
default is to address the batch size all at once, so this is something
|
||||||
|
that you must opt-in to. OS configuration (such as making sure config
|
||||||
|
files are correct) does not typically have to use the rolling update
|
||||||
model, but can do so if desired.
|
model, but can do so if desired.
|
||||||
|
|
||||||
Runner
|
|
||||||
++++++
|
|
||||||
|
|
||||||
A core software component of Ansible that is the power behind /usr/bin/ansible directly -- and corresponds to the invocation
|
|
||||||
of each task in a playbook. The Runner is something Ansible developers may talk about, but it's not really user land
|
|
||||||
vocabulary.
|
|
||||||
|
|
||||||
Serial
|
Serial
|
||||||
++++++
|
.. seealso::
|
||||||
|
|
||||||
See "Rolling Update".
|
:term:`Rolling Update`
|
||||||
|
|
||||||
Sudo
|
Sudo
|
||||||
++++
|
Ansible does not require root logins, and since it's daemonless,
|
||||||
|
definitely does not require root level daemons (which can be
|
||||||
Ansible does not require root logins, and since it's daemonless, definitely does not require root level daemons (which can
|
a security concern in sensitive environments). Ansible can log in and
|
||||||
be a security concern in sensitive environments). Ansible can log in and perform many operations wrapped in a sudo command,
|
perform many operations wrapped in a sudo command, and can work with
|
||||||
and can work with both password-less and password-based sudo. Some operations that don't normally work with sudo (like scp
|
both password-less and password-based sudo. Some operations that
|
||||||
file transfer) can be achieved with Ansible's copy, template, and fetch modules while running in sudo mode.
|
don't normally work with sudo (like scp file transfer) can be achieved
|
||||||
|
with Ansible's :ref:`copy <copy>`, :ref:`template <template>`, and
|
||||||
|
:ref:`fetch <fetch>` modules while running in sudo mode.
|
||||||
|
|
||||||
SSH (Native)
|
SSH (Native)
|
||||||
++++++++++++
|
Native OpenSSH as an Ansible transport is specified with ``-c ssh``
|
||||||
|
(or a config file, or a directive in the :term:`playbook <playbooks>`)
|
||||||
Native OpenSSH as an Ansible transport is specified with "-c ssh" (or a config file, or a directive in the playbook)
|
and can be useful if wanting to login via Kerberized SSH or using SSH
|
||||||
and can be useful if wanting to login via Kerberized SSH or using SSH jump hosts, etc. In 1.2.1, 'ssh' will be used by default if the OpenSSH binary
|
jump hosts, etc. In 1.2.1, ``ssh`` will be used by default if the
|
||||||
on the control machine is sufficiently new. Previously, Ansible selected 'paramiko' as a default.
|
OpenSSH binary on the control machine is sufficiently new.
|
||||||
Using a client that supports ControlMaster and ControlPersist is recommended for maximum performance -- if you don't have that and don't need Kerberos, jump hosts, or other features, paramiko is a good choice. Ansible will warn you if it doesn't detect ControlMaster/ControlPersist capability.
|
Previously, Ansible selected ``paramiko`` as a default. Using
|
||||||
|
a client that supports ``ControlMaster`` and ``ControlPersist`` is
|
||||||
|
recommended for maximum performance -- if you don't have that and
|
||||||
|
don't need Kerberos, jump hosts, or other features, ``paramiko`` is
|
||||||
|
a good choice. Ansible will warn you if it doesn't detect
|
||||||
|
ControlMaster/ControlPersist capability.
|
||||||
|
|
||||||
Tags
|
Tags
|
||||||
++++
|
Ansible allows tagging resources in a :term:`playbook <playbooks>`
|
||||||
|
with arbitrary keywords, and then running only the parts of the
|
||||||
Ansible allows tagging resources in a playbook with arbitrary keywords, and then running only the parts of the playbook that
|
playbook that correspond to those keywords. For instance, it is
|
||||||
correspond to those keywords. For instance, it is possible to have an entire OS configuration, and have certain steps
|
possible to have an entire OS configuration, and have certain steps
|
||||||
labeled "ntp", and then run just the "ntp" steps to reconfigure the time server information on a remote host.
|
labeled ``ntp``, and then run just the ``ntp`` steps to reconfigure
|
||||||
|
the time server information on a remote host.
|
||||||
|
|
||||||
Tasks
|
Tasks
|
||||||
+++++
|
:term:`Playbooks` exist to run tasks. Tasks combine an :term:`action`
|
||||||
|
(a module and its arguments) with a name and optionally some other
|
||||||
Playbooks exist to run tasks. Tasks combine an action (a module and its arguments) with a name and optionally some other keywords (like looping directives). Handlers are also tasks, but they are a special kind of task that do not run unless they are notified by name when a task reports an underlying change on a remote system.
|
keywords (like :term:`looping directives <loops>`). :term:`Handlers`
|
||||||
|
are also tasks, but they are a special kind of task that do not run
|
||||||
|
unless they are notified by name when a task reports an underlying
|
||||||
|
change on a remote system.
|
||||||
|
|
||||||
Templates
|
Templates
|
||||||
+++++++++
|
Ansible can easily transfer files to remote systems but often it is
|
||||||
|
desirable to substitute variables in other files. Variables may come
|
||||||
Ansible can easily transfer files to remote systems, but often it is desirable to substitute variables in other files. Variables
|
from the :term:`inventory` file, :term:`Host Vars`, :term:`Group
|
||||||
may come from the inventory file, Host Vars, Group Vars, or Facts. Templates use the Jinja2 template engine and can also include logical
|
Vars`, or :term:`Facts`. Templates use the :term:`Jinja2` template
|
||||||
constructs like loops and if statements.
|
engine and can also include logical constructs like loops and if
|
||||||
|
statements.
|
||||||
|
|
||||||
Transport
|
Transport
|
||||||
+++++++++
|
Ansible uses :term:``Connection Plugins`` to define types of available
|
||||||
|
transports. These are simply how Ansible will reach out to managed
|
||||||
Ansible uses "Connection Plugins" to define types of available transports. These are simply how Ansible will reach out to managed systems. Transports included are paramiko, SSH (using OpenSSH), and local.
|
systems. Transports included are :term:`paramiko`,
|
||||||
|
:term:`ssh <SSH (Native)>` (using OpenSSH), and
|
||||||
|
:term:`local <Local Connection>`.
|
||||||
|
|
||||||
When
|
When
|
||||||
++++
|
An optional conditional statement attached to a :term:`task <tasks>` that is used to
|
||||||
|
determine if the task should run or not. If the expression following
|
||||||
An optional conditional statement attached to a task that is used to determine if the task should run or not. If the expression following the "when:" keyword evaluates to false, the task will be ignored.
|
the ``when:`` keyword evaluates to false, the task will be ignored.
|
||||||
|
|
||||||
Van Halen
|
|
||||||
+++++++++
|
|
||||||
|
|
||||||
For no particular reason, other than the fact that Michael really likes them, all Ansible 0.x and 1.x releases are codenamed after Van Halen songs. There is no preference given to David Lee Roth vs. Sammy Lee Hagar-era songs, and instrumentals are also allowed. It is unlikely that there will ever be a Jump release, but a Van Halen III codename release is possible. You never know.
|
|
||||||
|
|
||||||
Vars (Variables)
|
Vars (Variables)
|
||||||
++++++++++++++++
|
As opposed to :term:`Facts`, variables are names of values (they can
|
||||||
|
be simple scalar values -- integers, booleans, strings) or complex
|
||||||
As opposed to Facts, variables are names of values (they can be simple scalar values -- integers, booleans, strings) or complex ones (dictionaries/hashes, lists) that can be used in templates and playbooks. They are declared things, not things that are inferred from the remote system's current state or nature (which is what Facts are).
|
ones (dictionaries/hashes, lists) that can be used in templates and
|
||||||
|
:term:`playbooks`. They are declared things, not things that are
|
||||||
|
inferred from the remote system's current state or nature (which is
|
||||||
|
what Facts are).
|
||||||
|
|
||||||
YAML
|
YAML
|
||||||
++++
|
Ansible does not want to force people to write programming language
|
||||||
|
code to automate infrastructure, so Ansible uses YAML to define
|
||||||
Ansible does not want to force people to write programming language code to automate infrastructure, so Ansible uses YAML to define playbook configuration languages and also variable files. YAML is nice because it has a minimum of syntax and is very clean and easy for people to skim. It is a good data format for configuration files and humans, but also machine readable. Ansible's usage of YAML stemmed from Michael's first use of it inside of Cobbler around 2006. YAML is fairly popular in the dynamic language community and the format has libraries available
|
:term:`playbook <playbooks>` configuration languages and also variable
|
||||||
for serialization in many languages (Python, Perl, Ruby, etc.).
|
files. YAML is nice because it has a minimum of syntax and is very
|
||||||
|
clean and easy for people to skim. It is a good data format for
|
||||||
|
configuration files and humans, but also machine readable. Ansible's
|
||||||
|
usage of YAML stemmed from Michael DeHaan's first use of it inside of
|
||||||
|
Cobbler around 2006. YAML is fairly popular in the dynamic language
|
||||||
|
community and the format has libraries available for serialization in
|
||||||
|
many languages (Python, Perl, Ruby, etc.).
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
|
|
|
@ -485,7 +485,7 @@ module_set_locale
|
||||||
=================
|
=================
|
||||||
|
|
||||||
This boolean value controls whether or not Ansible will prepend locale-specific environment variables (as specified
|
This boolean value controls whether or not Ansible will prepend locale-specific environment variables (as specified
|
||||||
via the :doc:`module_lang` configuration option). By default this is enabled, and results in the LANG and LC_MESSAGES
|
via the :ref:`module_lang` configuration option). By default this is enabled, and results in the LANG and LC_MESSAGES
|
||||||
being set when the module is executed on the given remote system.
|
being set when the module is executed on the given remote system.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
Loading…
Reference in a new issue