Ansible loops & conditionals.
Two tiny keywords carry most of Ansible's logic: `loop` runs a task once per element (exposed as {{ item }}), and `when` decides β per host and per loop item β whether it runs at all. Then teach command/shell what `changed` and `failed` really mean.
Ansible loops and conditionals animated tutorial. Looping a task over a list with loop and the item variable, replacing legacy with_items, when conditionals as bare Jinja expressions, combining loop with when to skip iterations per item, registering looped tasks and reading result.results, changed_when and failed_when for non-idempotent command and shell tasks, loop_control with label and index_var, and until/retries/delay polling. RHCE EX294 ready.Two tiny keywords carry most of Ansible's logic: loop runs a task once per element, and when decides whether it runs at all. Watch a task iterate over users, get gated per host, and learn what "changed" really means.
- Β·You've written a basic playbook with tasks
- Β·Comfortable with YAML lists and dictionaries
- Β·Know what a fact / variable is in Ansible
Loop a task over a list with {{ item }}, gate tasks with when:, combine the two to skip iterations, redefine changed/failed for command tasks, and poll with until/retries.
pace: 9 minutes
- name: Create usertaskitem=aliceβ changeditem=bobβ changeditem=carolβ changedloop β do one task many times
Add `loop:` with a list and Ansible runs the task once per element, exposing the current element as `{{ item }}`. Modern `loop:` replaces the older `with_items` and friends. You can loop over a plain list, a variable that holds a list, or a list of dictionaries β then reach into each dict with `{{ item.name }}`. One task definition, many runs.
$- name: Create user\n ansible.builtin.user:\n name: "{{ item }}"\n loop: [alice, bob, carol]$loop: "{{ users }}"$- ansible.builtin.user:\n name: "{{ item.name }}"\n groups: "{{ item.groups }}"\n loop: "{{ user_list }}"Two small keywords carry most of Ansible's logic: `loop` runs a task once per element (the current one is {{ item }}), and `when` decides per host (and per loop item) whether it runs at all. And because command/shell aren't idempotent, `changed_when`/`failed_when` let you teach Ansible what "changed" and "failed" actually mean for them.
$loop: [a, b, c]$loop: "{{ list }}"${{ item }} / {{ item.key }}$with_items: [β¦]$when: COND$when: a and b$when: x is defined$when:\n - c1\n - c2$register: r β r.results$changed_when: false$failed_when: COND$loop_control: label / index_var / pause$until: COND retries: N delay: S$loop: "{{ d | dict2items }}"Do you wrap a `when:` condition in `{{ }}`?
How do you make a one-off `command` task never report "changed"?
You loop over 3 users and `register` the result. Where are the per-item results?
What does `until` + `retries` + `delay` do?
These aren't graded β they're just for active recall, which is what actually makes the lesson stick.
Ansible templates (Jinja2)
Loops and conditionals also live inside config files. Render per-host config with the `template` module and Jinja2 β variables, loops, and `when`-style logic, straight into /etc.
keep going β these pair well with what you just learned.
Ansible control node & inventory
Ansible is agentless β one control node pushes work to a fleet over SSH. Install ansible-core, write an inventory with groups, ping the fleet, and fire ad-hoc commands. RHCE-ready.
Ansible playbooks & YAML
Plays, tasks, and idempotency. Watch a playbook run task-by-task β ok, changed, skipped β then run it again and watch everything go green with 0 changed. RHCE-ready.
Ansible core modules
file, user, copy, dnf, service β the modules that do the real work. Declare the desired state and let Ansible converge to it, idempotently. RHCE-ready.