in samcli/lib/samlib/resource_metadata_normalizer.py [0:0]
def normalize(template_dict, normalize_parameters=False):
"""
Normalize all Resources in the template with the Metadata Key on the resource.
This method will mutate the template
Parameters
----------
template_dict dict
Dictionary representing the template
"""
resources = template_dict.get(RESOURCES_KEY, {})
for logical_id, resource in resources.items():
# copy metadata to another variable, change its values and assign it back in the end
resource_metadata = deepcopy(resource.get(METADATA_KEY)) or {}
is_normalized = resource_metadata.get(SAM_IS_NORMALIZED, False)
if not is_normalized:
asset_property = resource_metadata.get(ASSET_PROPERTY_METADATA_KEY)
if asset_property == IMAGE_ASSET_PROPERTY:
asset_metadata = ResourceMetadataNormalizer._extract_image_asset_metadata(resource_metadata)
ResourceMetadataNormalizer._update_resource_metadata(resource_metadata, asset_metadata)
# For image-type functions, the asset path is expected to be the name of the Docker image.
# When building, we set the name of the image to be the logical id of the function.
asset_path = logical_id.lower()
else:
asset_path = resource_metadata.get(ASSET_PATH_METADATA_KEY)
ResourceMetadataNormalizer._replace_property(asset_property, asset_path, resource, logical_id)
if asset_path and asset_property:
resource_metadata[SAM_IS_NORMALIZED] = True
# Set SkipBuild metadata iff is-bundled metadata exists, and value is True
skip_build = resource_metadata.get(ASSET_BUNDLED_METADATA_KEY, False)
if skip_build:
ResourceMetadataNormalizer._update_resource_metadata(
resource_metadata,
{
SAM_METADATA_SKIP_BUILD_KEY: True,
},
)
# Set Resource Id
ResourceMetadataNormalizer._update_resource_metadata(
resource_metadata,
{SAM_RESOURCE_ID_KEY: ResourceMetadataNormalizer.get_resource_id(resource, logical_id)},
)
resource[METADATA_KEY] = resource_metadata
# This is a work around to allow the customer to use sam deploy or package commands without the need to provide
# values for the CDK auto generated asset parameters. The suggested solution is to let CDK add some metadata to
# the autogenerated parameters, so sam can skip them safely.
# Normalizing CDK auto generated parameters. Search for parameters that meet these conditions:
# 1- parameter name matches pattern
# `AssetParameters[0-9a-f]{64}(?:S3Bucket|S3VersionKey|ArtifactHash)[0-9A-F]{8}`
# 2- parameter type is string
# 3- there is no reference to this parameter any where in the template resources, except in Nested Stack
# Parameters property.
# 4- there is no default value for this parameter
# We set an empty string as default value for the matching parameters, so the customer can use sam deploy or
# package commands without providing values for the auto generated parameters, as these parameters are not used
# in SAM (sam set the resources paths directly, and does not depend on template parameters)
if normalize_parameters and is_cdk_project(template_dict):
resources_copy = {
logical_id: resource
for logical_id, resource in resources.items()
if resource.get("Type", "") != AWS_CLOUDFORMATION_STACK
}
resources_as_string = json.dumps(resources_copy)
parameters = template_dict.get("Parameters", {})
default_value = " "
for parameter_name, parameter_value in parameters.items():
parameter_name_match = CDK_ASSET_PARAMETER_PATTERN.match(parameter_name)
if (
parameter_name_match
and "Default" not in parameter_value
and parameter_value.get("Type", "") == "String"
and f'"Ref": "{parameter_name}"' not in resources_as_string
):
LOG.debug("set default value for parameter %s to '%s'", parameter_name, default_value)
parameter_value["Default"] = default_value