Skip to content

Commit 6638a0f

Browse files
committed
Ignore role content types not known to system in sync
1 parent 20dc761 commit 6638a0f

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

ansible_base/resource_registry/shared_types.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from rest_framework import serializers
2+
from rest_framework.exceptions import ValidationError
23

34
from ansible_base.rbac.models import DABContentType, DABPermission
45
from ansible_base.resource_registry.utils.resource_type_serializers import AnsibleResourceForeignKeyField, SharedResourceTypeSerializer
@@ -104,3 +105,18 @@ class RoleDefinitionType(SharedResourceTypeSerializer):
104105
default=None,
105106
)
106107
permissions = LenientPermissionSlugListField()
108+
109+
def is_valid(self, raise_exception=False):
110+
if not raise_exception:
111+
return super().is_valid(raise_exception=False)
112+
113+
try:
114+
return super().is_valid(raise_exception=True)
115+
except ValidationError as e:
116+
if hasattr(e, 'detail') and 'content_type' in e.detail:
117+
fd_detail = e.detail['content_type'][0]
118+
if fd_detail.code == "does_not_exist":
119+
from ansible_base.resource_registry.tasks.sync import SkipResource
120+
121+
raise SkipResource(*e.args)
122+
raise

ansible_base/resource_registry/tasks/sync.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ class ResourceDeletionError(Error):
3636
class ResourceSyncHTTPError(HTTPError):
3737
"""Custom catchall error"""
3838

39+
class SkipResource(ValidationError):
40+
"""To raise by serializers if the item should be skipped"""
41+
default_detail = "The specified content_type slug was not found."
42+
default_code = "content_type_does_not_exist"
43+
3944

4045
class SyncStatus(str, Enum):
4146
CREATED = "created"
@@ -226,6 +231,8 @@ def _attempt_create_resource(
226231
ansible_id=manifest_item.ansible_id,
227232
service_id=resource_service_id,
228233
)
234+
except SkipResource:
235+
return SyncResult(SyncStatus.NOOP, manifest_item)
229236
except IntegrityError:
230237
# This typically means that there was a duplicate key error. To mitigate this
231238
# we will attempt to hanlde the conflicting resource and perform the operation

test_app/tests/resource_registry/test_resource_sync.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
from ansible_base.lib.testing.util import StaticResourceAPIClient
99
from ansible_base.lib.utils.response import get_relative_url
10-
from ansible_base.resource_registry.models import Resource
10+
from ansible_base.resource_registry.models import Resource, ResourceType
1111
from ansible_base.resource_registry.models.service_identifier import service_id
12-
from ansible_base.resource_registry.tasks.sync import ResourceSyncHTTPError, SyncExecutor
12+
from ansible_base.resource_registry.tasks.sync import ResourceSyncHTTPError, SyncExecutor, _attempt_create_resource, ManifestItem
13+
from ansible_base.rbac import permission_registry
14+
from ansible_base.rbac.models import RoleDefinition
1315

1416

1517
@pytest.fixture(scope="function")
@@ -178,6 +180,36 @@ def test_resource_sync_update_conflict(static_api_client, stdout, resource_to_up
178180
assert Resource.objects.get(ansible_id=new_id).name == "was_renamed"
179181

180182

183+
@pytest.mark.django_db
184+
def test_resource_sync_create_local_role_definition(static_api_client, stdout, resource_to_update):
185+
item_data = {"name": "Organization Inventory Role", "content_type": "shared.organization", "managed": True, "permissions": []}
186+
manifest_item = ManifestItem(str(uuid4()), str(uuid4()), item_data)
187+
result = _attempt_create_resource(
188+
manifest_item=manifest_item,
189+
resource_data=item_data,
190+
resource_type=ResourceType.objects.get(name='shared.roledefinition'),
191+
resource_service_id=str(uuid4()),
192+
api_client=static_api_client # unused
193+
)
194+
assert result.status == 'created'
195+
196+
197+
@pytest.mark.django_db
198+
def test_resource_sync_create_non_local_role_definition(static_api_client, stdout, resource_to_update):
199+
item_data = {"name": "Remote Role", "content_type": "shared.foo_type", "managed": True, "permissions": []}
200+
manifest_item = ManifestItem(str(uuid4()), str(uuid4()), item_data)
201+
result = _attempt_create_resource(
202+
manifest_item=manifest_item,
203+
resource_data=item_data,
204+
resource_type=ResourceType.objects.get(name='shared.roledefinition'),
205+
resource_service_id=str(uuid4()),
206+
api_client=static_api_client # unused
207+
)
208+
assert result.status == 'noop'
209+
210+
assert not RoleDefinition.objects.filter(name="Remote Role").exists()
211+
212+
181213
@pytest.mark.django_db
182214
def test_resource_sync_create_conflict(static_api_client, stdout, resource_to_update):
183215
# Update the ansible ID on the local resources so that it causes a conflict to happen.

0 commit comments

Comments
 (0)