AnsibleVIII · Modules and the Module ModelThe module model
Reading module documentation like an operator
What you'll learn
- Navigate ansible-doc with -l, -s, -t and -j to answer a specific question quickly
- Read the attributes table and interpret full, partial, none and N/A support
- Determine before running whether --check and --diff will tell you anything
- Use ansible-doc -t keyword to look up play and task keywords, not just modules
Prerequisites
Verified against ansible-core 2.21.x · ansible (community package) 14.x · Python (controller) 3.12+ · ansible-lint 26.x · Molecule 26.x · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL / Rocky / AlmaLinux 9.x · 2026-08-11
The single highest-value skill in this part is not memorising modules. It is being able to answer, in about ten seconds and without a browser, questions like does this module support check mode, what does it return, and does this option exist in the version I am running.
ansible-doc answers all three from the installed code, which means it
is correct for your version rather than for whichever version the
website is currently rendering. That distinction matters more than it
sounds: a module page on docs.ansible.com describes the latest release,
and you are running whatever your controller has.
The four invocations worth knowing
-l — what exists
$ ansible-doc -lansible.builtin.add_host Add a host (and alternatively a grou...
ansible.builtin.apt Manages apt-packages
ansible.builtin.apt_key Add or remove an apt key
ansible.builtin.apt_repository Add and remove APT repositories
ansible.builtin.assemble Assemble configuration files from fr...Illustrative output
On a bare ansible-core 2.21 install this lists 71 modules. That is
worth internalising: ansible-core is small, and the thousands of
modules people talk about live in collections you install separately.
The argument to -l filters by namespace or collection, which is how you
find out what a collection you just installed actually contains:
$ ansible-doc -l community.generalSearching by topic is the thing -l does not do well. There is no
keyword search, so the usual approach is ansible-doc -l | grep -i firewall, which greps the one-line summaries and is exactly as good as
those summaries happen to be.
-s — the snippet
$ ansible-doc -s ansible.builtin.ping- name: Try to connect to host, verify a usable python and return `pong' on success
ping:
data: # Data to return for the `ping' return value. If
# this parameter is
# set to `crash', the
# module will cause
# an exception.One caution: -s emits the short module name, ping: rather than
ansible.builtin.ping:. If you paste the snippet directly you have
written a short name into a playbook, which the next lesson argues
against and which ansible-lint will flag. Add the namespace by hand.
-t — other plugin types
-t defaults to module, and the other values are where a lot of
otherwise hard-to-find documentation lives:
become cache callback cliconf connection httpapi inventory
lookup netconf shell vars module strategy test filter
role keyword
-t keyword is the one people do not know exists. It documents the play,
block and task keywords themselves — the things that are not modules:
$ ansible-doc -t keyword collectionscollections:
applies_to:
- Play
- Role
- Block
- Task
- Handler
description: "List of collection namespaces to search for modules, plugins, and
roles. ..."
priority: 100
template: static
type: listIllustrative output
ansible-doc -t keyword -l lists all of them, which is a better
reference for “is it serial or batch_size” than any web search.
-j — JSON, for when you are asking about more than one module
$ ansible-doc -j ansible.builtin.copy | jq -r '.[].doc.attributes.check_mode.support'fullThis is the invocation that turns “I wonder whether check mode is meaningful in this play” from a research task into a one-liner.
The attributes table
Every module page has an ATTRIBUTES section, below the options and
above the examples. Almost nobody reads it. It is the most operationally
important part of the page.
$ ansible-doc ansible.builtin.command | sed -n '/ATTRIBUTES/,/NOTES/p'ATTRIBUTES:
check_mode:
description: Can run in check_mode and return changed status prediction without modifying
target, if not supported the action will be skipped.
details: while the command itself is arbitrary and cannot be subject to the check
mode semantics it adds `creates'/`removes' options as a workaround
support: partial
diff_mode:
description: Will return details on what has changed (or possibly needs changing in
check_mode), when in diff mode
support: none
platform:
description: Target OS/families that can be operated against
platforms: posix
support: full
raw:
description: Indicates if an action takes a 'raw' or 'free form' string as an option
and has it's own special parsing of it
support: fullThe support levels
| Level | What it means |
|---|---|
full | The capability works as described, with no qualification. |
partial | It works in some circumstances. Read the details line — it tells you which. |
none | It does not work. For check_mode, this means the task is skipped in --check. |
N/A | The question does not apply to this module, usually because it dispatches to another one. |
partial is the level that misleads, because it reads like “mostly
works”. For command it means check mode functions only through the
creates and removes options, and does nothing at all without them.
The details line says exactly that, in eighteen words, and is the
reason the attributes table is worth reading rather than skimming.
The attributes you will actually use
| Attribute | Question it answers |
|---|---|
check_mode | Will --check evaluate this task, or skip it? |
diff_mode | Will --diff show me the content that changes? |
platform | Which OS families does this module claim to support? |
action | Does part of this run on the controller rather than the target? |
become | Does privilege escalation apply, or is it ignored? |
async | Can this be backgrounded with async and poll? |
safe_file_operations | Does it write atomically, or can a failure leave a partial file? |
bypass_host_loop | Does this run once globally rather than per host? |
facts | Does it inject facts into the host, as setup does? |
action is the one that explains a whole class of confusion, and it has
its own lesson later in this part.
The check-mode picture across ansible-core
Because -j makes this answerable, here is the actual distribution
across the 70 documented modules in ansible-core 2.21:
check_mode support | Count | Notable members |
|---|---|---|
full | 52 | file, copy, template, lineinfile, user, cron, apt, systemd |
partial | 8 | command, shell, script, get_url, unarchive, add_host, group_by, meta |
none | 8 | raw, uri, expect, tempfile, wait_for, wait_for_connection, include_tasks, import_tasks |
N/A | 2 | package, service |
The majority are full, which is the reassuring half of the picture. The
alarming half is the membership of the other two columns: command,
shell, script and raw are precisely the modules people reach for
when no purpose-built module exists — that is, in the tasks that are
hardest to reason about and most in need of a dry run.
diff_mode: full is rarer still: 18 modules, essentially the ones that
manage file content (copy, template, lineinfile, blockinfile,
replace, assemble, cron, git) plus the package and repository
modules.
A worked question
The change window is Thursday. Will --check on this play tell me
anything useful?
$ for m in package template service command; do printf '%-10s %s\n' "$m" "$(ansible-doc -j ansible.builtin.$m | jq -r '.[].doc.attributes.check_mode.support')"; donepackage N/A
template full
service N/A
command partialRead that as: the template task will be evaluated properly and will show
a diff. The command task will be skipped entirely unless it has a
creates guard. The package and service tasks depend on what they
dispatch to on the target, which on a systemd Debian host means apt
(full) and systemd_service (full).
So the check run is informative for three of the four tasks and blind to the fourth — and the fourth is the one running an arbitrary script. That is a useful thing to know before Thursday.
Knowledge check
Knowledge check · 4 questions
Q1. ansible-doc reports check_mode: N/A for ansible.builtin.service. What should you conclude?
Q2. Which of these questions can ansible-doc answer without a browser? Select all that apply.
Q3. A module documenting check_mode: partial requires you to read its details line, because partial describes a specific qualification rather than a general degree of support.
Q4. You paste an `ansible-doc -s` snippet straight into a playbook and ansible-lint complains. Why?
Passing score: 75%. Answers are checked in this browser.