# Hierarchical hostgroups

**URL:** <https://forum.ansible.com/t/hierarchical-hostgroups/23154>\
**Category:** Ansible Developer\
**Created:** [December 1, 2016, 1:53pm UTC](https://forum.ansible.com/t/hierarchical-hostgroups/23154 "2016-12-01T13:53:36Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gregor\_Giesen](https://avatars.discourse-cdn.com/v4/letter/g/47e85d/32.png) [@Gregor\_Giesen](https://forum.ansible.com/u/Gregor_Giesen)\
**Post date:** [December 1, 2016, 1:53pm UTC](https://forum.ansible.com/t/hierarchical-hostgroups/23154/1 "2016-12-01T13:53:36Z")

</div>

Hello everybody,

our current configuration management system uses a path notation for  
hierarchical hostgroups (subgroups), i.e.

testgroup  
testgroup/subgroup1  
testgroup/subgroup2

which would correspond to Ansible's

[testgroup:children]  
testgroup/subgroup1  
testgroup/subgroup2

[testgroup/subgroup1]

[testgroup/subgroup2]

While using a dynamic inventory source for adapting the legacy inventory,  
(Ansible does not care about the slash '/' in a group name), we ran into  
problems declaring group variables via .yml-files on the filesystem:

group\_vars/test/subgroup1/somevars.yml

is found by hosts in any of the above hostgroups, since Ansible  
searches for all yml-files below group\_vars/test/ and assigns their variables  
to every host in the 'test' group.

One way around this problem might be to "flatten" the group tree by  
replacing the '/' by '\_' in the dynamic inventory source. Apart from  
possible (though unlikely) naming conflicts, this would be quite ugly  
abanding not only a quite nice notation for subgroups but also the  
much cleaner organisation of files and directories below group\_vars.

Is there an alternative apart from rewriting Ansible's part of parsing  
the group\_vars directories?

Many thanks in advance,  
Gregor

---

<div class="post-metadata">

**Author:** ![Devin\_Christensen](https://avatars.discourse-cdn.com/v4/letter/d/ecc23a/32.png) [@Devin\_Christensen](https://forum.ansible.com/u/Devin_Christensen)\
**Post date:** [December 1, 2016, 4:26pm UTC](https://forum.ansible.com/t/hierarchical-hostgroups/23154/2 "2016-12-01T16:26:56Z")

</div>

The biggest caveat here is that groups with a slash (/) in the name no longer work in the latest version of ansible. It treats everything up to but excluding the first slash as the group name.

We were doing this for a while but broke it out so there was no overlap by having a prefix for each group that defined the group's scope, E.g.

site/site1  
site/site2  
site-env/site1-prod  
site-env/site1-testing  
env/sand  
env/testing

It's no longer hierarchical, but still takes advantage of folders for organization, and you can set lookup priority by, E.g., making site-env/site1-testing a child of the env/testing group.

To make this compatible with the latest ansible, I replaced slashes with underscores. It's not as pretty but it works.

---

<div class="post-metadata">

**Author:** ![Devin\_Christensen](https://avatars.discourse-cdn.com/v4/letter/d/ecc23a/32.png) [@Devin\_Christensen](https://forum.ansible.com/u/Devin_Christensen)\
**Post date:** [December 1, 2016, 10:49pm UTC](https://forum.ansible.com/t/hierarchical-hostgroups/23154/3 "2016-12-01T22:49:47Z")

</div>

If you’re interested, the crux of the issue with the latest ansible is here: [https://github.com/ansible/ansible/blob/8217c1c39c8de848550e2a6c816377f11cc60e9f/lib/ansible/inventory/\_\_init\_\_.py#L777-L785](https://github.com/ansible/ansible/blob/8217c1c39c8de848550e2a6c816377f11cc60e9f/lib/ansible/inventory/ __init__.py#L777-L785)

Ansible is pre-loading a list of all the files in the group\_vars directory one level deep. You can still assign your machine to a group named “one/two/three”, but ansible will only have added a group\_vars\_file entry of “one” from the call to \_find\_group\_vars\_files. During variable lookup for the group “one/two/three” it checks for a group\_vars\_files entry of “one/two/three” ([https://github.com/ansible/ansible/blob/8217c1c39c8de848550e2a6c816377f11cc60e9f/lib/ansible/inventory/\_\_init\_\_.py#L833](https://github.com/ansible/ansible/blob/8217c1c39c8de848550e2a6c816377f11cc60e9f/lib/ansible/inventory/ __init__.py#L833)). When it finds none, it just moves on.
