10000 Fix layer version handling for external Lambda layers by joe4dev · Pull Request #9286 · localstack/localstack · GitHub
[go: up one dir, main page]

Skip to content

Fix layer version handling for external Lambda layers #9286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 6, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions localstack/services/lambda_/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,25 +588,31 @@ def _validate_layers(self, new_layers: list[str], region: str, account_id: int):

visited_layers = dict()
for layer_version_arn in new_layers:
layer_region, layer_account_id, layer_name, layer_version = api_utils.parse_layer_arn(
layer_version_arn
)
if layer_version is None:
(
layer_region,
layer_account_id,
layer_name,
layer_version_str,
) = api_utils.parse_layer_arn(layer_version_arn)
if layer_version_str is None:
raise ValidationException(
f"1 validation error detected: Value '[{layer_version_arn}]'"
+ r" at 'layers' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 140, Member must have length greater than or equal to 1, Member must satisfy regular expression pattern: (arn:[a-zA-Z0-9-]+:lambda:[a-zA-Z0-9-]+:\d{12}:layer:[a-zA-Z0-9-_]+:[0-9]+)|(arn:[a-zA-Z0-9-]+:lambda:::awslayer:[a-zA-Z0-9-_]+), Member must not be null]",
)

state = lambda_stores[layer_account_id][layer_region]
layer = state.layers.get(layer_name)
layer_version = None
if layer is not None:
layer_version = layer.layer_versions.get(layer_version_str)
if layer_account_id == get_aws_account_id():
if region and layer_region != region:
raise InvalidParameterValueException(
f"Layers are not in the same region as the function. "
f"Layers are expected to be in region {region}.",
Type="User",
)
if layer is None or layer.layer_versions.get(layer_version) is None:
if layer is None or layer.layer_versions.get(layer_version_str) is None:
raise InvalidParameterValueException(
f"Layer version {layer_version_arn} does not exist.", Type="User"
)
Expand All @@ -618,7 +624,7 @@ def _validate_layers(self, new_layers: list[str], region: str, account_id: int):
raise AccessDeniedException(
f"User: arn:aws:iam::{account_id}:{user} is not authorized to perform: lambda:GetLayerVersion on resource: {layer_version_arn} because no resource-based policy allows the lambda:GetLayerVersion action"
)
if layer is None:
if layer is None or layer_version is None:
# Limitation: cannot fetch external layers when using the same account id as the target layer
# because we do not want to trigger the layer fetcher for every non-existing layer.
if self.layer_fetcher is None:
Expand All @@ -633,7 +639,16 @@ def _validate_layers(self, new_layers: list[str], region: str, account_id: int):
raise AccessDeniedException(
f"User: arn:aws:iam::{account_id}:{user} is not authorized to perform: lambda:GetLayerVersion on resource: {layer_version_arn} because no resource-based policy allows the lambda:GetLayerVersion action"
)
state.layers[layer_name] = layer

# Distinguish between new layer and new layer version
if layer_version is None:
# Create whole layer from scratch
state.layers[layer_name] = layer
51C5 else:
# Create layer version if another version of the same layer already exists
state.layers[layer_name].layer_versions[
layer_version_str
] = layer.layer_versions.get(layer_version_str)

# only the first two matches in the array are considered for the error message
layer_arn = ":".join(layer_version_arn.split(":")[:-1])
Expand Down
0