Dynamically constructing and managing data structures is a crucial skill in Ansible automation, especially for tasks that require flexible and reusable configurations. In this article, we’ll explore this concept using a practical example: managing user accounts and groups on Linux systems.
Scenario: Dynamic User and Group Management
Imagine you have a user_list variable defining multiple users and their associated groups:
``yaml
user_list:
alice:
groups:
- admin
- developers
bob:
groups:
- developers
charlie:
groups:
- admin
- qa
`
Your goal is to:
- Dynamically construct a user and group data structure.
- Use this structure to manage user accounts and assign them to the appropriate groups.
The Ansible Playbook
Here’s how you can achieve this using set_fact and Jinja2 templating:
`yaml
- name: Manage users dynamically
hosts: localhost
gather_facts: false
vars:
user_list:
alice:
groups:
- admin
- developers
bob:
groups:
- developers
charlie:
groups:
- admin
- qa
tasks:
- name: Construct user data
set_fact:
user_data: >
{%- set users = [] -%}
{%- for username, details in user_list.items() -%}
{{ users.append({'name': username, 'groups': details.groups}) }}
{%- endfor -%}
{{ users }}
- name: Debug constructed user data
debug:
var: user_data
- name: Create users and assign groups
ansible.builtin.user:
name: "{{ item.name }}"
groups: "{{ item.groups | join(',') }}"
loop: "{{ user_data }}"
`
Key Components
1. Data Construction with set_fact:
- The set_fact task dynamically builds user_data as a list of dictionaries, each containing:
- name: The username.
- groups: The list of groups.
Example output:
`yaml
user_data:
- name: alice
groups:
- admin
- developers
- name: bob
groups:
- developers
- name: charlie
groups:
- admin
- qa
`
2. Dynamic User Management:
- The ansible.builtin.user module iterates through user_data, creating users and assigning them to their respective groups. The groups field is converted to a comma-separated string using join(',').
3. Debugging:
- The debug task ensures that the user_data structure is correct before applying it.
Benefits of This Approach
- Dynamic and Reusable:
- Adapts to changes in the input user_list without modifying the playbook logic.
- Centralized Logic:
- Data construction is isolated in the set_fact` task, making the playbook easier to read and maintain.
- Scalable:
- Handles any number of users and groups effortlessly.
- Error Detection:
- Intermediate debugging ensures correctness before execution.
Conclusion
This app