-
Notifications
You must be signed in to change notification settings - Fork 298
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(new): Added AWS Lambda module (#655)
As part of the effort described, detailed and presented on #559 This is the 4th (and final in this track) PR that should provide support for AWS Lambda containers. This module will add the ability to test and run Amazon Lambdas (using the built-in runtime interface emulator) For example: ```python from testcontainers.aws import AWSLambdaContainer from testcontainers.core.waiting_utils import wait_for_logs from testcontainers.core.image import DockerImage with DockerImage(path="./modules/aws/tests/lambda_sample", tag="test-lambda:latest") as image: with AWSLambdaContainer(image=image, port=8080) as func: response = func.send_request(data={'payload': 'some data'}) assert response.status_code == 200 assert "Hello from AWS Lambda using Python" in response.json() delay = wait_for_logs(func, "START RequestId:") ``` This can (and probably will) be used with the provided [LocalStackContainer](https://testcontainers-python.readthedocs.io/en/latest/modules/localstack/README.html) to help simulate more advance AWS cases. --- Based on the work done on: - #585 - #595 - #612 Expended from issue #83
- Loading branch information
1 parent
068c431
commit 9161cb6
Showing
8 changed files
with
151 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
:code:`testcontainers-aws` is a set of AWS containers modules that can be used to create AWS containers. | ||
|
||
.. autoclass:: testcontainers.aws.AWSLambdaContainer | ||
.. title:: testcontainers.aws.AWSLambdaContainer | ||
|
||
The following environment variables are used by the AWS Lambda container: | ||
|
||
+-------------------------------+--------------------------+------------------------------+ | ||
| Env Variable | Default | Notes | | ||
+===============================+==========================+==============================+ | ||
| ``AWS_DEFAULT_REGION`` | ``us-west-1`` | Fetched from os environment | | ||
+-------------------------------+--------------------------+------------------------------+ | ||
| ``AWS_ACCESS_KEY_ID`` | ``testcontainers-aws`` | Fetched from os environment | | ||
+-------------------------------+--------------------------+------------------------------+ | ||
| ``AWS_SECRET_ACCESS_KEY`` | ``testcontainers-aws`` | Fetched from os environment | | ||
+-------------------------------+--------------------------+------------------------------+ | ||
|
||
Each one of the environment variables is expected to be set in the host machine where the test is running. | ||
|
||
Make sure you are using an image based on :code:`public.ecr.aws/lambda/python` | ||
|
||
Please checkout https://docs.aws.amazon.com/lambda/latest/dg/python-image.html for more information on how to run AWS Lambda functions locally. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .aws_lambda import AWSLambdaContainer # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import os | ||
from typing import Union | ||
|
||
import httpx | ||
|
||
from testcontainers.core.image import DockerImage | ||
from testcontainers.generic.server import ServerContainer | ||
|
||
RIE_PATH = "/2015-03-31/functions/function/invocations" | ||
# AWS OS-only base images contain an Amazon Linux distribution and the runtime interface emulator (RIE) for Lambda. | ||
|
||
|
||
class AWSLambdaContainer(ServerContainer): | ||
""" | ||
AWS Lambda container that is based on a custom image. | ||
Example: | ||
.. doctest:: | ||
>>> from testcontainers.aws import AWSLambdaContainer | ||
>>> from testcontainers.core.waiting_utils import wait_for_logs | ||
>>> from testcontainers.core.image import DockerImage | ||
>>> with DockerImage(path="./modules/aws/tests/lambda_sample", tag="test-lambda:latest") as image: | ||
... with AWSLambdaContainer(image=image, port=8080) as func: | ||
... response = func.send_request(data={'payload': 'some data'}) | ||
... assert response.status_code == 200 | ||
... assert "Hello from AWS Lambda using Python" in response.json() | ||
... delay = wait_for_logs(func, "START RequestId:") | ||
:param image: Docker image to be used for the container. | ||
:param port: Port to be exposed on the container (default: 8080). | ||
""" | ||
|
||
def __init__(self, image: Union[str, DockerImage], port: int = 8080) -> None: | ||
super().__init__(port, str(image)) | ||
self.with_env("AWS_DEFAULT_REGION", os.environ.get("AWS_DEFAULT_REGION", "us-west-1")) | ||
self.with_env("AWS_ACCESS_KEY_ID", os.environ.get("AWS_ACCESS_KEY_ID", "testcontainers-aws")) | ||
self.with_env("AWS_SECRET_ACCESS_KEY", os.environ.get("AWS_SECRET_ACCESS_KEY", "testcontainers-aws")) | ||
|
||
def get_api_url(self) -> str: | ||
return self._create_connection_url() + RIE_PATH | ||
|
||
def send_request(self, data: dict) -> httpx.Response: | ||
""" | ||
Send a request to the AWS Lambda function. | ||
:param data: Data to be sent to the AWS Lambda function. | ||
:return: Response from the AWS Lambda function. | ||
""" | ||
client = self.get_client() | ||
return client.post(self.get_api_url(), json=data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
FROM public.ecr.aws/lambda/python:3.9 | ||
|
||
RUN pip install boto3 | ||
|
||
COPY lambda_function.py ${LAMBDA_TASK_ROOT} | ||
|
||
EXPOSE 8080 | ||
|
||
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) | ||
CMD [ "lambda_function.handler" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import sys | ||
|
||
|
||
def handler(event, context): | ||
return "Hello from AWS Lambda using Python" + sys.version + "!" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import re | ||
import os | ||
|
||
import pytest | ||
from unittest.mock import patch | ||
|
||
from testcontainers.core.image import DockerImage | ||
from testcontainers.aws import AWSLambdaContainer | ||
from testcontainers.aws.aws_lambda import RIE_PATH | ||
|
||
DOCKER_FILE_PATH = "./modules/aws/tests/lambda_sample" | ||
IMAGE_TAG = "lambda:test" | ||
|
||
|
||
def test_aws_lambda_container(): | ||
with DockerImage(path=DOCKER_FILE_PATH, tag="test-lambda:latest") as image: | ||
with AWSLambdaContainer(image=image, port=8080) as func: | ||
assert func.get_container_host_ip() == "localhost" | ||
assert func.internal_port == 8080 | ||
assert func.env["AWS_DEFAULT_REGION"] == "us-west-1" | ||
assert func.env["AWS_ACCESS_KEY_ID"] == "testcontainers-aws" | ||
assert func.env["AWS_SECRET_ACCESS_KEY"] == "testcontainers-aws" | ||
assert re.match(rf"http://localhost:\d+{RIE_PATH}", func.get_api_url()) | ||
response = func.send_request(data={"payload": "test"}) | ||
assert response.status_code == 200 | ||
assert "Hello from AWS Lambda using Python" in response.json() | ||
for log_str in ["START RequestId", "END RequestId", "REPORT RequestId"]: | ||
assert log_str in func.get_stdout() | ||
|
||
|
||
def test_aws_lambda_container_external_env_vars(): | ||
vars = { | ||
"AWS_DEFAULT_REGION": "region", | ||
"AWS_ACCESS_KEY_ID": "id", | ||
"AWS_SECRET_ACCESS_KEY": "key", | ||
} | ||
with patch.dict(os.environ, vars): | ||
with DockerImage(path=DOCKER_FILE_PATH, tag="test-lambda-env-vars:latest") as image: | ||
with AWSLambdaContainer(image=image, port=8080) as func: | ||
assert func.env["AWS_DEFAULT_REGION"] == "region" | ||
assert func.env["AWS_ACCESS_KEY_ID"] == "id" | ||
assert func.env["AWS_SECRET_ACCESS_KEY"] == "key" | ||
|
||
|
||
def test_aws_lambda_container_no_port(): | ||
with DockerImage(path=DOCKER_FILE_PATH, tag="test-lambda-no-port:latest") as image: | ||
with AWSLambdaContainer(image=image) as func: | ||
response = func.send_request(data={"payload": "test"}) | ||
assert response.status_code == 200 | ||
|
||
|
||
def test_aws_lambda_container_no_path(): | ||
with pytest.raises(TypeError): | ||
with DockerImage(path=DOCKER_FILE_PATH, tag="test-lambda-no-path:latest") as image: | ||
with AWSLambdaContainer() as func: # noqa: F841 | ||
pass |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters