Skip to content

Commit

Permalink
feat(core): Added AWS Lambda module
Browse files Browse the repository at this point in the history
  • Loading branch information
Tranquility2 committed May 15, 2024
1 parent 8ef441a commit f4490c2
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 1 deletion.
1 change: 1 addition & 0 deletions index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ testcontainers-python facilitates the use of Docker containers for functional an

core/README
modules/arangodb/README
modules/awslambda/README
modules/azurite/README
modules/cassandra/README
modules/chroma/README
Expand Down
6 changes: 6 additions & 0 deletions modules/aws/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. autoclass:: testcontainers.aws.AWSLambdaContainer
.. title:: testcontainers.aws.AWSLambdaContainer

Make sure you are using an image based on `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.
1 change: 1 addition & 0 deletions modules/aws/testcontainers/aws/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .aws_lambda import AWSLambdaContainer # noqa: F401
52 changes: 52 additions & 0 deletions modules/aws/testcontainers/aws/aws_lambda.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from typing import Optional

import httpx

from testcontainers.core.generic import SrvContainer

RIE_PATH = "/2015-03-31/functions/function/invocations"
# AWS OS-only base images contain an Amazon Linux distribution and the runtime interface emulator.


class AWSLambdaContainer(SrvContainer):
"""
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
>>> with AWSLambdaContainer(path="./modules/aws/tests/lambda_sample", port=8080, tag="lambda_func:latest") 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:")
"""

def __init__(self, path: str, port: int, tag: Optional[str] = None, image_cleanup: bool = True) -> None:
"""
:param path: Path to the AWS Lambda dockerfile.
:param port: Port to expose the AWS Lambda function.
:param tag: Tag for the image to be built (default: None).
:param image_cleanup: Clean up the image after the container is stopped (default: True).
"""
super().__init__(path, port, tag, image_cleanup)

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 = httpx.Client()
return client.post(self.get_api_url(), json=data)

def get_stdout(self) -> str:
return self.get_logs()[0].decode("utf-8")
10 changes: 10 additions & 0 deletions modules/aws/tests/lambda_sample/Dockerfile
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" ]
5 changes: 5 additions & 0 deletions modules/aws/tests/lambda_sample/lambda_function.py
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 + "!"
38 changes: 38 additions & 0 deletions modules/aws/tests/test_aws.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import re
import pytest

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 AWSLambdaContainer(path=DOCKER_FILE_PATH, port=8080, tag=IMAGE_TAG, image_cleanup=False) as func:
assert func.get_container_host_ip() == "localhost"
assert func.internal_port == 8080
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_no_tag():
with AWSLambdaContainer(path=DOCKER_FILE_PATH, port=8080, image_cleanup=True) as func:
response = func.send_request(data={"payload": "test"})
assert response.status_code == 200


def test_aws_lambda_container_no_port():
with pytest.raises(TypeError):
with AWSLambdaContainer(path=DOCKER_FILE_PATH, tag=IMAGE_TAG, image_cleanup=False):
pass


def test_aws_lambda_container_no_path():
with pytest.raises(TypeError):
with AWSLambdaContainer(port=8080, tag=IMAGE_TAG, image_cleanup=True):
pass
3 changes: 2 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ classifiers = [
packages = [
{ include = "testcontainers", from = "core" },
{ include = "testcontainers", from = "modules/arangodb" },
{ include = "testcontainers", from = "modules/aws"},
{ include = "testcontainers", from = "modules/azurite" },
{ include = "testcontainers", from = "modules/cassandra" },
{ include = "testcontainers", from = "modules/chroma" },
Expand Down Expand Up @@ -104,6 +105,7 @@ httpx = { version = "*", optional = true }

[tool.poetry.extras]
arangodb = ["python-arango"]
aws = ["boto3"]
azurite = ["azure-storage-blob"]
cassandra = []
clickhouse = ["clickhouse-driver"]
Expand Down

0 comments on commit f4490c2

Please sign in to comment.