From 482751f731516bcd60892d6104b554d8646203ac Mon Sep 17 00:00:00 2001 From: Hugo Lopes Tavares Date: Tue, 16 Feb 2016 16:43:33 -0500 Subject: [PATCH] [lambda] Add S3 validation for Code["S3Bucket"] and Code["S3Key"]. TODO: validate region. --- moto/awslambda/models.py | 21 ++++++++++- moto/awslambda/responses.py | 10 +++-- tests/test_awslambda/__init__.py | 63 +++++++++++++++++++++++++++----- 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index 0a8760964..bf928deb2 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -6,6 +6,8 @@ import hashlib import boto.awslambda from moto.core import BaseBackend +from moto.s3.models import s3_backend +from moto.s3.exceptions import MissingBucket class LambdaFunction(object): @@ -35,8 +37,23 @@ class LambdaFunction(object): self.code_size = len(code) self.code_sha_256 = hashlib.sha256(code).hexdigest() else: - self.code_size = 123 - self.code_sha_256 = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + # validate s3 bucket + try: + # FIXME: does not validate bucket region + key = s3_backend.get_key(self.code['S3Bucket'], self.code['S3Key']) + except MissingBucket: + raise ValueError( + "InvalidParameterValueException", + "Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist") + else: + # validate s3 key + if key is None: + raise ValueError( + "InvalidParameterValueException", + "Error occurred while GetObject. S3 Error Code: NoSuchKey. S3 Error Message: The specified key does not exist.") + else: + self.code_size = 123 + self.code_sha_256 = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' self.function_arn = 'arn:aws:lambda:123456789012:function:{}'.format(self.function_name) @property diff --git a/moto/awslambda/responses.py b/moto/awslambda/responses.py index 13457820a..73f969890 100644 --- a/moto/awslambda/responses.py +++ b/moto/awslambda/responses.py @@ -39,9 +39,13 @@ class LambdaResponse(BaseResponse): lambda_backend = self.get_lambda_backend(full_url) spec = json.loads(request.body) - fn = lambda_backend.create_function(spec) - config = fn.get_configuration() - return 201, headers, json.dumps(config) + try: + fn = lambda_backend.create_function(spec) + except ValueError as e: + return 400, headers, json.dumps({"Error": {"Code": e.args[0], "Message": e.args[1]}}) + else: + config = fn.get_configuration() + return 201, headers, json.dumps(config) def _delete_function(self, request, full_url, headers): lambda_backend = self.get_lambda_backend(full_url) diff --git a/tests/test_awslambda/__init__.py b/tests/test_awslambda/__init__.py index a6f53aa3b..cdd61db35 100644 --- a/tests/test_awslambda/__init__.py +++ b/tests/test_awslambda/__init__.py @@ -8,7 +8,18 @@ import zipfile import sure # noqa from freezegun import freeze_time -from moto import mock_lambda +from moto import mock_lambda, mock_s3 + + +def get_test_zip_file(): + zip_output = io.BytesIO() + with zipfile.ZipFile(zip_output, 'w') as f: + f.writestr('lambda_function.py', b'''\ +def handler(event, context): + return "hello world" +''') + zip_output.seek(0) + return zip_output.read() @mock_lambda @@ -22,7 +33,36 @@ def test_list_functions(): @mock_lambda @freeze_time('2015-01-01 00:00:00') +def test_create_based_on_s3_with_missing_bucket(): + conn = boto3.client('lambda', 'us-west-2') + + conn.create_function.when.called_with( + FunctionName='testFunction', + Runtime='python2.7', + Role='test-iam-role', + Handler='lambda_function.handler', + Code={ + 'S3Bucket': 'this-bucket-does-not-exist', + 'S3Key': 'test.zip', + }, + Description='test lambda function', + Timeout=3, + MemorySize=128, + Publish=True, + VpcConfig={ + "SecurityGroupIds": ["sg-123abc"], + "SubnetIds": ["subnet-123abc"], + }, + ).should.throw(botocore.client.ClientError) + + +@mock_lambda +@mock_s3 +@freeze_time('2015-01-01 00:00:00') def test_create_function_from_aws_bucket(): + s3_conn = boto3.client('s3', 'us-west-2') + s3_conn.create_bucket(Bucket='test-bucket') + s3_conn.put_object(Bucket='test-bucket', Key='test.zip', Body=get_test_zip_file()) conn = boto3.client('lambda', 'us-west-2') result = conn.create_function( @@ -71,14 +111,7 @@ def test_create_function_from_aws_bucket(): def test_create_function_from_zipfile(): conn = boto3.client('lambda', 'us-west-2') - zip_output = io.BytesIO() - with zipfile.ZipFile(zip_output, 'w') as f: - f.writestr('lambda_function.py', b'''\ -def handler(event, context): - return "hello world" -''') - zip_output.seek(0) - zip_content = zip_output.read() + zip_content = get_test_zip_file() result = conn.create_function( FunctionName='testFunction', Runtime='python2.7', @@ -115,8 +148,12 @@ def handler(event, context): @mock_lambda +@mock_s3 @freeze_time('2015-01-01 00:00:00') def test_get_function(): + s3_conn = boto3.client('s3', 'us-west-2') + s3_conn.create_bucket(Bucket='test-bucket') + s3_conn.put_object(Bucket='test-bucket', Key='test.zip', Body=get_test_zip_file()) conn = boto3.client('lambda', 'us-west-2') conn.create_function( @@ -165,7 +202,11 @@ def test_get_function(): @mock_lambda +@mock_s3 def test_delete_function(): + s3_conn = boto3.client('s3', 'us-west-2') + s3_conn.create_bucket(Bucket='test-bucket') + s3_conn.put_object(Bucket='test-bucket', Key='test.zip', Body=get_test_zip_file()) conn = boto3.client('lambda', 'us-west-2') conn.create_function( @@ -190,12 +231,16 @@ def test_delete_function(): @mock_lambda +@mock_s3 @freeze_time('2015-01-01 00:00:00') def test_list_create_list_get_delete_list(): """ test `list -> create -> list -> get -> delete -> list` integration """ + s3_conn = boto3.client('s3', 'us-west-2') + s3_conn.create_bucket(Bucket='test-bucket') + s3_conn.put_object(Bucket='test-bucket', Key='test.zip', Body=get_test_zip_file()) conn = boto3.client('lambda', 'us-west-2') conn.list_functions()['Functions'].should.have.length_of(0)