Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible - Filter a dict with a list of keys

Tags:

loops

ansible

I have a list which is actually a list of keys of a dict. And I want to get a concatenated string with the dict filtered on this list of keys and use it in a module option.

My use case here is users that have a list of public keys's name to generate an authorized_keys file.

 1 ---
 2 - hosts: localhost
 3   become: false
 4   vars:
 5     pub_keys:
 6       key01: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ[…]5/ someuser@somehost
 7       key02: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ[…]ea otheruser@somewher
 8       key03: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ[…]dN anyser@anyhost
 9     users:
10       root:
11         home: /root
12         shell: /bin/bash
13         authorized_keys:
14           - key01
15       mgmtusr:
16         home: /home/mgmtusr
17         shell: /bin/bash
18         authorized_keys:
19           - key01
20           - key02
21           - key03
22
23   tasks:
24     - name: Debug Authorized Keys
25       debug:
26         msg: "USER:{{ item.key }} AUTHKEYSLIST:{{ pub_keys|selectattr(item.authorized_keys) }}"
27       with_dict: "{{ users }}"
28
29     - name: Manage users Authorized Keys
30       authorized_key:
31         user: "{{ item.key }}"
32         key: "{{ pub_keys|selectattr(item.authorized_keys) }}"
33         exclusive: yes
34       with_dict: "{{ users }}"
35

As you can see here, I give it a try with dict|selectattr(list) but it fails.

Getting <generator object select_or_reject at 0x…> in the debug module and of course an invalid key specified in the authorized_key module.

TASK [Debug Authorized Keys] **************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => (item={'key': u'mgmtusr', 'value': {u'home': u'/home/mgmtusr', u'shell': u'/bin/bash', u'authorized_keys': [u'key01', u'key02', u'key03']}}) => {
    "item": {
        "key": "mgmtusr",
        "value": {
            "authorized_keys": [
                "key01",
                "key02",
                "key03"
            ],
            "home": "/home/mgmtusr",
            "shell": "/bin/bash"
        }
    },
    "msg": "USER:mgmtusr AUTHKEYSLIST:"
}
ok: [localhost] => (item={'key': u'root', 'value': {u'home': u'/root', u'shell': u'/bin/bash', u'authorized_keys': [u'key01']}}) => {
    "item": {
        "key": "root",
        "value": {
            "authorized_keys": [
                "key01"
            ],
            "home": "/root",
            "shell": "/bin/bash"
        }
    },
    "msg": "USER:root AUTHKEYSLIST:"
}

TASK [Manage users Authorized Keys] *******************************************************************************************************************************************************************************************************************************************
failed: [localhost] (item={'key': u'mgmtusr', 'value': {u'home': u'/home/mgmtusr', u'shell': u'/bin/bash', u'authorized_keys': [u'key01', u'key02', u'key03']}}) => {"changed": false, "failed": true, "item": {"key": "mgmtusr", "value": {"authorized_keys": ["key01", "key02", "key03"], "home": "/home/mgmtusr", "shell": "/bin/bash"}}, "msg": "Failed to lookup user mgmtusr: 'getpwnam(): name not found: mgmtusr'"}
failed: [localhost] (item={'key': u'root', 'value': {u'home': u'/root', u'shell': u'/bin/bash', u'authorized_keys': [u'key01']}}) => {"changed": false, "failed": true, "item": {"key": "root", "value": {"authorized_keys": ["key01"], "home": "/root", "shell": "/bin/bash"}}, "msg": "invalid key specified: "}

Like other tries (with_subelements, lookup('template', …) selectattr does not seems the solution. Any proposition?

like image 734
xenlo Avatar asked Jan 30 '23 05:01

xenlo


1 Answers

Here you go:

- name: Manage users Authorized Keys
  authorized_key:
    user: "{{ item.key }}"
    key: "{{ item.value.authorized_keys | map('extract',pub_keys) | list | join('\n') }}"
    exclusive: yes
  with_dict: "{{ users }}"

See extract filter usage.

Also when you use map you should almost always typecast it to list to prevent generator object value.

like image 136
Konstantin Suvorov Avatar answered Mar 20 '23 03:03

Konstantin Suvorov