0

Gurus, I'm learning ansible and trying to understand how the variables can be used, i have come across writing below playbook but i'm not understanding How to assign a particular group to particular users based on the Variables i have defined in the play for both Users and Groups under vars

I have below play where i want to create Users anika and rigved and want to assign them to a docker group while ayush and eshant should have the test group assigned.

I'm not getting the idea to achieve this so far. However as of now while running it creates users and assigns both group to all users.

$ cat nested_playbook-1.yml
---
- name: testing nested play
  hosts: localhost
  vars:
    users:
      - anika
      - rigved
      - ayush
      - eshant
    grps:
      - docker
      - test
  tasks:
    - name: make users members of groups
      user:
        name: "{{ item[0] }}"
        state: present
        groups: "{{ item[0] }}"
      with_nested:
        - "{{ users }}"
        - "{{ grps }}"
user2023
  • 452
  • 5
  • 22
  • So you want to somehow join the list of users and groups with somehow the same count of subgroups? I mean split the list of users by the count of groups and then iterate over users? Why `ayush` should not have the `docker` group? How is that information stored? What if there would be 5 users? Or 13 users and 11 groups? – KamilCuk Jan 17 '20 at 12:11
  • @KamilCuk, Sorry if you don't understand , my intent is the same as `larsks` explained, please let me know if you have any open solution. – user2023 Jan 17 '20 at 16:39

1 Answers1

1

The way you've structured your data doesn't show any relationship between users and groups. One option would be to structure it like this:

grps:
  - name: docker
    users:
      - anika
      - rigved
  - name: test
    users:
      - ayush
      - eshant

With this structure, you can loop over grps using the subelements filter, like this:

---
- name: testing nested play
  gather_facts: false
  hosts: localhost
  vars:
    grps:
      - name: docker
        users:
          - anika
          - rigved
      - name: test
        users:
          - ayush
          - eshant
  tasks:
    - debug:
        msg:
          user:
            name: "{{ item.1 }}"
            state: present
            groups: "{{ item.0.name }}"
      loop: "{{ grps|subelements('users') }}"
      loop_control:
        label: "{{ item.1 }}"

The subelements filter is a way of creating a "nested loop": it iterates over each member of the 'users' key for each group in grps. During each loop iteration, item is a 2-tuple in which the first item is the corresponding element from grps and the second item iterates over the users key for that element. In other words, you end up iterating over this list:

  • [{'name': 'docker', 'users': ['anika', 'rigved']}, anika}
  • [{'name': 'docker', 'users': ['anika', 'rigved']}, rigved}
  • [{'name': 'test', 'users': ['ayush', 'eshant']}, ayush}
  • [{'name': 'test', 'users': ['ayush', 'eshant']}, eshant}

So within the loop, item.0 refers to the group entry itself (and thus item.0.name is the group name), and item.1 refers to the user.

PLAY [testing nested play] *******************************************************************

TASK [debug] *********************************************************************************
ok: [localhost] => (item=anika) => {
    "msg": {
        "user": {
            "groups": "docker",
            "name": "anika",
            "state": "present"
        }
    }
}
ok: [localhost] => (item=rigved) => {
    "msg": {
        "user": {
            "groups": "docker",
            "name": "rigved",
            "state": "present"
        }
    }
}
ok: [localhost] => (item=ayush) => {
    "msg": {
        "user": {
            "groups": "test",
            "name": "ayush",
            "state": "present"
        }
    }
}
ok: [localhost] => (item=eshant) => {
    "msg": {
        "user": {
            "groups": "test",
            "name": "eshant",
            "state": "present"
        }
    }
}

PLAY RECAP ***********************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Alternately, you could structure your data like this:

users:
  - name: anika
    group: docker
  - name: rigved
    group: docker
  - name: ayush
    group: docker
  - name: eshant
    group: docker

You can just use a simple loop to process this structure:

---
- name: testing nested play
  gather_facts: false
  hosts: localhost
  vars:
    users:
      - name: anika
        group: docker
      - name: rigved
        group: docker
      - name: ayush
        group: docker
      - name: eshant
        group: docker
  tasks:
    - debug:
        msg:
          user:
            name: "{{ item.name }}"
            state: present
            groups: "{{ item.group }}"
      loop: "{{ users }}"
      loop_control:
        label: "{{ item.name }}"


Note that in both the above examples I'm using loop_control on the tasks just to set the loop label and make the output look nicer. You could remove loop_control from the above tasks with no impact on how they operate.

larsks
  • 277,717
  • 41
  • 399
  • 399