Skip to content
Draft
Show file tree
Hide file tree
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
28 changes: 20 additions & 8 deletions moto/awslambda/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,6 @@ def convert(s: Any) -> str: # type: ignore[misc]
return s

def _invoke_lambda(self, event: Optional[str] = None) -> tuple[str, bool, str]:
import docker
import docker.errors

# Create the LogGroup if necessary, to write the result to
Expand Down Expand Up @@ -1000,6 +999,10 @@ def _invoke_lambda(self, event: Optional[str] = None) -> tuple[str, bool, str]:
if settings.is_test_proxy_mode():
env_vars["HTTPS_PROXY"] = env_vars["MOTO_HTTP_ENDPOINT"]
env_vars["AWS_CA_BUNDLE"] = "/var/task/ca.crt"
else:
# When the proxy is active, we should keep the original URL
# Else: redirect requests to our server
env_vars["AWS_ENDPOINT_URL"] = env_vars["MOTO_HTTP_ENDPOINT"]

container = exit_code = None
log_config = docker.types.LogConfig(type=docker.types.LogConfig.types.JSON)
Expand All @@ -1017,9 +1020,8 @@ def _invoke_lambda(self, event: Optional[str] = None) -> tuple[str, bool, str]:
elif network_mode:
run_kwargs["network_mode"] = network_mode
elif settings.TEST_SERVER_MODE:
# AWSLambda can make HTTP requests to a Docker container called 'motoserver'
# Only works if our Docker-container is named 'motoserver'
# TODO: should remove this and rely on 'network_mode' instead, as this is too tightly coupled with our own test setup
# TODO: should remove this in 6.x - it's no longer necessary for internal tests, but users may rely on it
run_kwargs["links"] = {"motoserver": "motoserver"}

# add host.docker.internal host on linux to emulate Mac + Windows behavior
Expand All @@ -1039,12 +1041,19 @@ def _invoke_lambda(self, event: Optional[str] = None) -> tuple[str, bool, str]:
# - lambci/lambda (the repo with older/outdated AWSLambda images
#
# We'll cycle through all of them - when we find the repo that contains our image, we use it

idx = re.search("[0-9]", self.run_time).start() # type: ignore[union-attr,arg-type]
language, version = self.run_time[:idx], self.run_time[idx:] # type: ignore[index]

