import functools, logging, operator from enum import Enum from typing import Dict, List, Tuple, Union from common.orm.Database import Database from common.orm.HighLevel import get_or_create_object, update_or_create_object from common.orm.backend.Tools import key_to_str from common.orm.fields.EnumeratedField import EnumeratedField from common.orm.fields.ForeignKeyField import ForeignKeyField from common.orm.fields.IntegerField import IntegerField from common.orm.fields.PrimaryKeyField import PrimaryKeyField from common.orm.fields.StringField import StringField from common.orm.model.Model import Model from context.proto.context_pb2 import ConfigActionEnum from context.service.database.Tools import fast_hasher, grpc_to_enum, remove_dict_key LOGGER = logging.getLogger(__name__) class ORM_ConfigActionEnum(Enum): UNDEFINED = ConfigActionEnum.CONFIGACTION_UNDEFINED SET = ConfigActionEnum.CONFIGACTION_SET DELETE = ConfigActionEnum.CONFIGACTION_DELETE grpc_to_enum__config_action = functools.partial( grpc_to_enum, ConfigActionEnum, ORM_ConfigActionEnum) class ConfigModel(Model): # pylint: disable=abstract-method pk = PrimaryKeyField() def dump(self) -> List[Dict]: db_config_rule_pks = self.references(ConfigRuleModel) config_rules = [ConfigRuleModel(self.database, pk).dump(include_position=True) for pk,_ in db_config_rule_pks] config_rules = sorted(config_rules, key=operator.itemgetter('position')) return [remove_dict_key(config_rule, 'position') for config_rule in config_rules] class ConfigRuleModel(Model): # pylint: disable=abstract-method pk = PrimaryKeyField() config_fk = ForeignKeyField(ConfigModel) position = IntegerField(min_value=0, required=True) action = EnumeratedField(ORM_ConfigActionEnum, required=True) key = StringField(required=True, allow_empty=False) value = StringField(required=True, allow_empty=False) def dump(self, include_position=True) -> Dict: # pylint: disable=arguments-differ result = { 'action': self.action.value, 'resource_key': self.key, 'resource_value': self.value, } if include_position: result['position'] = self.position return result def set_config_rule( database : Database, db_config : ConfigModel, grpc_config_rule, position : int ) -> Tuple[ConfigRuleModel, bool]: str_rule_key_hash = fast_hasher(grpc_config_rule.resource_key) str_config_rule_key = key_to_str([db_config.pk, str_rule_key_hash], separator=':') result : Tuple[ConfigRuleModel, bool] = update_or_create_object(database, ConfigRuleModel, str_config_rule_key, { 'config_fk': db_config, 'position' : position, 'action' : grpc_to_enum__config_action(grpc_config_rule.action), 'key' : grpc_config_rule.resource_key, 'value' : grpc_config_rule.resource_value, }) db_config_rule, updated = result return db_config_rule, updated def set_config( database : Database, db_parent_pk : str, config_name : str, grpc_config_rules ) -> List[Tuple[Union[ConfigModel, ConfigRuleModel], bool]]: str_config_key = key_to_str([db_parent_pk, config_name], separator=':') result : Tuple[ConfigModel, bool] = get_or_create_object(database, ConfigModel, str_config_key) db_config, created = result db_objects = [(db_config, created)] for position,grpc_config_rule in enumerate(grpc_config_rules): result : Tuple[ConfigRuleModel, bool] = set_config_rule(database, db_config, grpc_config_rule, position) db_config_rule, updated = result db_objects.append((db_config_rule, updated)) return db_objects