mirror of
https://github.com/ansible/awx.git
synced 2026-03-21 02:47:35 -02:30
Merge pull request #230 from rooftopcellist/si_no_match
Fix for no_match on grouped hosts in smart inventories
This commit is contained in:
@@ -2386,45 +2386,53 @@ class InventoryScriptView(RetrieveAPIView):
|
|||||||
if obj.variables_dict:
|
if obj.variables_dict:
|
||||||
all_group = data.setdefault('all', OrderedDict())
|
all_group = data.setdefault('all', OrderedDict())
|
||||||
all_group['vars'] = obj.variables_dict
|
all_group['vars'] = obj.variables_dict
|
||||||
|
if obj.kind == 'smart':
|
||||||
|
if len(obj.hosts.all()) == 0:
|
||||||
|
return Response({})
|
||||||
|
else:
|
||||||
|
all_group = data.setdefault('all', OrderedDict())
|
||||||
|
smart_hosts_qs = obj.hosts.all().order_by('name')
|
||||||
|
smart_hosts = list(smart_hosts_qs.values_list('name', flat=True))
|
||||||
|
all_group['hosts'] = smart_hosts
|
||||||
|
else:
|
||||||
|
# Add hosts without a group to the all group.
|
||||||
|
groupless_hosts_qs = obj.hosts.filter(groups__isnull=True, **hosts_q).order_by('name')
|
||||||
|
groupless_hosts = list(groupless_hosts_qs.values_list('name', flat=True))
|
||||||
|
if groupless_hosts:
|
||||||
|
all_group = data.setdefault('all', OrderedDict())
|
||||||
|
all_group['hosts'] = groupless_hosts
|
||||||
|
|
||||||
# Add hosts without a group to the all group.
|
# Build in-memory mapping of groups and their hosts.
|
||||||
groupless_hosts_qs = obj.hosts.filter(groups__isnull=True, **hosts_q).order_by('name')
|
group_hosts_kw = dict(group__inventory_id=obj.id, host__inventory_id=obj.id)
|
||||||
groupless_hosts = list(groupless_hosts_qs.values_list('name', flat=True))
|
if 'enabled' in hosts_q:
|
||||||
if groupless_hosts:
|
group_hosts_kw['host__enabled'] = hosts_q['enabled']
|
||||||
all_group = data.setdefault('all', OrderedDict())
|
group_hosts_qs = Group.hosts.through.objects.filter(**group_hosts_kw)
|
||||||
all_group['hosts'] = groupless_hosts
|
group_hosts_qs = group_hosts_qs.order_by('host__name')
|
||||||
|
group_hosts_qs = group_hosts_qs.values_list('group_id', 'host_id', 'host__name')
|
||||||
|
group_hosts_map = {}
|
||||||
|
for group_id, host_id, host_name in group_hosts_qs:
|
||||||
|
group_hostnames = group_hosts_map.setdefault(group_id, [])
|
||||||
|
group_hostnames.append(host_name)
|
||||||
|
|
||||||
# Build in-memory mapping of groups and their hosts.
|
# Build in-memory mapping of groups and their children.
|
||||||
group_hosts_kw = dict(group__inventory_id=obj.id, host__inventory_id=obj.id)
|
group_parents_qs = Group.parents.through.objects.filter(
|
||||||
if 'enabled' in hosts_q:
|
from_group__inventory_id=obj.id,
|
||||||
group_hosts_kw['host__enabled'] = hosts_q['enabled']
|
to_group__inventory_id=obj.id,
|
||||||
group_hosts_qs = Group.hosts.through.objects.filter(**group_hosts_kw)
|
)
|
||||||
group_hosts_qs = group_hosts_qs.order_by('host__name')
|
group_parents_qs = group_parents_qs.order_by('from_group__name')
|
||||||
group_hosts_qs = group_hosts_qs.values_list('group_id', 'host_id', 'host__name')
|
group_parents_qs = group_parents_qs.values_list('from_group_id', 'from_group__name', 'to_group_id')
|
||||||
group_hosts_map = {}
|
group_children_map = {}
|
||||||
for group_id, host_id, host_name in group_hosts_qs:
|
for from_group_id, from_group_name, to_group_id in group_parents_qs:
|
||||||
group_hostnames = group_hosts_map.setdefault(group_id, [])
|
group_children = group_children_map.setdefault(to_group_id, [])
|
||||||
group_hostnames.append(host_name)
|
group_children.append(from_group_name)
|
||||||
|
|
||||||
# Build in-memory mapping of groups and their children.
|
# Now use in-memory maps to build up group info.
|
||||||
group_parents_qs = Group.parents.through.objects.filter(
|
for group in obj.groups.all():
|
||||||
from_group__inventory_id=obj.id,
|
group_info = OrderedDict()
|
||||||
to_group__inventory_id=obj.id,
|
group_info['hosts'] = group_hosts_map.get(group.id, [])
|
||||||
)
|
group_info['children'] = group_children_map.get(group.id, [])
|
||||||
group_parents_qs = group_parents_qs.order_by('from_group__name')
|
group_info['vars'] = group.variables_dict
|
||||||
group_parents_qs = group_parents_qs.values_list('from_group_id', 'from_group__name', 'to_group_id')
|
data[group.name] = group_info
|
||||||
group_children_map = {}
|
|
||||||
for from_group_id, from_group_name, to_group_id in group_parents_qs:
|
|
||||||
group_children = group_children_map.setdefault(to_group_id, [])
|
|
||||||
group_children.append(from_group_name)
|
|
||||||
|
|
||||||
# Now use in-memory maps to build up group info.
|
|
||||||
for group in obj.groups.all():
|
|
||||||
group_info = OrderedDict()
|
|
||||||
group_info['hosts'] = group_hosts_map.get(group.id, [])
|
|
||||||
group_info['children'] = group_children_map.get(group.id, [])
|
|
||||||
group_info['vars'] = group.variables_dict
|
|
||||||
data[group.name] = group_info
|
|
||||||
|
|
||||||
if hostvars:
|
if hostvars:
|
||||||
data.setdefault('_meta', OrderedDict())
|
data.setdefault('_meta', OrderedDict())
|
||||||
@@ -2432,18 +2440,6 @@ class InventoryScriptView(RetrieveAPIView):
|
|||||||
for host in obj.hosts.filter(**hosts_q):
|
for host in obj.hosts.filter(**hosts_q):
|
||||||
data['_meta']['hostvars'][host.name] = host.variables_dict
|
data['_meta']['hostvars'][host.name] = host.variables_dict
|
||||||
|
|
||||||
# workaround for Ansible inventory bug (github #3687), localhost
|
|
||||||
# must be explicitly listed in the all group for dynamic inventory
|
|
||||||
# scripts to pick it up.
|
|
||||||
localhost_names = ('localhost', '127.0.0.1', '::1')
|
|
||||||
localhosts_qs = obj.hosts.filter(name__in=localhost_names, **hosts_q)
|
|
||||||
localhosts = list(localhosts_qs.values_list('name', flat=True))
|
|
||||||
if localhosts:
|
|
||||||
all_group = data.setdefault('all', OrderedDict())
|
|
||||||
all_group_hosts = all_group.get('hosts', [])
|
|
||||||
all_group_hosts.extend(localhosts)
|
|
||||||
all_group['hosts'] = sorted(set(all_group_hosts))
|
|
||||||
|
|
||||||
return Response(data)
|
return Response(data)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
75
awx/main/tests/functional/api/test_script_endpoint.py
Normal file
75
awx/main/tests/functional/api/test_script_endpoint.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import pytest
|
||||||
|
import json
|
||||||
|
from awx.api.versioning import reverse
|
||||||
|
|
||||||
|
from awx.main.models import Inventory, Host
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_empty_inventory(post, get, admin_user, organization, group_factory):
|
||||||
|
inventory = Inventory(name='basic_inventory',
|
||||||
|
kind='',
|
||||||
|
organization=organization)
|
||||||
|
inventory.save()
|
||||||
|
resp = get(reverse('api:inventory_script_view', kwargs={'version': 'v2', 'pk': inventory.pk}), admin_user)
|
||||||
|
jdata = json.loads(resp.content)
|
||||||
|
|
||||||
|
assert inventory.hosts.count() == 0
|
||||||
|
assert jdata == {}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_empty_smart_inventory(post, get, admin_user, organization, group_factory):
|
||||||
|
smart_inventory = Inventory(name='smart',
|
||||||
|
kind='smart',
|
||||||
|
organization=organization,
|
||||||
|
host_filter='enabled=True')
|
||||||
|
smart_inventory.save()
|
||||||
|
resp = get(reverse('api:inventory_script_view', kwargs={'version': 'v2', 'pk': smart_inventory.pk}), admin_user)
|
||||||
|
smartjdata = json.loads(resp.content)
|
||||||
|
|
||||||
|
assert smart_inventory.hosts.count() == 0
|
||||||
|
assert smartjdata == {}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_ungrouped_hosts(post, get, admin_user, organization, group_factory):
|
||||||
|
inventory = Inventory(name='basic_inventory',
|
||||||
|
kind='',
|
||||||
|
organization=organization)
|
||||||
|
inventory.save()
|
||||||
|
Host.objects.create(name='first_host', inventory=inventory)
|
||||||
|
Host.objects.create(name='second_host', inventory=inventory)
|
||||||
|
resp = get(reverse('api:inventory_script_view', kwargs={'version': 'v2', 'pk': inventory.pk}), admin_user)
|
||||||
|
jdata = json.loads(resp.content)
|
||||||
|
assert inventory.hosts.count() == 2
|
||||||
|
assert len(jdata['all']['hosts']) == 2
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_grouped_hosts_smart_inventory(post, get, admin_user, organization, group_factory):
|
||||||
|
inventory = Inventory(name='basic_inventory',
|
||||||
|
kind='',
|
||||||
|
organization=organization)
|
||||||
|
inventory.save()
|
||||||
|
groupA = group_factory('test_groupA')
|
||||||
|
host1 = Host.objects.create(name='first_host', inventory=inventory)
|
||||||
|
host2 = Host.objects.create(name='second_host', inventory=inventory)
|
||||||
|
Host.objects.create(name='third_host', inventory=inventory)
|
||||||
|
groupA.hosts.add(host1)
|
||||||
|
groupA.hosts.add(host2)
|
||||||
|
smart_inventory = Inventory(name='smart_inventory',
|
||||||
|
kind='smart',
|
||||||
|
organization=organization,
|
||||||
|
host_filter='enabled=True')
|
||||||
|
smart_inventory.save()
|
||||||
|
resp = get(reverse('api:inventory_script_view', kwargs={'version': 'v2', 'pk': inventory.pk}), admin_user)
|
||||||
|
jdata = json.loads(resp.content)
|
||||||
|
resp = get(reverse('api:inventory_script_view', kwargs={'version': 'v2', 'pk': smart_inventory.pk}), admin_user)
|
||||||
|
smartjdata = json.loads(resp.content)
|
||||||
|
|
||||||
|
assert getattr(smart_inventory, 'kind') == 'smart'
|
||||||
|
assert inventory.hosts.count() == 3
|
||||||
|
assert len(jdata['all']['hosts']) == 1
|
||||||
|
assert smart_inventory.hosts.count() == 3
|
||||||
|
assert len(smartjdata['all']['hosts']) == 3
|
||||||
Reference in New Issue
Block a user