mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 18:09:57 -03:30
AC-601 Add groups/hosts collections to inventory sources, add inventory sources collections to groups/hosts to indicate which inventory source(s) have created/updated the given groups/hosts. Prevent setting an explicit inventory source for a group that is being managed by another parent with cloud inventory source.
This commit is contained in:
parent
d7f31f9777
commit
008ec8f86e
@ -722,7 +722,7 @@ class HostSerializer(BaseSerializerWithVariables):
|
||||
job_events = reverse('api:host_job_events_list', args=(obj.pk,)),
|
||||
job_host_summaries = reverse('api:host_job_host_summaries_list', args=(obj.pk,)),
|
||||
activity_stream = reverse('api:host_activity_stream_list', args=(obj.pk,)),
|
||||
#inventory_sources = reverse('api:host_inventory_sources_list', args=(obj.pk,)),
|
||||
inventory_sources = reverse('api:host_inventory_sources_list', args=(obj.pk,)),
|
||||
))
|
||||
if obj.inventory and obj.inventory.active:
|
||||
res['inventory'] = reverse('api:inventory_detail', args=(obj.inventory.pk,))
|
||||
@ -833,7 +833,7 @@ class GroupSerializer(BaseSerializerWithVariables):
|
||||
job_events = reverse('api:group_job_events_list', args=(obj.pk,)),
|
||||
job_host_summaries = reverse('api:group_job_host_summaries_list', args=(obj.pk,)),
|
||||
activity_stream = reverse('api:group_activity_stream_list', args=(obj.pk,)),
|
||||
#inventory_sources = reverse('api:group_inventory_sources_list', args=(obj.pk,)),
|
||||
inventory_sources = reverse('api:group_inventory_sources_list', args=(obj.pk,)),
|
||||
))
|
||||
if obj.inventory and obj.inventory.active:
|
||||
res['inventory'] = reverse('api:inventory_detail', args=(obj.inventory.pk,))
|
||||
@ -981,8 +981,8 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
|
||||
inventory_updates = reverse('api:inventory_source_updates_list', args=(obj.pk,)),
|
||||
schedules = reverse('api:inventory_source_schedules_list', args=(obj.pk,)),
|
||||
activity_stream = reverse('api:inventory_activity_stream_list', args=(obj.pk,)),
|
||||
#hosts = reverse('api:inventory_source_hosts_list', args=(obj.pk,)),
|
||||
#groups = reverse('api:inventory_source_groups_list', args=(obj.pk,)),
|
||||
hosts = reverse('api:inventory_source_hosts_list', args=(obj.pk,)),
|
||||
groups = reverse('api:inventory_source_groups_list', args=(obj.pk,)),
|
||||
))
|
||||
if obj.inventory and obj.inventory.active:
|
||||
res['inventory'] = reverse('api:inventory_detail', args=(obj.inventory.pk,))
|
||||
|
||||
@ -81,7 +81,7 @@ host_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/job_events/', 'host_job_events_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'host_job_host_summaries_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'host_activity_stream_list'),
|
||||
#url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'host_inventory_sources_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'host_inventory_sources_list'),
|
||||
)
|
||||
|
||||
group_urls = patterns('awx.api.views',
|
||||
@ -95,7 +95,7 @@ group_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'group_job_host_summaries_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/potential_children/$', 'group_potential_children_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'group_activity_stream_list'),
|
||||
#url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'group_inventory_sources_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'group_inventory_sources_list'),
|
||||
)
|
||||
|
||||
inventory_source_urls = patterns('awx.api.views',
|
||||
@ -105,8 +105,8 @@ inventory_source_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/inventory_updates/$', 'inventory_source_updates_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'inventory_source_activity_stream_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/schedules/$', 'inventory_source_schedules_list'),
|
||||
#url(r'^(?P<pk>[0-9]+)/groups/$', 'inventory_source_groups_list'),
|
||||
#url(r'^(?P<pk>[0-9]+)/hosts/$', 'inventory_source_hosts_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/groups/$', 'inventory_source_groups_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/hosts/$', 'inventory_source_hosts_list'),
|
||||
)
|
||||
|
||||
inventory_update_urls = patterns('awx.api.views',
|
||||
|
||||
@ -722,6 +722,14 @@ class HostAllGroupsList(SubListAPIView):
|
||||
sublist_qs = parent.all_groups.distinct()
|
||||
return qs & sublist_qs
|
||||
|
||||
class HostInventorySourcesList(SubListAPIView):
|
||||
|
||||
model = InventorySource
|
||||
serializer_class = InventorySourceSerializer
|
||||
parent_model = Host
|
||||
relationship = 'inventory_sources'
|
||||
new_in_148 = True
|
||||
|
||||
class HostActivityStreamList(SubListAPIView):
|
||||
|
||||
model = ActivityStream
|
||||
@ -815,6 +823,14 @@ class GroupAllHostsList(SubListAPIView):
|
||||
sublist_qs = parent.all_hosts.distinct()
|
||||
return qs & sublist_qs
|
||||
|
||||
class GroupInventorySourcesList(SubListAPIView):
|
||||
|
||||
model = InventorySource
|
||||
serializer_class = InventorySourceSerializer
|
||||
parent_model = Group
|
||||
relationship = 'inventory_sources'
|
||||
new_in_148 = True
|
||||
|
||||
class GroupActivityStreamList(SubListAPIView):
|
||||
|
||||
model = ActivityStream
|
||||
@ -980,7 +996,6 @@ class InventorySourceDetail(RetrieveUpdateAPIView):
|
||||
serializer_class = InventorySourceSerializer
|
||||
new_in_14 = True
|
||||
|
||||
|
||||
class InventorySourceSchedulesList(SubListCreateAPIView):
|
||||
|
||||
view_name = "Inventory Source Schedules"
|
||||
@ -1000,6 +1015,22 @@ class InventorySourceActivityStreamList(SubListAPIView):
|
||||
relationship = 'activitystream_set'
|
||||
new_in_145 = True
|
||||
|
||||
class InventorySourceHostsList(SubListAPIView):
|
||||
|
||||
model = Host
|
||||
serializer_class = HostSerializer
|
||||
parent_model = InventorySource
|
||||
relationship = 'hosts'
|
||||
new_in_148 = True
|
||||
|
||||
class InventorySourceGroupsList(SubListAPIView):
|
||||
|
||||
model = Group
|
||||
serializer_class = GroupSerializer
|
||||
parent_model = InventorySource
|
||||
relationship = 'groups'
|
||||
new_in_148 = True
|
||||
|
||||
class InventorySourceUpdatesList(SubListAPIView):
|
||||
|
||||
model = InventoryUpdate
|
||||
|
||||
@ -682,6 +682,16 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions):
|
||||
return True
|
||||
return False
|
||||
|
||||
def clean_source(self):
|
||||
source = self.source
|
||||
if source and self.group:
|
||||
qs = self.group.inventory_sources.filter(source__in=CLOUD_INVENTORY_SOURCES, active=True, group__active=True)
|
||||
existing_sources = qs.exclude(pk=self.pk)
|
||||
if existing_sources.count():
|
||||
s = u', '.join([x.group.name for x in existing_sources])
|
||||
raise ValidationError('Unable to configure this item for cloud sync. It is already managed by %s.' % s)
|
||||
return source
|
||||
|
||||
|
||||
class InventoryUpdate(UnifiedJob, InventorySourceOptions):
|
||||
'''
|
||||
|
||||
@ -1046,15 +1046,30 @@ class InventoryUpdatesTest(BaseTransactionTest):
|
||||
if initial:
|
||||
self.assertEqual(inventory.groups.count(), 1)
|
||||
self.assertEqual(inventory.hosts.count(), 0)
|
||||
self.assertEqual(inventory_source.groups.count(), 0)
|
||||
self.assertEqual(inventory_source.hosts.count(), 0)
|
||||
inventory_update = self.check_inventory_update(inventory_source)
|
||||
inventory_source = InventorySource.objects.get(pk=inventory_source.pk)
|
||||
self.assertNotEqual(inventory.groups.count(), 1)
|
||||
self.assertNotEqual(inventory.hosts.count(), 0)
|
||||
self.assertNotEqual(inventory_source.groups.count(), 0)
|
||||
self.assertNotEqual(inventory_source.hosts.count(), 0)
|
||||
with self.current_user(self.super_django_user):
|
||||
url = reverse('api:inventory_source_groups_list', args=(inventory_source.pk,))
|
||||
response = self.get(url, expect=200)
|
||||
self.assertNotEqual(response['count'], 0)
|
||||
url = reverse('api:inventory_source_hosts_list', args=(inventory_source.pk,))
|
||||
response = self.get(url, expect=200)
|
||||
self.assertNotEqual(response['count'], 0)
|
||||
for host in inventory.hosts.all():
|
||||
source_pks = host.inventory_sources.values_list('pk', flat=True)
|
||||
self.assertTrue(inventory_source.pk in source_pks)
|
||||
self.assertTrue(host.has_inventory_sources)
|
||||
self.assertTrue(host.enabled)
|
||||
with self.current_user(self.super_django_user):
|
||||
url = reverse('api:host_inventory_sources_list', args=(host.pk,))
|
||||
response = self.get(url, expect=200)
|
||||
self.assertNotEqual(response['count'], 0)
|
||||
for group in inventory.groups.all():
|
||||
source_pks = group.inventory_sources.values_list('pk', flat=True)
|
||||
self.assertTrue(inventory_source.pk in source_pks)
|
||||
@ -1062,6 +1077,23 @@ class InventoryUpdatesTest(BaseTransactionTest):
|
||||
# Make sure EC2 instance ID groups are excluded.
|
||||
self.assertFalse(re.match(r'^i-[0-9a-f]{8}$', group.name, re.I),
|
||||
group.name)
|
||||
with self.current_user(self.super_django_user):
|
||||
url = reverse('api:group_inventory_sources_list', args=(group.pk,))
|
||||
response = self.get(url, expect=200)
|
||||
self.assertNotEqual(response['count'], 0)
|
||||
# Try to set a source on a child group that was imported. Should not
|
||||
# be allowed.
|
||||
for group in inventory_source.group.children.all():
|
||||
inv_src_2 = group.inventory_source
|
||||
inv_src_url2 = reverse('api:inventory_source_detail', args=(inv_src_2.pk,))
|
||||
with self.current_user(self.super_django_user):
|
||||
data = self.get(inv_src_url2, expect=200)
|
||||
data.update({
|
||||
'source': inventory_source.source,
|
||||
'credential': inventory_source.credential.pk,
|
||||
})
|
||||
response = self.put(inv_src_url2, data, expect=400)
|
||||
self.assertTrue('source' in response, response)
|
||||
|
||||
def test_put_inventory_source_detail_with_regions(self):
|
||||
creds_url = reverse('api:credential_list')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user