class

Krikri::Task

Inherits Reference < Object

Represents a single task in a playbook

Constants

IMPORT_PLAYBOOK_SPELLINGS = ["import_playbook", "ansible.builtin.import_playbook", "ansible.legacy.import_playbook"]

Ansible-core ships import_playbook as a doc-only stub module (lib/ansible/modules/import_playbook.py: DOCUMENTATION and EXAMPLES only, no code, no shebang). It is a play-level keyword only; a TASK whose action is one of these spellings still RESOLVES as a module on the controller (the loader finds the stub file), and the base action plugin's _execute_module then dies on its shebang check - a per-task failure "Task failed: module (X) is missing interpreter line" that honors ignore_errors:, NOT the graceful unported-module skip the rest of the unavailable_module flow gives (live-verified vs 2.19.11, issue #762).

Constructors

new(name : String, module_name : String)
Source

Instance methods

action_name

The module spelling AS WRITTEN in the task source (before FQCN resolution and before MODULE_ALIASES redirect) - Ansible's "Unsupported parameters for (...) module" argument-validation error echoes this spelling verbatim for non-delegating modules (bare lineinfile: prints "(lineinfile)", the FQCN prints the FQCN), so argspec validation needs it alongside the resolved module_name. nil for tasks built outside the parser (defaults to module_name).

Source
action_name=(action_name : String | Nil)

The module spelling AS WRITTEN in the task source (before FQCN resolution and before MODULE_ALIASES redirect) - Ansible's "Unsupported parameters for (...) module" argument-validation error echoes this spelling verbatim for non-delegating modules (bare lineinfile: prints "(lineinfile)", the FQCN prints the FQCN), so argspec validation needs it alongside the resolved module_name. nil for tasks built outside the parser (defaults to module_name).

Source
always_tasks
Source
always_tasks=(always_tasks : Array(Task) | Nil)
Source
ansible_collection_name

The namespace.collection this task's own role belongs to - exposed as the ansible_collection_name magic var, only ever set for a role invoked via its full namespace.collection.role FQCN (a collection-shipped role, as opposed to a plain Galaxy role install). Several real collections use it to strip their own namespace prefix back off ansible_parent_role_names (prometheus. prometheus._common's own regex_replace(ansible_collection_name ~ '.', ''), computing a short service/tag name from the invoking role's FQCN).

Source
ansible_collection_name=(ansible_collection_name : String | Nil)

The namespace.collection this task's own role belongs to - exposed as the ansible_collection_name magic var, only ever set for a role invoked via its full namespace.collection.role FQCN (a collection-shipped role, as opposed to a plain Galaxy role install). Several real collections use it to strip their own namespace prefix back off ansible_parent_role_names (prometheus. prometheus._common's own regex_replace(ansible_collection_name ~ '.', ''), computing a short service/tag name from the invoking role's FQCN).

Source
async_raw

The parser only sees the task's raw YAML, so a templated value ("{{ n }}") cannot be turned into seconds here - ansible resolves these per host at execution time. Keeping the raw text lets the executor do that resolution instead of silently dropping async behavior for every templated value.

Source
async_raw=(async_raw : String | Nil)

The parser only sees the task's raw YAML, so a templated value ("{{ n }}") cannot be turned into seconds here - ansible resolves these per host at execution time. Keeping the raw text lets the executor do that resolution instead of silently dropping async behavior for every templated value.

Source
async_seconds

async: / poll: - run the module in the background (as a detached OS process, not a Fiber, so it outlives the poll loop) up to async: seconds, checking every poll: seconds (default 10, matching Ansible) until it finishes or the async: timeout elapses; poll: 0 returns immediately with the job id instead of waiting at all. Local connections only - see TaskExecutor#execute_async.

Source
async_seconds=(async_seconds : Int32 | Nil)

async: / poll: - run the module in the background (as a detached OS process, not a Fiber, so it outlives the poll loop) up to async: seconds, checking every poll: seconds (default 10, matching Ansible) until it finishes or the async: timeout elapses; poll: 0 returns immediately with the job id instead of waiting at all. Local connections only - see TaskExecutor#execute_async.

Source
become=(become : Bool)
Source
become?
Source
become_expr

Raw {{ ... }} text when become: is a templated expression rather than a literal boolean (ansible-community.ansible-vault's own become: "{{ vault_privileged_install }}", defaulting false). become above still holds a best-effort parse-time guess (used as a fallback if this can't be rendered for some reason), but the executor re-renders and overrides it at execution time, once real host/role vars are available - parse time never has that context.

Source
become_expr=(become_expr : String | Nil)

Raw {{ ... }} text when become: is a templated expression rather than a literal boolean (ansible-community.ansible-vault's own become: "{{ vault_privileged_install }}", defaulting false). become above still holds a best-effort parse-time guess (used as a fallback if this can't be rendered for some reason), but the executor re-renders and overrides it at execution time, once real host/role vars are available - parse time never has that context.

Source
become_flags

Raw become_flags: keyword text (Ansible appends it to the sudo become plugin's fixed argument set); templating happens at execution time, like become_user's.

Source
become_flags=(become_flags : String | Nil)

Raw become_flags: keyword text (Ansible appends it to the sudo become plugin's fixed argument set); templating happens at execution time, like become_user's.

Source
become_user
Source
become_user=(become_user : String | Nil)
Source
block?
Source
block_inherited_when

The clauses a block: contributes to this task through Ansible's PARENT CHAIN, kept apart from the merged when_condition because that chain also reaches the tasks a dynamic include loads: real evaluates a block's when: once per executed child, and an include_tasks:/include_role: child's own file re-evaluates it too (live-verified against 2.21.6 with jetune.docker_swarm_master, issue #990: the block's fact read is reported after the FIRST included task's banner, Origin'd at the block's own clause item). The include statement's OWN when: stays out of this chain - real evaluates that once, at the include, and never for its children. origins maps each clause to its own YAML token so the clauses keep the block's Origin instead of the inner task's.

Source
block_inherited_when=(block_inherited_when : BlockInheritedWhen | Nil)

The clauses a block: contributes to this task through Ansible's PARENT CHAIN, kept apart from the merged when_condition because that chain also reaches the tasks a dynamic include loads: real evaluates a block's when: once per executed child, and an include_tasks:/include_role: child's own file re-evaluates it too (live-verified against 2.21.6 with jetune.docker_swarm_master, issue #990: the block's fact read is reported after the FIRST included task's banner, Origin'd at the block's own clause item). The include statement's OWN when: stays out of this chain - real evaluates that once, at the include, and never for its children. origins maps each clause to its own YAML token so the clauses keep the block's Origin instead of the inner task's.

Source
block_name_chain

Raw (unrendered) name: of every enclosing block:/rescue:/always: wrapper, outermost first - nil for a task with no enclosing block. ansible-core 2.19 templates a BLOCK's name keyword strictly when one of its children actually goes to run, failing that child with "Task failed: Error processing keyword 'name': 'X' is undefined" (ikke_t.podman_container_systemd round 813203: the block named do tasks when "{{ service_name }}" state is "running" hard-failed Ansible when the role ran without grafana_podman's container_name above it - this engine rendered the name leniently and kept executing). A TASK's own name stays lenient there (Ansible banners it as "<< error 1 - 'nope' is undefined >>" and still runs/skips it normally), so only the enclosing-chain names are tracked.

Source
block_name_chain=(block_name_chain : Array(String) | Nil)

Raw (unrendered) name: of every enclosing block:/rescue:/always: wrapper, outermost first - nil for a task with no enclosing block. ansible-core 2.19 templates a BLOCK's name keyword strictly when one of its children actually goes to run, failing that child with "Task failed: Error processing keyword 'name': 'X' is undefined" (ikke_t.podman_container_systemd round 813203: the block named do tasks when "{{ service_name }}" state is "running" hard-failed Ansible when the role ran without grafana_podman's container_name above it - this engine rendered the name leniently and kept executing). A TASK's own name stays lenient there (Ansible banners it as "<< error 1 - 'nope' is undefined >>" and still runs/skips it normally), so only the enclosing-chain names are tracked.

Source
block_name_chain_origins

Parallel to block_name_chain: each entry is the origin context of the corresponding enclosing block's own name: VALUE (first character of the rendered-to-be scalar), nil when no source map located it - the child task's own file section has no name: key for the block, so the keyword-failure chain's middle link must be pointed at the block's own line the way ansible-core 2.19 does.

Source
block_name_chain_origins=(block_name_chain_origins : Array(String | Nil) | Nil)

Parallel to block_name_chain: each entry is the origin context of the corresponding enclosing block's own name: VALUE (first character of the rendered-to-be scalar), nil when no source map located it - the child task's own file section has no name: key for the block, so the keyword-failure chain's middle link must be pointed at the block's own line the way ansible-core 2.19 does.

Source
block_tasks

block: / rescue: / always: - only set when module_name == "_block" (a pseudo-module marking this Task as a block rather than a plugin invocation). Blocks can nest, since these are themselves Task lists.

Source
block_tasks=(block_tasks : Array(Task) | Nil)

block: / rescue: / always: - only set when module_name == "_block" (a pseudo-module marking this Task as a block rather than a plugin invocation). Blocks can nest, since these are themselves Task lists.

Source
changed_when

changed_when: / failed_when: - override the module's own changed/failed verdict with a condition evaluated against the task's result (accessible via its own register: name, same as any other post-task condition; a bare literal like "false" needs no register: at all). Same string/eval pipeline as when_condition/until_condition: substituted for {{ }} expressions, then handed to ConditionalEvaluator.

Source
changed_when=(changed_when : String | Nil)

changed_when: / failed_when: - override the module's own changed/failed verdict with a condition evaluated against the task's result (accessible via its own register: name, same as any other post-task condition; a bare literal like "false" needs no register: at all). Same string/eval pipeline as when_condition/until_condition: substituted for {{ }} expressions, then handed to ConditionalEvaluator.

Source
check_mode=(check_mode : Bool | Nil)
Source
check_mode?
Source
check_mode_expr

Raw {{ ... }} text when check_mode: is a templated expression rather than a literal boolean - same deferred-evaluation shape become_expr uses, and evaluated in TaskExecutor# resolve_task_check_mode against live vars.

Source
check_mode_expr=(check_mode_expr : String | Nil)

Raw {{ ... }} text when check_mode: is a templated expression rather than a literal boolean - same deferred-evaluation shape become_expr uses, and evaluated in TaskExecutor# resolve_task_check_mode against live vars.

Source
check_mode_invalid

Raw text of a task-level check_mode:/diff: literal that ansible's boolean() post-validation refuses (issue #735: diff: banana, diff: 2). Real fails the TASK with "Error processing keyword 'diff': The value 'banana' could not be converted to 'bool'." at keyword-validation time; krikri's parse previously read both as nil ("unset") and silently ran the task. Recorded here instead of raising at parse time so play/block/include-apply scopes (where the parse result only seeds an inheritable default) keep their lenient behavior, and the executor can fail the task with the same keyword-failure shape become:'s non-bool error uses.

Source
check_mode_invalid=(check_mode_invalid : String | Nil)

Raw text of a task-level check_mode:/diff: literal that ansible's boolean() post-validation refuses (issue #735: diff: banana, diff: 2). Real fails the TASK with "Error processing keyword 'diff': The value 'banana' could not be converted to 'bool'." at keyword-validation time; krikri's parse previously read both as nil ("unset") and silently ran the task. Recorded here instead of raising at parse time so play/block/include-apply scopes (where the parse result only seeds an inheritable default) keep their lenient behavior, and the executor can fail the task with the same keyword-failure shape become:'s non-bool error uses.

Source
connection

connection: - overrides the connection plugin for just this task (almost always "local"), independent of delegate_to: - it changes HOW the task's module runs (locally on the controller vs. over SSH), not WHICH host's vars/facts/register apply (that's still delegate_to:'s job). robertdebock.backup's own "Create backup_ directory" (writes to the controller's filesystem while still being attributed to the current host's own inventory_hostname) uses exactly this combination: connection: local, no delegate_to:.

Source
connection=(connection : String | Nil)

