When working with nested blocks in Ansible, proper YAML indentation and syntax for conditional statements is crucial. The error occurs because the when
clause isn't properly aligned with the nested block structure.
Here's the corrected version of your playbook with proper nesting:
- block:
- postgresql_db: name={{ dbname }} state=absent
- postgresql_db: name={{ dbname }}
...
- block:
- get_url: url={{ remote_database_dump }} dest={{ local_database_dump }}
- command: pg_restore -d {{ dbname }} {{ local_database_dump }}
when: remote_database_dump != ""
become: true
become_user: postgres
become_method: su
when: db_recreate == "true"
The key points to remember when nesting conditional blocks:
1. The inner 'when' clause must be indented exactly under the nested 'block'
2. Colon (:) is required after 'when'
3. The conditional expression needs proper spacing
Here's a more complex example showing multiple levels of nested conditionals:
- block:
- debug: msg="Outer block execution"
- block:
- debug: msg="First nested block"
- block:
- debug: msg="Second nested level"
when: second_level_condition
when: first_level_condition
when: outer_condition
Instead of deep nesting, consider these cleaner alternatives:
# Option 1: Separate tasks with individual when clauses
- postgresql_db: name={{ dbname }} state=absent
when: db_recreate == "true"
become: true
become_user: postgres
become_method: su
# Option 2: Use include_tasks with conditionals
- include_tasks: setup_db.yml
when: db_recreate == "true"
When troubleshooting nested conditionals:
1. Use ansible-playbook --syntax-check
2. Start with minimal nesting and build up
3. Test conditions separately before combining
4. Use debug messages to verify execution paths
When working with Ansible playbooks, you might encounter situations where you need to nest conditional blocks. The typical error occurs when trying to apply a when
clause to an inner block:
- block:
- postgresql_db: name={{ dbname }} state=absent
- postgresql_db: name={{ dbname }}
...
- block:
- get_url: url={{ remote_database_dump }} dest={{ local_database_dump }}
- command: pg_restore -d {{ dbname }} {{ local_database_dump }}
when remote_database_dump != ""
become: true
become_user: postgres
become_method: su
when: db_recreate == "true"
The error occurs because YAML requires proper indentation for nested structures. The when
clause must be aligned with the block
keyword it applies to:
- block:
- postgresql_db: name={{ dbname }} state=absent
- postgresql_db: name={{ dbname }}
- block:
- get_url: url={{ remote_database_dump }} dest={{ local_database_dump }}
- command: pg_restore -d {{ dbname }} {{ local_database_dump }}
when: remote_database_dump != ""
become: true
become_user: postgres
become_method: su
when: db_recreate == "true"
If you find nested blocks difficult to read, consider these alternatives:
Option 1: Apply conditions to individual tasks
- name: Remove existing database
postgresql_db:
name: "{{ dbname }}"
state: absent
when: db_recreate == "true"
become: true
become_user: postgres
become_method: su
- name: Create new database
postgresql_db:
name: "{{ dbname }}"
when: db_recreate == "true"
become: true
become_user: postgres
become_method: su
- name: Download remote dump
get_url:
url: "{{ remote_database_dump }}"
dest: "{{ local_database_dump }}"
when: db_recreate == "true" and remote_database_dump != ""
become: true
become_user: postgres
become_method: su
Option 2: Use include_tasks for complex conditional logic
- name: Handle database recreation
block:
- include_tasks: remove_and_create_db.yml
- include_tasks: restore_from_dump.yml
when: remote_database_dump != ""
when: db_recreate == "true"
become: true
become_user: postgres
become_method: su
- Always maintain consistent indentation (2 or 4 spaces)
- Consider breaking complex nested blocks into separate files
- Use comments to explain why conditions are needed
- Test playbooks with
--syntax-check
flag - Keep the maximum nesting level to 2-3 for readability