# request: group\_vars loading strategy to handle deploy-specific roles variables

**URL:** <https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842>\
**Category:** Ansible Project\
**Created:** [March 24, 2014, 2:37pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842 "2014-03-24T14:37:26Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kesten\_Broughton2](https://avatars.discourse-cdn.com/v4/letter/k/ecc23a/32.png) [@Kesten\_Broughton2](https://forum.ansible.com/u/Kesten_Broughton2)\
**Post date:** [March 24, 2014, 2:37pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/1 "2014-03-24T14:37:26Z")

</div>

In a [previous thread](https://groups.google.com/forum/#!topic/ansible-project/LgiQ6CRHRCY), it was discussed how one could apply deployment specific vars to a play. My solution at the time was to pass in a master config “pointer” file via the commandline with the -e “@filename” idiom containing file names that could be loaded by vars\_files or include\_vars.

ansible-playbook -i hosts site.yml -e “@cluster\_config.yml”

Then in site.yml (or a tasks file with include\_vars: )

- hosts: hadoop\_cluster  
vars\_files:
- ["{{network\_config}}]
- ["{{environment\_config}}]
- ["{{hadoop\_config}}]

Michael suggested this was an anti pattern and I did find a maintenance problem because of all those vars\_files lines sprinkled about the playbook.

My preferred method is now to modify the hosts file to add additional deployment specific groups to the top of the hosts file and have the vars loaded automatically via group\_vars.

Currently, the group\_vars loader does what I would call “Immediate folder match”. If a top level folder in group\_vars matches any of the groups, all descended files and folders ending in .yml will be loaded.

This prevents hierarchical groupings of deployments. I would like to organize my deployments like this

[kbroughton@mb-kbroughton:lynx-ansible/dev-ansible + (develop)] tree …/21ct-ansible/group\_vars/  
…/21ct-ansible/group\_vars/  
├── all  
└── datacenter  
├── datacenter.yml  
├── production

> ├── production.yml # vars common to all prod systems  
> │ └── client1\_prod  
> │ ├── client1\_app.yml

│ └── client2\_prod  
│ ├── client2\_app.yml

└── staging

├── staging.yml  
├── client1\_stag  
│ ├── client1\_stag.yml  
│ ├── client1\_app.yml  
└── client2\_stag

Each step of the descent, files in a matching folder are loaded but only matching subfolders will be descended into.

I’m writing this to open discussion again on how to best accomplish deployment-specific vars. At the moment, my solution is to modify the signature of the \_load\_vars and related methods in  
[ansible](https://github.com/ansible/ansible)/[lib](https://github.com/ansible/ansible/tree/devel/lib)/[ansible](https://github.com/ansible/ansible/tree/devel/lib/ansible)/[inventory](https://github.com/ansible/ansible/tree/devel/lib/ansible/inventory)/ **vars\_plugins** group\_vars.py

to pass in groups information.  
Then I add the checking that only descends into a directory if it is a in groups[host].

The default behavior could remain as it is with a new variable in .ansible.cfg  
group\_vars\_load\_strategy: { one of HIERARCHICAL\_FOLDER\_MATCH,  
IMMEDIATE\_FOLDER\_MATCH - the current behavior  
}

Would a pull request along these lines be considered, or is there an alternate preferred method that achieves the deployment-specific vars management we need?

kesten

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [March 24, 2014, 3:23pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/2 "2014-03-24T15:23:15Z")

</div>

“Would a pull request along these lines be considered…”

It wouldn’t, as I don’t want too many ways to do this and wouldn’t want to maintain the code for a fringe case – however this is a great example of a case where you could write your own external inventory script to implement any behavior you like, and this is why these exist – they aren’t just for talking to a database, can also be for “I want to organize my information differently and have these preferences…”

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [March 24, 2014, 3:41pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/3 "2014-03-24T15:41:17Z")

</div>

Another option might also be to write your own vars\_plugin.  
Though working with an inventory script, as Michael put it, is the better way to do it, and will also be a lot more performant.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [March 24, 2014, 3:43pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/4 "2014-03-24T15:43:19Z")

</div>

Yep, the vars plugin will (currently) be evaluated once per host.

---

<div class="post-metadata">

**Author:** ![Kesten\_Broughton2](https://avatars.discourse-cdn.com/v4/letter/k/ecc23a/32.png) [@Kesten\_Broughton2](https://forum.ansible.com/u/Kesten_Broughton2)\
**Post date:** [April 1, 2014, 2:50pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/5 "2014-04-01T14:50:17Z")

</div>

Thanks serge and michael.

I’m not opposed to writing my own plugin, though I’m basically happy with group\_vars.py. My change is just the 5 lines here.

# directory

if stat.S\_ISDIR(pathstat.st\_mode):

# support organizing variables across multiple files in a directory

**if GROUP\_VARS\_STRATEGY == ‘HIERARCHICAL\_FOLDER\_MATCH’:**  
**if os.path.basename(path) in groups:**

**return True, \_load\_vars\_from\_folder(groups, path, results)**  
**else:**  
**return True, results**

**else:**  
return True, \_load\_vars\_from\_folder(groups, path, results) # the original group\_vars.py line

So what is the porper way to get ansible to use my\_group\_vars.py as the plugin rather than group\_vars.py? I would like to keep pulling in future changes to group\_vars.py and just run off a local branch with my patch applied. Should i just locally over-write group\_vars.py or is there a proper plugin switch? I will have to distribute my plugin across multiple users.

kesten

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [April 1, 2014, 3:46pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/6 "2014-04-01T15:46:16Z")

</div>

​Just put your plugin in ./vars\_plugins/ where . = the dir where your  
inventory (hosts file) is.  
Update your plugin to only handle the subdirs you need, the original plugin  
will continue to work as intended (but in practice not loading any vars in  
your setup.)  
​

---

<div class="post-metadata">

**Author:** ![Kesten\_Broughton2](https://avatars.discourse-cdn.com/v4/letter/k/ecc23a/32.png) [@Kesten\_Broughton2](https://forum.ansible.com/u/Kesten_Broughton2)\
**Post date:** [April 1, 2014, 5:33pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/7 "2014-04-01T17:33:00Z")

</div>

Sorry, i missed the “distributing plugins” section at the bottom  
[http://docs.ansible.com/developing\_plugins.html#distributing-plugins](http://docs.ansible.com/developing_plugins.html#distributing-plugins)

However, i’m not clear if dropping my group\_vars into ansible/plugins/vars\_plugins/group\_vars.py will run before, after or instead of lib/ansible/inventory/vars\_plugins/group\_vars.py?  
Is there a way to specify ordering / precedence of files in a plugin directory? Maybe just point me to the plugin loader code?

k

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [April 1, 2014, 5:52pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/8 "2014-04-01T17:52:04Z")

</div>

​They will all run, and the order is not really defined, nor configureable,  
though i \*think\* the core plugin will run first.

Plugin loader code is in ​lib/ansible/utils/plugins.py.  
The vars plugin get initialized in lib/ansible/inventory/\_\_init\_\_.py (at  
the end of the Inventory constructor)

---

<div class="post-metadata">

**Author:** ![kesten\_broughton1](https://avatars.discourse-cdn.com/v4/letter/k/dc4da7/32.png) [@kesten\_broughton1](https://forum.ansible.com/u/kesten_broughton1)\
**Post date:** [April 29, 2014, 5:04pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/9 "2014-04-29T17:04:09Z")

</div>

Serge, thanks for pointing me to the help.

It seems that group\_vars.py plugin runs after my plugin which gives the wrong precedence for what i need.  
Just to close the loop on this thread, my solution was to add self.priority = 1 in the constructor of VarsModule for my deploy\_vars.py plugin and then this in  
lib/ansible/inventory/ **init**.py

#self.\_vars\_plugins = [x for x in utils.plugins.vars\_loader.all(self)] # original line replaced by the lines below

# 21ct KB add priority to all deploy\_vars to have higher precedence than group\_vars

# higher priority value = higher precedence

unsorted\_plugins = [x for x in utils.plugins.vars\_loader.all(self) if not hasattr(x,‘priority’)]  
sorted\_plugins = [x for x in utils.plugins.vars\_loader.all(self) if hasattr(x,‘priority’)]  
sorted\_plugins = sorted(sorted\_plugins, key=lambda t: t. **getattribute** (‘priority’))

# last in list has highest precedence

self.\_vars\_plugins = (unsorted\_plugins or ) + (sorted\_plugins or )

thanks for your assistance on this.

kesten

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [April 30, 2014, 8:05pm UTC](https://forum.ansible.com/t/request-group-vars-loading-strategy-to-handle-deploy-specific-roles-variables/14842/10 "2014-04-30T20:05:18Z")

</div>

Removing the core plugin is unsupported and would create a legion of issues if you were to file bugs on a version of ansible that ran different code than everyone else is running.

I would recommend using it as implemented.
