diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index 0f22c4a6c..fd2ce11c1 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -8,16 +8,21 @@ from moto.core import BaseBackend class LambdaFunction(object): def __init__(self, spec): - self.function_name = spec['FunctionName'] - self.run_time = spec['Runtime'] - self.role = spec['Role'] - self.handler = spec['Handler'] - self.description = spec['Description'] - self.timeout = spec['Timeout'] - self.memory_size = spec['MemorySize'] - self.vpc_config = spec.get('VpcConfig', {}) + # required self.code = spec['Code'] + self.function_name = spec['FunctionName'] + self.handler = spec['Handler'] + self.role = spec['Role'] + self.run_time = spec['Runtime'] + # optional + self.description = spec.get('Description', '') + self.memory_size = spec.get('MemorySize', 128) + self.publish = spec.get('Publish', False) + self.timeout = spec.get('Timeout', 3) + self.vpc_config = spec.get('VpcConfig', {}) + + # auto-generated self.version = '$LATEST' self.last_modified = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') self.code_size = 210 # hello world function @@ -53,6 +58,28 @@ class LambdaFunction(object): "Configuration": self.get_configuration(), } + @classmethod + def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): + properties = cloudformation_json['Properties'] + + backend = lambda_backends[region_name] + fn = backend.create_function({ + # required + 'Code': properties['Code'], + 'FunctionName': resource_name, + 'Handler': properties['Handler'], + 'Role': properties['Role'], + 'Runtime': properties['Runtime'], + + # optional + 'Description': properties.get('Description', ''), + 'MemorySize': properties.get('MemorySize', 128), + 'Publish': properties.get('Publish', False), + 'Timeout': properties.get('Timeout', 3), + 'VpcConfig': properties.get('VpcConfig', {}), + }) + return fn + class LambdaBackend(BaseBackend): diff --git a/moto/cloudformation/parsing.py b/moto/cloudformation/parsing.py index 418d736d5..ebdd83634 100644 --- a/moto/cloudformation/parsing.py +++ b/moto/cloudformation/parsing.py @@ -4,6 +4,7 @@ import functools import logging from moto.autoscaling import models as autoscaling_models +from moto.awslambda import models as lambda_models from moto.datapipeline import models as datapipeline_models from moto.ec2 import models as ec2_models from moto.elb import models as elb_models @@ -21,6 +22,7 @@ from boto.exception import BotoServerError MODEL_MAP = { "AWS::AutoScaling::AutoScalingGroup": autoscaling_models.FakeAutoScalingGroup, "AWS::AutoScaling::LaunchConfiguration": autoscaling_models.FakeLaunchConfiguration, + "AWS::Lambda::Function": lambda_models.LambdaFunction, "AWS::EC2::EIP": ec2_models.ElasticAddress, "AWS::EC2::Instance": ec2_models.Instance, "AWS::EC2::InternetGateway": ec2_models.InternetGateway, diff --git a/tests/test_cloudformation/test_cloudformation_stack_integration.py b/tests/test_cloudformation/test_cloudformation_stack_integration.py index 29b5396e1..4a7ff7f77 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_integration.py +++ b/tests/test_cloudformation/test_cloudformation_stack_integration.py @@ -13,6 +13,7 @@ import boto.redshift import boto.sns import boto.sqs import boto.vpc +import boto3 import sure # noqa from moto import ( @@ -22,6 +23,7 @@ from moto import ( mock_ec2, mock_elb, mock_iam, + mock_lambda, mock_rds, mock_redshift, mock_route53, @@ -1478,3 +1480,49 @@ def test_datapipeline(): stack_resources = cf_conn.list_stack_resources(stack_id) stack_resources.should.have.length_of(1) stack_resources[0].physical_resource_id.should.equal(data_pipelines['pipelineIdList'][0]['id']) + + +@mock_cloudformation +@mock_lambda +def test_lambda_function(): + conn = boto3.client('lambda', 'us-east-1') + template = { + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "lambdaTest": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": {"Fn::Join": [ + "\n", + """ + exports.handler = function(event, context) { + context.succeed(); + } + """.splitlines() + ]} + }, + "Handler": "index.handler", + "Description": "Test function", + "MemorySize": 128, + "Role": "test-role", + "Runtime": "nodejs", + } + }, + } + } + + template_json = json.dumps(template) + cf_conn = boto.cloudformation.connect_to_region("us-east-1") + cf_conn.create_stack( + "test_stack", + template_body=template_json, + ) + + result = conn.list_functions() + result['Functions'].should.have.length_of(1) + result['Functions'][0]['Description'].should.equal('Test function') + result['Functions'][0]['Handler'].should.equal('index.handler') + result['Functions'][0]['MemorySize'].should.equal(128) + result['Functions'][0]['Role'].should.equal('test-role') + result['Functions'][0]['Runtime'].should.equal('nodejs')