-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Update lambda runtime deprecations and fix Lambda ARM builds #10441
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
Changes from all commits
be8f62d
7ebdb39
c05da77
7753d56
b77fa7c
3852948
265449e
1c076cf
b00d96c
0762b66
a29c768
72ccc7f
394d9fa
afade71
dc176b1
bc9d9c4
c3bc0ab
44221c7
f065419
a3e29bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,8 +7,10 @@ | |
from pathlib import Path | ||
from typing import TYPE_CHECKING, Literal, Mapping, Optional, Sequence, overload | ||
|
||
from localstack import config | ||
from localstack.services.lambda_.runtimes import RUNTIMES_AGGREGATED | ||
from localstack.utils.files import load_file | ||
from localstack.utils.platform import Arch, get_arch | ||
from localstack.utils.strings import short_uid | ||
from localstack.utils.sync import ShortCircuitWaitException, retry | ||
from localstack.utils.testutil import get_lambda_log_events | ||
|
@@ -35,21 +37,18 @@ | |
**dict.fromkeys(RUNTIMES_AGGREGATED.get("nodejs"), "index.handler"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("ruby"), "function.handler"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("java"), "echo.Handler"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("custom"), "function.handler"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("go"), "main"), | ||
"dotnetcore3.1": "dotnetcore31::dotnetcore31.Function::FunctionHandler", # TODO lets see if we can accumulate those | ||
"dotnet6": "dotnet6::dotnet6.Function::FunctionHandler", | ||
# The handler value does not matter unless the custom runtime reads it in some way but it is a required field. | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("provided"), "function.handler"), | ||
"dotnet6": "dotnet6::dotnet6.Function::FunctionHandler", # TODO lets see if we can accumulate those | ||
} | ||
|
||
PACKAGE_FOR_RUNTIME = { | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("python"), "python"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("nodejs"), "nodejs"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("ruby"), "ruby"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("java"), "java"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("custom"), "provided"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("go"), "go"), | ||
**dict.fromkeys(RUNTIMES_AGGREGATED.get("provided"), "provided"), | ||
"dotnet6": "dotnet6", | ||
"dotnetcore3.1": "dotnetcore3.1", | ||
} | ||
|
||
|
||
|
@@ -94,7 +93,7 @@ def package_for_lang(scenario: str, runtime: str, root_folder: Path) -> str: | |
generic_runtime_dir_candidate = scenario_dir / runtime_folder | ||
|
||
# if a more specific folder exists, use that one | ||
# otherwise: try to fall back to generic runtime (e.g. python for python3.9) | ||
# otherwise: try to fall back to generic runtime (e.g. python for python3.12) | ||
if runtime_dir_candidate.exists() and runtime_dir_candidate.is_dir(): | ||
runtime_dir = runtime_dir_candidate | ||
else: | ||
|
@@ -109,7 +108,19 @@ def package_for_lang(scenario: str, runtime: str, root_folder: Path) -> str: | |
return package_path | ||
|
||
# packaging | ||
result = subprocess.run(["make", "build"], cwd=runtime_dir) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. L90 above: We could consider renaming |
||
# Use the default Lambda architecture x86_64 unless the ignore architecture flag is configured. | ||
# This enables local testing of both architectures on multi-architecture platforms such as Apple Silicon machines. | ||
architecture = "x86_64" | ||
if config.LAMBDA_IGNORE_ARCHITECTURE: | ||
architecture = "arm64" if get_arch() == Arch.arm64 else "x86_64" | ||
build_cmd = ["make", "build", f"ARCHITECTURE={architecture}"] | ||
LOG.debug( | ||
"Building Lambda function for scenario %s and runtime %s using %s.", | ||
scenario, | ||
runtime, | ||
" ".join(build_cmd), | ||
) | ||
result = subprocess.run(build_cmd, cwd=runtime_dir) | ||
if result.returncode != 0: | ||
raise Exception( | ||
f"Failed to build multiruntime {scenario=} for {runtime=} with error code: {result.returncode}" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Top-level Makefile to invoke all make targets in sub-directories | ||
|
||
# Based on https://stackoverflow.com/a/72209214/6875981 | ||
SUBDIRS := $(patsubst %/,%,$(wildcard */)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
|
||
.PHONY: all $(MAKECMDGOALS) $(SUBDIRS) | ||
$(MAKECMDGOALS) all: $(SUBDIRS) | ||
|
||
$(SUBDIRS): | ||
$(MAKE) -C $@ $(MAKECMDGOALS) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Lambda Multiruntime Builds | ||
|
||
This directory contains the source code and build instructions for Lambda multiruntime tests. | ||
Example tests are available under `tests.aws.lambda_.functions.common` | ||
|
||
Each scenario (e.g., "echo") has the following folder structure: `./<scenario>/runtime/` | ||
A runtime can be an aggregated runtime defined in `runtimes.py` (e.g., "python") or | ||
a specific runtime (e.g., "python3.12") if customizations are required. | ||
|
||
Each runtime directory defines a `Makefile` that | ||
* MUST define a `build` target that: | ||
* a) creates a `build` directory containing all Lambda sources ready for packaging | ||
* b) creates a `handler.zip` file with a Lambda deployment package | ||
* SHOULD define an `ARCHITECTURE` parameter to overwrite the target architecture (i.e., `x86_64` or `arm64`) | ||
if architecture-specific builds are required (e.g., Dotnet, Golang, Rust). | ||
* By default, the Makefile should build a deployment package with the same architecture as the host. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This default behavior is debatable:
Hence, on multi-architecture platforms (e.g., Apple Silicon), x86_64 builds require a parameter |
||
* However, for testing on multi-architecture platforms, we should be able to overwrite the `ARCHITECTURE` parameter. | ||
* We need to standardize `uname -m` into `ARCHITECTURE` because the output differs depending on the platform. | ||
Ubuntu yields `aarch64` and macOS yields `arm64`. | ||
* If we want to support dev systems without the `uname` utility, we could add `|| echo x86_64` to the uname detection. | ||
* SHOULD define a `clean` target that deletes any build artefacts, including the `handler.zip`. | ||
This helps a lot during development to tidy up and invalidate caching. | ||
|
||
Checkout the [AWS guides](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-package.html) on | ||
"Building with <language>" (e.g., "Building with Java") for instructions how to | ||
build Lambda deployment packages correctly. | ||
|
||
The top-level and intermediary directories provided a meta-Makefile that automatically invokes sub-Makefiles such that | ||
we can run `make clean` at the top-level recursively. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Top-level Makefile to invoke all make targets in sub-directories | ||
|
||
# Based on https://stackoverflow.com/a/72209214/6875981 | ||
SUBDIRS := $(patsubst %/,%,$(wildcard */)) | ||
|
||
.PHONY: all $(MAKECMDGOALS) $(SUBDIRS) | ||
$(MAKECMDGOALS) all: $(SUBDIRS) | ||
|
||
$(SUBDIRS): | ||
$(MAKE) -C $@ $(MAKECMDGOALS) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,20 @@ | ||
UNAME := $(shell uname -m) | ||
ifeq ($(UNAME),x86_64) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wished this could be shorter but Ubuntu (in CI) yields |
||
ARCHITECTURE ?= x86_64 | ||
else | ||
ARCHITECTURE ?= arm64 | ||
endif | ||
DOCKER_PLATFORM ?= linux/$(ARCHITECTURE) | ||
# The packaging function architecture is x86_64 by default and needs to be set explicitly for arm64 | ||
# https://github.com/aws/aws-extensions-for-dotnet-cli/blob/cdd490450e0407139d49248d94a4a899367e84df/src/Amazon.Lambda.Tools/LambdaDefinedCommandOptions.cs#L111 | ||
FUNCTION_ARCHITECTURE ?= $(ARCHITECTURE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dotnet is a good example why an explicit
|
||
|
||
# https://gallery.ecr.aws/sam/build-dotnet6 | ||
IMAGE ?= public.ecr.aws/sam/build-dotnet6:1.103.0 | ||
IMAGE ?= public.ecr.aws/sam/build-dotnet6:1.112.0 | ||
|
||
build: | ||
mkdir -p build && \ | ||
docker run --rm -v $$(pwd)/src:/app -v $$(pwd)/build:/out $(IMAGE) bash -c "mkdir -p /app2 && cp /app/* /app2 && cd /app2 && dotnet lambda package -o ../out/handler.zip" && \ | ||
docker run --rm --platform=$(DOCKER_PLATFORM) -v $$(pwd)/src:/app -v $$(pwd)/build:/out $(IMAGE) bash -c "mkdir -p /app2 && cp /app/* /app2 && cd /app2 && dotnet lambda package --function-architecture $(FUNCTION_ARCHITECTURE) -o ../out/handler.zip" && \ | ||
cp build/handler.zip handler.zip | ||
|
||
clean: | ||
|
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
|
||
build: | ||
mkdir -p build && \ | ||
cp -r ./src/* build/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
|
||
build: | ||
mkdir build && \ | ||
cp -r ./src/* build/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Top-level Makefile to invoke all make targets in sub-directories | ||
|
||
# Based on https://stackoverflow.com/a/72209214/6875981 | ||
SUBDIRS := $(patsubst %/,%,$(wildcard */)) | ||
|
||
.PHONY: all $(MAKECMDGOALS) $(SUBDIRS) | ||
$(MAKECMDGOALS) all: $(SUBDIRS) | ||
|
||
$(SUBDIRS): | ||
$(MAKE) -C $@ $(MAKECMDGOALS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be removed with the follow-up addition in the Dotnet8 PR