connection: - overrides the connection plugin for just this task (almost always "local"), independent of delegate_to: - it changes HOW the task's module runs (locally on the controller vs. over SSH), not WHICH host's vars/facts/register apply (that's still delegate_to:'s job). robertdebock.backup's own "Create backup_ directory" (writes to the controller's filesystem while still being attributed to the current host's own inventory_hostname) uses exactly this combination: connection: local, no delegate_to:.

Source
debugger

debugger: at task scope - see Play#debugger.

Source
debugger=(debugger : String | Nil)

debugger: at task scope - see Play#debugger.

Source
delay
Source
delay=(delay : Int32)
Source
delay_template
Source
delay_template=(delay_template : String | Nil)
Source
delegate_facts=(delegate_facts : Bool)

delegate_facts: - when true alongside delegate_to:, a module's returned ansible_facts (set_fact:, fact-gathering modules) attach to the delegate_to: target's own hostvars instead of the delegating host's - Ansible's own documented meaning ("apply facts to a delegated host instead of the inventory_hostname"). register: is unaffected either way (always attaches to the delegating host).

Source
delegate_facts?

delegate_facts: - when true alongside delegate_to:, a module's returned ansible_facts (set_fact:, fact-gathering modules) attach to the delegate_to: target's own hostvars instead of the delegating host's - Ansible's own documented meaning ("apply facts to a delegated host instead of the inventory_hostname"). register: is unaffected either way (always attaches to the delegating host).

Source
delegate_to

delegate_to: - run this task's actual module/connection against a different host than the one the play is iterating (e.g. "localhost"), while variables/facts/register/stats still belong to the original host. May be templated ({{ vars }}), so kept as a raw string and resolved at execution time (same reasoning as include_file).

Source
delegate_to=(delegate_to : String | Nil)

delegate_to: - run this task's actual module/connection against a different host than the one the play is iterating (e.g. "localhost"), while variables/facts/register/stats still belong to the original host. May be templated ({{ vars }}), so kept as a raw string and resolved at execution time (same reasoning as include_file).

Source
diff_mode=(diff_mode : Bool | Nil)
Source
diff_mode?
Source
diff_mode_expr

