3 O4\5@sLddlmZddlmZGdddeZGdddeZGdddeZd S) )SamResourceType) is_intrinsicsc@seZdZdZdZdZejjddddddd d d d d ddddddgej jddddddddddddd d!d"gej jd#giZ d$d%Z d&d'Z ed(d)Zd*d+Zd,d-Zd.S)/Globalsz Class to parse and process Globals section in SAM template. If a property is specified at Global section for say Function, then this class will add it to each resource of AWS::Serverless::Function type. zAWS::Serverless::HandlerZRuntimeZCodeUriZDeadLetterQueue DescriptionZ MemorySizeZTimeoutZ VpcConfig EnvironmentZTagsZTracingZ KmsKeyArnZAutoPublishAliasZLayersZDeploymentPreferenceZPermissionsBoundaryZReservedConcurrentExecutionsZAuthNameZ DefinitionUriZCacheClusterEnabledZCacheClusterSize VariablesZEndpointConfigurationZMethodSettingsZBinaryMediaTypesZMinimumCompressionSizeZCorsZGatewayResponsesZAccessLogSettingZ CanarySettingZTracingEnabledZSSESpecificationcsJfddjjD_jji_j|krFj|j_dS)zp Constructs an instance of this object :param dict template: SAM template to be parsed csg|]}|jjdqS))replace_RESOURCE_PREFIX).0x)self/Users/sshvans/Documents/Work/Quickstart/python-virtual-environments/env/lib/python3.6/site-packages/samtranslator/plugins/globals/globals.py Fsz$Globals.__init__..N)supported_propertieskeys supported_resource_section_namessorttemplate_globals_KEYWORD_parse)rtemplater)rr__init__@s    zGlobals.__init__cCs"||jkr|S|j|}|j|S)a Adds global properties to the resource, if necessary. This method is a no-op if there are no global properties for this resource type :param string resource_type: Type of the resource (Ex: AWS::Serverless::Function) :param dict resource_properties: Properties of the resource that need to be merged :return dict: Merged properties of the resource )rmerge)r resource_typeZresource_propertiesZ global_propsrrrrPs  z Globals.mergecCs|j|kr||j=dS)z Helper method to delete the Globals section altogether from the template :param dict template: SAM template :return: Modified SAM template with Globals section N)r)clsrrrr del_sectionbs zGlobals.del_sectionc Csi}t|ts"t|jdj|jx|jD]\}}|j|}||jkr`t|jdj||jdt|tsvt|jdx>|jD]2\}}|j|}||krt|jdj|||dqWt |||<q,W|S)af Takes a SAM template as input and parses the Globals section :param globals_dict: Dictionary representation of the Globals section :return: Processed globals dictionary which can be used to quickly identify properties to merge :raises: InvalidResourceException if the input contains properties that we don't support z!It must be a non-empty dictionaryzO'{section}' is not supported. Must be one of the following values - {supported})section supportedz(Value of ${section} must be a dictionaryze'{key}' is not a supported property of '{section}'. Must be one of the following values - {supported})keyr r!) isinstancedictInvalidGlobalsSectionExceptionrformatitems_make_resource_typerrGlobalProperties) rZ globals_dictglobals section_nameZ propertiesrr"valuer!rrrrns*        zGlobals._parsecCs |j|S)N)r )rr"rrrr(szGlobals._make_resource_typeN)__name__ __module__ __qualname____doc__rr rZFunctionr,ZApiZ SimpleTablerrr classmethodrrr(rrrrrsX )rc@sVeZdZdZddZddZddZdd Zd d Zd d Z ddZ GdddZ dS)r)av Object holding the global properties of given type. It also contains methods to perform a merge between Global & resource-level properties. Here are the different cases during the merge and how we handle them: **Primitive Type (String, Integer, Boolean etc)** If either global & local are of primitive types, then we the value at local will overwrite global. Example: ``` Global: Function: Runtime: nodejs Function: Runtime: python ``` After processing, Function resource will contain: ``` Runtime: python ``` **Different data types** If a value at Global is a array, but local is a dictionary, then we will simply use the local value. There is no merge to be done here. Similarly for other data type mismatches between global & local value. Example: ``` Global: Function: CodeUri: s3://bucket/key Function: CodeUri: Bucket: foo Key: bar ``` After processing, Function resource will contain: ``` CodeUri: Bucket: foo Key: bar ``` **Arrays** If a value is an array at both global & local level, we will simply concatenate them without de-duplicating. Customers can easily fix the duplicates: Example: ``` Global: Function: Policy: [Policy1, Policy2] Function: Policy: [Policy1, Policy3] ``` After processing, Function resource will contain: (notice the duplicates) ``` Policy: [Policy1, Policy2, Policy1, Policy3] ``` **Dictionaries** If both global & local value is a dictionary, we will recursively merge properties. If a value is one of the above types, they will handled according the above rules. Example: ``` Global: EnvironmentVariables: TableName: foo DBName: generic-db Function: EnvironmentVariables: DBName: mydb ConnectionString: bar ``` After processing, Function resource will contain: ``` EnvironmentVariables: TableName: foo DBName: mydb ConnectionString: bar ``` ***Optional Properties*** Some resources might have optional properties with default values when it is skipped. If an optional property is skipped at local level, an explicitly specified value at global level will be used. Example: Global: DeploymentPreference: Enabled: False Type: Canary Function: DeploymentPreference: Type: Linear After processing, Function resource will contain: ``` DeploymentPreference: Enabled: False Type: Linear ``` (in other words, Deployments will be turned off for the Function) cCs ||_dS)N)global_properties)rr2rrrrszGlobalProperties.__init__cCs|j|j|S)z Merge Global & local level properties according to the above rules :return local_properties: Dictionary of local properties ) _do_merger2)rZlocal_propertiesrrrrszGlobalProperties.mergecCs|j|}|j|}||kr(|j||S|jj|ko>|knrP|j||S|jj|kof|knrx|j||S|jj|ko|knr|j||Stdj ||dS)aK Actually perform the merge operation for the given inputs. This method is used as part of the recursion. Therefore input values can be of any type. So is the output. :param global_value: Global value to be merged :param local_value: Local value to be merged :return: Merged result z8Unsupported type of objects. GlobalType={}, LocalType={}N) _token_of _prefer_localTOKEN PRIMITIVEDICT _merge_dictLIST _merge_lists TypeErrorr&)r global_value local_valueZ token_globalZ token_localrrrr3s      zGlobalProperties._do_mergecCs||S)a Merges the global list with the local list. List merging is simply a concatenation = global + local :param global_list: Global value list :param local_list: Local value list :return: New merged list with the elements shallow copied r)rZ global_listZ local_listrrrr;<s zGlobalProperties._merge_listscCsL|j}x>|jD]2}||kr8|j||||||<q||||<qW|S)z Merges the two dictionaries together :param global_dict: Global dictionary to be merged :param local_dict: Local dictionary to be merged :return: New merged dictionary with values shallow copied )copyrr3)rZ global_dictZ local_dictr"rrrr9Gs zGlobalProperties._merge_dictcCs|S)a; Literally returns the local value whatever it may be. This method is useful to provide a unified implementation for cases that don't require special handling. :param global_value: Global value :param local_value: Local value :return: Simply returns the local value r)rr=r>rrrr5_s zGlobalProperties._prefer_localcCsBt|tr$t|r|jjS|jjSnt|tr6|jjS|jjSdS)z Returns the token type of the input. :param input: Input whose type is to be determined :return TOKENS: Token type of the input N)r#r$rr6r7r8listr:)rinputrrrr4js   zGlobalProperties._token_ofc@seZdZdZdZdZdZdS)zGlobalProperties.TOKENz4 Enum of tokens used in the merging Z primitiver$r@N)r-r.r/r0r7r8r:rrrrr6sr6N) r-r.r/r0rrr3r;r9r5r4r6rrrrr)sv  r)c@s$eZdZdZddZeddZdS)r%zxException raised when a Globals section is is invalid. Attributes: message -- explanation of the error cCs||_||_dS)N) _logical_id_message)rZ logical_idmessagerrrrsz'InvalidGlobalsSectionException.__init__cCsdj|j|jS)Nz'{}' section is invalid. {})r&rBrC)rrrrrDsz&InvalidGlobalsSectionException.messageN)r-r.r/r0rpropertyrDrrrrr%sr%N) Z!samtranslator.public.sdk.resourcerZsamtranslator.public.intrinsicsrobjectrr) Exceptionr%rrrrs  q