mirror of
https://github.com/ansible/awx.git
synced 2026-01-19 05:31:22 -03:30
More updates for InventorySource changes
This commit is contained in:
parent
c905d98b9e
commit
7458788562
@ -1238,7 +1238,7 @@ class HostSerializer(BaseSerializerWithVariables):
|
||||
|
||||
|
||||
class GroupSerializer(BaseSerializerWithVariables):
|
||||
show_capabilities = ['start', 'copy', 'schedule', 'edit', 'delete']
|
||||
show_capabilities = ['copy', 'edit', 'delete']
|
||||
|
||||
class Meta:
|
||||
model = Group
|
||||
@ -1427,13 +1427,12 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
|
||||
status = serializers.ChoiceField(choices=InventorySource.INVENTORY_SOURCE_STATUS_CHOICES, read_only=True)
|
||||
last_update_failed = serializers.BooleanField(read_only=True)
|
||||
last_updated = serializers.DateTimeField(read_only=True)
|
||||
show_capabilities = ['start', 'schedule', 'edit', 'delete']
|
||||
|
||||
class Meta:
|
||||
model = InventorySource
|
||||
fields = ('*', 'inventory', 'update_on_launch',
|
||||
'update_cache_timeout') + \
|
||||
fields = ('*', 'name', 'inventory', 'update_on_launch', 'update_cache_timeout') + \
|
||||
('last_update_failed', 'last_updated') # Backwards compatibility.
|
||||
read_only_fields = ('*', 'name', 'inventory')
|
||||
|
||||
def get_related(self, obj):
|
||||
res = super(InventorySourceSerializer, self).get_related(obj)
|
||||
@ -1450,8 +1449,6 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
|
||||
))
|
||||
if obj.inventory:
|
||||
res['inventory'] = self.reverse('api:inventory_detail', kwargs={'pk': obj.inventory.pk})
|
||||
if obj.group:
|
||||
res['group'] = self.reverse('api:group_detail', kwargs={'pk': obj.group.pk})
|
||||
# Backwards compatibility.
|
||||
if obj.current_update:
|
||||
res['current_update'] = self.reverse('api:inventory_update_detail',
|
||||
@ -1467,8 +1464,6 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
|
||||
return ret
|
||||
if 'inventory' in ret and not obj.inventory:
|
||||
ret['inventory'] = None
|
||||
if 'group' in ret and not obj.group:
|
||||
ret['group'] = None
|
||||
return ret
|
||||
|
||||
|
||||
|
||||
@ -2154,7 +2154,7 @@ class InventoryTreeView(RetrieveAPIView):
|
||||
root_group_pks = inventory.root_groups.order_by('name').values_list('pk', flat=True)
|
||||
groups_qs = inventory.groups
|
||||
groups_qs = groups_qs.select_related('inventory')
|
||||
groups_qs = groups_qs.prefetch_related('inventory_source')
|
||||
groups_qs = groups_qs.prefetch_related('inventory_sources')
|
||||
all_group_data = GroupSerializer(groups_qs, many=True).data
|
||||
all_group_data_map = dict((x['id'], x) for x in all_group_data)
|
||||
tree_data = [all_group_data_map[x] for x in root_group_pks]
|
||||
@ -2164,22 +2164,17 @@ class InventoryTreeView(RetrieveAPIView):
|
||||
return Response(tree_data)
|
||||
|
||||
|
||||
class InventoryInventorySourcesList(SubListAPIView):
|
||||
class InventoryInventorySourcesList(SubListCreateAPIView):
|
||||
|
||||
view_name = _('Inventory Source List')
|
||||
|
||||
model = InventorySource
|
||||
serializer_class = InventorySourceSerializer
|
||||
parent_model = Inventory
|
||||
relationship = None # Not defined since using get_queryset().
|
||||
view_name = _('Inventory Source List')
|
||||
relationship = 'inventory_sources'
|
||||
parent_key = 'inventory'
|
||||
new_in_14 = True
|
||||
|
||||
def get_queryset(self):
|
||||
parent = self.get_parent_object()
|
||||
self.check_parent_access(parent)
|
||||
qs = self.request.user.get_queryset(self.model)
|
||||
return qs.filter(Q(inventory__pk=parent.pk) |
|
||||
Q(group__inventory__pk=parent.pk))
|
||||
|
||||
|
||||
class InventorySourceList(ListAPIView):
|
||||
|
||||
|
||||
@ -670,7 +670,7 @@ class GroupAccess(BaseAccess):
|
||||
def get_queryset(self):
|
||||
qs = Group.objects.filter(inventory__in=Inventory.accessible_objects(self.user, 'read_role'))
|
||||
qs = qs.select_related('created_by', 'modified_by', 'inventory')
|
||||
return qs.prefetch_related('parents', 'children', 'inventory_source').all()
|
||||
return qs.prefetch_related('parents', 'children').all()
|
||||
|
||||
def can_read(self, obj):
|
||||
return obj and self.user in obj.inventory.read_role
|
||||
@ -720,11 +720,6 @@ class GroupAccess(BaseAccess):
|
||||
"active_jobs": active_jobs})
|
||||
return True
|
||||
|
||||
def can_start(self, obj, validate_license=True):
|
||||
if obj and obj.inventory:
|
||||
return self.user.can_access(Inventory, 'start', obj.inventory, validate_license=validate_license)
|
||||
return False
|
||||
|
||||
|
||||
class InventorySourceAccess(BaseAccess):
|
||||
'''
|
||||
@ -736,10 +731,9 @@ class InventorySourceAccess(BaseAccess):
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.model.objects.all()
|
||||
qs = qs.select_related('created_by', 'modified_by', 'group', 'inventory')
|
||||
qs = qs.select_related('created_by', 'modified_by', 'inventory')
|
||||
inventory_ids = self.user.get_queryset(Inventory)
|
||||
return qs.filter(Q(inventory_id__in=inventory_ids) |
|
||||
Q(group__inventory_id__in=inventory_ids))
|
||||
return qs.filter(Q(inventory_id__in=inventory_ids))
|
||||
|
||||
def can_read(self, obj):
|
||||
if obj and obj.inventory:
|
||||
@ -748,8 +742,10 @@ class InventorySourceAccess(BaseAccess):
|
||||
return False
|
||||
|
||||
def can_add(self, data):
|
||||
# Automatically created from group or management command.
|
||||
return False
|
||||
if not data or 'inventory' not in data:
|
||||
return False
|
||||
# Checks for admin or change permission on inventory.
|
||||
return self.check_related('inventory', Inventory, data)
|
||||
|
||||
def can_change(self, obj, data):
|
||||
# Checks for admin or change permission on group.
|
||||
@ -780,8 +776,7 @@ class InventoryUpdateAccess(BaseAccess):
|
||||
|
||||
def get_queryset(self):
|
||||
qs = InventoryUpdate.objects.distinct()
|
||||
qs = qs.select_related('created_by', 'modified_by', 'inventory_source__group',
|
||||
'inventory_source__inventory')
|
||||
qs = qs.select_related('created_by', 'modified_by', 'inventory_source__inventory')
|
||||
inventory_sources_qs = self.user.get_queryset(InventorySource)
|
||||
return qs.filter(inventory_source__in=inventory_sources_qs)
|
||||
|
||||
|
||||
@ -24,6 +24,11 @@ class Migration(migrations.Migration):
|
||||
model_name='inventorysource',
|
||||
name='group',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='inventorysource',
|
||||
name='inventory',
|
||||
field=models.ForeignKey(related_name='inventory_sources', default=None, to='main.Inventory', null=True),
|
||||
),
|
||||
|
||||
# Facts Latest
|
||||
migrations.CreateModel(
|
||||
|
||||
@ -1060,7 +1060,6 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions):
|
||||
related_name='inventory_sources',
|
||||
null=True,
|
||||
default=None,
|
||||
editable=False,
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
update_on_launch = models.BooleanField(
|
||||
@ -1169,16 +1168,6 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions):
|
||||
success=list(success_notification_templates),
|
||||
any=list(any_notification_templates))
|
||||
|
||||
def clean_source(self):
|
||||
source = self.source
|
||||
if source and self.group:
|
||||
qs = self.group.inventory_sources.filter(source__in=CLOUD_INVENTORY_SOURCES)
|
||||
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, JobNotificationMixin):
|
||||
'''
|
||||
@ -1213,8 +1202,6 @@ class InventoryUpdate(UnifiedJob, InventorySourceOptions, JobNotificationMixin):
|
||||
|
||||
def websocket_emit_data(self):
|
||||
websocket_data = super(InventoryUpdate, self).websocket_emit_data()
|
||||
if self.inventory_source.group is not None:
|
||||
websocket_data.update(dict(group_id=self.inventory_source.group.id))
|
||||
return websocket_data
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
||||
@ -97,6 +97,21 @@ def test_edit_inventory_group(put, group, alice, role_field, expected_status_cod
|
||||
put(reverse('api:group_detail', kwargs={'pk': group.id}), data, alice, expect=expected_status_code)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("role_field,expected_status_code", [
|
||||
(None, 403),
|
||||
('admin_role', 201),
|
||||
('update_role', 403),
|
||||
('adhoc_role', 403),
|
||||
('use_role', 403)
|
||||
])
|
||||
@pytest.mark.django_db
|
||||
def test_create_inventory_inventory_source(post, inventory, alice, role_field, expected_status_code):
|
||||
data = { 'source': 'ec2', 'name': 'ec2-inv-source'}
|
||||
if role_field:
|
||||
getattr(inventory, role_field).members.add(alice)
|
||||
post(reverse('api:inventory_inventory_sources_list', kwargs={'pk': inventory.id}), data, alice, expect=expected_status_code)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("role_field,expected_status_code", [
|
||||
(None, 403),
|
||||
('admin_role', 204),
|
||||
|
||||
@ -341,28 +341,6 @@ def test_manual_projects_no_update(project, get, admin_user):
|
||||
assert not response.data['summary_fields']['user_capabilities']['schedule']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_group_update_capabilities_possible(group, inventory_source, admin_user):
|
||||
group.inventory_source = inventory_source
|
||||
group.save()
|
||||
|
||||
capabilities = get_user_capabilities(admin_user, group.inventory, method_list=['start'])
|
||||
assert capabilities['start']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_group_update_capabilities_impossible(group, inventory_source, admin_user):
|
||||
"Manual groups can not be updated or scheduled"
|
||||
inventory_source.source = ""
|
||||
inventory_source.save()
|
||||
group.inventory_source = inventory_source
|
||||
group.save()
|
||||
|
||||
capabilities = get_user_capabilities(admin_user, group, method_list=['edit', 'start', 'schedule'])
|
||||
assert not capabilities['start']
|
||||
assert not capabilities['schedule']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_license_check_not_called(mocker, job_template, project, org_admin, get):
|
||||
job_template.project = project
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user