Raw {{ ... }} text when diff: is a templated expression rather than a literal boolean - same deferred-evaluation shape check_mode_expr uses, resolved against live vars at execution time (TaskExecutor#resolve_task_diff_mode). martin-micimo.haproxy's diff: "{{ haproxy_show_template_diffs }}" used to leave diff_mode nil, so the plugin got the CLI --diff fallback (off in the role-tester runs) and its template tasks printed no diff block where ansible prints one.

Source
diff_mode_expr=(diff_mode_expr : String | Nil)

Raw {{ ... }} text when diff: is a templated expression rather than a literal boolean - same deferred-evaluation shape check_mode_expr uses, resolved against live vars at execution time (TaskExecutor#resolve_task_diff_mode). martin-micimo.haproxy's diff: "{{ haproxy_show_template_diffs }}" used to leave diff_mode nil, so the plugin got the CLI --diff fallback (off in the role-tester runs) and its template tasks printed no diff block where ansible prints one.

Source
diff_mode_invalid
Source
diff_mode_invalid=(diff_mode_invalid : String | Nil)
Source
effective_module_defaults

The merged module_defaults in force for this task's scope, stamped by the apply_module_defaults post-pass (play defaults + every enclosing block/task scope). Ansible's module_defaults context is a RUNTIME stack, so it also covers tasks an include_tasks: loads at run time - which no parse-time pass ever sees. The include sites hand this to apply_module_defaults for the tasks they parse then (agaffney.synology_dsm's wrapper block gives its included login.yml the synology_dsm_api_request base_url, without which the plugin falls back to localhost and the failure message diverges, issue #399).

Source
effective_module_defaults=(effective_module_defaults : Hash(String, Hash(String, String)))

The merged module_defaults in force for this task's scope, stamped by the apply_module_defaults post-pass (play defaults + every enclosing block/task scope). Ansible's module_defaults context is a RUNTIME stack, so it also covers tasks an include_tasks: loads at run time - which no parse-time pass ever sees. The include sites hand this to apply_module_defaults for the tasks they parse then (agaffney.synology_dsm's wrapper block gives its included login.yml the synology_dsm_api_request base_url, without which the plugin falls back to localhost and the failure message diverges, issue #399).

Source
environment

environment: - per-task env vars (Ansible keyword). Raw, unsubstituted string values, same convention as params - the executor substitutes them at run time and forwards the result to the plugin, which applies them around its own shelled-out commands.

Source
environment=(environment : Hash(String, String) | Nil)

environment: - per-task env vars (Ansible keyword). Raw, unsubstituted string values, same convention as params - the executor substitutes them at run time and forwards the result to the plugin, which applies them around its own shelled-out commands.

Source
environment_raw

Raw {{ ... }} string form of environment: (environment: "{{ proxy_env }}", ryandaniels.server_update_reboot's own apt/yum tasks). Ansible accepts a single templated value here and evaluates it to the env-var dict at task finalization - failing the task when the referenced variable is undefined ("Error processing keyword 'environment': 'proxy_env' is undefined"). The parser has no vars context to resolve it against, so the raw text is stashed here and the executor substitutes it strictly at run time.

Source
environment_raw=(environment_raw : String | Nil)

Raw {{ ... }} string form of environment: (environment: "{{ proxy_env }}", ryandaniels.server_update_reboot's own apt/yum tasks). Ansible accepts a single templated value here and evaluates it to the env-var dict at task finalization - failing the task when the referenced variable is undefined ("Error processing keyword 'environment': 'proxy_env' is undefined"). The parser has no vars context to resolve it against, so the raw text is stashed here and the executor substitutes it strictly at run time.

Source
failed_when
Source
failed_when=(failed_when : String | Nil)
Source
has_explicit_name=(has_explicit_name : Bool)

Whether the task had its own name: key in the YAML. Real's --list-tasks prints task.action (no role prefix) when task.name is unset and task.get_name() ("role : name") otherwise; krikri names unnamed tasks with their as-written action, so without this flag the two are indistinguishable and an unnamed task inside a role wrongly gained the "role : " prefix in the listing.

Source
has_explicit_name?

Whether the task had its own name: key in the YAML. Real's --list-tasks prints task.action (no role prefix) when task.name is unset and task.get_name() ("role : name") otherwise; krikri names unnamed tasks with their as-written action, so without this flag the two are indistinguishable and an unnamed task inside a role wrongly gained the "role : " prefix in the listing.

Source
ignore_errors=(ignore_errors : Bool)
Source
ignore_errors?
Source
ignore_errors_explicit=(ignore_errors_explicit : Bool)

Whether the task WROTE its own ignore_errors: (vs inheriting the default) - block: children inherit the block's value only when they define none of their own, and without this marker an explicit ignore_errors: false on a child is indistinguishable from the default false, so the block's value would clobber it either way.

Source
ignore_errors_explicit?

Whether the task WROTE its own ignore_errors: (vs inheriting the default) - block: children inherit the block's value only when they define none of their own, and without this marker an explicit ignore_errors: false on a child is indistinguishable from the default false, so the block's value would clobber it either way.

Source
ignore_errors_expr

Raw {{ ... }} text when ignore_errors: is a templated expression rather than a literal boolean (dj-wasabi.telegraf's own ignore_errors: "{{ ansible_check_mode }}", whose parse-time fallback guess below is wrong on Ansible runs - see TaskExecutor#resolve_task_ignore_errors, which re-renders this against live vars (ansible_check_mode is bound there) and overrides the guess, the same deferred-evaluation shape check_mode_expr/become_expr use).

Source
ignore_errors_expr=(ignore_errors_expr : String | Nil)

Raw {{ ... }} text when ignore_errors: is a templated expression rather than a literal boolean (dj-wasabi.telegraf's own ignore_errors: "{{ ansible_check_mode }}", whose parse-time fallback guess below is wrong on Ansible runs - see TaskExecutor#resolve_task_ignore_errors, which re-renders this against live vars (ansible_check_mode is bound there) and overrides the guess, the same deferred-evaluation shape check_mode_expr/become_expr use).

Source
ignore_unreachable=(ignore_unreachable : Bool)

ignore_unreachable: true - an unreachable host does not fail the play at this task; it is reported, counted as ignored, and the host carries on to the next task (which may itself be unreachable).

Source
ignore_unreachable?

ignore_unreachable: true - an unreachable host does not fail the play at this task; it is reported, counted as ignored, and the host carries on to the next task (which may itself be unreachable).

Source
imported_when_origins

The import_tasks: line's own when: clauses WITH each clause's exact source position (path, 1-based line/col of the clause's YAML token), recorded on EVERY task the import statically inlines - unlike inherited_when_origin above, also when the child carries its own when:. Ansible evaluates a merged import when: clause-by-clause with the IMPORT's items first (they prefix the merged list), so a failing import clause's conditional-failure chain "caused by" Origin belongs at that clause's position in the IMPORTING file - even when the child's own file word-for-word contains the same clause and would otherwise be mislabeled (daixijun.mysql issue #328, where both levels write the identical inventory_hostname in groups[...]). If the import line's when: is a list, each item maps to its own item line; a scalar maps to the when: value token (the shape inherited_when_origin already covers for childless tasks). Keys are the exact clause strings placed into Task#when_condition_list, so the executor can look up the failing clause directly. nil when no import when: contributed clauses with a locatable position.

Source
imported_when_origins=(imported_when_origins : Hash(String, Tuple(String, Int32, Int32)) | Nil)

The import_tasks: line's own when: clauses WITH each clause's exact source position (path, 1-based line/col of the clause's YAML token), recorded on EVERY task the import statically inlines - unlike inherited_when_origin above, also when the child carries its own when:. Ansible evaluates a merged import when: clause-by-clause with the IMPORT's items first (they prefix the merged list), so a failing import clause's conditional-failure chain "caused by" Origin belongs at that clause's position in the IMPORTING file - even when the child's own file word-for-word contains the same clause and would otherwise be mislabeled (daixijun.mysql issue #328, where both levels write the identical inventory_hostname in groups[...]). If the import line's when: is a list, each item maps to its own item line; a scalar maps to the when: value token (the shape inherited_when_origin already covers for childless tasks). Keys are the exact clause strings placed into Task#when_condition_list, so the executor can look up the failing clause directly. nil when no import when: contributed clauses with a locatable position.

Source
include_apply_become

apply: on an include_tasks:/include_role: statement - Ansible builds an implicit parent BLOCK from that mapping (task_include.py's build_parent_block), so every task the include loads inherits these as block-level defaults, with each task's own keyword still winning. The mapping is shape-validated at load time; these fields hold the parsed values, which the executor's include paths merge into the tasks once the included file (or role) has actually been loaded - the include's own become/check_mode resolve into inherited there, its vars/when are applied per loaded task. tags: IS carried (include_apply_tags): tag selection runs over the play's own task list once (TagFilter) AND again over every run-time-loaded include's tasks, and the apply: tags join the inherited context of that second pass. A templated become:/check_mode: inside apply: is taken at its parse-time value, the same approximation parse_block_task makes for a block's own templated become:.

Found via pandemonium1986.ohmyzsh: include_tasks: {apply: {become: true, become_user: "{{ loop_ohmyzsh_users.user_name }}"}} validated cleanly and was then dropped on the floor, so the included tasks ran with the play's own become_user (root) - the oh-my-zsh installer wrote /root/.zshrc instead of the user's, and lineinfile failed with "Destination /home/pandemonium//.zshrc does not exist !" on a host where ansible-playbook succeeded.

Source
include_apply_become=(include_apply_become : Bool | Nil)

apply: on an include_tasks:/include_role: statement - Ansible builds an implicit parent BLOCK from that mapping (task_include.py's build_parent_block), so every task the include loads inherits these as block-level defaults, with each task's own keyword still winning. The mapping is shape-validated at load time; these fields hold the parsed values, which the executor's include paths merge into the tasks once the included file (or role) has actually been loaded - the include's own become/check_mode resolve into inherited there, its vars/when are applied per loaded task. tags: IS carried (include_apply_tags): tag selection runs over the play's own task list once (TagFilter) AND again over every run-time-loaded include's tasks, and the apply: tags join the inherited context of that second pass. A templated become:/check_mode: inside apply: is taken at its parse-time value, the same approximation parse_block_task makes for a block's own templated become:.

Found via pandemonium1986.ohmyzsh: include_tasks: {apply: {become: true, become_user: "{{ loop_ohmyzsh_users.user_name }}"}} validated cleanly and was then dropped on the floor, so the included tasks ran with the play's own become_user (root) - the oh-my-zsh installer wrote /root/.zshrc instead of the user's, and lineinfile failed with "Destination /home/pandemonium//.zshrc does not exist !" on a host where ansible-playbook succeeded.

Source
include_apply_become_flags
Source
include_apply_become_flags=(include_apply_become_flags : String | Nil)
Source
include_apply_become_user
Source
include_apply_become_user=(include_apply_become_user : String | Nil)
Source
include_apply_check_mode
Source
include_apply_check_mode=(include_apply_check_mode : Bool | Nil)
Source
include_apply_check_mode_expr
Source
include_apply_check_mode_expr=(include_apply_check_mode_expr : String | Nil)
Source
include_apply_tags

apply: {tags: [...]} on an include_tasks:/include_role: - unlike the statement's own tags:, these ARE given to every task the include loads (Ansible's implicit apply-Block carries them), so the executor's runtime tag filter merges them into the inherited context (live-verified vs 2.19.11: apply tags change --tags/--skip-tags/never selection of the loaded tasks exactly like an enclosing block's tags would). nil when no apply: was given.

Source
include_apply_tags=(include_apply_tags : Array(String) | Nil)

apply: {tags: [...]} on an include_tasks:/include_role: - unlike the statement's own tags:, these ARE given to every task the include loads (Ansible's implicit apply-Block carries them), so the executor's runtime tag filter merges them into the inherited context (live-verified vs 2.19.11: apply tags change --tags/--skip-tags/never selection of the loaded tasks exactly like an enclosing block's tags would). nil when no apply: was given.

Source
include_apply_vars
Source
include_apply_vars=(include_apply_vars : Hash(String, JSON::Any) | Nil)
Source
include_apply_when
Source
include_apply_when=(include_apply_when : String | Nil)
Source
include_apply_when_list
Source
include_apply_when_list=(include_apply_when_list : Array(String) | Nil)
Source
include_file

include_tasks: - only set when module_name == "_include_tasks". Unlike import_tasks (resolved at parse time), the file path may be templated ({{ vars }}) and isn't resolved until this task actually runs, so both the raw path and the directory to resolve it against (wherever the include_tasks: line itself lives) are carried on the Task for the executor to use at run time.

Source
include_file=(include_file : String | Nil)

include_tasks: - only set when module_name == "_include_tasks". Unlike import_tasks (resolved at parse time), the file path may be templated ({{ vars }}) and isn't resolved until this task actually runs, so both the raw path and the directory to resolve it against (wherever the include_tasks: line itself lives) are carried on the Task for the executor to use at run time.

Source
include_file_dir
Source
include_file_dir=(include_file_dir : String | Nil)
Source
include_file_native

The same value as include_file when the playbook wrote it as a non-string YAML literal (file: 21), kept native: Ansible's fatal include dump echoes the value as written - "include": 21, not "include": "21" - while the path it is resolved from is the Python str() of it. nil for every ordinary (string) path.

Source
include_file_native=(include_file_native : JSON::Any | Nil)

The same value as include_file when the playbook wrote it as a non-string YAML literal (file: 21), kept native: Ansible's fatal include dump echoes the value as written - "include": 21, not "include": "21" - while the path it is resolved from is the Python str() of it. nil for every ordinary (string) path.

Source
include_role?
Source
include_role_args

The include_role: directive's own args AS WRITTEN (name/tasks_from/ vars_from/apply/allow_duplicates/...), unrendered. Ansible's IncludeRole result carries them back out under include_args - but RENDERED, per invocation (live-verified vs 2.19.11: name: "{{ rn }}" registers include_args.name as the resolved role name) - so the executor renders each value when it builds the registered result (issue #888: the register: on an include_role:/include_tasks: statement used to leave the variable undefined for every later when: that referenced it).

Source
include_role_args=(include_role_args : Hash(String, JSON::Any) | Nil)

The include_role: directive's own args AS WRITTEN (name/tasks_from/ vars_from/apply/allow_duplicates/...), unrendered. Ansible's IncludeRole result carries them back out under include_args - but RENDERED, per invocation (live-verified vs 2.19.11: name: "{{ rn }}" registers include_args.name as the resolved role name) - so the executor renders each value when it builds the registered result (issue #888: the register: on an include_role:/include_tasks: statement used to leave the variable undefined for every later when: that referenced it).

Source
include_role_bool_failure

An include_role:'s own boolean keyword (public/allow_duplicates/ rolespec_validate) whose value real cannot convert to a Python bool

  • Ansible reports that before it resolves the role at all, as a normal task failure (see RoleBoolKeywords). nil for every convertible (or templated) value, and always nil for a static import_role:, where the same failure is a playbook-load abort instead.
Source
include_role_bool_failure=(include_role_bool_failure : RoleBoolKeywords::Failure | Nil)

An include_role:'s own boolean keyword (public/allow_duplicates/ rolespec_validate) whose value real cannot convert to a Python bool

  • Ansible reports that before it resolves the role at all, as a normal task failure (see RoleBoolKeywords). nil for every convertible (or templated) value, and always nil for a static import_role:, where the same failure is a playbook-load abort instead.
Source
include_role_collections

The enclosing play's collections: at parse time - the runtime include_role search-path display carries that prefix (live-verified vs 2.19.11), but the executor only has the task, not the play.

Source
include_role_collections=(include_role_collections : Array(String) | Nil)

The enclosing play's collections: at parse time - the runtime include_role search-path display carries that prefix (live-verified vs 2.19.11), but the executor only has the task, not the play.

Source
include_role_dir
Source
include_role_dir=(include_role_dir : String | Nil)
Source
include_role_loop_item_origins

For an include_role: whose loop: is a literal YAML sequence, each entry's own line/column. Real's looped role-not-found Origin points at the failing ITEM's position, not the name: value (live-verified vs 2.19.11). nil when the loop is not a literal sequence.

Source
include_role_loop_item_origins=(include_role_loop_item_origins : Array(Tuple(Int32, Int32)) | Nil)

For an include_role: whose loop: is a literal YAML sequence, each entry's own line/column. Real's looped role-not-found Origin points at the failing ITEM's position, not the name: value (live-verified vs 2.19.11). nil when the loop is not a literal sequence.

Source
include_role_name

include_role: - only set when module_name == "_include_role". The dynamic counterpart to a roles: list entry: resolved at execution time (role name may be templated), via RoleLoader, same as roles:.

Source
include_role_name=(include_role_name : String | Nil)

include_role: - only set when module_name == "_include_role". The dynamic counterpart to a roles: list entry: resolved at execution time (role name may be templated), via RoleLoader, same as roles:.

Source
include_role_name_origin

The name: (or role:) value's own line/column inside the task's source - the runtime role-not-found failure's Origin block points there, not at the task's first key (live-verified vs 2.19.11).

Source
include_role_name_origin=(include_role_name_origin : Tuple(Int32, Int32) | Nil)

The name: (or role:) value's own line/column inside the task's source - the runtime role-not-found failure's Origin block points there, not at the task's first key (live-verified vs 2.19.11).

Source
include_role_nonstring_name

A DYNAMIC include_role: whose name/role: value is present but NOT a string - real's IncludeRole.load only requires the KEY to exist, the type check happens later in RoleInclude.load ("Invalid role definition."), which for the dynamic form runs at RUN time, after the task banner has printed (issue #761). Holds the raw value (as JSON) so the executor can abort the run the way real's escaped exception does; a static import_role:'s same value refuses the whole playbook at parse time instead (see parse_include_role) and never reaches the executor.

Source
include_role_nonstring_name=(include_role_nonstring_name : JSON::Any | Nil)

A DYNAMIC include_role: whose name/role: value is present but NOT a string - real's IncludeRole.load only requires the KEY to exist, the type check happens later in RoleInclude.load ("Invalid role definition."), which for the dynamic form runs at RUN time, after the task banner has printed (issue #761). Holds the raw value (as JSON) so the executor can abort the run the way real's escaped exception does; a static import_role:'s same value refuses the whole playbook at parse time instead (see parse_include_role) and never reaches the executor.

Source
include_role_tasks_from

tasks_from: - loads tasks/<name>.yml instead of tasks/main.yml. Common in collection-shipped "shared logic" roles (e.g. prometheus.prometheus's own _common role, invoked repeatedly by every exporter role with a different tasks_from: per call - one role directory, several distinct task-file entry points).

Source
include_role_tasks_from=(include_role_tasks_from : String | Nil)

tasks_from: - loads tasks/<name>.yml instead of tasks/main.yml. Common in collection-shipped "shared logic" roles (e.g. prometheus.prometheus's own _common role, invoked repeatedly by every exporter role with a different tasks_from: per call - one role directory, several distinct task-file entry points).

Source
include_role_vars
Source
include_role_vars=(include_role_vars : Hash(String, JSON::Any) | Nil)
Source
include_role_vars_from

vars_from: - loads vars/<name>.yml instead of vars/main.yml as the role's own vars. Issue #128 found krikri parsed (and validated) the key but discarded it, so a role gated on a var defined only in the alt vars file failed its when: as undefined while Ansible passed.

Source
include_role_vars_from=(include_role_vars_from : String | Nil)

vars_from: - loads vars/<name>.yml instead of vars/main.yml as the role's own vars. Issue #128 found krikri parsed (and validated) the key but discarded it, so a role gated on a var defined only in the alt vars file failed its when: as undefined while Ansible passed.

Source
include_tasks?
Source
include_vars

vars: on an include_tasks: statement - visible to every task in the included file (unlike import_tasks:'s vars:, which is merged directly into each imported task at parse time, this has to be carried on the Task and propagated at execution time, same as loop:'s item).

Source
include_vars=(include_vars : Hash(String, JSON::Any) | Nil)

vars: on an include_tasks: statement - visible to every task in the included file (unlike import_tasks:'s vars:, which is merged directly into each imported task at parse time, this has to be carried on the Task and propagated at execution time, same as loop:'s item).

Source
include_vars?
Source
include_vars_depth
Source
include_vars_depth=(include_vars_depth : String | Nil)
Source
include_vars_dir

dir:-mode parameters (Ansible's include_vars directory form, the Ansible module) - include_vars_dir is the (possibly templated) directory to load every vars file from; include_vars_depth is the raw depth: string (templated, resolved at run time - Ansible's depth: 0 default means UNLIMITED recursion, depth: 1 means top-level files only); files_matching/ ignore_files/extensions/ignore_unknown_extensions mirror the module's own options. The executor's execute_include_vars_dir owns the details.

Source
include_vars_dir=(include_vars_dir : String | Nil)

dir:-mode parameters (Ansible's include_vars directory form, the Ansible module) - include_vars_dir is the (possibly templated) directory to load every vars file from; include_vars_depth is the raw depth: string (templated, resolved at run time - Ansible's depth: 0 default means UNLIMITED recursion, depth: 1 means top-level files only); files_matching/ ignore_files/extensions/ignore_unknown_extensions mirror the module's own options. The executor's execute_include_vars_dir owns the details.

Source
include_vars_dir_type_error
Source
include_vars_dir_type_error=(include_vars_dir_type_error : String | Nil)
Source
include_vars_extensions
Source
include_vars_extensions=(include_vars_extensions : Array(String) | Nil)
Source
include_vars_extensions_type_error=(include_vars_extensions_type_error : Bool)

2.20 made a non-list extensions: an error ("The 'extensions' option must be a list."); a bare string used to be wrapped into a one-element list silently.

Source
include_vars_extensions_type_error?

2.20 made a non-list extensions: an error ("The 'extensions' option must be a list."); a bare string used to be wrapped into a one-element list silently.

Source
include_vars_file

include_vars: - only set when module_name == "_include_vars". include_vars_file is the file to load (may be templated, so it is resolved at run time); include_vars_name is the optional name: parameter, which loads the file into a single dict variable of that name instead of merging its keys into the context.

Source
include_vars_file=(include_vars_file : String | Nil)

include_vars: - only set when module_name == "_include_vars". include_vars_file is the file to load (may be templated, so it is resolved at run time); include_vars_name is the optional name: parameter, which loads the file into a single dict variable of that name instead of merging its keys into the context.

Source
include_vars_file_type_error

The Python type name of a TRUTHY non-string file:/dir: value. Ansible's include_vars action plugin touches that value itself there - os.path.join(current_dir, self.source_dir) for dir, and the dataloader's source.split('/') (2.21's path_dwim_relative_stack, which used to reach source.startswith('~') instead) for file - and crashes with the type name in the message, before any str() copy of the path is taken (live-verified vs 2.21.6). A FALSY non-string value (0, 0.0, false, "", [], {}, null) is not an error at all: Ansible's if not self.source_dir and not self.source_file check discards it and the lookup goes on with a None needle, which is exactly the plain null-file failure this engine already produces. nil for every ordinary (string) value.

Source
include_vars_file_type_error=(include_vars_file_type_error : String | Nil)

The Python type name of a TRUTHY non-string file:/dir: value. Ansible's include_vars action plugin touches that value itself there - os.path.join(current_dir, self.source_dir) for dir, and the dataloader's source.split('/') (2.21's path_dwim_relative_stack, which used to reach source.startswith('~') instead) for file - and crashes with the type name in the message, before any str() copy of the path is taken (live-verified vs 2.21.6). A FALSY non-string value (0, 0.0, false, "", [], {}, null) is not an error at all: Ansible's if not self.source_dir and not self.source_file check discards it and the lookup goes on with a None needle, which is exactly the plain null-file failure this engine already produces. nil for every ordinary (string) value.

Source
include_vars_files_matching
Source
include_vars_files_matching=(include_vars_files_matching : String | Nil)
Source
include_vars_ignore_files
Source
include_vars_ignore_files=(include_vars_ignore_files : Array(String) | Nil)
Source
include_vars_ignore_files_string_deprecated=(include_vars_ignore_files_string_deprecated : Bool)

2.20 deprecated a bare-string ignore_files: (still accepted, one deprecation warning per run) - removed in 2.24.

Source
include_vars_ignore_files_string_deprecated?

2.20 deprecated a bare-string ignore_files: (still accepted, one deprecation warning per run) - removed in 2.24.

Source
include_vars_ignore_unknown_extensions
Source
include_vars_ignore_unknown_extensions=(include_vars_ignore_unknown_extensions : Bool | Nil)
Source
include_vars_invalid_arg

The first include_vars: argument Ansible's action-level validation loop rejects ("<key> is not a valid option in include_vars"), and whether a file:-style key appears beside a dir:-style key (the "You are mixing file only and dir only arguments" failure). Both fire at RUN time in Ansible, never at parse - see execute_include_vars.

Source
include_vars_invalid_arg=(include_vars_invalid_arg : String | Nil)

The first include_vars: argument Ansible's action-level validation loop rejects ("<key> is not a valid option in include_vars"), and whether a file:-style key appears beside a dir:-style key (the "You are mixing file only and dir only arguments" failure). Both fire at RUN time in Ansible, never at parse - see execute_include_vars.

Source
include_vars_mixed=(include_vars_mixed : Bool)
Source
include_vars_mixed?
Source
include_vars_name
Source
include_vars_name=(include_vars_name : String | Nil)
Source
include_vars_origin_key

The task-argument key ansible-core pins its Origin on for a top-level fact read inside include_vars's own path: the free-form statement's include_vars: key, file: in the mapping form, dir: for dir mode (live-verified against 2.21.6 - each names that value's own column). The path is templated by the executor rather than the generic task-arg finalization, so the key has to be kept from parse time.

Source
include_vars_origin_key=(include_vars_origin_key : String | Nil)

The task-argument key ansible-core pins its Origin on for a top-level fact read inside include_vars's own path: the free-form statement's include_vars: key, file: in the mapping form, dir: for dir mode (live-verified against 2.21.6 - each names that value's own column). The path is templated by the executor rather than the generic task-arg finalization, so the key has to be kept from parse time.

Source
index_var

loop_control.index_var - exposes the current loop iteration's zero-based index under this variable name (Ansible's own loop_control: { index_var: idx }, commonly paired with a register:ed loop result so some_registered.results[idx] can be looked up against the SAME item currently being processed - e.g. results[index].stat.exists as a when: guard skipping re-work already verified by an earlier per-item stat: loop). Previously entirely unimplemented - parsed nowhere, injected into vars_context nowhere - so {{ index }} (or whatever name was configured) always resolved to "undefined" throughout the loop body, silently breaking any downstream results[index] lookup. Found via robertdebock. mount's own "Create mountpoint" task.

Source
index_var=(index_var : String | Nil)

loop_control.index_var - exposes the current loop iteration's zero-based index under this variable name (Ansible's own loop_control: { index_var: idx }, commonly paired with a register:ed loop result so some_registered.results[idx] can be looked up against the SAME item currently being processed - e.g. results[index].stat.exists as a when: guard skipping re-work already verified by an earlier per-item stat: loop). Previously entirely unimplemented - parsed nowhere, injected into vars_context nowhere - so {{ index }} (or whatever name was configured) always resolved to "undefined" throughout the loop body, silently breaking any downstream results[index] lookup. Found via robertdebock. mount's own "Create mountpoint" task.

Source
inherited_environment

Environment layers inherited from the play and any enclosing blocks, outermost first. Ansible's environment: is an extend=True keyword: the play's env, then each enclosing block's, then the task's own merge into one dict with the innermost value winning per variable - so a play-level environment: {PATH: ...} applies to every task in the play even when the task sets nothing of its own. Snapshotted from Play#environment_layers at parse time (the ambient carrier parse_block_task raises/lowers around its children); a layer is either an already-parsed dict (templates still raw inside) or the raw templated string form, substituted and merged in order at execution.

Source
inherited_environment=(inherited_environment : Array(Hash(String, String) | String))

Environment layers inherited from the play and any enclosing blocks, outermost first. Ansible's environment: is an extend=True keyword: the play's env, then each enclosing block's, then the task's own merge into one dict with the innermost value winning per variable - so a play-level environment: {PATH: ...} applies to every task in the play even when the task sets nothing of its own. Snapshotted from Play#environment_layers at parse time (the ambient carrier parse_block_task raises/lowers around its children); a layer is either an already-parsed dict (templates still raw inside) or the raw templated string form, substituted and merged in order at execution.

Source
inherited_tags

Context tags this task carries from OUTSIDE itself - the play's own tags, every enclosing block's tags, a roles:/import_ * invocation's tags - but never the task's own declared tags:. Written by TagFilter at every selection point (play task list, block children, and each run-time-loaded include), it is what an include_tasks:/include_role: passes down to the tasks it loads at run time: those inherit these plus apply: tags, while the include statement's OWN tags stay with the statement (Ansible gives dynamic includes' children the parent-chain tags only - live-verified vs 2.19.11: a tags:-bearing include_tasks: does not tag its children, but an enclosing block's, a play's, a roles: entry's and an import_role:'s tags all do).

Source
inherited_tags=(inherited_tags : Array(String))

Context tags this task carries from OUTSIDE itself - the play's own tags, every enclosing block's tags, a roles:/import_ * invocation's tags - but never the task's own declared tags:. Written by TagFilter at every selection point (play task list, block children, and each run-time-loaded include), it is what an include_tasks:/include_role: passes down to the tasks it loads at run time: those inherit these plus apply: tags, while the include statement's OWN tags stay with the statement (Ansible gives dynamic includes' children the parent-chain tags only - live-verified vs 2.19.11: a tags:-bearing include_tasks: does not tag its children, but an enclosing block's, a play's, a roles: entry's and an import_role:'s tags all do).

Source
inherited_when_origin

The file/line/col of an import_tasks: line's own when: VALUE token that was statically ANDed onto this task - the position real 2.19 points the conditional-failure chain's "caused by" Origin at for an inlined task (the IMPORTING file, not the inlined task's own file, where no when: exists to locate; Jooho.okd_prerequisites issue #252). nil when the task carries no statically inherited import when:, or when its own when: also contributed to the merged condition.

Source
inherited_when_origin=(inherited_when_origin : Tuple(String, Int32, Int32) | Nil)

The file/line/col of an import_tasks: line's own when: VALUE token that was statically ANDed onto this task - the position real 2.19 points the conditional-failure chain's "caused by" Origin at for an inlined task (the IMPORTING file, not the inlined task's own file, where no when: exists to locate; Jooho.okd_prerequisites issue #252). nil when the task carries no statically inherited import when:, or when its own when: also contributed to the merged condition.

Source
is_static_import=(is_static_import : Bool)

True when this _include_role task actually came from import_role: (statically resolved), not include_role: (dynamic). Both currently share the same runtime inclusion machinery (see parse_include_role's own comment on that pragmatic approximation), but Ansible's import_role: produces NO task result of its own at all - no "TASK [...]" banner, no ok/skipped recap increment - since it's a true parse-time splice; only include_role: (genuinely dynamic) does. Used by the executor to suppress the wrapper's own display/counting for the import_role: case while still running the included role's own tasks (each gets its own normal banner) exactly the same way either directive reaches them. Found via round171's robertdebock. revealmd (import_role: name: robertdebock.service): Ansible's recap was ok=17, crystal's was ok=18 - an extra "Create revealmd service" TASK banner + ok that Ansible never shows at all.

Source
is_static_import?

True when this _include_role task actually came from import_role: (statically resolved), not include_role: (dynamic). Both currently share the same runtime inclusion machinery (see parse_include_role's own comment on that pragmatic approximation), but Ansible's import_role: produces NO task result of its own at all - no "TASK [...]" banner, no ok/skipped recap increment - since it's a true parse-time splice; only include_role: (genuinely dynamic) does. Used by the executor to suppress the wrapper's own display/counting for the import_role: case while still running the included role's own tasks (each gets its own normal banner) exactly the same way either directive reaches them. Found via round171's robertdebock. revealmd (import_role: name: robertdebock.service): Ansible's recap was ok=17, crystal's was ok=18 - an extra "Create revealmd service" TASK banner + ok that Ansible never shows at all.

Source
listen

Ansible's handler listen: accepts a single topic string OR a list of topics (CVi.thanos's own handlers/main.yml listens on three at once, round 811339) - same single-string-or-list shape as notify: above, parsed identically. nil when absent.

Source
listen=(listen : Array(String) | Nil)

Ansible's handler listen: accepts a single topic string OR a list of topics (CVi.thanos's own handlers/main.yml listens on three at once, round 811339) - same single-string-or-list shape as notify: above, parsed identically. nil when absent.

Source
loop
Source
loop=(loop : Array(JSON::Any) | Nil)
Source
loop_extended=(loop_extended : Bool)

loop_control.extended - exposes the ansible_loop dict (index, first/last, allitems, nextitem/previtem, ...) for the iteration.

Source
loop_extended?

loop_control.extended - exposes the ansible_loop dict (index, first/last, allitems, nextitem/previtem, ...) for the iteration.

Source
loop_file

with_file: entries - unlike with_fileglob (a pattern to match filenames), each entry names a specific file whose CONTENT becomes item (Ansible's file lookup plugin). Resolved at execution time for the same reasons as loop_fileglob (needs {{ vars }} substitution and filesystem access, plus role_path for a relative entry - conventionally searched under the role's own files/ dir).

Source
loop_file=(loop_file : Array(String) | Nil)

with_file: entries - unlike with_fileglob (a pattern to match filenames), each entry names a specific file whose CONTENT becomes item (Ansible's file lookup plugin). Resolved at execution time for the same reasons as loop_fileglob (needs {{ vars }} substitution and filesystem access, plus role_path for a relative entry - conventionally searched under the role's own files/ dir).

Source
loop_fileglob

with_fileglob patterns, resolved at execution time (needs {{ vars }} substitution and filesystem access, neither available at parse time).

Source
loop_fileglob=(loop_fileglob : Array(String) | Nil)

with_fileglob patterns, resolved at execution time (needs {{ vars }} substitution and filesystem access, neither available at parse time).

Source
loop_filetree

with_community.general.filetree sources - the directories to walk, kept as their raw ({{ }}-unsubstituted) strings since a source is ordinarily {{ role_path }}/templates/<something> and can only be resolved at execution time once the variable context exists. See FiletreeLookup for the real lookup-plugin semantics the executor's resolve_loop_filetree hands these to.

Source
loop_filetree=(loop_filetree : Array(String) | Nil)

with_community.general.filetree sources - the directories to walk, kept as their raw ({{ }}-unsubstituted) strings since a source is ordinarily {{ role_path }}/templates/<something> and can only be resolved at execution time once the variable context exists. See FiletreeLookup for the real lookup-plugin semantics the executor's resolve_loop_filetree hands these to.

Source
loop_first_found

with_first_found candidate paths, resolved at execution time for the same reasons as loop_fileglob. Unlike a glob this yields at most one item - the first candidate that exists. loop_first_found_skip is the skip: true form, which makes "none of them exist" a skipped task rather than an error.

Source
loop_first_found=(loop_first_found : Array(String) | Nil)

with_first_found candidate paths, resolved at execution time for the same reasons as loop_fileglob. Unlike a glob this yields at most one item - the first candidate that exists. loop_first_found_skip is the skip: true form, which makes "none of them exist" a skipped task rather than an error.

Source
loop_first_found_paths

with_first_found:'s own paths: sub-key (as opposed to the lookup('first_found', {files:, paths:})/query() function-call idiom, which already threads paths: through via evaluate_first_found since it goes through a raw hash, not this dedicated keyword parser). Previously silently discarded - resolution always fell back to the hardcoded files/templates/vars/role-root search roots regardless of what paths: actually specified.

Source
loop_first_found_paths=(loop_first_found_paths : Array(String) | Nil)

with_first_found:'s own paths: sub-key (as opposed to the lookup('first_found', {files:, paths:})/query() function-call idiom, which already threads paths: through via evaluate_first_found since it goes through a raw hash, not this dedicated keyword parser). Previously silently discarded - resolution always fell back to the hardcoded files/templates/vars/role-root search roots regardless of what paths: actually specified.

Source
loop_first_found_skip=(loop_first_found_skip : Bool)
Source
loop_first_found_skip?
Source
loop_first_found_string_form=(loop_first_found_string_form : Bool)

true only for the scalar string form (with_first_found: "{{ var }}"

  • parse_first_found wraps it into a one-element list, so the executor couldn't otherwise tell it apart from a one-element literal list). The distinction decides WHERE the undefined-ness of a reference is surfaced: Ansible templates the keyword's own value strictly (a scalar {{ undefined_var }} source fails the task), but hands a literal list's candidate strings to the first_found lookup plugin, which templates each term leniently - an undefined reference inside a list candidate renders to nothing and just never matches a file.
Source
loop_first_found_string_form?

true only for the scalar string form (with_first_found: "{{ var }}"

  • parse_first_found wraps it into a one-element list, so the executor couldn't otherwise tell it apart from a one-element literal list). The distinction decides WHERE the undefined-ness of a reference is surfaced: Ansible templates the keyword's own value strictly (a scalar {{ undefined_var }} source fails the task), but hands a literal list's candidate strings to the first_found lookup plugin, which templates each term leniently - an undefined reference inside a list candidate renders to nothing and just never matches a file.
Source
loop_flattened

with_community.general.flattened sources, kept as their raw task strings. Each is ordinarily a {{ some_list_var }} reference to a list; like loop_fileglob/loop_first_found they can only be resolved at execution time once the variable context exists, so the parser stores them verbatim and TaskExecutor flattens the resolved lists.

Source
loop_flattened=(loop_flattened : Array(String) | Nil)

with_community.general.flattened sources, kept as their raw task strings. Each is ordinarily a {{ some_list_var }} reference to a list; like loop_fileglob/loop_first_found they can only be resolved at execution time once the variable context exists, so the parser stores them verbatim and TaskExecutor flattens the resolved lists.

Source
loop_items

Loop items already resolved at parse time (loop:, with_items:, with_dict:, with_nested:, with_sequence:, with_indexed_items:).

Source
loop_items=(loop_items : Array(JSON::Any) | Nil)

Loop items already resolved at parse time (loop:, with_items:, with_dict:, with_nested:, with_sequence:, with_indexed_items:).

Source
loop_items_needs_flatten=(loop_items_needs_flatten : Bool)

True only when loop_items came from a literal with_items: array (not loop:, which has no such behavior). Ansible's with_items: implicitly applies flatten(levels=1) across ALL rendered elements - with_items: ["{{ list_a }}", "{{ list_b }}"] where each renders to its own list yields one iteration per INNER element (list_a's items then list_b's items), not one iteration per outer element holding a whole list as item. Found via nicolai86.prepare-release's own with_items: ["{{ default_directories }}", "{{ directories }}"].

Source
loop_items_needs_flatten?

True only when loop_items came from a literal with_items: array (not loop:, which has no such behavior). Ansible's with_items: implicitly applies flatten(levels=1) across ALL rendered elements - with_items: ["{{ list_a }}", "{{ list_b }}"] where each renders to its own list yields one iteration per INNER element (list_a's items then list_b's items), not one iteration per outer element holding a whole list as item. Found via nicolai86.prepare-release's own with_items: ["{{ default_directories }}", "{{ directories }}"].

Source
loop_label

loop_control.label - what the per-item result line shows instead of the raw item, e.g. label: "{{ item.name }}" to keep a big dict out of the output.

Source
loop_label=(loop_label : String | Nil)

loop_control.label - what the per-item result line shows instead of the raw item, e.g. label: "{{ item.name }}" to keep a big dict out of the output.

Source
loop_literal_kind

Which keyword carried a LITERAL loop list (loop: vs with_items:). loop_template_kind only marks loop sources that need templating, but the executor's undefined-item Origin reporting must still land under the keyword that actually holds the failing list element - ansible reports with_items: there, not its generic loop: default (live-verified vs 2.19.11, issue #228).

Source
loop_literal_kind=(loop_literal_kind : String | Nil)

Which keyword carried a LITERAL loop list (loop: vs with_items:). loop_template_kind only marks loop sources that need templating, but the executor's undefined-item Origin reporting must still land under the keyword that actually holds the failing list element - ansible reports with_items: there, not its generic loop: default (live-verified vs 2.19.11, issue #228).

Source
loop_lookup_plugin

Any OTHER legacy with_<lookup>: source (with_url:, with_lines:, with_env:, with_pipe:, ...) - Ansible treats ANY with_-prefixed task key as a loop keyword equivalent to loop: "{{ lookup('<plugin>', <terms>, wantlist=True) }}", with the terms templated first. Kept raw (plugin name + term list) and resolved at execution time by TaskExecutor#resolve_loop_lookup; without this the keyword silently fell through as an unrecognized task key and the task ran exactly ONCE with the loop variable unbound ("'sha_url_item' is undefined" - lean_delivery. solr_standalone's sha512 fetch).

Source
loop_lookup_plugin=(loop_lookup_plugin : String | Nil)

Any OTHER legacy with_<lookup>: source (with_url:, with_lines:, with_env:, with_pipe:, ...) - Ansible treats ANY with_-prefixed task key as a loop keyword equivalent to loop: "{{ lookup('<plugin>', <terms>, wantlist=True) }}", with the terms templated first. Kept raw (plugin name + term list) and resolved at execution time by TaskExecutor#resolve_loop_lookup; without this the keyword silently fell through as an unrecognized task key and the task ran exactly ONCE with the loop variable unbound ("'sha_url_item' is undefined" - lean_delivery. solr_standalone's sha512 fetch).

Source
loop_lookup_terms
Source
loop_lookup_terms=(loop_lookup_terms : Array(JSON::Any) | Nil)
Source
loop_nested_sources

with_nested: given as an array whose entries include one or more {{ ... }}-templated scalars (the classic with_nested: ["{{ users }}", "{{ groups }}"] shape). The cartesian product's FACTOR SIZES are only knowable at execution time (a source var's real length, including zero), so unlike a fully-literal with_nested array this can't be resolved by LoopResolver at parse time - the old parse-time branch wrapped every templated scalar as a ONE-element literal list, pinning each factor to size 1 and iterating once with item = the whole rendered list, no matter how many elements the variable actually held. Sources are kept as their raw strings (a literal sub-array entry serializes to JSON text) and resolved + multiplied by TaskExecutor#resolve_loop_nested, mirroring loop_flattened's own defer-until-runtime design.

Source
loop_nested_sources=(loop_nested_sources : Array(String) | Nil)

with_nested: given as an array whose entries include one or more {{ ... }}-templated scalars (the classic with_nested: ["{{ users }}", "{{ groups }}"] shape). The cartesian product's FACTOR SIZES are only knowable at execution time (a source var's real length, including zero), so unlike a fully-literal with_nested array this can't be resolved by LoopResolver at parse time - the old parse-time branch wrapped every templated scalar as a ONE-element literal list, pinning each factor to size 1 and iterating once with item = the whole rendered list, no matter how many elements the variable actually held. Sources are kept as their raw strings (a literal sub-array entry serializes to JSON text) and resolved + multiplied by TaskExecutor#resolve_loop_nested, mirroring loop_flattened's own defer-until-runtime design.

Source
loop_subelements_key
Source
loop_subelements_key=(loop_subelements_key : String | Nil)
Source
loop_subelements_list

with_subelements: the raw list template (usually a {{ registered_var .results }} reference) and the subelement key. Both kept verbatim and resolved at execution time once the variable context + registered vars exist.

Source
loop_subelements_list=(loop_subelements_list : String | Nil)

with_subelements: the raw list template (usually a {{ registered_var .results }} reference) and the subelement key. Both kept verbatim and resolved at execution time once the variable context + registered vars exist.

Source
loop_template
Source
loop_template=(loop_template : String | Nil)
Source
loop_template_array_wrapped=(loop_template_array_wrapped : Bool)

true only for the single-element-array template form (with_items: ["{{ some_list }}"]) - see #find_loop_template's own comment for why that shape deliberately flattens a resolved-to-scalar value into one loop item instead of raising. The direct scalar form (loop: "{{ var }}", false here) does NOT get that legacy flattening: Ansible hard-fails a loop:/with_items: source that resolves to anything other than a real list ("The loop value must resolve to a 'list', not '<type>'.") - round174 differential matrix scenarios 11a/11c, live-verified against ansible-core 2.19.12. Only the array-wrapped form keeps the old lenient single-item behavior (loop_scalar_flatten_spec.cr).

Source
loop_template_array_wrapped?

true only for the single-element-array template form (with_items: ["{{ some_list }}"]) - see #find_loop_template's own comment for why that shape deliberately flattens a resolved-to-scalar value into one loop item instead of raising. The direct scalar form (loop: "{{ var }}", false here) does NOT get that legacy flattening: Ansible hard-fails a loop:/with_items: source that resolves to anything other than a real list ("The loop value must resolve to a 'list', not '<type>'.") - round174 differential matrix scenarios 11a/11c, live-verified against ansible-core 2.19.12. Only the array-wrapped form keeps the old lenient single-item behavior (loop_scalar_flatten_spec.cr).

Source
loop_template_kind

loop:/with_items:/with_dict:/with_nested:/with_indexed_items: given as a Jinja variable reference ("{{ some_var }}") rather than a literal inline list/dict. Unresolvable at parse time since the YAML value is just a scalar string until the variable context exists, so the raw source keyword and template string are carried for the executor to resolve at execution time (mirrors loop_fileglob).

Source
loop_template_kind=(loop_template_kind : String | Nil)

loop:/with_items:/with_dict:/with_nested:/with_indexed_items: given as a Jinja variable reference ("{{ some_var }}") rather than a literal inline list/dict. Unresolvable at parse time since the YAML value is just a scalar string until the variable context exists, so the raw source keyword and template string are carried for the executor to resolve at execution time (mirrors loop_fileglob).

Source
loop_together_sources

with_together: given as an array whose entries include {{ ... }} -templated scalars (the classic with_together: ["{{ users }}", "{{ groups }}"] shape, manala.accounts's own manala_accounts_users pairing). Same defer-until-runtime design as loop_nested_sources right above: the zip's row count is only knowable once the variable context exists (a source var's real length, including zero - the role defaults both to empty lists), so the raw source strings are kept here and resolved + zipped by TaskExecutor#resolve_loop_together.

Source
loop_together_sources=(loop_together_sources : Array(String) | Nil)

with_together: given as an array whose entries include {{ ... }} -templated scalars (the classic with_together: ["{{ users }}", "{{ groups }}"] shape, manala.accounts's own manala_accounts_users pairing). Same defer-until-runtime design as loop_nested_sources right above: the zip's row count is only knowable once the variable context exists (a source var's real length, including zero - the role defaults both to empty lists), so the raw source strings are kept here and resolved + zipped by TaskExecutor#resolve_loop_together.

Source
loop_var

loop_control.loop_var - the variable name the loop item is exposed under (Ansible default "item"). Roles like dev-sec os_hardening set loop_control: { loop_var: mount } so an include_tasks/loop can refer to mount.path, mount.owner, etc. rather than always item. Kept verbatim and resolved at execution time; nil means the default "item".

Source
loop_var=(loop_var : String | Nil)

loop_control.loop_var - the variable name the loop item is exposed under (Ansible default "item"). Roles like dev-sec os_hardening set loop_control: { loop_var: mount } so an include_tasks/loop can refer to mount.path, mount.owner, etc. rather than always item. Kept verbatim and resolved at execution time; nil means the default "item".

Source
meta?
Source
meta_action

meta: - only set when module_name == "_meta". Holds the meta action ("clear_facts"); see TaskExecutor#execute_meta.

Source
meta_action=(meta_action : String | Nil)

meta: - only set when module_name == "_meta". Holds the meta action ("clear_facts"); see TaskExecutor#execute_meta.

Source
module_args_string_form=(module_args_string_form : Bool)

Whether the task's module argument was written as a bare STRING (raw: echo hi) rather than a mapping (raw: {cmd: echo hi}): the two end up with identical params (the string lands under cmd for the command-style modules), but Ansible routes them differently - a bare string always becomes the free-form module's _raw_params, while a mapping only carries the keys it names. The executor's raw: gate (see TaskExecutor#raw_missing_raw_params_failure) needs the distinction: real's raw action reads ONLY _raw_params, so a mapping-form raw without one crashes where the bare string runs.

Source
module_args_string_form?

Whether the task's module argument was written as a bare STRING (raw: echo hi) rather than a mapping (raw: {cmd: echo hi}): the two end up with identical params (the string lands under cmd for the command-style modules), but Ansible routes them differently - a bare string always becomes the free-form module's _raw_params, while a mapping only carries the keys it names. The executor's raw: gate (see TaskExecutor#raw_missing_raw_params_failure) needs the distinction: real's raw action reads ONLY _raw_params, so a mapping-form raw without one crashes where the bare string runs.

Source
module_defaults

Block- and task-scope module_defaults: - see Play#module_defaults.

Source
module_defaults=(module_defaults : Hash(String, Hash(String, String)))

Block- and task-scope module_defaults: - see Play#module_defaults.

Source
module_name
Source
module_name=(module_name : String)
Source
name
Source
name=(name : String)
Source
no_log=(no_log : Bool)

no_log: true - suppress this task's result detail. A SECURITY control: it is how a playbook keeps a password, token or key out of the log. Previously unparsed and unused, so every such task printed its secret in full.

Source
no_log?

no_log: true - suppress this task's result detail. A SECURITY control: it is how a playbook keeps a password, token or key out of the log. Previously unparsed and unused, so every such task printed its secret in full.

Source
no_log_explicit=(no_log_explicit : Bool)

True when the task wrote its own no_log: (nearest scope wins over a block's no_log: that its children inherit).

Source
no_log_explicit?

True when the task wrote its own no_log: (nearest scope wins over a block's no_log: that its children inherit).

Source
no_log_expr

Raw {{ ... }} text when no_log: is a templated expression rather than a literal boolean (newrelic.newrelic-infra's own no_log: "{{ nrinfragent_hide_config_values }}", defaulting false). The parse-time guess above (parse_become_value) defaults ANY templated value to true - the safe direction for a SECURITY control (never under-hides a real secret), but it means a task like this one has its failure message suppressed on EVERY run regardless of the real value, masking Ansible errors for debugging (found chasing newrelic.newrelic-infra's own merge_yaml failure, whose actual message was invisible in every log because of this). Re-rendered in TaskExecutor#resolve_task_no_log against live vars, same deferred-evaluation shape ignore_errors_expr/check_mode_expr use.

Source
no_log_expr=(no_log_expr : String | Nil)

Raw {{ ... }} text when no_log: is a templated expression rather than a literal boolean (newrelic.newrelic-infra's own no_log: "{{ nrinfragent_hide_config_values }}", defaulting false). The parse-time guess above (parse_become_value) defaults ANY templated value to true - the safe direction for a SECURITY control (never under-hides a real secret), but it means a task like this one has its failure message suppressed on EVERY run regardless of the real value, masking Ansible errors for debugging (found chasing newrelic.newrelic-infra's own merge_yaml failure, whose actual message was invisible in every log because of this). Re-rendered in TaskExecutor#resolve_task_no_log against live vars, same deferred-evaluation shape ignore_errors_expr/check_mode_expr use.

Source
notify
Source
notify=(notify : Array(String) | Nil)
Source
params
Source
params=(params : Hash(String, String))
Source
pending_reserved_warning

ansible emits a task-level reserved-name warning from VariableManager.get_vars - once the strategy actually reaches the task, not while the playbook loads (issue #473: a load-time print fires even for a task an earlier failure keeps from ever running). The parse-time scan parks the text here; the executor prints it just before the task's banner, or never when the play ends first.

Source
pending_reserved_warning=(pending_reserved_warning : String | Nil)

ansible emits a task-level reserved-name warning from VariableManager.get_vars - once the strategy actually reaches the task, not while the playbook loads (issue #473: a load-time print fires even for a task an earlier failure keeps from ever running). The parse-time scan parks the text here; the executor prints it just before the task's banner, or never when the play ends first.

Source
poll_raw
Source
poll_raw=(poll_raw : String | Nil)
Source
poll_seconds
Source
poll_seconds=(poll_seconds : Int32 | Nil)
Source
register
Source
register=(register : String | Nil)
Source
remote_user

remote_user: at task scope - see Play#remote_user.

Source
remote_user=(remote_user : String | Nil)

remote_user: at task scope - see Play#remote_user.

Source
rescue_tasks
Source
rescue_tasks=(rescue_tasks : Array(Task) | Nil)
Source
resolved_templated_name

The module name resolve_templated_action rendered OUT of templated_action, stamped on the shallow copy it returns - the shared original task must keep the as-written template text, but display/register decisions that key on the module (debug's changed-stripping) run later against that original and need the resolved spelling; they read it back off the task's result.

Source
resolved_templated_name=(resolved_templated_name : String | Nil)

The module name resolve_templated_action rendered OUT of templated_action, stamped on the shallow copy it returns - the shared original task must keep the as-written template text, but display/register decisions that key on the module (debug's changed-stripping) run later against that original and need the resolved spelling; they read it back off the task's result.

Source
retries
Source
retries=(retries : Int32)
Source
retries_template

retries:/delay: given as Jinja templates (collivier.xtesting does retries: "{{ ((jenkins_wait | int) / 5) | int }}") cannot become a number at parse time: real ansible templates both per task against the task's own vars, so the raw string is kept for run_until_retries to resolve and the numeric properties above only hold the implicit defaults (3/5) for that case.

Source
retries_template=(retries_template : String | Nil)

retries:/delay: given as Jinja templates (collivier.xtesting does retries: "{{ ((jenkins_wait | int) / 5) | int }}") cannot become a number at parse time: real ansible templates both per task against the task's own vars, so the raw string is kept for run_until_retries to resolve and the numeric properties above only hold the implicit defaults (3/5) for that case.

Source
role_dedup_key

Run-time dedup identity of the meta/main.yml DEPENDENCY invocation whose load produced this task (issue #320): krikri used to collapse a duplicate dependency at LOAD time, but real ansible's decision is per-host and run-time - an identical re-invocation is silently skipped only when an EARLIER identical invocation actually completed a non-skipped task for that host, so a shared dependency whose every task was skipped ({ role: c, when: ansible_distribution == 'MacOSX' } on a Linux host) still prints its full skipping: block on every later reach. role_dedup_key is the shared identity string (RoleLoader's own dedup key), role_occurrence_id a fresh token per load_role invocation, so the executor's per-host tracker can tell "the owner occurrence" (keeps running) from "a later identical occurrence" (gets silently skipped). Nil for play-level roles:/import_role:/include_role: task streams - those keep their own load-level dedup-per-call behaviour; only meta/main.yml dependency loads participate (and allow_duplicates: true loads are never tagged at all, so they keep running every time).

Source
role_dedup_key=(role_dedup_key : String | Nil)

Run-time dedup identity of the meta/main.yml DEPENDENCY invocation whose load produced this task (issue #320): krikri used to collapse a duplicate dependency at LOAD time, but real ansible's decision is per-host and run-time - an identical re-invocation is silently skipped only when an EARLIER identical invocation actually completed a non-skipped task for that host, so a shared dependency whose every task was skipped ({ role: c, when: ansible_distribution == 'MacOSX' } on a Linux host) still prints its full skipping: block on every later reach. role_dedup_key is the shared identity string (RoleLoader's own dedup key), role_occurrence_id a fresh token per load_role invocation, so the executor's per-host tracker can tell "the owner occurrence" (keeps running) from "a later identical occurrence" (gets silently skipped). Nil for play-level roles:/import_role:/include_role: task streams - those keep their own load-level dedup-per-call behaviour; only meta/main.yml dependency loads participate (and allow_duplicates: true loads are never tagged at all, so they keep running every time).

Source
role_default_origins

Where each of the role layers' raw values was defined - the Origin real prints when a task NAME's template chain fails inside one of them (see VarOrigin). Mirrors role_defaults/role_vars' merges, so a lookup here answers for exactly the value vars_context serves.

Source
role_default_origins=(role_default_origins : Hash(String, VarOrigin))

Where each of the role layers' raw values was defined - the Origin real prints when a task NAME's template chain fails inside one of them (see VarOrigin). Mirrors role_defaults/role_vars' merges, so a lookup here answers for exactly the value vars_context serves.

Source
role_defaults

Set on every task loaded from a role (tasks/main.yml and handlers/main.yml alike) by RoleLoader. role_defaults is the lowest precedence tier (role's defaults/main.yml); role_vars sits above play/host vars but below the task's own vars: (role's vars/main.yml, merged with the role invocation's own vars:). role_files_dir/ role_templates_dir let the executor resolve a copy:/template: src: relative to the role's files//templates/ directory, since the plugin subprocess itself has no concept of roles.

Source
role_defaults=(role_defaults : Hash(String, JSON::Any) | Nil)

Set on every task loaded from a role (tasks/main.yml and handlers/main.yml alike) by RoleLoader. role_defaults is the lowest precedence tier (role's defaults/main.yml); role_vars sits above play/host vars but below the task's own vars: (role's vars/main.yml, merged with the role invocation's own vars:). role_files_dir/ role_templates_dir let the executor resolve a copy:/template: src: relative to the role's files//templates/ directory, since the plugin subprocess itself has no concept of roles.

Source
role_files_dir
Source
role_files_dir=(role_files_dir : String | Nil)
Source
role_invocation_id

Identity of ONE dynamic include_role: execution (a fresh random token per run_include_role_once - per host, per loop item). What meta: end_role keys its per-host "role ended" flag on: two invocations of the same role in one play are independent for end_role purposes (verified against ansible-core 2.19.4 - a looped include_role whose first item ends the role still runs the second item in full). Statically loaded role tasks (roles:/import_role:) leave this nil and key on role_path instead - a static role body executes exactly once per play, so the path is already a unique invocation identity there.

Source
role_invocation_id=(role_invocation_id : String | Nil)

Identity of ONE dynamic include_role: execution (a fresh random token per run_include_role_once - per host, per loop item). What meta: end_role keys its per-host "role ended" flag on: two invocations of the same role in one play are independent for end_role purposes (verified against ansible-core 2.19.4 - a looped include_role whose first item ends the role still runs the second item in full). Statically loaded role tasks (roles:/import_role:) leave this nil and key on role_path instead - a static role body executes exactly once per play, so the path is already a unique invocation identity there.

Source
role_name

The role's invocation name, exactly as written in role:/name: (a bare name or a full local path) - exposed to templates as the ansible_role_name magic var (dev-sec nginx_hardening's own hardening.conf.j2: # Generated by Ansible role {{ ansible_role_ name }}). Ansible sets this to the same string the play actually invoked the role with, not a normalized basename - verified against a ansible-playbook run using a full local path for role:, which echoed that exact path back.

Source
role_name=(role_name : String | Nil)

The role's invocation name, exactly as written in role:/name: (a bare name or a full local path) - exposed to templates as the ansible_role_name magic var (dev-sec nginx_hardening's own hardening.conf.j2: # Generated by Ansible role {{ ansible_role_ name }}). Ansible sets this to the same string the play actually invoked the role with, not a normalized basename - verified against a ansible-playbook run using a full local path for role:, which echoed that exact path back.

Source
role_occurrence_id
Source
role_occurrence_id=(role_occurrence_id : Int64 | Nil)
Source
role_parent_names

The chain of ancestor role names (root-first, NOT including this role's own name) that led to this role being invoked via include_role: from within another role's own tasks - exposed as the ansible_parent_role_names magic var. Empty/nil for a role listed directly under a play's own roles: (not nested inside any other role). Several real collections (prometheus.prometheus's own _common shared-logic role, invoked by every exporter role) guard against direct invocation with ansible_parent_role_names is defined and ansible_parent_role_names | length > 0.

Source
role_parent_names=(role_parent_names : Array(String) | Nil)

The chain of ancestor role names (root-first, NOT including this role's own name) that led to this role being invoked via include_role: from within another role's own tasks - exposed as the ansible_parent_role_names magic var. Empty/nil for a role listed directly under a play's own roles: (not nested inside any other role). Several real collections (prometheus.prometheus's own _common shared-logic role, invoked by every exporter role) guard against direct invocation with ansible_parent_role_names is defined and ansible_parent_role_names | length > 0.

Source
role_parent_paths

The role_path (filesystem root) of each ancestor role, same ordering/population rules as role_parent_names above - Ansible searches a role task's ENTIRE parent-role chain (not just the currently-executing role's own templates/files dir) for a relative template:/copy: src:. Found via prometheus.prometheus._ common's own "Create systemd service unit" task: src: "{{ _common_service_name }}.service.j2" lives in the CALLING role's own templates/ dir (node_exporter/templates/node_exporter. service.j2), not _common's - a shared/generic role deliberately relying on this Ansible search-path behavior to let each exporter role supply its own service unit template.

Source
role_parent_paths=(role_parent_paths : Array(String) | Nil)

The role_path (filesystem root) of each ancestor role, same ordering/population rules as role_parent_names above - Ansible searches a role task's ENTIRE parent-role chain (not just the currently-executing role's own templates/files dir) for a relative template:/copy: src:. Found via prometheus.prometheus._ common's own "Create systemd service unit" task: src: "{{ _common_service_name }}.service.j2" lives in the CALLING role's own templates/ dir (node_exporter/templates/node_exporter. service.j2), not _common's - a shared/generic role deliberately relying on this Ansible search-path behavior to let each exporter role supply its own service unit template.

Source
role_path

The role's own root directory on disk - exposed to templates as the role_path magic var (linux-system-roles/logging's own include_role: name: "{{ role_path }}/roles/rsyslog", a common pattern for a role to reference one of its own private subroles by absolute path).

Source
role_path=(role_path : String | Nil)

The role's own root directory on disk - exposed to templates as the role_path magic var (linux-system-roles/logging's own include_role: name: "{{ role_path }}/roles/rsyslog", a common pattern for a role to reference one of its own private subroles by absolute path).

Source
role_templates_dir
Source
role_templates_dir=(role_templates_dir : String | Nil)
Source
role_var_origins
Source
role_var_origins=(role_var_origins : Hash(String, VarOrigin))
Source
role_vars
Source
role_vars=(role_vars : Hash(String, JSON::Any) | Nil)
Source
role_vars_dir

The role's vars/ directory - where include_vars: and with_first_found: resolve a relative filename from, the same way role_files_dir serves copy:'s src:.

Source
role_vars_dir=(role_vars_dir : String | Nil)

The role's vars/ directory - where include_vars: and with_first_found: resolve a relative filename from, the same way role_files_dir serves copy:'s src:.

Source
run_once=(run_once : Bool)

run_once: - only actually execute this task for the first host in the play; later hosts skip it outright (no output/stats), same as Ansible.

Source
run_once?

run_once: - only actually execute this task for the first host in the play; later hosts skip it outright (no output/stats), same as Ansible.

Source
source_col
Source
source_col=(source_col : Int32)
Source
source_file

Where this task's own YAML mapping starts in its source file - Ansible's task-level Origin: position (the first key of the task mapping, e.g. name at column 5 of - name: x). Sourced from YamlSourceMap during parsing; line/col 0 = unknown (scan failed or exotic structure), which suppresses origin-labeled error output rather than mislabeling it.

Source
source_file=(source_file : String | Nil)

Where this task's own YAML mapping starts in its source file - Ansible's task-level Origin: position (the first key of the task mapping, e.g. name at column 5 of - name: x). Sourced from YamlSourceMap during parsing; line/col 0 = unknown (scan failed or exotic structure), which suppresses origin-labeled error output rather than mislabeling it.

Source
source_line
Source
source_line=(source_line : Int32)
Source
tag_exempt=(tag_exempt : Bool)

True for tasks loaded from a HANDLER (and for everything such a load nests further down): Ansible never tag-filters handlers or anything a handler includes - a never-tagged handler runs when notified under a plain invocation, and an inner never task in a handler's include_tasks: file ran under --tags zzz (live-verified vs 2.19.11). Set at the handler include path and propagated by the executor's runtime filter so nested includes stay exempt.

Source
tag_exempt?

True for tasks loaded from a HANDLER (and for everything such a load nests further down): Ansible never tag-filters handlers or anything a handler includes - a never-tagged handler runs when notified under a plain invocation, and an inner never task in a handler's include_tasks: file ran under --tags zzz (live-verified vs 2.19.11). Set at the handler include path and propagated by the executor's runtime filter so nested includes stay exempt.

Source
tags
Source
tags=(tags : Array(String))
Source
templated_action

A legacy action:/local_action: free-form directive whose module name is itself a {{ }} template (action: "{{ ansible_pkg_mgr }} state=present name={{ item }}", jdauphant.intellij) can't resolve at parse time - the raw free-form string is kept here and resolved at execution (TaskExecutor#resolve_templated_action): the substituted first token names the Ansible module, the rest re-parses as its params. Deliberately distinct from unavailable_module: a module name that is only resolvable at run time must FAIL the task when it doesn't resolve (Ansible: "couldn't resolve module/action 'x'"), never be skipped like an unknown module.

Source
templated_action=(templated_action : String | Nil)

A legacy action:/local_action: free-form directive whose module name is itself a {{ }} template (action: "{{ ansible_pkg_mgr }} state=present name={{ item }}", jdauphant.intellij) can't resolve at parse time - the raw free-form string is kept here and resolved at execution (TaskExecutor#resolve_templated_action): the substituted first token names the Ansible module, the rest re-parses as its params. Deliberately distinct from unavailable_module: a module name that is only resolvable at run time must FAIL the task when it doesn't resolve (Ansible: "couldn't resolve module/action 'x'"), never be skipped like an unknown module.

Source
templated_action_site

Where templated_action's module NAME was written: the YAML key it sits under (action/local_action as written, or module for the mapping form, whose only templated token that is) plus that value token's source position. ansible-core renders the name during task post-validation and tags it with the value's own Origin, so a top-level fact read while resolving it deprecates there (live-verified against 2.21.6: the directive value's opening quote - action: "{{ ansible_pkg_mgr }}" reports its column 11, the mapping form's module: value its own). The position comes from the YAML source map, not a text scan, because the directive can sit on the task's own - action: ... line (galexrt.ntp, issue #988).

Source
templated_action_site=(templated_action_site : Tuple(String, Int32, Int32) | Nil)

Where templated_action's module NAME was written: the YAML key it sits under (action/local_action as written, or module for the mapping form, whose only templated token that is) plus that value token's source position. ansible-core renders the name during task post-validation and tags it with the value's own Origin, so a top-level fact read while resolving it deprecates there (live-verified against 2.21.6: the directive value's opening quote - action: "{{ ansible_pkg_mgr }}" reports its column 11, the mapping form's module: value its own). The position comes from the YAML source map, not a text scan, because the directive can sit on the task's own - action: ... line (galexrt.ntp, issue #988).

Source
throttle

throttle: - cap how many hosts run this task at once, below the run's own --forks. 0/absent means no extra cap.

Source
throttle=(throttle : Int32)

throttle: - cap how many hosts run this task at once, below the run's own --forks. 0/absent means no extra cap.

Source
timeout

timeout: - the per-task wall-clock limit in seconds (ansible-core's TASK_TIMEOUT: the controller fails the task once it runs longer than this). 0/absent means no limit. Templated values keep their raw {{ }} text in timeout_expr and resolve per host at execution time, the same deferred shape become_expr/check_mode_expr use.

Source
timeout=(timeout : Int64 | Nil)

timeout: - the per-task wall-clock limit in seconds (ansible-core's TASK_TIMEOUT: the controller fails the task once it runs longer than this). 0/absent means no limit. Templated values keep their raw {{ }} text in timeout_expr and resolve per host at execution time, the same deferred shape become_expr/check_mode_expr use.

Source
timeout_expr
Source
timeout_expr=(timeout_expr : String | Nil)
Source
to_s(io : IO) : Nil

Appends a short String representation of this object which includes its class name and its object address.

class Person
  def initialize(@name : String, @age : Int32)
  end
end

Person.new("John", 32).to_s # => #<Person:0x10a199f20>
Source
unavailable_import_playbook?

True when this task's unavailable module is an import_playbook spelling: the executor fails it like Ansible's stub-module shebang check instead of skipping it (see IMPORT_PLAYBOOK_SPELLINGS above).

Source
unavailable_module

Set for ANY module name that resolves to nothing this engine ships - a role-private library/<name>.py module (module_name above keeps the raw requested name, e.g. "sr_fingerprint", whose source PythonModuleRunner will find at run time), OR a plain unimplemented module (0.9.1050, reversing 0.9.903's parse-time hard-stop - round 811000: the unconditional raise aborted whole plays for tasks Ansible would simply skip, e.g. robertdebock.podman's containers.podman.podman_container behind when: podman_containers is defined, false on the role's own defaults). Either way the task can't dispatch to a native plugin binary: with a library/ source it RUNS through the py_module runner (see executor_run_loop.cr); without one it takes the graceful per-task skip (task marked skipped, "skipping" line, play continued) - exactly what Ansible does when evaluating when: before resolving the action - and the executor records the name into reachable_unavailable_ modules (after its own when: evaluates) for the final exit-code decision. Previously an unimplemented task raised "Plugin not available" at PARSE time and was dropped entirely - before its own when: was ever evaluated - so a task gated behind e.g. when: ansible_facts['pkg_mgr'] == "zypper" (always false on RHEL/Ubuntu) vanished from the recap/task list completely. Found via round171's robertdebock.haproxy (seport, now a real plugin) and robertdebock.jenkins (zypper_repository, SUSE-only, out of this project's scope).

Source
unavailable_module=(unavailable_module : String | Nil)

Set for ANY module name that resolves to nothing this engine ships - a role-private library/<name>.py module (module_name above keeps the raw requested name, e.g. "sr_fingerprint", whose source PythonModuleRunner will find at run time), OR a plain unimplemented module (0.9.1050, reversing 0.9.903's parse-time hard-stop - round 811000: the unconditional raise aborted whole plays for tasks Ansible would simply skip, e.g. robertdebock.podman's containers.podman.podman_container behind when: podman_containers is defined, false on the role's own defaults). Either way the task can't dispatch to a native plugin binary: with a library/ source it RUNS through the py_module runner (see executor_run_loop.cr); without one it takes the graceful per-task skip (task marked skipped, "skipping" line, play continued) - exactly what Ansible does when evaluating when: before resolving the action - and the executor records the name into reachable_unavailable_ modules (after its own when: evaluates) for the final exit-code decision. Previously an unimplemented task raised "Plugin not available" at PARSE time and was dropped entirely - before its own when: was ever evaluated - so a task gated behind e.g. when: ansible_facts['pkg_mgr'] == "zypper" (always false on RHEL/Ubuntu) vanished from the recap/task list completely. Found via round171's robertdebock.haproxy (seport, now a real plugin) and robertdebock.jenkins (zypper_repository, SUSE-only, out of this project's scope).

Source
unresolvable_mapping_module=(unresolvable_mapping_module : Bool)

A MAPPING-form legacy action:/local_action: whose module name is DEFINITIVELY unresolvable on the controller (CollectionIndex# controller_resolves? verdict resolves: false - no collection ships it, nothing redirects to it). Ansible does not refuse such a playbook at load the way it refuses a bare-key module name: the mapping's module resolves lazily, so the task only fails (per host, rc=2, "Cannot resolve '...' to an action or module.", issue #666) when its own when: actually lets it run - behind when: false it is an ordinary skip. Deliberately distinct from unavailable_module (a name the controller CAN resolve but krikri has not ported - those keep the graceful skip plus the exit-4 reachable_unavailable_ modules accounting); the executor's reached-unavailable paths key on this flag to fail instead of skip.

Source
unresolvable_mapping_module?

A MAPPING-form legacy action:/local_action: whose module name is DEFINITIVELY unresolvable on the controller (CollectionIndex# controller_resolves? verdict resolves: false - no collection ships it, nothing redirects to it). Ansible does not refuse such a playbook at load the way it refuses a bare-key module name: the mapping's module resolves lazily, so the task only fails (per host, rc=2, "Cannot resolve '...' to an action or module.", issue #666) when its own when: actually lets it run - behind when: false it is an ordinary skip. Deliberately distinct from unavailable_module (a name the controller CAN resolve but krikri has not ported - those keep the graceful skip plus the exit-4 reachable_unavailable_ modules accounting); the executor's reached-unavailable paths key on this flag to fail instead of skip.

Source
unresolvable_mapping_name

The as-written module name the failure message echoes.

Source
unresolvable_mapping_name=(unresolvable_mapping_name : String | Nil)

The as-written module name the failure message echoes.

Source
unresolvable_mapping_origin

The mapping's own module: VALUE token - playbook path plus 1-based (line, column) - which real 2.19.11 pins the chain's "caused by" Origin at (6:17 in the issue #666 repro), distinct from the task-level Origin at the task's name line. nil without a source map (the stanza is then omitted, never mislabeled).

Source
unresolvable_mapping_origin=(unresolvable_mapping_origin : Tuple(String, Int32, Int32) | Nil)

The mapping's own module: VALUE token - playbook path plus 1-based (line, column) - which real 2.19.11 pins the chain's "caused by" Origin at (6:17 in the issue #666 repro), distinct from the task-level Origin at the task's name line. nil without a source map (the stanza is then omitted, never mislabeled).

Source
until_condition

until: / retries: / delay: - retry a task until a condition passes.

Source
until_condition=(until_condition : String | Nil)

until: / retries: / delay: - retry a task until a condition passes.

Source
validate_argument_spec?
Source
validate_argument_spec_auto_name=(validate_argument_spec_auto_name : Bool)

True only on the role-synthesized validate_argument_spec task. Real never templates that task's banner name: its name is built in Python (Role._create_validation_task), not read from YAML, so under 2.19's template-trust model it is never trusted as a template - a short_description containing {{ role_name }} (trallnag.endlessh, issue #856) or even the always-defined {{ inventory_hostname }} banners RAW, with no << error >> marker rewriting or warning. A user-written validate_argument_spec task's name: comes from YAML and templates normally, so this must only ride the synthesized one.

Source
validate_argument_spec_auto_name?

True only on the role-synthesized validate_argument_spec task. Real never templates that task's banner name: its name is built in Python (Role._create_validation_task), not read from YAML, so under 2.19's template-trust model it is never trusted as a template - a short_description containing {{ role_name }} (trallnag.endlessh, issue #856) or even the always-defined {{ inventory_hostname }} banners RAW, with no << error >> marker rewriting or warning. A user-written validate_argument_spec task's name: comes from YAML and templates normally, so this must only ride the synthesized one.

Source
validate_argument_spec_inline=(validate_argument_spec_inline : Bool)

True for a USER-written validate_argument_spec: task (any spelling), false for the role-synthesized one. The inline form validates against the task's vars context COMBINED with its own provided_arguments: (ansible-core's action plugin always validates combine_vars(args_from_task_vars, provided_arguments) - verified in the 2.19.11 plugin source and live: a play var satisfies an inline required option), and its validate_args_context is {} (the role machinery is what injects the role context into the synthesized task's args), while its [ERROR] block pins Origin at the task's own source location instead of <unknown>.

Source
validate_argument_spec_inline?

True for a USER-written validate_argument_spec: task (any spelling), false for the role-synthesized one. The inline form validates against the task's vars context COMBINED with its own provided_arguments: (ansible-core's action plugin always validates combine_vars(args_from_task_vars, provided_arguments) - verified in the 2.19.11 plugin source and live: a play var satisfies an inline required option), and its validate_args_context is {} (the role machinery is what injects the role context into the synthesized task's args), while its [ERROR] block pins Origin at the task's own source location instead of <unknown>.

Source
validate_argument_spec_non_dict_type

Inline-only: the Python class name Ansible's datatag layer reports for an argument_spec: that is neither a mapping nor a string. Captured at parse time because the executor cannot recover it: a literal dict is pre-parsed into validate_argument_spec_options and both an explicit YAML null and an absent key read as nil there, and the name follows the VALUE's type, not its content - real 2.19.11 fails the task with the value's own class (live-verified: bools ride untagged <class 'bool'>, an explicit null is <class 'NoneType'>, ints/lists the _AnsibleTagged* subclasses, floats the same rule) BEFORE any option validation runs.

Source
validate_argument_spec_non_dict_type=(validate_argument_spec_non_dict_type : String | Nil)

Inline-only: the Python class name Ansible's datatag layer reports for an argument_spec: that is neither a mapping nor a string. Captured at parse time because the executor cannot recover it: a literal dict is pre-parsed into validate_argument_spec_options and both an explicit YAML null and an absent key read as nil there, and the name follows the VALUE's type, not its content - real 2.19.11 fails the task with the value's own class (live-verified: bools ride untagged <class 'bool'>, an explicit null is <class 'NoneType'>, ints/lists the _AnsibleTagged* subclasses, floats the same rule) BEFORE any option validation runs.

Source
validate_argument_spec_options

Synthesized by RoleLoader when a role ships argument specs (meta/argument_specs.yml/.yaml/.json, or the meta main file's argument_specs: key) - only set when module_name == "_validate_argument_spec". Ansible auto-inserts this as the role's first task ("Validating arguments against arg spec 'main' - <short_description>"); holds the entry point's options: map (name -> {type, required, ...}) for TaskExecutor#execute_validate_argument_spec to check the effective vars against.

Source
validate_argument_spec_options=(validate_argument_spec_options : Hash(String, JSON::Any) | Nil)

Synthesized by RoleLoader when a role ships argument specs (meta/argument_specs.yml/.yaml/.json, or the meta main file's argument_specs: key) - only set when module_name == "_validate_argument_spec". Ansible auto-inserts this as the role's first task ("Validating arguments against arg spec 'main' - <short_description>"); holds the entry point's options: map (name -> {type, required, ...}) for TaskExecutor#execute_validate_argument_spec to check the effective vars against.

Source
validate_argument_spec_provided

Inline-only: the task's own provided_arguments: dict (literal form). These override same-named vars in the vars context (combine_vars order) and are templated at execution time.

Source
validate_argument_spec_provided=(validate_argument_spec_provided : Hash(String, JSON::Any) | Nil)

Inline-only: the task's own provided_arguments: dict (literal form). These override same-named vars in the vars context (combine_vars order) and are templated at execution time.

Source
validate_argument_spec_raw_options

Inline-only: an argument_spec: written as a Jinja STRING (the real-world form "{{ (lookup('ansible.builtin.file', role_path ~ '/meta/argument_specs.yml') | from_yaml).argument_specs.main.options }}") is resolved at EXECUTION time with the task's vars context - a literal dict is pre-parsed into validate_argument_spec_options instead and this stays nil.

Source
validate_argument_spec_raw_options=(validate_argument_spec_raw_options : String | Nil)

Inline-only: an argument_spec: written as a Jinja STRING (the real-world form "{{ (lookup('ansible.builtin.file', role_path ~ '/meta/argument_specs.yml') | from_yaml).argument_specs.main.options }}") is resolved at EXECUTION time with the task's vars context - a literal dict is pre-parsed into validate_argument_spec_options instead and this stays nil.

Source
vars
Source
vars=(vars : Hash(String, JSON::Any))
Source
vars_origins

The task's own vars: entries' defining positions (the task's own source file) - same Origin purpose as the role layers above.

Source
vars_origins=(vars_origins : Hash(String, VarOrigin))

The task's own vars: entries' defining positions (the task's own source file) - same Origin purpose as the role layers above.

Source
when_condition
Source
when_condition=(when_condition : String | Nil)
Source
when_condition_list

The when: LIST's own per-item condition strings, kept alongside the " and "-joined when_condition so the STRICT when: evaluation path (TaskExecutor#evaluate_when) can type-check each item SEPARATELY, exactly as ansible-core 2.19 does: a list-form when: is a sequence of independent conditionals, each required to end in a real boolean

  • when: [str_var, bool_var] fails ("Conditional result ... was derived from value of type 'str'") even though the equivalent single-string when: str_var and bool_var PASSES there (Python's and returns the last operand, so the whole expression's result type is bool and only the whole result gets the strict check - both behaviors verified live against 2.19.4). Joining the list into one and string and strict-checking only the JOINED result made crazikpl.logging's when: [(...or ...), use_rsyslog] pass silently where Ansible failed the task. nil when when: wasn't a multi-item list (single-item lists and scalars evaluate identically either way); the joined when_condition remains the source of truth for every non-strict consumer (loop pre-gates, register:/ batcher scans, block/import inheritance display).
Source
when_condition_list=(when_condition_list : Array(String) | Nil)

The when: LIST's own per-item condition strings, kept alongside the " and "-joined when_condition so the STRICT when: evaluation path (TaskExecutor#evaluate_when) can type-check each item SEPARATELY, exactly as ansible-core 2.19 does: a list-form when: is a sequence of independent conditionals, each required to end in a real boolean

  • when: [str_var, bool_var] fails ("Conditional result ... was derived from value of type 'str'") even though the equivalent single-string when: str_var and bool_var PASSES there (Python's and returns the last operand, so the whole expression's result type is bool and only the whole result gets the strict check - both behaviors verified live against 2.19.4). Joining the list into one and string and strict-checking only the JOINED result made crazikpl.logging's when: [(...or ...), use_rsyslog] pass silently where Ansible failed the task. nil when when: wasn't a multi-item list (single-item lists and scalars evaluate identically either way); the joined when_condition remains the source of truth for every non-strict consumer (loop pre-gates, register:/ batcher scans, block/import inheritance display).
Source
written_action

--list-tasks/--list-tags display (TaskLister): the include-family directive key AS WRITTEN (include_role:, ansible.builtin.include_tasks:, ...). Real's listtasks CLI prints the bare action for a task with no name: of its own - for the include statements that is this key, not the synthesized "<action> : <role>" display name Task#name carries for runtime banners. nil for plain module tasks, whose AS-WRITTEN action is already what Task#name holds when unnamed.

Source
written_action=(written_action : String | Nil)

--list-tasks/--list-tags display (TaskLister): the include-family directive key AS WRITTEN (include_role:, ansible.builtin.include_tasks:, ...). Real's listtasks CLI prints the bare action for a task with no name: of its own - for the include statements that is this key, not the synthesized "<action> : <role>" display name Task#name carries for runtime banners. nil for plain module tasks, whose AS-WRITTEN action is already what Task#name holds when unnamed.

Source