From 69dc56c5a1cdde4a631a5af666968a221c2fa6ae Mon Sep 17 00:00:00 2001 From: Aaron Tan Date: Tue, 9 May 2017 13:54:37 -0400 Subject: [PATCH] Enable CTinT category-specific validation. --- awx/conf/__init__.py | 4 ++++ awx/conf/registry.py | 10 ++++++++++ awx/conf/serializers.py | 8 ++++++++ awx/conf/tests/unit/test_registry.py | 9 +++++++++ awx/main/conf.py | 24 +++++++++++++++++++++++- 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/awx/conf/__init__.py b/awx/conf/__init__.py index 8f00d64865..9371e22b2f 100644 --- a/awx/conf/__init__.py +++ b/awx/conf/__init__.py @@ -14,5 +14,9 @@ def register(setting, **kwargs): settings_registry.register(setting, **kwargs) +def register_validate(category, func): + settings_registry.register_validate(category, func) + + def autodiscover(): autodiscover_modules('conf', register_to=settings_registry) diff --git a/awx/conf/registry.py b/awx/conf/registry.py index faf210fbb0..936118e053 100644 --- a/awx/conf/registry.py +++ b/awx/conf/registry.py @@ -28,6 +28,7 @@ class SettingsRegistry(object): if settings is None: from django.conf import settings self._registry = OrderedDict() + self._validate_registry = {} self._dependent_settings = {} self.settings = settings @@ -56,6 +57,12 @@ class SettingsRegistry(object): for dependent_settings in self._dependent_settings.values(): dependent_settings.discard(setting) + def register_validate(self, category_slug, func): + self._validate_registry[category_slug] = func + + def unregister_validate(self, category_slug): + self._validate_registry.pop(category_slug, None) + def get_dependent_settings(self, setting): return self._dependent_settings.get(setting, set()) @@ -99,6 +106,9 @@ class SettingsRegistry(object): setting_names.append(setting) return setting_names + def get_registered_validate_func(self, category_slug): + return self._validate_registry.get(category_slug, None) + def is_setting_encrypted(self, setting): return bool(self._registry.get(setting, {}).get('encrypted', False)) diff --git a/awx/conf/serializers.py b/awx/conf/serializers.py index 4c2dd4748d..b6abe6d961 100644 --- a/awx/conf/serializers.py +++ b/awx/conf/serializers.py @@ -65,6 +65,14 @@ class SettingSingletonSerializer(serializers.Serializer): assert instance is None or not hasattr(instance, 'pk') super(SettingSingletonSerializer, self).__init__(instance, data, **kwargs) + def validate(self, attrs): + try: + category_slug = self.context['view'].kwargs.get('category_slug', 'all') + except (KeyError, AttributeError): + category_slug = '' + custom_validate = settings_registry.get_registered_validate_func(category_slug) + return custom_validate(self, attrs) if custom_validate else attrs + def get_fields(self): fields = super(SettingSingletonSerializer, self).get_fields() try: diff --git a/awx/conf/tests/unit/test_registry.py b/awx/conf/tests/unit/test_registry.py index e8fc5a477b..b996751f0f 100644 --- a/awx/conf/tests/unit/test_registry.py +++ b/awx/conf/tests/unit/test_registry.py @@ -309,3 +309,12 @@ def test_default_value_from_settings_with_custom_representation(reg): field = reg.get_setting_field('AWX_SOME_SETTING') assert field.default == 'default' + + +def test_validate_registry(reg): + validate_func = lambda x: None + reg.register_validate('FOO_BAR', validate_func) + assert reg.get_registered_validate_func('FOO_BAR') == validate_func + assert reg.get_registered_validate_func('NOT_EXIST') is None + reg.unregister_validate('FOO_BAR') + assert reg.get_registered_validate_func('FOO_BAR') is None diff --git a/awx/main/conf.py b/awx/main/conf.py index 7610a8fa0c..ae889c083a 100644 --- a/awx/main/conf.py +++ b/awx/main/conf.py @@ -6,8 +6,11 @@ import os # Django from django.utils.translation import ugettext_lazy as _ +# Django REST Framework +from rest_framework import serializers + # Tower -from awx.conf import fields, register +from awx.conf import fields, register, register_validate logger = logging.getLogger('awx.main.conf') @@ -347,3 +350,22 @@ register( category=_('Logging'), category_slug='logging', ) + + +def logging_validate(serializer, attrs): + if not serializer.instance: + return attrs + errors = [] + if attrs.get('LOG_AGGREGATOR_ENABLED', False): + if not serializer.instance.LOG_AGGREGATOR_HOST and not attrs.get('LOG_AGGREGATOR_HOST', None) or\ + serializer.instance.LOG_AGGREGATOR_HOST and not attrs.get('LOG_AGGREGATOR_HOST', True): + errors.append('Cannot enable log aggregator without providing host.') + if not serializer.instance.LOG_AGGREGATOR_TYPE and not attrs.get('LOG_AGGREGATOR_TYPE', None) or\ + serializer.instance.LOG_AGGREGATOR_TYPE and not attrs.get('LOG_AGGREGATOR_TYPE', True): + errors.append('Cannot enable log aggregator without providing type.') + if errors: + raise serializers.ValidationError(_('\n'.join(errors))) + return attrs + + +register_validate('logging', logging_validate)