From 90d67db6eae20ccde57356b694e013fd5864d14a Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Thu, 13 Apr 2023 09:25:47 +0000 Subject: [PATCH] AWSLambda: Do not keep downloading Docker images (#6207) --- moto/awslambda/models.py | 11 +++----- moto/utilities/docker_utilities.py | 7 +++++ .../test_lambda_eventsourcemapping.py | 26 +++++++++---------- tests/test_awslambda/test_lambda_invoke.py | 13 +++++----- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index 56d1ea985..a83c42511 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -54,7 +54,7 @@ from .utils import ( from moto.sqs import sqs_backends from moto.dynamodb import dynamodb_backends from moto.dynamodbstreams import dynamodbstreams_backends -from moto.utilities.docker_utilities import DockerModel, parse_image_ref +from moto.utilities.docker_utilities import DockerModel from tempfile import TemporaryDirectory logger = logging.getLogger(__name__) @@ -127,11 +127,9 @@ class _DockerDataVolumeContext: ) volumes = {self.name: {"bind": settings.LAMBDA_DATA_DIR, "mode": "rw"}} - self._lambda_func.docker_client.images.pull( - ":".join(parse_image_ref("alpine")) - ) + self._lambda_func.ensure_image_exists("busybox") container = self._lambda_func.docker_client.containers.run( - "alpine", "sleep 100", volumes=volumes, detach=True + "busybox", "sleep 100", volumes=volumes, detach=True ) try: tar_bytes = zip2tar(self._lambda_func.code_bytes) @@ -775,9 +773,8 @@ class LambdaFunction(CloudFormationModel, DockerModel): ) for image_repo in image_repos: image_ref = f"{image_repo}:{self.run_time}" - full_ref = ":".join(parse_image_ref(image_ref)) try: - self.docker_client.images.pull(full_ref) + self.ensure_image_exists(image_ref) break except docker.errors.NotFound: pass diff --git a/moto/utilities/docker_utilities.py b/moto/utilities/docker_utilities.py index 4e152194a..df2987985 100644 --- a/moto/utilities/docker_utilities.py +++ b/moto/utilities/docker_utilities.py @@ -36,6 +36,13 @@ class DockerModel: self.docker_client.api.get_adapter = replace_adapter_send return self.__docker_client + def ensure_image_exists(self, name: str) -> None: + full_name = ":".join(parse_image_ref(name)) + try: + self.docker_client.images.get(full_name) + except: # noqa: E722 Do not use bare except + self.docker_client.images.pull(full_name) + def parse_image_ref(image_name: str) -> Tuple[str, str]: # podman does not support short container image name out of box - try to make a full name diff --git a/tests/test_awslambda/test_lambda_eventsourcemapping.py b/tests/test_awslambda/test_lambda_eventsourcemapping.py index 6f941203c..367591626 100644 --- a/tests/test_awslambda/test_lambda_eventsourcemapping.py +++ b/tests/test_awslambda/test_lambda_eventsourcemapping.py @@ -31,7 +31,7 @@ def test_create_event_source_mapping(): conn = boto3.client("lambda", region_name="us-east-1") func = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, @@ -64,7 +64,7 @@ def test_invoke_function_from_sqs(key): conn = boto3.client("lambda", region_name="us-east-1") func = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, @@ -119,7 +119,7 @@ def test_invoke_function_from_dynamodb_put(): function_name = str(uuid4())[0:6] func = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, @@ -171,7 +171,7 @@ def test_invoke_function_from_dynamodb_update(): function_name = str(uuid4())[0:6] func = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, @@ -224,7 +224,7 @@ def test_invoke_function_from_sqs_exception(): conn = boto3.client("lambda", region_name="us-east-1") func = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file_error()}, @@ -242,7 +242,7 @@ def test_invoke_function_from_sqs_exception(): assert response["State"] == "Enabled" entries = [] - for i in range(3): + for i in range(2): body = {"uuid": str(uuid.uuid4()), "test": f"test_{i}"} entry = {"Id": str(i), "MessageBody": json.dumps(body)} entries.append(entry) @@ -268,7 +268,7 @@ def test_invoke_function_from_sqs_exception(): if "I failed!" in event["message"]: messages = queue.receive_messages(MaxNumberOfMessages=10) # Verify messages are still visible and unprocessed - assert len(messages) == 3 + assert len(messages) == 2 return time.sleep(1) @@ -292,7 +292,7 @@ def test_invoke_function_from_sns(): function_name = str(uuid4())[0:6] result = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, @@ -345,7 +345,7 @@ def test_list_event_source_mappings(): conn = boto3.client("lambda", region_name="us-east-1") func = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, @@ -378,7 +378,7 @@ def test_get_event_source_mapping(): conn = boto3.client("lambda", region_name="us-east-1") func = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, @@ -409,7 +409,7 @@ def test_update_event_source_mapping(): conn = boto3.client("lambda", region_name="us-east-1") func1 = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, @@ -420,7 +420,7 @@ def test_update_event_source_mapping(): ) func2 = conn.create_function( FunctionName="testFunction2", - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, @@ -455,7 +455,7 @@ def test_delete_event_source_mapping(): conn = boto3.client("lambda", region_name="us-east-1") func1 = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file3()}, diff --git a/tests/test_awslambda/test_lambda_invoke.py b/tests/test_awslambda/test_lambda_invoke.py index 8b981c494..c228c2668 100644 --- a/tests/test_awslambda/test_lambda_invoke.py +++ b/tests/test_awslambda/test_lambda_invoke.py @@ -23,7 +23,6 @@ from .utilities import ( from ..markers import requires_docker _lambda_region = "us-west-2" -boto3.setup_default_session(region_name=_lambda_region) @pytest.mark.network @@ -34,7 +33,7 @@ def test_invoke_function_that_throws_error(): function_name = str(uuid4())[0:6] conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file_error()}, @@ -54,7 +53,7 @@ def test_invoke_function_that_throws_error(): logs = base64.b64decode(failure_response["LogResult"]).decode("utf-8") logs.should.contain("START RequestId:") - logs.should.contain("I failed!: Exception") + logs.should.contain("I failed!") logs.should.contain("Traceback (most recent call last):") logs.should.contain("END RequestId:") @@ -69,7 +68,7 @@ def test_invoke_requestresponse_function(invocation_type, key): function_name = str(uuid4())[0:6] fxn = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file1()}, @@ -248,7 +247,7 @@ def test_invoke_dryrun_function(): function_name = str(uuid4())[0:6] conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file1()}, @@ -321,7 +320,7 @@ def lambda_handler(event, context): client = boto3.client("lambda", region_name="us-east-1") client.create_function( FunctionName="test-lambda-fx", - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Description="test lambda function", @@ -348,7 +347,7 @@ def test_invoke_async_function(key): function_name = str(uuid4())[0:6] fxn = conn.create_function( FunctionName=function_name, - Runtime="python2.7", + Runtime="python3.8", Role=get_role_name(), Handler="lambda_function.lambda_handler", Code={"ZipFile": get_test_zip_file1()},