// learn Β· linux Β· rhce Β· 9 min

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.
// ansible Β· loops & conditionals

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.

// before you start
you should know
  • Β·You've written a basic playbook with tasks
  • Β·Comfortable with YAML lists and dictionaries
  • Β·Know what a fact / variable is in Ansible
by the end you'll

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

ansible β€” step 1 / 5 Β· loops
- name: Create usertask
loop: [alice, bob, carol]
β”‚ runs once per item β”‚
item=alice● changed
item=bob● changed
item=carol● changed

loop β€” 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 }}"
// key insight

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.

// exam-ready Β· loops, conditionals & outcomes
$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 }}"
// check yourself
4 quick questions
Q1

Do you wrap a `when:` condition in `{{ }}`?

Q2

How do you make a one-off `command` task never report "changed"?

Q3

You loop over 3 users and `register` the result. Where are the per-item results?

Q4

What does `until` + `retries` + `delay` do?

These aren't graded β€” they're just for active recall, which is what actually makes the lesson stick.

🧬
// next: dynamic config

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.

open β†’
// more in systems

keep going β€” these pair well with what you just learned.

see all systems β†’
back to RHCSA / RHCE trackall lessons