ansible/ansible
Data models
Reference for the structured shapes that flow through ansible-core: task results, the dynamic-inventory protocol, the AnsiBallZ archive layout, and Vault file format.
Task result JSON
Every module returns a JSON dict. The conventional shape:
{
"changed": true,
"failed": false,
"msg": "Optional human-readable message",
"rc": 0,
"stdout": "command output",
"stdout_lines": ["..."],
"stderr": "",
"stderr_lines": [],
"skipped": false,
"diff": [
{
"before": "...",
"after": "...",
"before_header": "...",
"after_header": "..."
}
],
"warnings": [],
"deprecations": [],
"ansible_facts": {},
"_ansible_no_log": false,
"_ansible_verbose_always": false,
"invocation": {
"module_args": { "...": "..." }
}
}Module authors call module.exit_json(**result) (or module.fail_json(...)) and AnsibleModule adds the underscore-prefixed metadata fields automatically.
The action plugin layer can augment the result before it returns to the executor. For example, the template action plugin adds dest, src, and checksum fields not generated by the underlying copy module.
The TQM wraps the dict in a CallbackTaskResult (lib/ansible/executor/task_result.py) before passing to callback plugins.
Test plugin predicates over a result
The test plugins (is changed, is succeeded, is failed, is skipped, etc.) look at standard fields:
is changed—result.get('changed') is True.is succeeded— neitherfailed:truenor unreachable.is failed—result.get('failed') is True.is skipped—result.get('skipped') is True.is unreachable—result.get('unreachable') is True.
Dynamic inventory protocol
Inventory scripts (run by the script inventory plugin) and ansible-inventory --list produce JSON in this shape:
{
"_meta": {
"hostvars": {
"web01.example.com": {
"ansible_host": "10.0.1.42",
"ansible_user": "deploy",
"env": "prod"
}
}
},
"all": {
"children": ["webservers", "dbservers", "ungrouped"]
},
"webservers": {
"hosts": ["web01.example.com", "web02.example.com"],
"vars": { "http_port": 80 }
},
"dbservers": {
"hosts": ["db01.example.com"],
"vars": {}
},
"ungrouped": {
"hosts": []
}
}Top-level keys are group names; each maps to a dict with optional hosts, vars, and children. The reserved _meta.hostvars block is the optimization that lets a script return all per-host vars in one shot rather than being polled per-host.
A script that responds to --host <name> should return just that host's vars dict:
{ "ansible_host": "10.0.1.42", "env": "prod" }This protocol is what ansible-inventory --list produces for any inventory source — making the dynamic-inventory format a stable interchange shape for tooling.
AnsiBallZ archive layout
A typical Python AnsiBallZ archive looks like:
__main__.py # Boilerplate shim that runs the module
ansible/__init__.py
ansible/module_utils/
__init__.py
basic.py # Always shipped
common/
common/parameters.py
common/text/
common/text/converters.py
_internal/
_internal/_datatag.py
... (more module_utils as discovered by AST walk)
ansible/modules/<module_name>.py
ANSIBALLZ_PARAMS # JSON-serialized argumentsThe whole zip is base64-encoded into a Python script; the script decodes the zip, hooks it onto sys.path via zipimport, imports ansible.modules.<name>, and calls main(). The result JSON is written to stdout.
For PowerShell modules on Windows, the equivalent is generated by lib/ansible/executor/powershell/module_manifest.py; the wrapper is a PowerShell script with embedded C# helper assemblies and a payload section.
See Module execution and AnsiBallZ for the build flow.
Vault file format
Header line:
$ANSIBLE_VAULT;1.2;AES256;<vault_id>Followed by hex-encoded payload (multiple lines for readability):
65613534393531393433386532373035613131333061626336303032313637...Decoded payload structure:
salt (32 bytes) | hmac (32 bytes) | ciphertextKDF: PBKDF2-HMAC-SHA256, 10,000 rounds, 80-byte output split into AES key (32), HMAC key (32), IV (16). Cipher: AES-256-CTR.
The legacy 1.1 format omits the <vault_id> suffix. The legacy 1.0 format (no longer written, only readable) lacks both the vault id and uses an older mac scheme.
See Systems → Vault encryption for the cryptographic details.
Inventory data shape (Python)
InventoryData (lib/ansible/inventory/data.py) holds:
class InventoryData:
groups: dict[str, Group]
hosts: dict[str, Host]
current_source: str | NoneA Host:
class Host:
name: str
address: str # often == name
vars: dict
groups: list[Group]
implicit: bool # True for auto-created localhost/127.0.0.1A Group:
class Group:
name: str
vars: dict
hosts: list[Host]
child_groups: list[Group]
parent_groups: list[Group]
priority: int # default 1; higher wins on conflictsPlugin DOCUMENTATION YAML
The schema for any plugin's top-of-file DOCUMENTATION block:
---
name: <plugin_name>
short_description: <one-line description>
description:
- <multi-paragraph long description>
author:
- <Name <email>>
version_added: '2.X'
options:
<option_name>:
description: <description>
type: <str|int|bool|list|dict|path|raw>
required: <true|false>
default: <value>
choices:
- <value>
vars: # plugin-config-only: where to read this option's value
- name: <var_name>
env:
- name: <ENV_VAR>
ini:
- section: defaults
key: <key_name>
version_added: '2.Y'
extends_documentation_fragment:
- <fragment_name>
notes:
- <note>
seealso:
- module: <related_module>The extends_documentation_fragment mechanism lets plugins inherit common option declarations (e.g., inventory_cache brings in cache-related options).
Cross-links
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.