Importing user variables from multiple variable sources

41 views
Skip to first unread message

Suhail Choudhury

unread,
Feb 27, 2019, 10:15:59 AM2/27/19
to Ansible Project
Hi,

I want to know how I can import user account variables at multiple levels using loops/arrays and importing them all.

i.e. i have a generic module which has users defined in roles/common/tasks/main.yml as an array(or loop if more precise):

  - name: add admin users on RHEL
    user:
      name: "{{ item.username }}"
      comment: "{{ item.comment }}"
      state: present
      groups: wheel
      shell: /bin/bash
      password: "{{ item.password }}"
    with_items: "{{ users }}"
    when: ansible_facts["os_family"] == "RedHat"
    tags: common

and the user attributes are all set as variables and the variables for these users are being picked up from roles/common/vars/main.yml

I also have user variables defined under group_vars/dev and group_vars/prd

And I also have specific users defined at host level under host_vars/server1

Now the problem is that Ansible is only picking up users from one level, whilst I want to pick up all the user variables from all levels, i.e. sysadmins, dev users & specific host users, and add them all in, not just from the most preferred variable source.

In Puppet this is achieved by using Hiera and "hiera_hash" which allows variable values to get collectively applied from all hiera levels.

How can the same be achieved with Ansible please?

Regards,
Suhail.

Suhail Choudhury

unread,
Feb 28, 2019, 5:08:40 AM2/28/19
to Ansible Project
Has anyone come across this before? Surely it must be a common ask.

Adam E

unread,
Mar 2, 2019, 7:25:46 PM3/2/19
to Ansible Project
I have a similar issue and solved it by this PR https://github.com/ansible/ansible/pull/51466 . if you want to use it, just grab the source code and add it to your local library directory until it's merged. Also see this thread https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/ansible-project/Ssnk6exNjNs/sCKlrOp_FQAJ

With the approach above, the code would merge together all lists that match a pattern, this way you can defined as many "users" variables as you want as long as they are unique and start with say "users_"

If you don't want to copy the library or wait for the PR, then you could also just merge a set of predefined lists.

ie..
with_items: "{{ users_host|default([]) + users_group_l1|default([]) + users_group_l2|default([[) }}"

Suhail Choudhury

unread,
Mar 21, 2019, 7:58:59 AM3/21/19
to Ansible Project
Thanks for your earlier reply Adam.

So how can I combine variables for a list of "users" defined like so:

group_vars/all

users:
  - name: alice
    comment: Alice

group_vars/group1

users:
  - name: bob
    comment: Bob

host_vars/host1

users:
  - name: charlie
    comment: Charlie

How can all these variables be combined using "loop" or "with_items"?
What if there are duplicates?
Can the "host_vars/host1" variables override and take precedence over the "group_vars/all" variables?

Regards,
Suhail.

Kai Stian Olstad

unread,
Mar 21, 2019, 2:50:04 PM3/21/19
to ansible...@googlegroups.com
On 21.03.2019 12:58, Suhail Choudhury wrote:
> Thanks for your earlier reply Adam.
>
> So how can I combine variables for a list of "users" defined like so:
>
> *group_vars/all*
>
> users:
> - name: alice
> comment: Alice
>
> *group_vars/group1*
>
> users:
> - name: bob
> comment: Bob
>
> *host_vars/host1*
>
> users:
> - name: charlie
> comment: Charlie
>
> How can all these variables be combined using "loop" or "with_items"?

You can't, they will be overwritten in the order listed here
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

> What if there are duplicates?

They are duplicates since all are call users and will be overwritten.


> Can the "host_vars/host1" variables override and take precedence over the
> "group_vars/all" variables?

It does.


--
Kai Stian Olstad

Suhail Choudhury

unread,
Mar 21, 2019, 3:07:09 PM3/21/19
to ansible...@googlegroups.com
Hi.

Thanks for reply Kai.

Default Ansible cannot solve this problem, which I find very odd as it
was a common issue that is very elegantly addressed in Pupept using
Hiera.

However.... a solution has been found!

Have a look at:

http://leapfrogonline.io/articles/2017-02-22-explicit-merging-of-ansible-variables/
https://github.com/leapfrogonline/ansible-merge-vars

They have solved exactly this issue and I'm testing their plugin and
so far so good. Certainly not as elegant as Puppet/Hiera but it's a
working solution.

Regards,
Suhail.
> --
> You received this message because you are subscribed to the Google Groups "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
> To post to this group, send email to ansible...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/86213972-a12c-474a-0284-747eaa825cdd%40olstad.com.
> For more options, visit https://groups.google.com/d/optout.

Adam E

unread,
Mar 21, 2019, 3:32:21 PM3/21/19
to Ansible Project
another alternative if you don't want to use an external plugin is to predefine your variable names and then combine them..

ie...
users_global
users_group 
users_host (variable you set in host_vars)

and then use the "combine" filter to combine them together . 
ie..
users_global | combine(users_group, recursive=True) | combine(users_host, recursive=True)


I agree though, I am also coming from puppet and miss hiera.   I may still consider going back to using it as there appears to be support for it, but it would be nice to be fully integrated

The strategy I ended up going with for the similar problem you have is
1. I created a "users" hash in vars/ which contains all users that can be managed
2. then in my host & group_vars I populate a list such as "linux_users_global" or linux_users_unique_name which contains the list of users that should be managed either globally, group or at the host level
3. then in my playbook I merge all the variables that match the pattern "linux_users.*" . (see this link)
4. then I loop through that merged list and manage those users

for me, the above solution works quite well.
Reply all
Reply to author
Forward
0 new messages