Skip to content

Commit 8bc1b08

Browse files
AntoniaSzecsiAstraea Quinn S
authored andcommitted
Implement local Lambda testing with Runtime Interface Emulator
1 parent 3ec0f50 commit 8bc1b08

File tree

9 files changed

+167
-33
lines changed

9 files changed

+167
-33
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,6 @@ deps/curl-*/
156156

157157
# local caches
158158
.DS_Store
159+
160+
# local build artifacts
161+
build-artifacts

Dockerfile.build

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
FROM python:3.9-alpine AS build-image
2+
3+
# Install build dependencies
4+
RUN apk add --no-cache \
5+
build-base \
6+
libtool \
7+
autoconf \
8+
automake \
9+
elfutils-dev \
10+
make \
11+
cmake \
12+
libcurl \
13+
curl \
14+
libstdc++ \
15+
binutils
16+
17+
# Build awslambdaric
18+
ARG RIC_BUILD_DIR="/home/build/"
19+
RUN mkdir -p ${RIC_BUILD_DIR}
20+
WORKDIR ${RIC_BUILD_DIR}
21+
COPY . .
22+
RUN pip install setuptools
23+
RUN curl -sSL https://install.python-poetry.org | python3 - && \
24+
ln -s /root/.local/bin/poetry /usr/local/bin/poetry
25+
RUN make init build
26+
27+
# Keep the built wheel accessible
28+
CMD ["sh", "-c", "echo 'Build complete. Wheel available in /home/build/dist/'"]

