Ansible Data Structures - The Silent Architect Way
You install Ansible.
You automate the first system.
The gain is visible.
It feels liberating.
Projects. Inventories. Variables. Secrets.
New items pop up.
They're scattered around.
Then they're duplicated in different places.
Confusion.
Errors.
Bug hunts.
Re-architect your growing data - like a Silent Architect.
Variables Haunt You - Everywhere
You start it simple.
Variables thrive in tasks. Roles. Playbooks.
Defaults, vars files. Even in templates.
name: DeadSwitch slogan: Fear the silence, Fear the Switch.
You just use it.
- name: Using a variable ansible.builtin.debug: msg: "The variable is: {{ slogan }} ."
Then you realize you need structure.
You build lists.
occupations:
- Ghost Operator
- Silent Architect
- Digital Resistance Leader
The occupations
variable is a list.
Comfortable.
You don't pick one element. You iterate the structure.
- name: Iterating a list ansible.builtin.debug: msg: The element is: {{ item }}. loop: " {{ occupations }} "
The silent echo comes:
ok: [localhost] => ( item=Ghost Operator) => The element is: Ghost Operator ok: [localhost] => ( item=Silent Architect) => The element is: Silent Architect ok: [localhost] => ( item=Digital Resistance Leader) => The element is: Digital Resistance Leader
With dictionaries you identify the values.
They have keys.
user: deadswitch: name: DeadSwitch slogan: Fear the silence, Fear the Switch. occupation: Silent Architect
You can pick an element.
- name: Picking a dictionary element ansible.builtin.debug: msg: "The user's occupation is: {{ user.deadswitch.occupation }} ."
Clean and dry.
Then Dark Ghosts possess the structure.
The Architect must tame them.
When The Structure Is Haunted - Embedded Data Structures
The lists were clean.
The dictionaries were sharp.
Then they merge.
They nest.
They twist inside each other.
servers: web: hosts: - web1.ghostnet.local - web2.ghostnet.local vars: role: frontend ssl: true db: hosts: - db1.ghostnet.local vars: role: backend replication: enabled
Now the structure is alive.
Keys hold lists. Lists hide keys.
Ghost Operators must know the paths.
- name: Access a nested dictionary ansible.builtin.debug: msg: "DB role is: {{ servers.db.vars.role }} "
- name: Iterate hosts of the web group ansible.builtin.debug: msg: "Web host: {{ item }} " loop: " {{ servers.web.hosts }} "
Haunted structures demand clarity.
Without discipline, you chase ghosts.
Walk The Path Of The Ghosts - Iterate The Structure
You tamed the Dark Ghosts.
The paths are clear.
Now you want to walk it.
A part of it. Or the entire system.
users: - name: ghost1 role: watcher - name: ghost2 role: operator - name: ghost3 role: architect
Iterating a list of dictionaries:
- name: Walk through each ghost ansible.builtin.debug: msg: " {{ item.name }} takes the role: {{ item.role }} " loop: " {{ users }} "
But sometimes the dictionary itself must be walked:
secrets: key1: shadow key2: fog key3: silence
- name: Dict to items ansible.builtin.debug: msg: "Key: {{ item.key }} | Value: {{ item.value }} " loop: " {{ secrets | dict2items }} "
When the map is too twisted, flatten it.
When the ghosts hide, reveal them.
Exorcism Tools - Filters And Transforms
Walking the paths is not enough.
Sometimes you reshape them.
Bend them.
Burn away the noise.
Filters are the exorcism tools.
users: - name: ghost1 role: watcher - name: ghost2 role: operator - name: ghost3 role: architect
Map reveals only what you need:
- name: Extract only the roles ansible.builtin.debug: msg: "Role: {{ item }} " loop: " {{ users | map(attribute='role') | list }} "
It whispers:
ok: [localhost] => ( item=watcher) => Role: watcher ok: [localhost] => ( item=operator) => Role: operator ok: [localhost] => ( item=architect) => Role: architect
Select banishes what does not fit:
- name: Keep only operators ansible.builtin.debug: msg: "Operator: {{ item.name }} " loop: " {{ users | selectattr('role', 'equalto', 'operator') | list }} "
When the maze grows darker, json_query
cuts through.
(JMESPath is your blade.)
- name: Using json_query ansible.builtin.debug: msg: "Architect: {{ users | json_query('[?role==`architect`].name') }} "
The echo is:
ok: [localhost] => Architect: [ 'ghost3']
Sometimes you want a clean string.
- name: Using json_query ansible.builtin.debug: msg: "Architect: {{ users | json_query('[?role==`architect`].name') | first }} "
The answer comes in a form of a string:
ok: [localhost] => Architect: ghost3
The Ghost Operator does not drown in data.
He transforms it.
The Architect reshapes the chaos into silence.
Final Whisper
The Operator is you.
You write the data. Architect the structure.
Then you bend it.
Lists grow, Dictionaries bind, Filters cut.