Ansible Best Practices - Group_Vars Not Being Applied As Expected

All,

I have been setting up my environment to match the best practices provided here: https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html#best-practices – However, I am running into some issues with how variables are being

Goal:

  • The system administrator user/group defined in group_vars/all.yml will be created on BOTH hosts
  • The oracle dba user/group defined in group_vars/oracle.yml will be created on the oracle box ONLY

What I Am Seeing:

  • The ‘jeff5’ user (system adminstrator) and AIXAdmin group are being created on the lx00011010d box ONLY (the expectation is that it would be created on both)
  • The oracle/DBA users are being created on lx00016141d, which is NOT the oracle box (expectation is that these would get created on lx00011010d only)

Code and output below:

[jeff@lx00010300p ansible-help]$ tree

.

– ansible.cfg
– common.yml
– group_vars

– all.yml
-- oracle.yml -- inventory -- oracle – other
– oracle.yml
– roles
-- ansible-users -- defaults – main.yml
– README.md
-- tasks – main.yml
`-- site.yml

[jeff@lx00010300p ansible-help]$ cat site.yml common.yml oracle.yml

It's not possible to explain the output below and other results you observe
with the input provided. You'll have to minimise the example and make it
verifiable. It's simply out of scope this way.

       PLAY [oracle]

Thank you for your time vlado. Below is the information you have requested:

Command Line:
ansible-playbook site.yml -C

ansible-inventory --list --vars
Question: Why is group ‘AIXAdmin’ and user ‘jeff5’ vars not getting applied to both boxes?

[admin@lx00010300p ansible-help]$ ansible-inventory --list --vars
{
“_meta”: {
“hostvars”: {
“lx00011010d”: {
“groups_to_create”: [
{
“gid”: “901”,
“name”: “AIXAdmin”,
“state”: “present”
}
],
“users”: [
{
“group”: “AIXAdmin”,
“name”: “Jeff - AIX Linux Engineer”,
“uid”: 318427,
“username”: “jeff5”
}
]
},
“lx00016141d”: {
“file”: “group_vars/oracle.yml”,
“groups_to_create”: [
{
“gid”: 201,
“name”: “dba”
}
],
“users”: [
{
“group”: “dba”,
“name”: “Oracle”,
“uid”: 202,
“username”: “oracle”
},
{
“group”: “dba”,
“name”: “Kathryn - DBA”,
“uid”: 225114,
“username”: “kwhit”
}
]
}
}
},
“all”: {
“children”: [
“oracle”,
“other”,
“ungrouped”
]
},
“oracle”: {
“hosts”: [
“lx00016141d”
]
},
“other”: {
“hosts”: [
“lx00011010d”
]
}
}

Ansible-Users role details:
There are only two files in this role. Details below:

[admin@lx00010300p ansible-users]$ cat defaults/main.yml

> > ################################### INVENTORY
> > # file: *inventory/oracle*
> > [oracle]
> > lx00011010d
> >
> > # file: *inventory/other*
> > [other]
> > lx00016141d
> > [...]
> > ################################### GROUP_VARS

*ansible-inventory --list --vars*
[...]
    "oracle": {
        "hosts": [
            "lx00016141d"
        ]
    },
    "other": {
        "hosts": [
            "lx00011010d"
        ]
    }
}

[admin@lx00010300p ansible-help]$ ansible-config dump
[...]
DEFAULT_HOST_LIST(/sdd/ansible-help/ansible.cfg) =
[u'/sdd/ansible-production/inventory']

The problem might be DEFAULT_HOST_LIST. The doc says
DEFAULT_HOST_LIST: "Comma separated list of Ansible inventory sources"
https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-host-list

Fix the configuration. For example in ansible.cfg

    [defaults]
    inventory = /sdd/ansible-production/inventory/oracle,
                /sdd/ansible-production/inventory/other

(note: ini_file doesn't handle multi-line entries #4413)
https://github.com/ansible/ansible-modules-core/issues/4413

If this does not help proceed with the simplified test below.

I had set this option also to *directory* "inventory", but this does not seem
to be a problem and I was not able to reproduce the behaviour where the groups
"oracle" and "other" swap the hosts.

    $ grep inventory ansible.cfg
    inventory = $PWD/inventory

    $ tree inventory/
    inventory/
    ├── oracle
    └── other

    $ cat inventory/oracle
    [oracle]
    lx00011010d

    $ cat inventory/other
    [other]
    lx00016141d

    $ tree group_vars
    group_vars
    ├── all.yml
    └── oracle.yml

    $ cat group_vars/all.yml
    users:
      - username: jeff5

    $ cat group_vars/oracle.yml
    users:
      - username: oracle

    $ ansible-inventory --list --var
    [...]
        "oracle": {
            "hosts": [
                "lx00011010d"
            ]
        },
        "other": {
            "hosts": [
                "lx00016141d"
            ]
        }

The goal is to explain why you see the groups "oracle" and "other" swapping
the hosts. Try to reproduce the simplified test above, step by step increase
the complexity of the use-case and isolate the problem.

Cheers,

  -vlado

Hi Vladimir,

Thank you again for your time.

https://justpaste.it/4jmp1 ← I have put my steps/output here in case it is easier to view.

Also, I simplified my example a bit. I am still unclear on why ‘jeff’ is not getting added to both servers:

[jeff@lx00010300p ansible-production3]$ ansible -i hosts -m ping all
lx00011010d | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: false,
“ping”: “pong”
}
lx00016141d | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: false,
“ping”: “pong”
}
[jeff@lx00010300p ansible-production3]$ ansible -i hosts -m ping oracle
lx00011010d | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: false,
“ping”: “pong”
}

[ifreling@lx00010300p ansible-production3]$ cat group_vars/oracle

Short story is that variables from "group_vars/all" are overridden by
variables from "group_vars/oracle".

See *Variable precedence: Where should I put a variable?*
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

It's possible to configure "hash_behaviour = merge", but quoting from the
doc:" This is not the default behavior and it does not affect variables whose
values are scalars (integers, strings) or arrays. We generally recommend not
using this setting unless you think you have an absolute need for it, ..."
https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-hash-behaviour

There are other options how to merge dictionaries. For example
*How to extend dict in ansible, not overwriting it?*
https://stackoverflow.com/questions/57335762/how-to-extend-dict-in-ansible-not-overwriting-it/

Details

For anyone looking to control the priority of variables at the same parent/child level of group variables, there’s also the ansible_group_priority setting. See https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#how-variables-are-merged.

Thank you alicia.

Given my examples, would you be able to advise on how I could apply this here to accomplish my goal?

Thanks.