Dockerfile.rie

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
FROM python:3.9-alpine
2+
3+
RUN apk add --no-cache libstdc++ curl
4+
5+
# Install RIE
6+
RUN curl -Lo /usr/local/bin/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \
7+
chmod +x /usr/local/bin/aws-lambda-rie
8+
9+
# Add the pre-built wheel
10+
ADD build-artifacts/*.whl /tmp/
11+
12+
# Install the wheel
13+
RUN pip install /tmp/*.whl
14+
15+
# Copy test handler
16+
COPY tests/integration/test-handlers/echo/app.py /var/task/app.py
17+
18+
# Set environment for local testing
19+
ENV AWS_LAMBDA_RUNTIME_API="127.0.0.1:8080"
20+
ENV LAMBDA_TASK_ROOT="/var/task"
21+
ENV _HANDLER="app.handler"
22+
23+
WORKDIR /var/task
24+
25+
ENTRYPOINT ["/usr/local/bin/aws-lambda-rie"]
26+
CMD ["python", "-m", "awslambdaric", "app.handler"]

Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ pr: init check-format check-security dev
5757
codebuild: setup-codebuild-agent
5858
CODEBUILD_IMAGE_TAG=codebuild-agent DISTRO="$(DISTRO)" tests/integration/codebuild-local/test_all.sh tests/integration/codebuild
5959

60+
.PHONY: build-container
61+
build-container:
62+
./scripts/build-container.sh
63+
64+
.PHONY: test-rie
65+
test-rie:
66+
./scripts/test-rie.sh
67+
6068
define HELP_MESSAGE
6169

6270
Usage: $ make [TARGETS]
@@ -68,6 +76,8 @@ TARGETS
6876
clean Cleans the working directory using scripts/dev.py.
6977
dev Run all development tests using scripts/dev.py.
7078
init Install dependencies via scripts/dev.py.
79+
build-container Build awslambdaric wheel in isolated container.
80+
test-rie Test with RIE using pre-built wheel (run build-container first).
7181
pr Perform all checks before submitting a Pull Request.
7282
test Run unit tests using scripts/dev.py.
7383
lint Run all linters via scripts/dev.py.

README.md

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,26 @@ The Python Runtime Interface Client package currently supports Python versions:
1414

1515
## Usage
1616

17+
### Container-Based Builds
18+
19+
For development or when you need to build awslambdaric from source, you can use container-based builds to ensure consistent compilation across different platforms, and native dependencies linking.
20+
21+
```shell script
22+
# Build awslambdaric wheel in a Linux container
23+
make build-container
24+
# Or with poetry (run 'poetry install' first):
25+
poetry run build-container
26+
27+
# Test with RIE using the built wheel
28+
make test-rie
29+
# Or with poetry:
30+
poetry run test-rie
31+
```
32+
33+
This approach builds the C++ extensions in a Linux environment, ensuring compatibility with Lambda's runtime environment regardless of your host OS.
34+
35+
**Note**: Running `make build` (or `poetry run build`) on non-Linux machines will not properly link the native C++ dependencies, resulting in a non-functional runtime client. Always use container-based builds for development.
36+
1737
### Creating a Docker Image for Lambda with the Runtime Interface Client
1838
First step is to choose the base image to be used. The supported Linux OS distributions are:
1939

@@ -103,38 +123,23 @@ def handler(event, context):
103123

104124
### Local Testing
105125

106-
To make it easy to locally test Lambda functions packaged as container images we open-sourced a lightweight web-server, Lambda Runtime Interface Emulator (RIE), which allows your function packaged as a container image to accept HTTP requests. You can install the [AWS Lambda Runtime Interface Emulator](https://github.com/aws/aws-lambda-runtime-interface-emulator) on your local machine to test your function. Then when you run the image function, you set the entrypoint to be the emulator.
107-
108-
*To install the emulator and test your Lambda function*
109-
110-
1) From your project directory, run the following command to download the RIE from GitHub and install it on your local machine.
126+
To test Lambda functions with the Runtime Interface Client, use the [AWS Lambda Runtime Interface Emulator (RIE)](https://github.com/aws/aws-lambda-runtime-interface-emulator). To test your local changes with RIE (Runtime Interface Emulator):
111127

112128
```shell script
113-
mkdir -p ~/.aws-lambda-rie && \
114-
curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \
115-
chmod +x ~/.aws-lambda-rie/aws-lambda-rie
129+
# Build your current code (do this when you make changes)
130+
# We build on a linux machine to ensure native build dependencies are met
131+
make build-container
132+
# Or with poetry:
133+
poetry run build-container
134+
135+
# Test with RIE (fast, repeatable)
136+
make test-rie
137+
# Or with poetry:
138+
poetry run test-rie
139+
140+
# Test the function
141+
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"message":"test"}'
116142
```
117-
2) Run your Lambda image function using the docker run command.
118-
119-
```shell script
120-
docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
121-
--entrypoint /aws-lambda/aws-lambda-rie \
122-
myfunction:latest \
123-
/usr/local/bin/python -m awslambdaric app.handler
124-
```
125-
126-
This runs the image as a container and starts up an endpoint locally at `http://localhost:9000/2015-03-31/functions/function/invocations`.
127-
128-
3) Post an event to the following endpoint using a curl command:
129-
130-
```shell script
131-
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
132-
```
133-
134-
This command invokes the function running in the container image and returns a response.
135-
136-
*Alternately, you can also include RIE as a part of your base image. See the AWS documentation on how to [Build RIE into your base image](https://docs.aws.amazon.com/lambda/latest/dg/images-test.html#images-test-alternative).*
137-
138143

139144
## Development
140145

@@ -145,7 +150,6 @@ Clone this repository and run:
145150
make init
146151
make build
147152
```
148-
149153
### Running tests
150154

151155
Make sure the project is built:

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ lint = "scripts.dev:lint"
2929
format = "scripts.dev:format_code"
3030
clean = "scripts.dev:clean"
3131
build = "scripts.dev:build"
32-
local-test = "scripts.dev:local_test"
32+
build-container = "scripts.dev:build_container"
33+
test-rie = "scripts.dev:test_rie"
3334

3435
[build-system]
3536
requires = ["poetry-core>=2.0.0,<3.0.0", "setuptools>=68", "wheel"]

scripts/build-container.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
TAG=${TAG:-latest}
5+
PYTHON_VERSION=${PYTHON_VERSION:-3.9}
6+
7+
echo "Building awslambdaric wheel for Python ${PYTHON_VERSION}..."
8+
9+
echo "Building wheel in container..."
10+
docker build \
11+
--build-arg PYTHON_VERSION="${PYTHON_VERSION}" \
12+
-f Dockerfile.build \
13+
-t "awslambdaric-builder:${TAG}" \
14+
.
15+
16+
echo "Extracting built wheel..."
17+
mkdir -p build-artifacts
18+
19+
docker run --rm -v $(pwd)/build-artifacts:/output awslambdaric-builder:${TAG} /bin/sh -c "
20+
cp /home/build/dist/*.whl /output/
21+
echo 'Wheel copied to build-artifacts/'
22+
ls -la /output/
23+
"
24+
25+
echo "Build complete! Wheel is available in build-artifacts/"

scripts/dev.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,20 @@ def build():
6262
run([sys.executable, "setup.py", "sdist", "bdist_wheel"], env=env)
6363

6464

65+
def build_container():
66+
print("Building awslambdaric wheel in container")
67+
run(["./scripts/build-container.sh"])
68+
69+
70+
def test_rie():
71+
print("Testing with RIE using pre-built wheel")
72+
run(["./scripts/test-rie.sh"])
73+
74+
6575
def main():
6676
parser = argparse.ArgumentParser(description="Development scripts")
6777
parser.add_argument("command", choices=[
68-
"init", "test", "lint", "format", "clean", "build"
78+
"init", "test", "lint", "format", "clean", "build", "build-container", "test-rie"
6979
])
7080

7181
args = parser.parse_args()
@@ -77,7 +87,8 @@ def main():
7787
"format": format_code,
7888
"clean": clean,
7989
"build": build,
80-
90+
"build-container": build_container,
91+
"test-rie": test_rie,
8192
}
8293

8394
command_map[args.command]()

scripts/test-rie.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
DOCKERFILE="Dockerfile.rie"
5+
6+
echo "Starting RIE test setup..."
7+
8+
# Check if build artifacts exist
9+
if [ ! -d "build-artifacts" ] || [ -z "$(ls -A build-artifacts/*.whl 2>/dev/null)" ]; then
10+
echo "No build artifacts found. Please run 'make build-container' first."
11+
exit 1
12+
fi
13+
14+
echo "Building test Docker image..."
15+
docker build \
16+
-f "${DOCKERFILE}" \
17+
-t awslambdaric-rie-test .
18+
19+
echo "Starting test container on port 9000..."
20+
echo ""
21+
echo "Test with:"
22+
echo "curl -XPOST \"http://localhost:9000/2015-03-31/functions/function/invocations\" -d '{\"message\":\"test\"}'"
23+
echo ""
24+
25+
docker run -it -p 9000:8080 \
26+
--rm awslambdaric-rie-test

0 commit comments

Comments
 (0)