# Inventory and group\_vars layout advice

**URL:** <https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604>\
**Category:** Ansible Project\
**Tags:** vmware, aws\
**Created:** [June 25, 2015, 11:55am UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604 "2015-06-25T11:55:12Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tom\_Paine](https://avatars.discourse-cdn.com/v4/letter/t/858c86/32.png) [@Tom\_Paine](https://forum.ansible.com/u/Tom_Paine)\
**Post date:** [June 25, 2015, 11:55am UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/1 "2015-06-25T11:55:12Z")

</div>

Seeking some best-practice advice about where to store variables within the following structure:

- multiple inventory folders ./inventory/x, ./inventory/y, ./inventory/z
- inside each inventory folder, combinations of dynamic and static inventory sources
- inside each inventory folder, environment specific group vars

Currently I am copy-pasting variables common to all of the inventories (environments) between the all.yml group\_vars files.

My question: is there a way to have a ‘global’ group variables file I can use for this type of variable?

I know I could source a file with include\_vars: at the start of each of the multiple plays inside the playbooks, but hoped there might be something more elegant and/or automatic (like group\_vars) available. Maybe even a simple restructure I can’t think of.

`

.  
├── inventory

│ ├── aws-dev  
│ │ ├── aws-dev  
│ │ ├── ec2.ini  
│ │ ├── ec2.py  
│ │ └── group\_vars  
│ │ ├── all  
│ │ │ ├── all.yml  
│ │ │ └── secrets.yml  
│ │ ├── security\_group\_app.yml  
│ │ └── security\_group\_util  
│ │ ├── secrets.yml  
│ │ └── security\_group\_util.yml  
│ ├── aws-prod  
│ │ ├── aws-prod  
│ │ └── group\_vars  
│ │ └── all  
│ │ ├── all.yml  
│ │ └── secrets.yml  
│ └── vmware-dev  
│ ├── group\_vars  
│ │ ├── all  
│ │ │ ├── all.yml  
│ │ │ └── secrets.yml  
│ │ └── tag\_role\_app.yml  
│ ├── vmware-dev  
│ ├── vmware.ini  
│ └── vmware.py  
├── roles

├── aws-configure.yml  
├── aws-provision.yml  
├── vmware-configure.yml  
└── vmware-provision.yml

`

---

<div class="post-metadata">

**Author:** ![Mark\_McCoy](https://avatars.discourse-cdn.com/v4/letter/m/ebca7d/32.png) [@Mark\_McCoy](https://forum.ansible.com/u/Mark_McCoy)\
**Post date:** [June 25, 2015, 12:37pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/2 "2015-06-25T12:37:03Z")

</div>

Have you thought about using role default variables instead? If all environments have the same setting, this would be simpler. Role default variables can then be overridden for specific groups in the group vars file.

---

<div class="post-metadata">

**Author:** ![Tom\_Paine](https://avatars.discourse-cdn.com/v4/letter/t/858c86/32.png) [@Tom\_Paine](https://forum.ansible.com/u/Tom_Paine)\
**Post date:** [June 25, 2015, 2:16pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/3 "2015-06-25T14:16:08Z")

</div>

Already doing that where possible, but for things like microservices that have templated configs that use the same variable, having it in defaults still requires copy-paste, but at that (potentially larger) level instead.

Might it be possible to add an ansible configuration param that forces a particular file to always be loaded, in addition to normal?

Abuse a vars\_plugin to always return the vars in a file…?

---

<div class="post-metadata">

**Author:** ![Hagai\_Kariti](https://avatars.discourse-cdn.com/v4/letter/h/4491bb/32.png) [@Hagai\_Kariti](https://forum.ansible.com/u/Hagai_Kariti)\
**Post date:** [June 25, 2015, 4:58pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/4 "2015-06-25T16:58:24Z")

</div>

I’d like to hear advices for this as well. I do have one idea that I don’t like however. You should be able to use group\_vars relative to your playbooks as well. So put a group\_vars dir outside of your inventories, next to your playbooks, and that will be evaluated for all envs.

---

<div class="post-metadata">

**Author:** ![Tom\_Paine](https://avatars.discourse-cdn.com/v4/letter/t/858c86/32.png) [@Tom\_Paine](https://forum.ansible.com/u/Tom_Paine)\
**Post date:** [June 25, 2015, 11:25pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/5 "2015-06-25T23:25:03Z")

</div>

Thanks Hafai,  
Confirming that works, unbelievably. A group\_vars/all.yml next to playbooks, as you say, is evaluated as well as in the inner group\_vars.

I’m warming to the idea of writing a vars plugin that is essentially just a pointer to a file somewhere. Advantage is that the target could be anywhere you like.

---

<div class="post-metadata">

**Author:** ![Hagai\_Kariti](https://avatars.discourse-cdn.com/v4/letter/h/4491bb/32.png) [@Hagai\_Kariti](https://forum.ansible.com/u/Hagai_Kariti)\
**Post date:** [June 25, 2015, 11:39pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/6 "2015-06-25T23:39:13Z")

</div>

Problem with a vars plugin is that you’ll have to specify it in each playbook. New idea: you could put another inventory script in your dir that evaluates your common file.

---

<div class="post-metadata">

**Author:** ![Tom\_Paine](https://avatars.discourse-cdn.com/v4/letter/t/858c86/32.png) [@Tom\_Paine](https://forum.ansible.com/u/Tom_Paine)\
**Post date:** [June 26, 2015, 5:03pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/7 "2015-06-26T17:03:30Z")

</div>

So vars plugins have to be specified per play, like ‘include\_vars:’ do? If so, no savings there.

An inventory script would be pretty good as it would be a write once, then stays the same for every extra inventory.

Can you clarify how it might work?

This command turns will output JSON from the Ansible .yml file:

`python -c 'import sys, yaml, json; json.dump(yaml.load(sys.stdin), sys.stdout, indent=4)' < all.yml > all.json`

The other inventory scripts return groups. Would I have to wrap that output in a ‘all’ group for it to work? Is that enough?

---

<div class="post-metadata">

**Author:** ![Tom\_Paine](https://avatars.discourse-cdn.com/v4/letter/t/858c86/32.png) [@Tom\_Paine](https://forum.ansible.com/u/Tom_Paine)\
**Post date:** [June 26, 2015, 5:05pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/8 "2015-06-26T17:05:35Z")

</div>

Some of the variables in the all.yml are also templated from other variables - would they be parsed properly if coming in from an inventory script?

---

<div class="post-metadata">

**Author:** ![Hagai\_Kariti](https://avatars.discourse-cdn.com/v4/letter/h/4491bb/32.png) [@Hagai\_Kariti](https://forum.ansible.com/u/Hagai_Kariti)\
**Post date:** [June 26, 2015, 6:52pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/9 "2015-06-26T18:52:09Z")

</div>

You need to wrap it in an ‘all’ group, yes. The output should look like this:

{  
“all”: {  
“vars”: {  
…your vars here…  
}  
}  
}

And templates are evaluated when used, so the vars can be templated.

---

<div class="post-metadata">

**Author:** ![Barry\_Kaplan](https://avatars.discourse-cdn.com/v4/letter/b/48db29/32.png) [@Barry\_Kaplan](https://forum.ansible.com/u/Barry_Kaplan)\
**Post date:** [June 27, 2015, 12:57am UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/10 "2015-06-27T00:57:11Z")

</div>

I have, and and still are, struggling with this as well. Our inventory is very similar to yours. We have three AWS environments, and dozens of other on-prem environments. For the AWS we need to share a bunch of variables. Putting those in playbook group\_vars does not work because the are only for AWS, not the other environments.

Hence I have resorted to soft-linking an aws-common.yml into each of the aws group\_vars. Since git handles the links its really no pain, just a bit of confusion when searching.

I do a similar thing in the playbooks for other reasons. But now reading below the under playbooks ansible will look up the tree for group\_vars I may not need those.

---

<div class="post-metadata">

**Author:** ![Tom\_Paine](https://avatars.discourse-cdn.com/v4/letter/t/858c86/32.png) [@Tom\_Paine](https://forum.ansible.com/u/Tom_Paine)\
**Post date:** [June 29, 2015, 5:16pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/11 "2015-06-29T17:16:27Z")

</div>

Thanks to Hagai I have a good solution worth sharing.

- add common\_vars.sh bash script to each of the inventories I wish to share variables. Make it executable. Point it where your common Ansible YAML variables are (in my case inventory/common\_vars.yml).
- add common\_vars.yml and populate it

Run your playbooks with the specified inventory path as normal (inventory/aws-dev, inventory/aws-prod etc)

Benefits

- inventory files are all kept in the inventory folder
- normal Ansible group\_vars are left alone
- only need one extra file per inventory, and no copy paste
- if you need a few top level common\_vars, you can just point your common\_vars to onprem\_common.yml and cloudstack\_common.yml, or as you like.
- feels like a proper Ansible way to do things without hacks

New dir structure below (compared to original). Bash script code after.

`

.  
├── inventory  
│ ├── common\_vars.yml

│ ├── aws-dev  
│ │ ├── aws-dev  
│ │ ├── common\_vars.sh

│ │ ├── ec2.ini  
│ │ ├── ec2.py  
│ │ └── group\_vars  
│ │ ├── all  
│ │ │ ├── all.yml  
│ │ │ └── secrets.yml  
│ │ ├── security\_group\_app.yml  
│ │ └── security\_group\_util  
│ │ ├── secrets.yml  
│ │ └── security\_group\_util.yml  
│ ├── aws-prod

│ │ ├── aws-prod  
│ │ ├── common\_vars.sh

│ │ ├── ec2.ini  
│ │ ├── ec2.py

│ │ └── group\_vars  
│ │ └── all  
│ │ ├── all.yml  
│ │ └── secrets.yml  
│ └── vmware-dev  
│ ├── group\_vars  
│ │ ├── all  
│ │ │ ├── all.yml  
│ │ │ └── secrets.yml  
│ │ └── tag\_role\_app.yml  
│ ├── common\_vars.sh

│ ├── vmware-dev  
│ ├── vmware.ini  
│ └── vmware.py  
├── roles

├── aws-configure.yml  
├── aws-provision.yml  
├── vmware-configure.yml  
└── vmware-provision.yml

`

common\_vars.sh

`

#!/usr/bin/env bash

# [http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in](http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in)

DIR=$( cd “$( dirname “${BASH\_SOURCE[0]}” )” && pwd )

# echo $DIR

# [http://stackoverflow.com/questions/27382552/converting-yaml-to-json-with-python-block-end-found](http://stackoverflow.com/questions/27382552/converting-yaml-to-json-with-python-block-end-found)

python -c ‘import sys, yaml, json; json.dump({“all”: {“vars”: yaml.load(sys.stdin) } }, sys.stdout, indent=4)’ \< $DIR/../common\_vars.yml # \> all.json

`

This accomplishes everything required without complexity.

Thanks Hagai!

---

<div class="post-metadata">

**Author:** ![Hagai\_Kariti](https://avatars.discourse-cdn.com/v4/letter/h/4491bb/32.png) [@Hagai\_Kariti](https://forum.ansible.com/u/Hagai_Kariti)\
**Post date:** [June 29, 2015, 5:30pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/12 "2015-06-29T17:30:37Z")

</div>

Thanks for sharing! Glad I could help. 🙂

---

<div class="post-metadata">

**Author:** ![Tom\_Paine1](https://avatars.discourse-cdn.com/v4/letter/t/3da27b/32.png) [@Tom\_Paine1](https://forum.ansible.com/u/Tom_Paine1)\
**Post date:** [July 14, 2015, 12:24pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/13 "2015-07-14T12:24:46Z")

</div>

This has worked incredibly well in practice. We’ve deduped all our variables and only have a handful of inventory specific vars. Perfect.

Any idea how this might be extended to use ansible-vault encrypted files?

Is the vault-password put into somewhere accessible, so that a modified script could do the same JSON-ification as it does with the clear YAML vars?

---

<div class="post-metadata">

**Author:** ![Hagai\_Kariti](https://avatars.discourse-cdn.com/v4/letter/h/4491bb/32.png) [@Hagai\_Kariti](https://forum.ansible.com/u/Hagai_Kariti)\
**Post date:** [July 14, 2015, 12:33pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/14 "2015-07-14T12:33:37Z")

</div>

Hm, can’t think of something. I think we must have ansible pass it as an environment variable for the script to use.

---

<div class="post-metadata">

**Author:** ![Quentin\_Stafford-Fra](https://avatars.discourse-cdn.com/v4/letter/q/b2d939/32.png) [@Quentin\_Stafford-Fra](https://forum.ansible.com/u/Quentin_Stafford-Fra)\
**Post date:** [July 14, 2015, 1:39pm UTC](https://forum.ansible.com/t/inventory-and-group-vars-layout-advice/18604/15 "2015-07-14T13:39:55Z")

</div>

Nice concept.

If you prefer not to mix python and bash, you could create a common\_vars.py instead. Something like:

`

#! /usr/bin/env python

import os, sys, yaml, json  
srcfile = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), ‘…’, ‘common\_vars.yml’))  
with open(srcfile) as f:  
json.dump({“all”: {“vars”: yaml.load(f) } }, sys.stdout, indent=4)

`

Remember to make it executable with chmod +x as with the bash script.
