Allow parent groups to be variables or literal (#53649)

* Allow parent groups to be variables or literal, requires {{ }}
* Check strict before failing on templating errors
* Don't add a group if an invalid parent group was provided
This commit is contained in:
Sloane Hertel 2019-03-14 13:22:18 -05:00 committed by Brian Coca
parent 90a38670be
commit 87ebc56de6
3 changed files with 75 additions and 0 deletions

View file

@ -0,0 +1,3 @@
minor_changes:
- inventory keyed_groups - allow the parent_group to be specified as a variable by using
brackets, such as "{{ placement.region }}", or as a string if brackets are not used.

View file

@ -404,6 +404,13 @@ class Constructable(object):
prefix = keyed.get('prefix', '') prefix = keyed.get('prefix', '')
sep = keyed.get('separator', '_') sep = keyed.get('separator', '_')
raw_parent_name = keyed.get('parent_group', None) raw_parent_name = keyed.get('parent_group', None)
if raw_parent_name:
try:
raw_parent_name = self.templar.template(raw_parent_name)
except AnsibleError as e:
if strict:
raise AnsibleParserError("Could not generate parent group %s for group %s: %s" % (raw_parent_name, key, to_native(e)))
continue
new_raw_group_names = [] new_raw_group_names = []
if isinstance(key, string_types): if isinstance(key, string_types):

View file

@ -19,6 +19,7 @@
import pytest import pytest
from ansible.errors import AnsibleParserError
from ansible.plugins.inventory.constructed import InventoryModule from ansible.plugins.inventory.constructed import InventoryModule
from ansible.inventory.data import InventoryData from ansible.inventory.data import InventoryData
from ansible.template import Templar from ansible.template import Templar
@ -116,3 +117,67 @@ def test_keyed_parent_groups(inventory_module):
all_regions = inventory_module.inventory.groups['region_list'] all_regions = inventory_module.inventory.groups['region_list']
assert all_regions.child_groups == [region_group] assert all_regions.child_groups == [region_group]
assert region_group.hosts == [host1, host2] assert region_group.hosts == [host1, host2]
def test_parent_group_templating(inventory_module):
inventory_module.inventory.add_host('cow')
inventory_module.inventory.set_variable('cow', 'sound', 'mmmmmmmmmm')
inventory_module.inventory.set_variable('cow', 'nickname', 'betsy')
host = inventory_module.inventory.get_host('cow')
keyed_groups = [
{
'key': 'sound',
'prefix': 'sound',
'parent_group': '{{ nickname }}'
},
{
'key': 'nickname',
'prefix': '',
'separator': '',
'parent_group': 'nickname' # statically-named parent group, conflicting with hostvar
},
{
'key': 'nickname',
'separator': '',
'parent_group': '{{ location | default("field") }}'
}
]
inventory_module._add_host_to_keyed_groups(
keyed_groups, host.vars, host.name, strict=True
)
# first keyed group, "betsy" is a parent group name dynamically generated
betsys_group = inventory_module.inventory.groups['betsy']
assert [child.name for child in betsys_group.child_groups] == ['sound_mmmmmmmmmm']
# second keyed group, "nickname" is a statically-named root group
nicknames_group = inventory_module.inventory.groups['nickname']
assert [child.name for child in nicknames_group.child_groups] == ['betsy']
# second keyed group actually generated the parent group of the first keyed group
# assert that these are, in fact, the same object
assert nicknames_group.child_groups[0] == betsys_group
# second keyed group has two parents
locations_group = inventory_module.inventory.groups['field']
assert [child.name for child in locations_group.child_groups] == ['betsy']
def test_parent_group_templating_error(inventory_module):
inventory_module.inventory.add_host('cow')
inventory_module.inventory.set_variable('cow', 'nickname', 'betsy')
host = inventory_module.inventory.get_host('cow')
keyed_groups = [
{
'key': 'nickname',
'separator': '',
'parent_group': '{{ location.barn-yard }}'
}
]
with pytest.raises(AnsibleParserError) as err_message:
inventory_module._add_host_to_keyed_groups(
keyed_groups, host.vars, host.name, strict=True
)
assert 'Could not generate parent group' in err_message
# invalid parent group did not raise an exception with strict=False
inventory_module._add_host_to_keyed_groups(
keyed_groups, host.vars, host.name, strict=False
)
# assert group was never added with invalid parent
assert 'betsy' not in inventory_module.inventory.groups