HiveBrain v1.2.0
Get Started
← Back to all entries
snippetMinor

Doing map and filter of a list of dictionaries in ansible

Submitted by: @import:stackexchange-devops··
0
Viewed 0 times
mapdictionariesdoingfilterandlistansible

Problem

Given a list of users:

# Python Syntax
users = [{'name': 'alice', 'sudo': True}, {'name': 'bob'}, {'name': 'charlie'}]

# YAML Syntax
users:
  - name: alice
    sudo: yes
  - name: bob
  - name: charlie


How would I do the following in an ansible playbook:

# Python Syntax
[ dict(user, home="/home/{}/".format(user['name'])) for user in users if not 'sudo' in user]

# more verbose
for user in users:
  if not 'sudo' in user:
    user['home'] = '/home/' + user['name'] + '/'


resulting in:

# Python Syntax
[{'name': 'bob', 'home': '/home/bob/'}, {'name': 'charlie', 'home': '/home/charlie/'}]

# YAML Syntax
users:
  - name: bob
    home: /home/bob/
  - name: charlie
    home: /home/charlie/


Is this even possible/intended use of playbook language?

Solution

There's a lot that you can do, but I'm not sure with the existing filters you easily augment a dict.

Creating a new filter to do it was easier.

$ cat filter_plugins/addhomedir.py
class FilterModule:
    @staticmethod
    def add_home(_val):
        return [dict(user, home='/home/{0}/'.format(user['name'])) for user in
                _val if 'sudo' not in user]

    def filters(self):
        return {
            'add_homedir': self.add_home
        }
$ cat test1.yml
---
- hosts: localhost
  vars:
     users:
         - name: alice
           sudo: yes
         - name: bob
         - name: charlie
  tasks:
      - debug:
          msg: "{{ users | add_homedir | list }}"


You can use set_facts and loop to get the values you want, but the question becomes what format and use of the data is really needed. I'm not sure creating a new structure is the Right Way (TM). It could be easier to just calculate the individual value for each item in the list when it is used.

$ cat test2.yml
---
- hosts: localhost
  vars:
      users:
        - name: alice
          sudo: yes
        - name: bob
        - name: charlie
  tasks:
     - user:
         name: "{{ item['name'] }}"
         create_home: true
         home: "{{ '/home/{}/'.format(item['name'] }}"
       when: "'sudo' not in item"
       loop: "{{ users }}"

Code Snippets

$ cat filter_plugins/addhomedir.py
class FilterModule:
    @staticmethod
    def add_home(_val):
        return [dict(user, home='/home/{0}/'.format(user['name'])) for user in
                _val if 'sudo' not in user]

    def filters(self):
        return {
            'add_homedir': self.add_home
        }
$ cat test1.yml
---
- hosts: localhost
  vars:
     users:
         - name: alice
           sudo: yes
         - name: bob
         - name: charlie
  tasks:
      - debug:
          msg: "{{ users | add_homedir | list }}"
$ cat test2.yml
---
- hosts: localhost
  vars:
      users:
        - name: alice
          sudo: yes
        - name: bob
        - name: charlie
  tasks:
     - user:
         name: "{{ item['name'] }}"
         create_home: true
         home: "{{ '/home/{}/'.format(item['name'] }}"
       when: "'sudo' not in item"
       loop: "{{ users }}"

Context

StackExchange DevOps Q#11481, answer score: 4

Revisions (0)

No revisions yet.