DevOps Classroom notes 16/Jun/2026

Ansible – Variables & Notify/Handlers


1. Ansible Variables

Variables store values that can be reused across tasks, playbooks, and roles.


1.1 Defining Variables

In a Playbook (vars block)

- name: Demo playbook
  hosts: webservers
  vars:
    http_port: 80
    app_name: myapp
  tasks:
    - name: Print app name
      debug:
        msg: "App is {{ app_name }} on port {{ http_port }}"
- name: demo
  become: yes
  hosts: ubuntu
  tasks:
    - name: Print app name
      ansible.builtin.debug:
        msg: "App is {{ app_name }} on port {{ http_port }}"

ansible-playbook -i ubuntu --user ansible -e "app_name=demo-vars http_port=8080" demo.yaml

In Separate Variable Files

# vars/main.yml
db_host: localhost
db_port: 5422
db_name: production
# Reference in playbook
- name: Setup DB
  hosts: dbservers
  vars_files:
    - vars/main.yml
  tasks:
    - debug:
        msg: "DB at {{ db_host }}:{{ db_port }}"
ansible-playbook playbook.yml -e "@vars_file.yml"

1.2 Variable Precedence (Low → High)

Priority Source
1 (lowest) Role defaults (defaults/main.yml)
2 Inventory group vars
2 Inventory host vars
4 Playbook group_vars/
5 Playbook host_vars/
6 Playbook vars: block
7 vars_files:
8 vars_prompt:
9 Task vars:
10 set_fact / registered vars
11 Extra vars -e (highest)

Rule of thumb: -e (extra vars) always wins.


1.3 group_vars and host_vars Directory Structure

inventory/
├── hosts                  # inventory file
├── group_vars/
│   ├── all.yml            # applies to ALL hosts
│   ├── webservers.yml     # applies to webservers group
│   └── dbservers.yml
└── host_vars/
    ├── web1.yml           # applies to host web1 only
    └── web2.yml
# group_vars/webservers.yml
nginx_version: "1.24"
max_workers: 4

1.4 Registering Variables

Capture the output of a task into a variable.

- name: Check disk usage
  command: df -h /
  register: disk_output

- name: Show disk info
  debug:
    msg: "{{ disk_output.stdout }}"

Common register attributes:

Attribute Description
.stdout Standard output as string
.stdout_lines Output as list of lines
.stderr Standard error output
.rc Return code (0 = success)
.failed Boolean – did the task fail?
.changed Boolean – did something change?

1.5 set_fact – Dynamic Variables

- name: Set a computed variable
  set_fact:
    full_url: "http://{{ ansible_host }}:{{ http_port }}/{{ app_name }}"

- name: Use the computed variable
  debug:
    msg: "URL is {{ full_url }}"

1.6 vars_prompt – Interactive Variables

- name: Deploy app
  hosts: all
  vars_prompt:
    - name: deploy_env
      prompt: "Enter environment (dev/staging/prod)"
      private: no
  tasks:
    - debug:
        msg: "Deploying to {{ deploy_env }}"

1.7 Extra Vars (Command Line)

# Pass single variable
ansible-playbook deploy.yml -e "version=2.1"

# Pass multiple variables
ansible-playbook deploy.yml -e "version=2.1 env=prod"

# Pass a vars file
ansible-playbook deploy.yml -e "@vars/prod.yml"

1.8 Variable Filters (Jinja2)

vars:
  names: ["alice", "bob", "charlie"]
  score: 85.6789

tasks:
  - debug:
      msg: "{{ names | join(', ') }}"         # alice, bob, charlie

  - debug:
      msg: "{{ score | round(2) }}"           # 85.68

  - debug:
      msg: "{{ undefined_var | default('N/A') }}"  # N/A if not defined

  - debug:
      msg: "{{ app_name | upper }}"           # MYAPP

2. Notify & Handlers

Handlers are tasks that run only when notified — used to trigger actions like restarting services after config changes.


2.1 Basic Notify + Handler Pattern

- name: Configure Nginx
  hosts: webservers
  tasks:
    - name: Copy nginx config
      copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf
      notify: Restart Nginx           # ← triggers handler IF task changes

  handlers:
    - name: Restart Nginx             # ← must match notify string exactly
      service:
        name: nginx
        state: restarted

