1

I have to create an LDAP structure with users and groups.
The groups are a bit complex with a lot of nested groups etc. I need to create a tree like structure in my inventory, like the following:

----
user_groups:
  - name: AllUsers
    members:
      - name: GitlabUsers
        members:
          - name: GitlabAdmins
          - name: GitlabUsers
          - name: GitlabViewers
      - name: StorageUsers
        members:
          - name: StorageAdmins
          - name: StorageReporters
      - name: IPAMUsers
        members:
          - name: IPAMAdmins
          - name: IPAMUsers
            members:
              - name: IPAMUsersStorage
              - name: IPAMUsersLinux
          - name: TowerViewers
      - name: BillingUsers
        members:
          - name: BillingAdmins
          - name: BillingUsers
            members:
              - name: BillingUsersDBA
              - name: BillingUsersReports

In any programming language that would be implemented with a recursive function, but Ansible is not a programming language

So, I wonder if it is possible to create structures like this in ansible, either with complex json queries or with a recursive call of include_tasks, or anything similar to that.

ptselios
  • 31
  • 4
  • What is the source of the data? – Vladimir Botka Apr 09 '20 at 08:17
  • I do wonder if you really 'need' a tree in ansible, or if you could get away with a flat structure. Maybe use something like the [LDIF](https://en.wikipedia.org/wiki/LDAP_Data_Interchange_Format) for inspiration about how you might store the data. – Zoredache Apr 09 '20 at 08:32
  • It's more or less the LDIF represented in a tree. Not my choice, I "just" have to find a way to implement it. – ptselios Apr 09 '20 at 09:17

1 Answers1

1

I guess what you're looking for is combine with recursive=True in a set_fact task:

This playboook, for example, gathers hostname => ip relations for each of my nodes which helps me to ensure /etc/hosts or dns configurations are consistent accross my cluster.

- hosts: all
  tasks:
    - name: Gather hosts ips
      shell: "dig {{ item }} +short"
      register: hosts_ips
      loop: "{{ ansible_play_batch }}"

    - name: dbg
      ansible.builtin.debug:
        var: hosts_ips

    - name: Storing ips as fact
      set_fact:
        hosts_status:
          "{{ hosts_status|default([]) | combine({
              item.item : {
                'ip': item.stdout,
              }
            }, recursive=True)
          }}"
      loop: "{{ hosts_ips.results | default([]) }}"

    - name: dbg hosts_status
      ansible.builtin.debug:
        var: hosts_status

Result on each server (They're the same so i'm good):

ok: [amsh-1] => {
    "hosts_status": {
        "amsh-1": {
            "ip": "192.168.121.28"
        },
        "amsh-2": {
            "ip": "192.168.121.109"
        },
        "amsh-3": {
            "ip": "192.168.121.229"
        },
        "amsh-4": {
            "ip": "192.168.121.92"
        }
    }
}
ok: [amsh-2] => {
    "hosts_status": {
        "amsh-1": {
            "ip": "192.168.121.28"
        },
        "amsh-2": {
            "ip": "192.168.121.109"
        },
        "amsh-3": {
            "ip": "192.168.121.229"
        },
        "amsh-4": {
            "ip": "192.168.121.92"
        }
    }
}
ok: [amsh-3] => {
    "hosts_status": {
        "amsh-1": {
            "ip": "192.168.121.28"
        },
        "amsh-2": {
            "ip": "192.168.121.109"
        },
        "amsh-3": {
            "ip": "192.168.121.229"
        },
        "amsh-4": {
            "ip": "192.168.121.92"
        }
    }
}
ok: [amsh-4] => {
    "hosts_status": {
        "amsh-1": {
            "ip": "192.168.121.28"
        },
        "amsh-2": {
            "ip": "192.168.121.109"
        },
        "amsh-3": {
            "ip": "192.168.121.229"
        },
        "amsh-4": {
            "ip": "192.168.121.92"
        }
    }
}

I guess you'll be able to make your data structure with it.

PS: btw, this script inline in an Ansible playbook is written in jinja2 if you look for docs: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-and-selecting-data

Jean Claveau
  • 111
  • 3