Ansible / Intermediate: reuse, secrets, and scoped validation / Lesson 12
Interpret check mode, diff mode, and tags honestly
Treat preview modes and task selection as scoped evidence, not a guarantee that a later run is harmless, complete, or correct.
On this page
Lesson goals
- Explain per-module check and diff support.
- Recognize tasks that override check behavior and external evaluation.
- Review tag selection together with prerequisites and reuse inheritance.
Check mode depends on module support and task policy
Check mode asks supported modules to predict changes rather than apply their ordinary target effects. Unsupported behavior can be skipped or limited, and a prediction is not application acceptance. Tasks can explicitly override check behavior, so a global check request is not an unconditional safety boundary. Inventory plugins, lookups, fact gathering, and controller-side evaluation may also have dependencies or external interactions. Read the exact task graph and module support before any later authorized preview. This course runs no check-mode command against hosts; YAML parsing and synthetic models are the performed checks.
Predicted results can leave later tasks without real data
A later task can depend on a registered command output that check mode did not produce. That path may fail or skip differently from normal execution. Guard genuinely optional result fields and design an explicit check-mode contract, but do not fabricate data to make the preview look successful. A read-only information task can have justified behavior under documented support, while a host-changing task should not be forced through check merely to satisfy a dependency. Test preview and normal execution as different evidence layers in a disposable authorized environment when the engine is available.
Diff explains content differences but can expose secrets
Diff support is module-specific and can show before/after content under the selected mode. It does not prove that the application accepts the result or that the operation is reversible. Secret-bearing content may need diff suppression even when ordinary task output is protected. Large diffs can also overwhelm review and hide a small critical line, so keep generated artifacts deterministic and reviewable. Distinguish an intended configuration delta from unrelated formatting churn. No live diff is collected in this course, and no private configuration is read to produce a teaching result.
Tags select tasks, not complete dependency transactions
Tags allow targeted execution, but choosing one tagged task can omit a prerequisite that normally ran earlier. Static imports, roles, dynamic includes, blocks, apply, and special tags have documented inheritance rules. Do not assume tagging an include automatically tags every dynamically included child in the desired way. Define supported partial-run entry points and keep required validation available for them. Handlers also have their own execution semantics, so a tag selection alone is not a complete activation plan. Review selected and omitted tasks together before claiming the partial run preserves the full workflow’s invariants.
- name: Illustrate tagged review tasks
hosts: lab_nodes
gather_facts: false
tasks:
- name: Describe validation
ansible.builtin.debug:
msg: Synthetic validation stage
tags: [validate]
- name: Describe configuration intent
ansible.builtin.debug:
msg: Synthetic configuration stage
tags: [configure]
The play is non-runnable and only its YAML structure was checked. The two labels do not automatically encode a dependency between the tasks.
Test the intended partial-run contract explicitly
An offline task-list model can show that selecting configure alone omits validate under a deliberately simple tag rule. It is not Ansible’s tag engine and excludes inheritance and special-tag behavior. Use the result to ask which invariant the project must enforce, not to infer the actual selected task set from a toy model. In later authorized testing, compare supported tag entry points, check-mode behavior, diff policy, expected changes, and application acceptance. A preview that reports no errors can still leave a required path untested or skipped.
tasks = [{'name': 'validate', 'tags': {'validate'}}, {'name': 'configure', 'tags': {'configure'}}]
requested = {'configure'}
selected = [task['name'] for task in tasks if task['tags'] & requested]
print(','.join(selected))
print('validation_selected=' + str('validate' in selected))
configure
validation_selected=False
The output illustrates this declared set-intersection rule only. It is not a list-tasks result from Ansible and does not evaluate a real playbook.
Common errors and fixes
Check mode is called a universal sandbox
- Why it happens
- Overrides, plugin evaluation, and module limits were omitted.
- How to fix it
- Review every task and external dependency before preview.
- Prevent it next time
- Keep check-mode claims scoped to documented support.
A tag skips required validation
- Why it happens
- Task selection was assumed to preserve workflow dependencies.
- How to fix it
- Define and test supported partial-run entry points.
- Prevent it next time
- Review omitted tasks as well as selected tasks.
Diff output is assumed safe because no_log exists elsewhere
- Why it happens
- Separate output channels and task scopes were conflated.
- How to fix it
- Apply a reviewed secret/diff policy to the relevant task.
- Prevent it next time
- Use synthetic data for output-policy tests.
Check your understanding
1. Why can a check-mode run fail on a registered field that exists during a normal run?
Show worked solution
The producing task may be skipped or provide only a prediction without that field. Inspect module support and execution state, then design an honest preview contract. Do not force a state-changing task to run merely to create data for the preview.
2. What must a configure-only tag contract say about validation?
Show worked solution
It must state whether validation is included, required beforehand with verifiable evidence, or enforced by the selected entry point. Tags do not automatically infer that dependency, so tests must cover the actual supported reuse and inheritance structure.
Key takeaways
- Treat previews and partial runs as distinct evidence layers.
- Preserve prerequisites, output privacy, and actual module support.