How to Conditionally Execute Ansible Tasks Based on Specific Tags Only


3 views

While Ansible tags are commonly used to exclude tasks from execution (by running playbooks with --skip-tags), many users need the inverse functionality - executing tasks only when specific tags are explicitly requested.

By default, when you run an Ansible playbook without any tag specifications:

  1. All tasks execute unless skipped via when conditions
  2. Tagged tasks still run unless explicitly skipped

What we want is the opposite behavior - a task should run only when its tag is specifically requested.

Ansible provides access to currently active tags through the ansible_run_tags magic variable. Here's how to use it:


- name: Only execute when 'foo' tag is specified
  debug:
    msg: "This task only runs with --tags foo"
  when: "'foo' in ansible_run_tags"

For more complex scenarios, consider these approaches:

1. Multiple tag requirement:


when: 
  - "'foo' in ansible_run_tags"
  - "'bar' in ansible_run_tags"

2. Tag with fallback condition:


when: 
  - "'deploy' in ansible_run_tags"
  - some_other_condition|default(false)

Here's how you might implement a database migration that should only run when explicitly requested:


- name: Run database migrations
  command: /usr/bin/db-migrate
  when: "'db_migrate' in ansible_run_tags"
  tags:
    - db_migrate
    - never

The never tag serves as additional protection against accidental execution.

  • Test thoroughly - tag conditions can affect idempotency
  • Document all tag-only tasks clearly
  • Consider combining with changed_when for better output

Another pattern is to place sensitive tasks in separate files and conditionally include them:


- name: Include dangerous operations
  include_tasks: dangerous.yml
  when: "'dangerous' in ansible_run_tags"

In Ansible playbooks, tags serve as powerful filters that allow you to selectively run portions of your automation. While the default behavior executes all tasks, we often need the opposite functionality - executing tasks only when specific tags are explicitly requested.

The standard tag implementation works as an exclusion filter, where untagged tasks always run unless skipped via --skip-tags. What if we need a task that:

  • Runs only when "foo" tag is specified
  • Remains skipped in all other cases (including no tags specified)

Ansible provides access to currently active tags through the ansible_run_tags variable. Here's how to use it:

- name: Task that runs only with 'foo' tag
  debug:
    msg: "This only appears when 'foo' tag is specified"
  when: "'foo' in ansible_run_tags'
  tags: foo

Consider these real-world scenarios:

1. Conditional Package Installation

- name: Install debug tools (only with 'debug' tag)
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - htop
    - lsof
    - strace
  when: "'debug' in ansible_run_tags"
  tags: debug

2. Environment-Specific Configuration

- name: Apply production firewall rules
  iptables:
    # rules here
  when: "'prod' in ansible_run_tags"
  tags: prod

Combining Multiple Tags

- name: Maintenance mode operations
  command: /usr/bin/maintenance_script
  when: 
    - "'maintenance' in ansible_run_tags"
    - "'critical' in ansible_run_tags"
  tags: maintenance,critical

Using Tag Inheritance in Roles

When working with roles, you can apply this pattern at the role level:

- name: Include database setup
  include_role:
    name: database
  when: "'db_setup' in ansible_run_tags"
  tags: db_setup
  • The ansible_run_tags variable contains tags actually specified in the command line
  • Always include the tag in the task's tags: field for consistency
  • This approach works in Ansible 2.5 and later
  • For complex conditions, consider using ansible_run_tags with other facts