image_repos = { # dict maintains insertion order
settings.moto_lambda_image(): None,
f"ghcr.io/shogo82148/lambda-{language}:{version}": None,
"mlupin/docker-lambda": None,
"lambci/lambda": None,
}
for image_repo in image_repos:
if not image_repo:
continue
image_ref = (
image_repo
if ":" in image_repo
Expand Down Expand Up @@ -1809,7 +1818,7 @@ def del_function(self, name_or_arn: str, qualifier: Optional[str] = None) -> Non
else:
self._functions[name]["versions"].remove(function)

# If theres no functions left
# If there are no functions left
if (
not self._functions[name]["versions"]
and not self._functions[name]["latest"]
Expand Down Expand Up @@ -1907,9 +1916,11 @@ class LambdaBackend(BaseBackend):

It is possible to connect from AWS Lambdas to other services, as long as you are running MotoProxy or the MotoServer in a Docker container.

When running the MotoProxy, calls to other AWS services are automatically proxied.
Moto injects the `AWS_ENDPOINT_URL` environment variable into every Lambda, which means that calls to other AWS services are automatically intercepted.

Note that, if you use a non-standard or older Docker image, the `AWS_ENDPOINT_URL` may not be supported.

When running MotoServer, the Lambda has access to environment variables `MOTO_HOST` and `MOTO_PORT`, which can be used to build the url that MotoServer runs on:
If that is the case, use the environment variables `MOTO_HOST` and `MOTO_PORT` to build the AWS endpoint url and point it to Moto:

.. sourcecode:: python

Expand Down Expand Up @@ -1949,8 +1960,9 @@ def lambda_handler(event, context):

The Docker images used by Moto are taken from the following repositories:

- `mlupin/docker-lambda` (for recent versions)
- `lambci/lambda` (for older/outdated versions)
- `shogo82148/lambda-python` (for recent versions)
- `mlupin/docker-lambda` (for older/outdated versions)
- `lambci/lambda` (for even older/outdated versions)

Use the following environment variable to configure Moto to look for images in an additional repository:

Expand Down
4 changes: 2 additions & 2 deletions moto/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ def moto_server_host() -> str:
return "http://host.docker.internal"


def moto_lambda_image() -> str:
return os.environ.get("MOTO_DOCKER_LAMBDA_IMAGE", "mlupin/docker-lambda")
def moto_lambda_image() -> Optional[str]:
return os.environ.get("MOTO_DOCKER_LAMBDA_IMAGE")


def moto_network_name() -> Optional[str]:
Expand Down
4 changes: 3 additions & 1 deletion tests/test_awslambda/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

from moto import mock_aws

from .utilities import PYTHON_VERSION


def lambda_aws_verified(func):
"""
Expand Down Expand Up @@ -98,7 +100,7 @@ def check_iam_role_is_ready_to_use(role_arn: str, role_name: str, region: str):
fn_name = f"fn_for_{role_name}"
_lambda.create_function(
FunctionName=fn_name,
Runtime="python3.11",
Runtime=PYTHON_VERSION,
Role=role_arn,
Handler="lambda_function.lambda_handler",
Code={"ZipFile": get_test_zip_file1()},
Expand Down
2 changes: 1 addition & 1 deletion tests/test_awslambda/test_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@

from . import lambda_aws_verified
from .utilities import (
PYTHON_VERSION,
_process_lambda,
create_invalid_lambda,
get_role_name,
get_test_zip_file1,
get_test_zip_file2,
)

PYTHON_VERSION = "python3.11"
LAMBDA_FUNC_NAME = "test"
_lambda_region = "us-west-2"

Expand Down
2 changes: 1 addition & 1 deletion tests/test_awslambda/test_lambda_alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID

from .utilities import (
PYTHON_VERSION,
get_role_name,
get_test_zip_file1,
get_test_zip_file2,
)

# See our Development Tips on writing tests for hints on how to write good tests:
# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
PYTHON_VERSION = "python3.11"


@mock_aws
Expand Down
3 changes: 1 addition & 2 deletions tests/test_awslambda/test_lambda_concurrency.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@

from moto import mock_aws

from .utilities import get_role_name, get_test_zip_file1
from .utilities import PYTHON_VERSION, get_role_name, get_test_zip_file1

PYTHON_VERSION = "python3.11"
_lambda_region = "us-west-2"


Expand Down
4 changes: 2 additions & 2 deletions tests/test_awslambda/test_lambda_eventsourcemapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@

from ..markers import requires_docker
from .utilities import (
PYTHON_VERSION,
get_role_name,
get_test_zip_file3,
get_test_zip_file_error,
wait_for_log_msg,
)

PYTHON_VERSION = "python3.11"
_lambda_region = "us-west-2"
botocore_version = sys.modules["botocore"].__version__

Expand Down Expand Up @@ -676,7 +676,7 @@ def test_event_source_mapping_tagging_lifecycle():
client = boto3.client("lambda", region_name="us-east-1")
client.create_function(
FunctionName="any-function-name",
Runtime="python3.6",
Runtime=PYTHON_VERSION,
Role=iam_role["Role"]["Arn"],
Handler="any-handler",
Code={
Expand Down
4 changes: 2 additions & 2 deletions tests/test_awslambda/test_lambda_invoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from ..markers import requires_docker
from .test_lambda import LooseVersion, boto3_version
from .utilities import (
PYTHON_VERSION,
get_lambda_using_environment_port,
get_lambda_using_network_mode,
get_proxy_zip_file,
Expand All @@ -24,7 +25,6 @@
get_zip_with_multiple_files,
)

PYTHON_VERSION = "python3.11"
_lambda_region = "us-west-2"


Expand Down Expand Up @@ -278,7 +278,7 @@ def test_invoke_function_with_multiple_files_in_zip():
}


if settings.TEST_SERVER_MODE:
if not settings.TEST_DECORATOR_MODE:

@mock_aws
def test_invoke_function_get_ec2_volume():
Expand Down
3 changes: 1 addition & 2 deletions tests/test_awslambda/test_lambda_layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
from tests.test_awslambda import delete_all_layer_versions
from tests.test_s3 import s3_aws_verified

from .utilities import get_role_name, get_test_zip_file1
from .utilities import PYTHON_VERSION, get_role_name, get_test_zip_file1

PYTHON_VERSION = "python3.11"
_lambda_region = "us-west-2"

boto3_version = sys.modules["botocore"].__version__
Expand Down
4 changes: 2 additions & 2 deletions tests/test_awslambda/test_lambda_layers_invoked.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from .utilities import _process_lambda, get_role_name

PYTHON_VERSION = "python3.11"
PYTHON_VERSION = "python3.13"
_lambda_region = "us-west-2"


Expand Down Expand Up @@ -56,7 +56,7 @@ def test_invoke_local_lambda_layers():

function_arn = conn.create_function(
FunctionName=lambda_name,
Runtime="python3.11",
Runtime=PYTHON_VERSION,
Role=get_role_name(),
Handler="lambda_function.lambda_handler",
Code={"ZipFile": get_requests_zip_file()},
Expand Down
16 changes: 6 additions & 10 deletions tests/test_awslambda/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
import pytest
from botocore.exceptions import ClientError

from moto import mock_aws, settings
from moto import mock_aws

PYTHON_VERSION = "python3.13"
_lambda_region = "us-west-2"


Expand All @@ -33,21 +34,16 @@ def lambda_handler(event, context):


def get_test_zip_file2():
base_url = (
"motoserver:5000"
if settings.TEST_SERVER_MODE
else "ec2.us-west-2.amazonaws.com"
)
func_str = f"""
func_str = """
import boto3

def lambda_handler(event, context):
ec2 = boto3.resource('ec2', region_name='us-west-2', endpoint_url='http://{base_url}')
ec2 = boto3.resource('ec2', region_name='us-west-2')

volume_id = event.get('volume_id')
vol = ec2.Volume(volume_id)

return {{'id': vol.id, 'state': vol.state, 'size': vol.size}}
return {'id': vol.id, 'state': vol.state, 'size': vol.size}
"""
return _process_lambda(func_str)

Expand Down Expand Up @@ -170,7 +166,7 @@ def create_invalid_lambda(role):
with pytest.raises(ClientError) as err:
conn.create_function(
FunctionName=function_name,
Runtime="python3.11",
Runtime=PYTHON_VERSION,
Role=role,
Handler="lambda_function.handler",
Code={"ZipFile": zip_content},
Expand Down
14 changes: 3 additions & 11 deletions tests/test_secretsmanager/test_secretsmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1187,10 +1187,7 @@ def test_rotate_secret_rotation_period_too_long():


def get_rotation_zip_file():
endpoint = "" if allow_aws_request() else 'endpoint_url="http://motoserver:5000"'

func_str = (
"""
func_str = """
import boto3
import json
import os
Expand All @@ -1200,9 +1197,7 @@ def lambda_handler(event, context):
token = event['ClientRequestToken']
step = event['Step']

client = boto3.client("secretsmanager", region_name="us-east-1", """
+ endpoint
+ """)
client = boto3.client("secretsmanager", region_name="us-east-1")
metadata = client.describe_secret(SecretId=arn)
metadata.pop('LastChangedDate', None)
metadata.pop('LastAccessedDate', None)
Expand All @@ -1223,9 +1218,7 @@ def lambda_handler(event, context):
pending_value = str(e)
print(pending_value)

dynamodb = boto3.resource("dynamodb", region_name="us-east-1", """
+ endpoint
+ """)
dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
table = dynamodb.Table(os.environ["table_name"])
table.put_item(Item={"pk": step, "token": token, "metadata": metadata, "versions": versions, "pending_value": pending_value})

Expand Down Expand Up @@ -1276,7 +1269,6 @@ def lambda_handler(event, context):
RemoveFromVersionId=token
)
"""
)
return _process_lambda(func_str)


Expand Down
Loading