def _compute_layer_name(is_defined_within_template, arn): """ Computes a unique name based on the LayerVersion Arn Format: <Name of the LayerVersion>-<Version of the LayerVersion>-<sha256 of the arn> Parameters ---------- is_defined_within_template bool True if the resource is a Ref to a resource otherwise False arn str ARN of the Resource Returns ------- str A unique name that represents the LayerVersion """ # If the Layer is defined in the template, the arn will represent the LogicalId of the LayerVersion Resource, # which does not require creating a name based on the arn. if is_defined_within_template: return arn try: _, layer_name, layer_version = arn.rsplit(":", 2) except ValueError as ex: raise InvalidLayerVersionArn(arn + " is an Invalid Layer Arn.") from ex return LayerVersion.LAYER_NAME_DELIMETER.join([ layer_name, layer_version, hashlib.sha256(arn.encode("utf-8")).hexdigest()[0:10] ])
def _compute_layer_version(is_defined_within_template, arn): """ Parses out the Layer version from the arn Parameters ---------- is_defined_within_template bool True if the resource is a Ref to a resource otherwise False arn str ARN of the Resource Returns ------- int The Version of the LayerVersion """ if is_defined_within_template: return None try: _, layer_version = arn.rsplit(":", 1) layer_version = int(layer_version) except ValueError as ex: raise InvalidLayerVersionArn(arn + " is an Invalid Layer Arn.") from ex return layer_version
def _parse_layer_info(list_of_layers, resources, ignore_code_extraction_warnings=False): """ Creates a list of Layer objects that are represented by the resources and the list of layers Parameters ---------- list_of_layers List(str) List of layers that are defined within the Layers Property on a function resources dict The Resources dictionary defined in a template Returns ------- List(samcli.commands.local.lib.provider.Layer) List of the Layer objects created from the template and layer list defined on the function. The order of the layers does not change. I.E: list_of_layers = ["layer1", "layer2"] the return would be [Layer("layer1"), Layer("layer2")] """ layers = [] for layer in list_of_layers: if layer == "arn:aws:lambda:::awslayer:AmazonLinux1803": LOG.debug("Skipped arn:aws:lambda:::awslayer:AmazonLinux1803 as the containers are AmazonLinux1803") continue if layer == "arn:aws:lambda:::awslayer:AmazonLinux1703": raise InvalidLayerVersionArn( "Building and invoking locally only supports AmazonLinux1803. See " "https://aws.amazon.com/blogs/compute/upcoming-updates-to-the-aws-lambda-execution-environment/ for more detials." ) # noqa: E501 # If the layer is a string, assume it is the arn if isinstance(layer, str): layers.append(LayerVersion(layer, None)) continue # In the list of layers that is defined within a template, you can reference a LayerVersion resource. # When running locally, we need to follow that Ref so we can extract the local path to the layer code. if isinstance(layer, dict) and layer.get("Ref"): layer_logical_id = layer.get("Ref") layer_resource = resources.get(layer_logical_id) if not layer_resource or layer_resource.get("Type", "") not in ( SamFunctionProvider.SERVERLESS_LAYER, SamFunctionProvider.LAMBDA_LAYER, ): raise InvalidLayerReference() layer_properties = layer_resource.get("Properties", {}) resource_type = layer_resource.get("Type") compatible_runtimes = layer_properties.get("CompatibleRuntimes") codeuri = None if resource_type == SamFunctionProvider.LAMBDA_LAYER: codeuri = SamFunctionProvider._extract_lambda_function_code(layer_properties, "Content") if resource_type == SamFunctionProvider.SERVERLESS_LAYER: codeuri = SamFunctionProvider._extract_sam_function_codeuri( layer_logical_id, layer_properties, "ContentUri", ignore_code_extraction_warnings ) layers.append( LayerVersion(layer_logical_id, codeuri, compatible_runtimes, layer_resource.get("Metadata", None)) ) return layers
def _parse_layer_info( stack: Stack, list_of_layers: List[Any], use_raw_codeuri: bool = False, ignore_code_extraction_warnings: bool = False, ) -> List[LayerVersion]: """ Creates a list of Layer objects that are represented by the resources and the list of layers Parameters ---------- stack : Stack The stack the layer is defined in list_of_layers : List[Any] List of layers that are defined within the Layers Property on a function, layer can be defined as string or Dict, in case customers define it in other types, use "Any" here. use_raw_codeuri : bool Do not resolve adjust core_uri based on the template path, use the raw uri. ignore_code_extraction_warnings : bool Whether to print warning when codeuri is not a local pth Returns ------- List(samcli.commands.local.lib.provider.Layer) List of the Layer objects created from the template and layer list defined on the function. The order of the layers does not change. I.E: list_of_layers = ["layer1", "layer2"] the return would be [Layer("layer1"), Layer("layer2")] """ layers = [] for layer in list_of_layers: if layer == "arn:aws:lambda:::awslayer:AmazonLinux1803": LOG.debug("Skipped arn:aws:lambda:::awslayer:AmazonLinux1803 as the containers are AmazonLinux1803") continue if layer == "arn:aws:lambda:::awslayer:AmazonLinux1703": raise InvalidLayerVersionArn( "Building and invoking locally only supports AmazonLinux1803. See " "https://aws.amazon.com/blogs/compute/upcoming-updates-to-the-aws-lambda-execution-environment/ " "for more detials." ) # noqa: E501 # If the layer is a string, assume it is the arn if isinstance(layer, str): layers.append( LayerVersion( layer, None, stack_path=stack.stack_path, ) ) continue # In the list of layers that is defined within a template, you can reference a LayerVersion resource. # When running locally, we need to follow that Ref so we can extract the local path to the layer code. if isinstance(layer, dict) and layer.get("Ref"): layer_logical_id = cast(str, layer.get("Ref")) layer_resource = stack.resources.get(layer_logical_id) if not layer_resource or layer_resource.get("Type", "") not in ( SamFunctionProvider.SERVERLESS_LAYER, SamFunctionProvider.LAMBDA_LAYER, ): raise InvalidLayerReference() layer_properties = layer_resource.get("Properties", {}) resource_type = layer_resource.get("Type") compatible_runtimes = layer_properties.get("CompatibleRuntimes") codeuri: Optional[str] = None if resource_type == SamFunctionProvider.LAMBDA_LAYER: codeuri = SamFunctionProvider._extract_lambda_function_code(layer_properties, "Content") if resource_type == SamFunctionProvider.SERVERLESS_LAYER: codeuri = SamFunctionProvider._extract_sam_function_codeuri( layer_logical_id, layer_properties, "ContentUri", ignore_code_extraction_warnings ) if codeuri and not use_raw_codeuri: LOG.debug("--base-dir is presented not, adjusting uri %s relative to %s", codeuri, stack.location) codeuri = SamLocalStackProvider.normalize_resource_path(stack.location, codeuri) layers.append( LayerVersion( layer_logical_id, codeuri, compatible_runtimes, layer_resource.get("Metadata", None), stack_path=stack.stack_path, ) ) return layers
def _parse_layer_info( stack: Stack, list_of_layers: List[Any], use_raw_codeuri: bool = False, ignore_code_extraction_warnings: bool = False, ) -> List[LayerVersion]: """ Creates a list of Layer objects that are represented by the resources and the list of layers Parameters ---------- stack : Stack The stack the layer is defined in list_of_layers : List[Any] List of layers that are defined within the Layers Property on a function, layer can be defined as string or Dict, in case customers define it in other types, use "Any" here. use_raw_codeuri : bool Do not resolve adjust core_uri based on the template path, use the raw uri. ignore_code_extraction_warnings : bool Whether to print warning when codeuri is not a local pth Returns ------- List(samcli.commands.local.lib.provider.Layer) List of the Layer objects created from the template and layer list defined on the function. The order of the layers does not change. I.E: list_of_layers = ["layer1", "layer2"] the return would be [Layer("layer1"), Layer("layer2")] """ layers = [] for layer in list_of_layers: if layer == "arn:aws:lambda:::awslayer:AmazonLinux1803": LOG.debug( "Skipped arn:aws:lambda:::awslayer:AmazonLinux1803 as the containers are AmazonLinux1803" ) continue if layer == "arn:aws:lambda:::awslayer:AmazonLinux1703": raise InvalidLayerVersionArn( "Building and invoking locally only supports AmazonLinux1803. See " "https://aws.amazon.com/blogs/compute/upcoming-updates-to-the-aws-lambda-execution-environment/ " "for more detials.") # noqa: E501 # If the layer is a string, assume it is the arn if isinstance(layer, str): layers.append( LayerVersion( layer, None, stack_path=stack.stack_path, )) continue # In the list of layers that is defined within a template, you can reference a LayerVersion resource. # When running locally, we need to follow that Ref so we can extract the local path to the layer code. if isinstance(layer, dict) and layer.get("Ref"): found_layer = SamFunctionProvider._locate_layer_from_ref( stack, layer, use_raw_codeuri, ignore_code_extraction_warnings) if found_layer: layers.append(found_layer) else: LOG.debug( 'layer "%s" is not recognizable, ' "it might be using intrinsic functions that we don't support yet. Skipping.", str(layer), ) return layers