mirror of
https://github.com/ansible/awx.git
synced 2026-02-20 12:40:06 -03:30
Blocks creation of Hosts, Groups, and IS for Smart Inventories
* Updated View unit tests * Refactored Validators * Validator Fix for Blocking
This commit is contained in:
@@ -1289,6 +1289,11 @@ class HostSerializer(BaseSerializerWithVariables):
|
|||||||
host, port = self._get_host_port_from_name(name)
|
host, port = self._get_host_port_from_name(name)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def validate_inventory(self, value):
|
||||||
|
if value.kind == 'smart':
|
||||||
|
raise serializers.ValidationError({"detail": _("Cannot create Host for Smart Inventory")})
|
||||||
|
return value
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
name = force_text(attrs.get('name', self.instance and self.instance.name or ''))
|
name = force_text(attrs.get('name', self.instance and self.instance.name or ''))
|
||||||
host, port = self._get_host_port_from_name(name)
|
host, port = self._get_host_port_from_name(name)
|
||||||
@@ -1407,6 +1412,11 @@ class GroupSerializer(BaseSerializerWithVariables):
|
|||||||
raise serializers.ValidationError(_('Invalid group name.'))
|
raise serializers.ValidationError(_('Invalid group name.'))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def validate_inventory(self, value):
|
||||||
|
if value.kind == 'smart':
|
||||||
|
raise serializers.ValidationError({"detail": _("Cannot create Group for Smart Inventory")})
|
||||||
|
return value
|
||||||
|
|
||||||
def to_representation(self, obj):
|
def to_representation(self, obj):
|
||||||
ret = super(GroupSerializer, self).to_representation(obj)
|
ret = super(GroupSerializer, self).to_representation(obj)
|
||||||
if obj is not None and 'inventory' in ret and not obj.inventory:
|
if obj is not None and 'inventory' in ret and not obj.inventory:
|
||||||
@@ -1660,6 +1670,11 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
|
|||||||
raise serializers.ValidationError(_("Setting not compatible with existing schedules."))
|
raise serializers.ValidationError(_("Setting not compatible with existing schedules."))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def validate_inventory(self, value):
|
||||||
|
if value.kind == 'smart':
|
||||||
|
raise serializers.ValidationError({"detail": _("Cannot create Inventory Source for Smart Inventory")})
|
||||||
|
return value
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
def get_field_from_model_or_attrs(fd):
|
def get_field_from_model_or_attrs(fd):
|
||||||
return attrs.get(fd, self.instance and getattr(self.instance, fd) or None)
|
return attrs.get(fd, self.instance and getattr(self.instance, fd) or None)
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ inventory sources:
|
|||||||
* `project_update`: ID of the project update job that was started if this inventory source is an SCM source.
|
* `project_update`: ID of the project update job that was started if this inventory source is an SCM source.
|
||||||
(interger, read-only, optional)
|
(interger, read-only, optional)
|
||||||
|
|
||||||
> *Note:* All manual inventory sources (source='') will be ignored by the update_inventory_sources endpoint.
|
Note: All manual inventory sources (source=' ') will be ignored by the update_inventory_sources endpoint. This endpoint will not update inventory sources for Smart Inventories.
|
||||||
|
|
||||||
|
|
||||||
Response code from this action will be:
|
Response code from this action will be:
|
||||||
|
|
||||||
|
|||||||
@@ -2480,6 +2480,8 @@ class InventoryInventorySourcesUpdate(RetrieveAPIView):
|
|||||||
|
|
||||||
def retrieve(self, request, *args, **kwargs):
|
def retrieve(self, request, *args, **kwargs):
|
||||||
inventory = self.get_object()
|
inventory = self.get_object()
|
||||||
|
if inventory.kind =='smart':
|
||||||
|
return Response(dict(error=_("Smart Inventories cannot host dynamic inventory sources.")), status=status.HTTP_400_BAD_REQUEST)
|
||||||
update_data = []
|
update_data = []
|
||||||
for inventory_source in inventory.inventory_sources.exclude(source=''):
|
for inventory_source in inventory.inventory_sources.exclude(source=''):
|
||||||
details = {'inventory_source': inventory_source.pk,
|
details = {'inventory_source': inventory_source.pk,
|
||||||
@@ -2492,6 +2494,8 @@ class InventoryInventorySourcesUpdate(RetrieveAPIView):
|
|||||||
update_data = []
|
update_data = []
|
||||||
successes = 0
|
successes = 0
|
||||||
failures = 0
|
failures = 0
|
||||||
|
if inventory.kind =='smart':
|
||||||
|
return Response(dict(error=_("Action cannot be completed with Smart Inventory.")), status=status.HTTP_400_BAD_REQUEST)
|
||||||
for inventory_source in inventory.inventory_sources.exclude(source=''):
|
for inventory_source in inventory.inventory_sources.exclude(source=''):
|
||||||
details = {'inventory_source': inventory_source.pk, 'status': None}
|
details = {'inventory_source': inventory_source.pk, 'status': None}
|
||||||
can_update = inventory_source.can_update
|
can_update = inventory_source.can_update
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ from django.core.exceptions import ValidationError
|
|||||||
|
|
||||||
from awx.api.versioning import reverse
|
from awx.api.versioning import reverse
|
||||||
|
|
||||||
from awx.main.models import InventorySource
|
from awx.main.models import InventorySource, Inventory
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -175,6 +177,54 @@ def test_delete_inventory_group(delete, group, alice, role_field, expected_statu
|
|||||||
delete(reverse('api:group_detail', kwargs={'pk': group.id}), alice, expect=expected_status_code)
|
delete(reverse('api:group_detail', kwargs={'pk': group.id}), alice, expect=expected_status_code)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_create_inventory_smarthost(post, get, inventory, admin_user, organization):
|
||||||
|
data = { 'name': 'Host 1', 'description': 'Test Host'}
|
||||||
|
smart_inventory = Inventory(name='smart',
|
||||||
|
kind='smart',
|
||||||
|
organization=organization,
|
||||||
|
host_filter='inventory_sources__source=ec2')
|
||||||
|
smart_inventory.save()
|
||||||
|
post(reverse('api:inventory_hosts_list', kwargs={'pk': smart_inventory.id}), data, admin_user)
|
||||||
|
resp = get(reverse('api:inventory_hosts_list', kwargs={'pk': smart_inventory.id}), admin_user)
|
||||||
|
jdata = json.loads(resp.content)
|
||||||
|
|
||||||
|
assert getattr(smart_inventory, 'kind') == 'smart'
|
||||||
|
assert jdata['count'] == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_create_inventory_smartgroup(post, get, inventory, admin_user, organization):
|
||||||
|
data = { 'name': 'Group 1', 'description': 'Test Group'}
|
||||||
|
smart_inventory = Inventory(name='smart',
|
||||||
|
kind='smart',
|
||||||
|
organization=organization,
|
||||||
|
host_filter='inventory_sources__source=ec2')
|
||||||
|
smart_inventory.save()
|
||||||
|
post(reverse('api:inventory_groups_list', kwargs={'pk': smart_inventory.id}), data, admin_user)
|
||||||
|
resp = get(reverse('api:inventory_groups_list', kwargs={'pk': smart_inventory.id}), admin_user)
|
||||||
|
jdata = json.loads(resp.content)
|
||||||
|
|
||||||
|
assert getattr(smart_inventory, 'kind') == 'smart'
|
||||||
|
assert jdata['count'] == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_create_inventory_smart_inventory_sources(post, get, inventory, admin_user, organization):
|
||||||
|
data = { 'name': 'Inventory Source 1', 'description': 'Test Inventory Source'}
|
||||||
|
smart_inventory = Inventory(name='smart',
|
||||||
|
kind='smart',
|
||||||
|
organization=organization,
|
||||||
|
host_filter='inventory_sources__source=ec2')
|
||||||
|
smart_inventory.save()
|
||||||
|
post(reverse('api:inventory_inventory_sources_list', kwargs={'pk': smart_inventory.id}), data, admin_user)
|
||||||
|
resp = get(reverse('api:inventory_inventory_sources_list', kwargs={'pk': smart_inventory.id}), admin_user)
|
||||||
|
jdata = json.loads(resp.content)
|
||||||
|
|
||||||
|
assert getattr(smart_inventory, 'kind') == 'smart'
|
||||||
|
assert jdata['count'] == 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("role_field,expected_status_code", [
|
@pytest.mark.parametrize("role_field,expected_status_code", [
|
||||||
(None, 403),
|
(None, 403),
|
||||||
('admin_role', 201),
|
('admin_role', 201),
|
||||||
|
|||||||
@@ -116,8 +116,8 @@ class TestInventoryInventorySourcesUpdate:
|
|||||||
def exclude(self, **kwargs):
|
def exclude(self, **kwargs):
|
||||||
return self.all()
|
return self.all()
|
||||||
|
|
||||||
Inventory = namedtuple('Inventory', ['inventory_sources'])
|
Inventory = namedtuple('Inventory', ['inventory_sources', 'kind'])
|
||||||
obj = Inventory(inventory_sources=InventorySources())
|
obj = Inventory(inventory_sources=InventorySources(), kind='')
|
||||||
|
|
||||||
mock_request = mocker.MagicMock()
|
mock_request = mocker.MagicMock()
|
||||||
mock_request.user.can_access.return_value = can_access
|
mock_request.user.can_access.return_value = can_access
|
||||||
|
|||||||
Reference in New Issue
Block a user