Ansible

How to Use Ansible 'map' filter

How to Use Ansible 'map' filter
In: Ansible, NetDevOps

In this blog post, let's explore what a map filter is in Ansible and look at some practical use cases. The map filter is a handy tool in Ansible, making it easier to manipulate and transform data within your playbooks. We'll keep things straightforward and show you how this filter can be a real game-changer in automating tasks.

What is a Map Filter?

The map filter in Ansible is a powerful tool that lets you modify or transform each item in a list without the need for looping. It's like giving a single command that all items in the list follow, saving you time and making your playbooks cleaner and more efficient.

The map filter applies a specified function to each element in a list. This function could be anything from changing the data type (like converting numbers to strings), appending or modifying strings, to more complex operations. Think of it as telling each item in your list to go through a transformation process, and what comes out is a new list with these changes applied.

Ansible Map Filter - Simple Example

To demonstrate the map filter in action, let's look at a straightforward example where we convert a list of numbers into strings. This is particularly useful when you need to ensure that your data is in the correct format for further processing or output.

---
- name: Convert numbers to strings
  hosts: localhost
  gather_facts: no
  vars:
    numbers: [1, 2, 3]

  tasks:
    - name: Convert each number to a string
      debug:
        msg: "{{ numbers | map('string') }}"
  • A list of numbers: 1, 2, and 3.
  • A task that uses the map filter with the string function. This function converts each number in our list into its string representation.

When you run this playbook, it will display each number as a string, like '1', '2', and '3'. This is a simple yet practical use of the map filter, showcasing how you can easily transform data in your Ansible playbooks.

Another Example - Adding a Prefix to List Items

Here's another easy-to-understand example using the map filter. Let's say you have a list of words, and you want to add a prefix to each word.

---
- name: Add prefix to words
  hosts: localhost
  gather_facts: no
  vars:
    words: ['dog', 'cat', 'bird']

  tasks:
    - name: Add 'pet_' prefix to each word
      debug:
        msg: "{{ words | map('regex_replace', '^', 'pet_') }}"
  • We define a list called words with the items 'dog', 'cat', and 'bird'.
  • In the task, we use the map filter with regex_replace.
  • regex_replace is a function that takes two main arguments:
    1. A regular expression pattern.
    2. The string to replace the pattern with.
    3. In our case, the pattern is '^', and the replacement string is 'pet_'.
  • The caret (^) sign in regular expressions represents the start of a string.
  • By using '^' as our pattern, we tell regex_replace to look at the beginning of each string in our list.
  • The replacement, 'pet_', is then added at the starting point of each string.

When you run this playbook, regex_replace acts on each item in the words list, adding 'pet_' at the start. So 'dog' becomes 'pet_dog', 'cat' becomes 'pet_cat', and 'bird' becomes 'pet_bird'.

Yet Another Example - Changing Case of List Items

Let's look at another example of using the map filter in Ansible. This time, we'll change the case of each item in a list from lowercase to uppercase.

---
- name: Convert list items to uppercase and update the list
  hosts: localhost
  gather_facts: no
  vars:
    items: ['apple', 'banana', 'cherry']

  tasks:
    - name: Change each item to uppercase
      set_fact:
        items: "{{ items | map('upper') }}"

    - name: Display the updated list
      debug:
        msg: "{{ items }}"
  1. We start with a list called items containing 'apple', 'banana', and 'cherry'.
  2. Using set_fact to Update the List
    • The set_fact module is used to redefine the items variable.
    • We apply the map filter with the upper function to each item in the list, which converts them to uppercase.
    • The result is then saved back into the items variable, effectively updating it.
  3. Displaying the Updated List
    • Finally, we use the debug module to display the updated items list.
    • Now, items will contain 'APPLE', 'BANANA', and 'CHERRY'.

Extracting Specific JSON Data

For a more advanced use of the map filter, let's consider a scenario where we have a list of JSON objects and we want to extract a specific value from each object. This kind of task is common when dealing with structured data like JSON, often used in configurations or API responses.

---
- name: Extract specific data from JSON objects
  hosts: localhost
  gather_facts: no
  vars:
    json_data: 
      - { name: "Alice", role: "Developer" }
      - { name: "Bob", role: "Designer" }
      - { name: "Charlie", role: "Manager" }

  tasks:
    - name: Extract the role of each person
      set_fact:
        roles: "{{ json_data | map(attribute='role') }}"

    - name: Display the extracted roles
      debug:
        msg: "{{ roles }}"
  1. We start with a variable json_data that contains a list of JSON objects. Each object represents a person with a name and role.
  2. Extracting Specific Information
    • The task uses set_fact to create a new list roles.
    • We use the map filter with the attribute='role' parameter. This tells Ansible to look inside each JSON object and pull out the value associated with the role key.
  3. The resulting list, containing only the roles, is then stored in the roles variable.
  4. The debug module is used to print the list of roles, which will be ['Developer', 'Designer', 'Manager'].

In this final example, we'll tackle a more complex scenario where we have a nested JSON structure. We'll extract specific data from this nested JSON which is all the department names.

---
- name: Extract data from nested JSON
  hosts: localhost
  gather_facts: no
  vars:
    json_data: 
      [
        {
            "name": "Alice",
            "details": {
                "age": 30,
                "department": "Engineering"
            }
        },
        {
            "name": "Bob",
            "details": {
                "age": 25,
                "department": "Design"
            }
        },
        {
            "name": "Charlie",
            "details": {
                "age": 35,
                "department": "Management"
            }
        }
      ]

  tasks:
    - name: Extract department of each person
      set_fact:
        departments: "{{ json_data | map(attribute='details') | map(attribute='department') }}"

    - name: Display the extracted departments
      debug:
        msg: "{{ departments }}"
  1. We have a list json_data, each item containing a name and a nested details object with age and department.
  2. Navigating the Nested Structure
    • The first map filter uses the extract function to navigate into the details sub-object for each item in the list.
    • The second map filter then extracts the department attribute from these details.
  3. Storing and Displaying the Results
    • The resulting list of departments is stored in the departments variable using set_fact.
    • Finally, we use debug to display the departments list, which will contain ['Engineering', 'Design', 'Management'].

Closing Up

To wrap up, the map filter in Ansible is a powerful yet straightforward tool for transforming lists. From appending prefixes to extracting data from nested JSON, this filter can handle a variety of tasks, making your playbooks cleaner and more efficient.

Written by
Suresh Vina
Tech enthusiast sharing Networking, Cloud & Automation insights. Join me in a welcoming space to learn & grow with simplicity and practicality.
Comments
More from Packetswitch
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Packetswitch.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.