diff --git a/awx/api/views.py b/awx/api/views.py index 2fa583ec33..40bff1d400 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -1070,8 +1070,15 @@ class InventoryScriptView(RetrieveAPIView): else: data = SortedDict() if self.object.variables_dict: - data['all'] = SortedDict() - data['all']['vars'] = self.object.variables_dict + all_group = data.setdefault('all', SortedDict()) + all_group['vars'] = self.object.variables_dict + + # Add hosts without a group to the all group. + groupless_hosts_qs = self.object.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', SortedDict()) + all_group['hosts'] = groupless_hosts # Build in-memory mapping of groups and their hosts. group_hosts_kw = dict(group__inventory_id=self.object.id, group__active=True, @@ -1120,8 +1127,10 @@ class InventoryScriptView(RetrieveAPIView): **hosts_q) localhosts = list(localhosts_qs.values_list('name', flat=True)) if localhosts: - data.setdefault('all', SortedDict()) - data['all']['hosts'] = localhosts + all_group = data.setdefault('all', SortedDict()) + all_group_hosts = all_group.get('hosts', []) + all_group_hosts.extend(localhosts) + all_group['hosts'] = sorted(set(all_group_hosts)) return Response(data) diff --git a/awx/main/tests/inventory.py b/awx/main/tests/inventory.py index ef4826cf1e..d71278ea13 100644 --- a/awx/main/tests/inventory.py +++ b/awx/main/tests/inventory.py @@ -797,13 +797,16 @@ class InventoryTest(BaseTest): h_c.groups.add(g_c) h_d = i_a.hosts.create(name='d', variables=json.dumps({'d-vars': 'ddd'})) h_d.groups.add(g_d) - + # Add another host not in any groups. + h_z = i_a.hosts.create(name='z', variables=json.dumps({'z-vars': 'zzz'})) + # Old, slow 1.2 way. url = reverse('api:inventory_script_view', args=(i_a.pk,)) with self.current_user(self.super_django_user): response = self.get(url, expect=200) self.assertTrue('all' in response) self.assertEqual(response['all']['vars'], i_a.variables_dict) + self.assertEqual(response['all']['hosts'], ['z']) for g in i_a.groups.all(): self.assertTrue(g.name in response) self.assertEqual(response[g.name]['vars'], g.variables_dict) @@ -818,11 +821,17 @@ class InventoryTest(BaseTest): response = self.get(h_url, expect=200) self.assertEqual(response, h.variables_dict) + # Now add localhost to the inventory. + h_l = i_a.hosts.create(name='localhost', variables=json.dumps({'ansible_connection': 'local'})) + # New 1.3 way. url = reverse('api:inventory_script_view', args=(i_a.pk,)) url = '%s?hostvars=1' % url with self.current_user(self.super_django_user): response = self.get(url, expect=200) + self.assertTrue('all' in response) + self.assertEqual(response['all']['vars'], i_a.variables_dict) + self.assertEqual(response['all']['hosts'], ['localhost', 'z']) self.assertTrue('_meta' in response) self.assertTrue('hostvars' in response['_meta']) for h in i_a.hosts.all():