Key behaviour:

  • Handler runs only if the task reports changed
  • Handler runs once at the end of the play — even if notified multiple times
  • If a task doesn’t change anything, the handler is NOT called

2.2 Notifying Multiple Handlers

tasks:
  - name: Update app config
    template:
      src: app.conf.j2
      dest: /etc/app/app.conf
    notify:
      - Restart App
      - Reload Firewall

handlers:
  - name: Restart App
    service:
      name: myapp
      state: restarted

  - name: Reload Firewall
    service:
      name: firewalld
      state: reloaded

2.2 Handler Triggered by Multiple Tasks

tasks:
  - name: Update nginx.conf
    copy:
      src: nginx.conf
      dest: /etc/nginx/nginx.conf
    notify: Restart Nginx

  - name: Update SSL cert
    copy:
      src: cert.pem
      dest: /etc/nginx/ssl/cert.pem
    notify: Restart Nginx             # same handler notified twice

handlers:
  - name: Restart Nginx               # runs ONCE at end of play
    service:
      name: nginx
      state: restarted

2.4 Forcing Handler Execution with meta

tasks:
  - name: Update config
    copy:
      src: app.conf
      dest: /etc/app/app.conf
    notify: Restart App

  - name: Flush handlers NOW (don't wait for end of play)
    meta: flush_handlers

  - name: Run smoke test (after restart)
    uri:
      url: http://localhost:8080/health
      status_code: 200

meta: flush_handlers forces all pending handlers to run immediately at that point.


2.5 Handlers in Roles

roles/
└── webserver/
    ├── tasks/
    │   └── main.yml
    └── handlers/
        └── main.yml      ← handlers live here in roles
# roles/webserver/handlers/main.yml
- name: Restart Nginx
  service:
    name: nginx
    state: restarted

- name: Reload Nginx
  service:
    name: nginx
    state: reloaded

2.6 Listening to Multiple Notifications

handlers:
  - name: Restart web stack
    service:
      name: nginx
      state: restarted
    listen: "web stack changed"       # alias topic name

tasks:
  - name: Update nginx config
    copy:
      src: nginx.conf
      dest: /etc/nginx/nginx.conf
    notify: "web stack changed"       # notifies by topic

  - name: Update PHP config
    copy:
      src: php.ini
      dest: /etc/php/php.ini
    notify: "web stack changed"       # same topic

2.7 changed_when — Controlling Handler Triggering

- name: Run custom script
  command: /opt/scripts/check_config.sh
  register: result
  changed_when: result.rc == 1       # Only "changed" if exit code is 1
  notify: Apply new config
- name: This task never triggers handlers
  command: /opt/scripts/read_only.sh
  changed_when: false
---
- name: demo
  become: yes
  hosts: localhost
  tasks:
    - ansible.builtin.debug:
        msg: "Installing tree package"

    - name: Install apache httpd (state=present is optional)
      ansible.builtin.apt:
        name: apache2
        update_cache: yes
        state: present
      notify: restart service apcahe

    - name: Install unzip
      ansible.builtin.apt:
        name: unzip
        state: present

    - name: Download gaming html
      ansible.builtin.get_url:
        url: https://templatemo.com/tm-zip-files-2020/templatemo_589_lugx_gaming.zip
        dest: /tmp/templatemo_589_lugx_gaming.zip
        mode: '0755'
      notify: restart service apcahe

    - name: unzip templated in apache2 html
      ansible.builtin.unarchive:
        src: /tmp/templatemo_589_lugx_gaming.zip
        dest: /tmp/
        remote_src: yes

    - name: copy files
      ansible.builtin.copy:
        src: /tmp/templatemo_589_lugx_gaming/
        dest: /var/www/html/
        remote_src: yes
        owner: www-data
        group: www-data
        mode: '0755'
      notify: restart service apcahe

    - ansible.builtin.debug:
        msg: "completed tasks"

  handlers:
    - name: restart service apcahe
      ansible.builtin.systemd_service:
        name: apache2
        enabled: yes
        state: restarted

Task:

  1. update existing playbook with variable
  2. create new playbook add print message disk space all nodes
  3. update playbook use handlers which will required when any change happend.

Leave a comment

Turn on JavaScript to leave a comment.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Please turn AdBlock off
Social Media Icons Powered by Acurax Web Design Company
Exit mobile version
%%footer%%