|
1 | 1 | import os |
2 | 2 | import uuid |
3 | | -from contextlib import nullcontext |
| 3 | +from contextlib import contextmanager, nullcontext |
4 | 4 | from unittest import mock |
5 | 5 |
|
6 | 6 | import pytest |
7 | 7 | from crum import impersonate |
8 | 8 | from django.contrib.auth.models import AnonymousUser |
9 | 9 | from django.db import IntegrityError, connection |
10 | | -from django.test.utils import CaptureQueriesContext |
| 10 | +from django.test.utils import CaptureQueriesContext, override_settings |
11 | 11 | from rest_framework.exceptions import ValidationError |
12 | 12 |
|
13 | 13 | from ansible_base.resource_registry import apps |
| 14 | +from ansible_base.resource_registry.models import Resource |
14 | 15 | from ansible_base.resource_registry.signals.handlers import no_reverse_sync |
15 | 16 | from ansible_base.resource_registry.utils.sync_to_resource_server import sync_to_resource_server |
16 | 17 | from test_app.models import Organization |
@@ -246,3 +247,69 @@ def test_should_reverse_sync(self, settings, new_settings, should_sync): |
246 | 247 | setattr(settings, key, value) |
247 | 248 |
|
248 | 249 | assert apps._should_reverse_sync() == should_sync |
| 250 | + |
| 251 | + |
| 252 | +@pytest.mark.django_db |
| 253 | +class TestConflitingSyncSettings: |
| 254 | + CONFLICT_SETTINGS = dict( |
| 255 | + ALLOW_LOCAL_RESOURCE_MANAGEMENT=True, |
| 256 | + RESOURCE_SERVER_SYNC_ENABLED=True, |
| 257 | + RESOURCE_SERVER={'URL': 'https://foo.invalid', 'SECRET_KEY': 'abcdefghijklmnopqrstuvwxyz'}, |
| 258 | + ) |
| 259 | + |
| 260 | + @contextmanager |
| 261 | + def apply_settings(self): |
| 262 | + with override_settings(**self.CONFLICT_SETTINGS): |
| 263 | + apps.connect_resource_signals(None) |
| 264 | + yield |
| 265 | + apps.disconnect_resource_signals(None) |
| 266 | + apps.connect_resource_signals(None) |
| 267 | + |
| 268 | + def mark_external(self, obj): |
| 269 | + "Make object appears as if managed by another system" |
| 270 | + if hasattr(obj, '_skip_reverse_resource_sync'): |
| 271 | + delattr(obj, '_skip_reverse_resource_sync') |
| 272 | + res = Resource.get_resource_for_object(obj) |
| 273 | + res.service_id = uuid.uuid4() |
| 274 | + res.save() |
| 275 | + |
| 276 | + def test_block_org_save(self, organization): |
| 277 | + with self.apply_settings(): |
| 278 | + organization.save() # does not error |
| 279 | + self.mark_external(organization) |
| 280 | + with pytest.raises(ValidationError): |
| 281 | + organization.name += 'foo' |
| 282 | + organization.save() |
| 283 | + |
| 284 | + def test_block_org_deletion(self, organization): |
| 285 | + with self.apply_settings(): |
| 286 | + organization.save() # create resource entry |
| 287 | + self.mark_external(organization) |
| 288 | + with pytest.raises(ValidationError): |
| 289 | + organization.delete() |
| 290 | + |
| 291 | + def test_change_non_synced_field(self, admin_user): |
| 292 | + with self.apply_settings(): |
| 293 | + admin_user.save() # create resource entry |
| 294 | + self.mark_external(admin_user) |
| 295 | + assert admin_user.is_superuser is True |
| 296 | + admin_user.is_superuser = False |
| 297 | + admin_user.save() # does not error |
| 298 | + |
| 299 | + def test_change_user_synced_field(self, admin_user): |
| 300 | + with self.apply_settings(): |
| 301 | + admin_user.save() # create resource entry |
| 302 | + self.mark_external(admin_user) |
| 303 | + with pytest.raises(ValidationError): |
| 304 | + admin_user.username = 'some_other_username' |
| 305 | + admin_user.save() |
| 306 | + |
| 307 | + def test_create_shared_resource(self): |
| 308 | + with self.apply_settings(): |
| 309 | + with pytest.raises(ValidationError): |
| 310 | + Organization.objects.create(name='new org') |
| 311 | + |
| 312 | + def test_create_allowed_no_sync(self): |
| 313 | + with self.apply_settings(): |
| 314 | + with no_reverse_sync(): |
| 315 | + Organization.objects.create(name='new org') |
0 commit comments