From 2b49cf547b1627f21e4b089c86b6e75ecf1bfb5d Mon Sep 17 00:00:00 2001 From: Talavrinova Sofya Date: Wed, 17 Nov 2021 17:14:56 +0300 Subject: [PATCH 1/3] ADCM-1974 Add date, time and log level in adcm_debug --- python/adcm/settings.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/adcm/settings.py b/python/adcm/settings.py index bb483a8b21..5690b8132d 100644 --- a/python/adcm/settings.py +++ b/python/adcm/settings.py @@ -230,11 +230,16 @@ 'format': '{asctime} {levelname} {module} {message}', 'style': '{', }, + 'django_debug': { + 'format': '{asctime} {levelname} {module} {message}', + 'style': '{', + }, }, 'handlers': { 'file': { 'level': 'DEBUG', 'filters': ['require_debug_false'], + 'formatter': 'django_debug', 'class': 'logging.FileHandler', 'filename': os.path.join(BASE_DIR, 'data/log/adcm_debug.log'), }, From bb483fdd32a8d33634a67be89b4e541b3198fae9 Mon Sep 17 00:00:00 2001 From: Talavrinova Sofya Date: Wed, 17 Nov 2021 17:40:50 +0300 Subject: [PATCH 2/3] ADCM-1974 Delete extra formatter --- python/adcm/settings.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/python/adcm/settings.py b/python/adcm/settings.py index 5690b8132d..30a09d3725 100644 --- a/python/adcm/settings.py +++ b/python/adcm/settings.py @@ -230,16 +230,12 @@ 'format': '{asctime} {levelname} {module} {message}', 'style': '{', }, - 'django_debug': { - 'format': '{asctime} {levelname} {module} {message}', - 'style': '{', - }, }, 'handlers': { 'file': { 'level': 'DEBUG', 'filters': ['require_debug_false'], - 'formatter': 'django_debug', + 'formatter': 'adwp', 'class': 'logging.FileHandler', 'filename': os.path.join(BASE_DIR, 'data/log/adcm_debug.log'), }, From 409e114e428ce5a43e69cde7de2d43fb58e255bd Mon Sep 17 00:00:00 2001 From: Alexandr Alferov Date: Thu, 18 Nov 2021 15:52:10 +0300 Subject: [PATCH 3/3] ADCM-2353 Added ignoring of check of read_only fields of type list and map for config and group config --- python/api/group_config/serializers.py | 29 +++++++++++++++++++---- python/cm/adcm_config.py | 8 +++++++ python/cm/models.py | 6 ++++- python/cm/unit_tests/test_config_group.py | 4 ++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/python/api/group_config/serializers.py b/python/api/group_config/serializers.py index 92ed1efd38..d216ab3fba 100644 --- a/python/api/group_config/serializers.py +++ b/python/api/group_config/serializers.py @@ -25,6 +25,7 @@ MultiHyperlinkedIdentityField, UIConfigField, ) +from cm.adcm_config import config_is_ro from cm.api import update_obj_config from cm.errors import AdcmEx from cm.models import GroupConfig, Host, ObjectConfig, ConfigLog @@ -249,19 +250,37 @@ class Meta: extra_kwargs = {'config': {'required': True}} def validate(self, attrs): - def check_value_unselected_field(cc, nc, gk): + def check_value_unselected_field(cc, nc, gk, spec, obj): + """ + Check value unselected field + + :param cc: Current config + :param nc: New config + :param gk: group_keys from attr + :param spec: Config specification + :param obj: Parent object (Cluster, Service, Component Provider or Host) + """ for k, v in gk.items(): if isinstance(v, Mapping): - check_value_unselected_field(cc[k], nc[k], gk[k]) + check_value_unselected_field(cc[k], nc[k], gk[k], spec[k]['fields'], obj) else: - if not v and k in cc and k in nc and cc[k] != nc[k]: - raise AdcmEx('GROUP_CONFIG_CHANGE_UNSELECTED_FIELD') + is_read_only_list_or_map = ( + config_is_ro(obj, k, spec[k]['limits']) + and spec[k]['type'] in ['list', 'map'] + ) + if not is_read_only_list_or_map: + if not v and k in cc and k in nc and cc[k] != nc[k]: + raise AdcmEx('GROUP_CONFIG_CHANGE_UNSELECTED_FIELD') obj_ref = self.context['obj_ref'] + config_spec = obj_ref.object.get_config_spec() + parent_obj = obj_ref.object.object current_config = ConfigLog.objects.get(id=obj_ref.current).config new_config = attrs.get('config') group_keys = attrs.get('attr', {}).get('group_keys', {}) - check_value_unselected_field(current_config, new_config, group_keys) + check_value_unselected_field( + current_config, new_config, group_keys, config_spec, parent_obj + ) return super().validate(attrs) @atomic diff --git a/python/cm/adcm_config.py b/python/cm/adcm_config.py index 89cecf2706..535a58ed31 100644 --- a/python/cm/adcm_config.py +++ b/python/cm/adcm_config.py @@ -487,6 +487,14 @@ def check_read_only(obj, spec, conf, old_conf): flat_old_conf = to_flat_dict(old_conf, spec) for s in spec: if config_is_ro(obj, s, spec[s].limits) and s in flat_conf: + + if spec[s].type == 'list': + if isinstance(flat_conf[s], list) and not flat_conf[s]: + continue + if spec[s].type == 'map': + if isinstance(flat_conf[s], dict) and not flat_conf[s]: + continue + if flat_conf[s] != flat_old_conf[s]: msg = 'config key {} of {} is read only' err('CONFIG_VALUE_ERROR', msg.format(s, proto_ref(obj.prototype))) diff --git a/python/cm/models.py b/python/cm/models.py index 770bc5e313..743f327e0f 100644 --- a/python/cm/models.py +++ b/python/cm/models.py @@ -693,7 +693,11 @@ def get_config_spec(self): group_customization = field.group_customization if group_customization is None: group_customization = self.object.prototype.config_group_customization - field_spec = {'type': field.type, 'group_customization': group_customization} + field_spec = { + 'type': field.type, + 'group_customization': group_customization, + 'limits': field.limits, + } if field.subname == '': if field.type == 'group': field_spec.update({'fields': {}}) diff --git a/python/cm/unit_tests/test_config_group.py b/python/cm/unit_tests/test_config_group.py index d21e6ed26c..f09cde67fa 100644 --- a/python/cm/unit_tests/test_config_group.py +++ b/python/cm/unit_tests/test_config_group.py @@ -95,20 +95,24 @@ def test_get_config_spec(self): 'group': { 'type': 'group', 'group_customization': False, + 'limits': {}, 'fields': { 'string': { 'type': 'string', 'group_customization': False, + 'limits': {}, } }, }, 'activatable_group': { 'type': 'group', 'group_customization': False, + 'limits': {}, 'fields': { 'integer': { 'type': 'integer', 'group_customization': False, + 'limits': {}, } }, },