# Inventory-specific group\_vars/all overrides

**URL:** <https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080>\
**Category:** Ansible Project\
**Created:** [December 16, 2014, 9:29pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080 "2014-12-16T21:29:41Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [December 16, 2014, 9:29pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/1 "2014-12-16T21:29:41Z")

</div>

Hi, I don’t see my issue addressed in the docs or existing issues. I’m trying to override site-wide group\_var/all config with an inventory-specific “all” but it looks like the site-wide vars get precedence, unexpectedly. Here’s my structure:

env  
├── dev

│ ├── group\_vars  
│ │ ├── all  
│ │ └── node  
│ └── inventory.py  
└── production  
├── group\_vars  
│ └── all  
└── inventory.py  
group\_vars  
└── all

I have a simple debug playbook to test vars: ansible-playbook -i env/dev debug.yml

1. In group\_vars/all, I set env: common

2. In env/dev/group\_vars/all I set env: common/dev, but it does not override the “common” value (unless I remove env: common from group\_vars/all

3. In env/dev/group\_vars/node I set env: common/dev/node, and it does override the “common” value for any hosts that belong to the “node” group.  
In #2, shouldn’t env/dev/group\_vars/all be overriding the value set from group\_vars/all?

Thanks,  
Trevor

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [December 16, 2014, 9:32pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/2 "2014-12-16T21:32:29Z")

</div>

No, the play specific group\_vars is there for overriding inventory  
group\_vars, this works as designed.

In general inventory is something you normally share across projects,  
plays are more specific to the action you want to accomplish, this is  
the logic followed for the above behavior.

---

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [December 16, 2014, 9:32pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/3 "2014-12-16T21:32:52Z")

</div>

Forgot to specify ansible version: ansible 1.8.2

---

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [December 16, 2014, 9:37pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/4 "2014-12-16T21:37:30Z")

</div>

Sorry, not following you. In this example I’m not storing any vars in playbooks.

I find it strange that group-specific vars at env/dev/group\_vars/node override group\_vars/all, but env/dev/group\_vars/all does not.

It sounds like that’s expected, so it’s not a bug, but I don’t understand the logic behind it.

An example of a var I’d like defined as a default but may want to override on a per-environment basis is version. Let’s say I want my default to be 0.9.0, but in production I want to override the default and specify 0.8.0.

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [December 16, 2014, 9:51pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/5 "2014-12-16T21:51:13Z")

</div>

Your plays are at the level of top env (assumed from how you call  
debug.yml) and they load that group\_vars, this is how you load  
inventory vars at the play level (different from play vars). It is  
meant to override the inventory as plays are more specific than  
inventory.

if you do not want this to be the case, put the inventory outside the same hier,

env/  
plays/

Then it would be ansible-playbook -i ../env/dev debug.yml and the  
../env/group\_vars/all will NOT be sourced.  
You are mixing 2 loading methods, one is part of inventory, the other  
part of plays, I think this is what is confusing you.

---

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [December 16, 2014, 9:58pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/6 "2014-12-16T21:58:24Z")

</div>

Thanks for explaining that.

It seem I have a pretty common use case, so it feels strange there isn’t a more direct way of solving it. I see what you mean by mixing 2 loading methods though. I structured it this way following [http://toja.io/using-host-and-group-vars-files-in-ansible/](http://toja.io/using-host-and-group-vars-files-in-ansible/)

There were other blog posts about multistage ansible environments, but this one was by far the simplest.

As a workaround, I might have my dynamic inventory script put all groups in a single supergroup “all\_groups” to allow me to override vars at the env-level (e.g. env/dev/group\_vars/all\_groups). Or is there a better way to specify a var default at the inventory level (instead of play level)?

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [December 16, 2014, 10:26pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/7 "2014-12-16T22:26:33Z")

</div>

i think the example you posted/followed is a bit confusing because  
their play is named group\_vars.yml, it does not have an actual  
group\_vars dir at play level.

---

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [December 18, 2014, 5:54pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/8 "2014-12-18T17:54:22Z")

</div>

You’re right, adding group\_vars/all was my own attempt at providing site-wide defaults that could be overriden at the env level.

So it sounds like I need a way to provide site-wide defaults at the Inventory level instead of Play level. I have an idea to manually load a defaults file with my dynamic inventory script and setting those vars, but it’s a bit ugly.

---

<div class="post-metadata">

**Author:** ![Azul](https://avatars.discourse-cdn.com/v4/letter/a/91b2a8/32.png) [@Azul](https://forum.ansible.com/u/Azul)\
**Post date:** [December 22, 2014, 6:07pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/9 "2014-12-22T18:07:43Z")

</div>

I use a different approach,

root  
├── inventory

│ |-- dev

│ │-- vagrant  
│ │-- preprod

│ └── production

> 

└── group\_vars

> – all.yaml  
> – dev/
> 
> > – secrets.yaml
> 
> – vagrant/
> 
> > – secrets.yaml
> 
> – preprod/
> 
> > – secrets.yaml
> 
> – production/  
> – secrets.yaml

where my group\_vars/all.yaml contains all my definitions for every environment, I keep it DRY by using lots of yaml anchors/aliases.  
[https://github.com/Azulinho/ansible-jenkins-showcase/blob/master/group\_vars/all.yaml#L686](https://github.com/Azulinho/ansible-jenkins-showcase/blob/master/group_vars/all.yaml#L686)

And in my inventory files, I set a variable ‘deploy\_env’  
[https://github.com/Azulinho/ansible-jenkins-showcase/blob/master/vagrant](https://github.com/Azulinho/ansible-jenkins-showcase/blob/master/vagrant)

I consume that ‘deploy\_env’ variable (typically matches my inventory file) at the end of my group\_vars/all.yaml file.  
[https://github.com/Azulinho/ansible-jenkins-showcase/blob/master/group\_vars/all.yaml#L713](https://github.com/Azulinho/ansible-jenkins-showcase/blob/master/group_vars/all.yaml#L713)

there are a gazillion ways of doing it, this one works well for me.

---

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [December 22, 2014, 6:18pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/10 "2014-12-22T18:18:27Z")

</div>

Thanks for posting Azul. It’s interesting to see another way of handling it. I ended up with this structure, which I’m liking a lot:

env  
├── defaults  
├── dev  
│ ├── group\_vars  
│ │ ├── backend  
│ │ ├── defaults  
│ │ ├── ingest  
│ │ ├── monitoring  
│ │ └── zookeeper  
│ └── inventory.py  
└── production  
├── group\_vars  
│ ├── backend  
│ ├── defaults  
│ ├── ingest  
│ ├── monitoring  
│ └── zookeeper  
└── inventory.py

1. I completely eschew Ansible’s “all” supergroup because precedence was not behaving as I expected.
2. I use a dynamic inventory script which adds all my groups to a “defaults” supergroup. This is my “all” replacement, so env/defaults is my new group\_vars/all. The script also manually reads in env/defaults and sets the vars in the JSON output.
3. env/defaults can specify site-wide defaults which can be overridden by env/dev/group\_vars/defaults. There’s a third level of specificity at env/dev/group\_vars/$group, e.g. env/dev/group\_vars/zookeeper, which would override anything in env/dev/group\_vars/defaults.

I’d really like to see Ansible create an official solution to this common problem. It’d take the burden off devs and increase uniformity in Ansible automation.

One awkward piece of my setup is having to set all my vars at the inventory level, when much of it belongs at the playbook level.

---

<div class="post-metadata">

**Author:** ![James\_Morgan1](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@James\_Morgan1](https://forum.ansible.com/u/James_Morgan1)\
**Post date:** [January 5, 2015, 1:43pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/11 "2015-01-05T13:43:43Z")

</div>

Hi,

I am seeing a similar problem with my inventory variables. I have the following defined

./group\_vars/all.yml: yum\_epel\_ansible\_managed: **false**

./inventory/db-builder/group\_vars/all.yml: yum\_epel\_ansible\_managed: **true**

Prior to 1.8.1 when running the db-builder inventory this would be overridden as **true**

Using 1.8.1 this is now left as **false**

“yum\_epel\_ansible\_managed”: “false”

We haven’t changed our playbooks or inventories.

This is causing us issues as you’d imagine. Is this approach incorrect as it has worked fine previously

Many thanks

James

---

<div class="post-metadata">

**Author:** ![James\_Morgan1](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@James\_Morgan1](https://forum.ansible.com/u/James_Morgan1)\
**Post date:** [January 5, 2015, 1:58pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/12 "2015-01-05T13:58:50Z")

</div>

Noticed this [https://github.com/ansible/ansible/issues/9877](https://github.com/ansible/ansible/issues/9877) though its a little unclear what the approach should be.

In my example I can make variable a role default which would fix it though I need to go and change every instance of this precedence issue.

The old behaviour seems logical

---

<div class="post-metadata">

**Author:** ![Patrick\_Martini](https://avatars.discourse-cdn.com/v4/letter/p/50afbb/32.png) [@Patrick\_Martini](https://forum.ansible.com/u/Patrick_Martini)\
**Post date:** [March 25, 2015, 3:54pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/13 "2015-03-25T15:54:49Z")

</div>

Hi Trevor,

can you share your dynamic inventory script with us ? it looks like the only way to have site-wide defaults.

Thanks  
Patrick

---

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [March 25, 2015, 4:45pm UTC](https://forum.ansible.com/t/inventory-specific-group-vars-all-overrides/17080/14 "2015-03-25T16:45:52Z")

</div>

Hi Patrick,

I’m using the [https://github.com/lukaspustina/dynamic-inventory-for-ansible-with-openstack](https://github.com/lukaspustina/dynamic-inventory-for-ansible-with-openstack) dynamic inventory script, specifically for obtaining inventory from C3. You can use it as a reference if you like.

I’m still using the directory structure I posted above, with group\_vars inside each env. The “defaults” group is the special one that I use to replace Ansible’s normal “all” group, except that I get expected override precedence. I modified the dynamic inventory script to load the non-env-specific defaults file and apply them like this:

def read\_default\_vars(self):  
c = ConfigParser.ConfigParser()  
c.read(“env/defaults”)  
section = “all”  
result = {}  
for key in c.options(section):  
result[key] = c.get(section, key)  
return result

def build\_defaults\_parent\_group(self):  
groups = list(self.inventory().iterkeys())  
groups.remove(“\_meta”)  
default\_vars = self.read\_default\_vars()  
self.inventory()[‘defaults’] = {  
‘hosts’: ,  
‘children’: groups,  
‘vars’: default\_vars}

That way the env-specific defaults file (e.g. env/dev/group\_vars/defaults) will override any vars set at env/defaults.

It is still awkward. I wish Ansible had a built-in solution.
