More updates for InventorySource changes

This commit is contained in:
Wayne Witzel III 2017-04-07 12:25:11 -04:00
parent c905d98b9e
commit 7458788562
7 changed files with 37 additions and 67 deletions

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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(

View File

@ -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):

View File

@ -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),

View File

@ -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