1

I'm new at using ansible for server management and I need some help managing users and group's membership definition according to host and hosts-group, with a minimum of duplication and a maximum of scalability.
(25 users/20 groups over 50 hosts, with differents "sudo" and " groups membership" at the end).
The idea is to have:

  • "groups_vars" files defining the users (list or hash) to create on each host of the hostgroup.
  • "host_vars" files defining users for a specific host. (At the end, I will need nested groups, more than specific host_vars files)

I need these "*_vars files" contents to be merged and not to be replaced (I understand how "vars precedence" work) because I want to avoid user declaration duplication.
To achieve this, I used hash syntax in "*_vars" files and set "hash_behaviour=merge" in /etc/ansible/ansible.cfg.
Here are my files :
My inventory :

all:
  children:
    type_a:
      hosts:
        vm1:
        vm2:

My debugging playbook :

- hosts: type_a
  tasks:
    - name: Debugging
      debug:
        msg: "{{ users }}"

group_vars/type_a.yaml :

users:
  user1:
    name: user1
  user2:
    name: user2

host_vars/vm1.yaml

users:
  user3_vm1_specific:
    name: user3_vm1_specific

At the end, I need the 3 users on the "vm1" and only "user1" and "user2" on "vm2" and then I will use the vars for the user creation. Using the merge option (that will be deprecated in newer version of ansible) is working, but doesn't seem to be a best practice.
I searched here on ServFault and on other web sites, and most of the time the solutions are:

  • to duplicate the user definition (more than 8 properties for each user and too many hostsgroup: unacceptable.)
  • to use an other name for the second user list, then to assemble both using "{{ user_list1 + user_list2 }}".
    Not very scalable if we want to add many nested groups. You will need to add custom named list each time. It also, makes duplicates if "host_vars" and "group_vars" have the same user defined: it does not merge the content, but declares it twice with a different content each time.

My first solution is working, but using a near-deprecated option. So what are the best practices in managing vars in this kind of situation ? (already have read the ansible documentation about vars but it didn't really helped me).

Also, maybe ansible tower or foreman could solve this problem ?

Regards
M.

1

Ansible Jinja2 has a combine() filter, that can be used to merge two dicts together.

In your case, you would have:

group_vars/type_a.yaml

group_users:
  user1:
    name: user1
  user2:
    name: user2

host_vars/vm1.yaml

host_users:
  user3_vm1_specific:
    name: user3_vm1_specific

And debugging playbook:

- hosts: type_a
  tasks:
    - name: Debugging
      debug:
        msg: "{{ group_users | combine(host_users) }}"

I think the merge strategy is deprecated because it is all or nothing and it can cause undesired side-effects.

3
  • 1
    This solution is better than if we used two lists as said in my first post because if we have duplicates users, instead of making duplicates, it will overwrites the users of the group var definition while combining the other definition. The problem still is that the content of the user is also completely replaced (it would be better to replace also only the duplicate options) but it is not a full blocker for my situation. The main problem of this (great) solution is that like for the two lists option, the two dicts have different names and it is not practical if we want to mix nested subgroups – naguam Sep 18 '20 at 8:50
  • Have you ever use foreman or tower, maybe can they manage inventory better than with this kind of var for my problem ? – naguam Sep 18 '20 at 14:46
  • Unfortunately I have no experience with them. – Tero Kilkanen Sep 18 '20 at 19:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.