# Anatomy of a Playbook — Ansible: Automate Servers with Playbooks

Source: https://www.geekswithgeeks.com/en/ansible/pb-anatomy

> Read a playbook: hosts, vars, tasks, modules and handlers.

## Plays and tasks

A playbook is a YAML list of **plays**. Each play names the **hosts** it targets, optional **vars**, a list of **tasks** run in order, and optional **handlers**. Every task has a human-readable `name` and calls a **module**, preferably by its fully qualified name such as `ansible.builtin.file`. YAML is sensitive to indentation (spaces, never tabs), so use an editor with YAML support.

## Plays, tasks, modules

A playbook contains plays; each play maps hosts to ordered tasks; each task calls one module.

![Three levels: playbook, play, task.](assets/figures/ansible/section-2-map.svg) — Figure 2.1 — Playbook, play and task.

## The example playbook

This is the exact `site.yml` I ran for the rest of this section. It creates an output directory once, renders a config for each web host, and notifies a handler.

```yaml
---
- name: Configure web servers
  hosts: web
  gather_facts: false
  vars:
    users: [asha, ravi]
    out_dir: "{{ playbook_dir }}/out"
  tasks:
    - name: Ensure output directory exists
      ansible.builtin.file:
        path: "{{ out_dir }}"
        state: directory
        mode: "0755"
      run_once: true
      delegate_to: localhost

    - name: Render config
      ansible.builtin.template:
        src: app.conf.j2
        dest: "{{ out_dir }}/{{ inventory_hostname }}.conf"
      delegate_to: localhost
      notify: Reload app

  handlers:
    - name: Reload app
      ansible.builtin.debug:
        msg: "reloading app on {{ inventory_hostname }}"
```

## Name every task

Good task names turn the run output into readable documentation. "Render config" tells the reader far more than "template".

**Quiz:** What does each task call?

- [ ] A whole play
- [x] One module
- [ ] An inventory
- [ ] A vault

*Answer:* One module. A task is a single module invocation with arguments.
