# -*- coding: utf-8 -*-"""This module implements the AWS CloudFormation resource tags handling logics.Due to the historical reason, the AWS CloudFormation resource tagstype definition is not consistent, we have to add more logic to handle bothold tag type and new tag type."""importtypingasTimportattrfrom.constantimportAttrMetaifT.TYPE_CHECKING:# pragma: no coverfrom.modelimportResourcedefget_tags_attribute_property_data(res_class:T.Type["Resource"])->dict:returnattr.fields_dict(res_class)[AttrMeta.TAGS].metadata[AttrMeta.DATA]defget_tag_type_hash_key(res_class:T.Type["Resource"])->str:data=get_tags_attribute_property_data(res_class)type=data.get("Type")item_type=data.get("ItemType")primitive_type=data.get("PrimitiveType")primitive_item_type=data.get("PrimitiveItemType")returnf"{type}-{item_type}-{primitive_type}-{primitive_item_type}"defget_tags_if_list_tag(res:"Resource")->T.Dict[str,str]:ifres.p_TagsisNone:# pragma: no coverreturndict()else:dct=dict()fortaginres.p_Tags:data=tag.serialize()dct[data["Key"]]=data["Value"]returndctdefput_tags_if_list_tag(res:"Resource",tags:T.Dict[str,str]):iflen(tags)==0:# pragma: no coverres.p_Tags=Noneelse:converter=attr.fields_dict(res.__class__)[AttrMeta.TAGS].converter# special handlingifres.AWS_OBJECT_TYPE=="AWS::AutoScaling::AutoScalingGroup":res.p_Tags=converter([{"rp_Key":key,"rp_Value":value,"rp_PropagateAtLaunch":True}forkey,valueintags.items()])returntry:data=[{"p_Key":key,"p_Value":value}forkey,valueintags.items()]res.p_Tags=converter(data)exceptTypeError:data=[{"rp_Key":key,"rp_Value":value}forkey,valueintags.items()]converter=attr.fields_dict(res.__class__)[AttrMeta.TAGS].converterres.p_Tags=converter(data)defget_tags_if_list_json(res:"Resource")->T.Dict[str,str]:ifres.p_TagsisNone:# pragma: no coverreturndict()else:return{dct["Key"]:dct["Value"]fordctinres.p_Tags}defput_tags_if_list_json(res:"Resource",tags:T.Dict[str,str]):iflen(tags)==0:# pragma: no coverres.p_Tags=Noneelse:res.p_Tags=[{"Key":key,"Value":value}forkey,valueintags.items()]defget_tags_if_map(res:"Resource")->T.Dict[str,str]:ifres.p_TagsisNone:# pragma: no coverreturndict()else:returnres.p_Tags.copy()defput_tags_if_map(res:"Resource",tags:T.Dict[str,str]):iflen(tags)==0:# pragma: no coverres.p_Tags=Noneelse:res.p_Tags=tags
[docs]defget_tags_if_tags(res:"Resource")->T.Dict[str,str]:""" The aws cft definition is wrong, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudwatch-insightrule-tags.html """returndict()
[docs]defput_tags_if_tags(res:"Resource",tags:T.Dict[str,str]):""" The aws cft definition is wrong, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudwatch-insightrule-tags.html """return
[docs]defupdate_tags(res:"Resource",tags:T.Dict[str,str],mode_skip:bool=False,mode_overwrite:bool=False,mode_raise:bool=False,)->T.Tuple[T.Dict[str,str],T.Dict[str,str]]:""" Update CloudFormation resource tags. :param res: the :class:`~cottonformation.core.model.Resource` object :param tags: key value tags in python dictionary :param mode_skip: if the key already exists, then skip it :param mode_overwrite: if the key already exists, then overwrite it with new value :param mode_raise: if the key already exists, then raise error :return: the before and after tags in python dictionary. """flag_sum=sum([mode_skip,mode_overwrite,mode_raise])ifflag_sum==0:mode_raise=Trueelifflag_sum>1:raiseValueError("only one of the 'mode_skip', 'mode_overwrite', 'mode_raise' ""can be True!")existing_tags=get_tags(res)iflen(tags)==0:returnexisting_tags,existing_tags.copy()new_tags=existing_tags.copy()ifmode_skip:fork,vintags.items():new_tags.setdefault(k,v)elifmode_overwrite:new_tags.update(tags)elifmode_raise:fork,vintags.items():ifknotinnew_tags:new_tags[k]=velse:raiseKeyError(f"{k!r} already exists in Tags! "f"Maybe you want to set on the ``mode_overwrite = True``.")put_tags(res,new_tags)returnexisting_tags,new_tags