I am attempting to use moto 1.3.7 (via serverless / localstack) to create a lambda that is triggered by SQS. When I tried to deploy I got the following stack trace
File ".venv/lib/python3.6/site-packages/werkzeug/serving.py", line 270, in run_wsgi
execute(self.server.app)
File ".venv/lib/python3.6/site-packages/werkzeug/serving.py", line 258, in execute
application_iter = app(environ, start_response)
File ".venv/lib/python3.6/site-packages/moto/server.py", line 101, in __call__
return backend_app(environ, start_response)
File ".venv/lib/python3.6/site-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File ".venv/lib/python3.6/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File ".venv/lib/python3.6/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File ".venv/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File ".venv/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File ".venv/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File ".venv/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File ".venv/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File ".venv/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File ".venv/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File ".venv/lib/python3.6/site-packages/moto/core/utils.py", line 140, in __call__
result = self.callback(request, request.url, {})
File ".venv/lib/python3.6/site-packages/moto/core/responses.py", line 117, in dispatch
return cls()._dispatch(*args, **kwargs)
File ".venv/lib/python3.6/site-packages/moto/core/responses.py", line 200, in _dispatch
return self.call_action()
File ".venv/lib/python3.6/site-packages/moto/core/responses.py", line 274, in call_action
response = method()
File ".venv/lib/python3.6/site-packages/moto/cloudformation/responses.py", line 262, in update_stack
tags=tags,
File ".venv/lib/python3.6/site-packages/moto/cloudformation/models.py", line 241, in update_stack
stack.update(template, role_arn, parameters=parameters, tags=tags)
File ".venv/lib/python3.6/site-packages/moto/cloudformation/models.py", line 111, in update
self.resource_map.update(self.template_dict, parameters)
File ".venv/lib/python3.6/site-packages/moto/cloudformation/parsing.py", line 483, in update
resource_name, resource_json, self, self._region_name)
File ".venv/lib/python3.6/site-packages/moto/cloudformation/parsing.py", line 299, in parse_and_create_resource
resource_name, resource_json, region_name)
File ".venv/lib/python3.6/site-packages/moto/awslambda/models.py", line 445, in create_from_cloudformation_json
'StartingPosition': properties['StartingPosition']
KeyError: 'StartingPosition'
The CloudFormation JSON being deployed is
{
"AWSTemplateFormatVersion":"2010-09-09",
"Description":"The AWS CloudFormation template for this Serverless application",
"Resources":{
"ServerlessDeploymentBucket":{
"Type":"AWS::S3::Bucket"
},
"HelloLogGroup":{
"Type":"AWS::Logs::LogGroup",
"Properties":{
"LogGroupName":"/aws/lambda/localstack-poc-hello"
}
},
"IamRoleLambdaExecution":{
"Type":"AWS::IAM::Role",
"Properties":{
"AssumeRolePolicyDocument":{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal":{
"Service":[
"lambda.amazonaws.com"
]
},
"Action":[
"sts:AssumeRole"
]
}
]
},
"Policies":[
{
"PolicyName":{
"Fn::Join":[
"-",
[
"local",
"localstack-poc",
"lambda"
]
]
},
"PolicyDocument":{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action":[
"logs:CreateLogStream"
],
"Resource":[
{
"Fn::Sub":"arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/localstack-poc-hello:*"
}
]
},
{
"Effect":"Allow",
"Action":[
"logs:PutLogEvents"
],
"Resource":[
{
"Fn::Sub":"arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/localstack-poc-hello:*:*"
}
]
},
{
"Effect":"Allow",
"Action":[
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes"
],
"Resource":[
{
"Fn::GetAtt":[
"MyQueue",
"Arn"
]
}
]
}
]
}
}
],
"Path":"/",
"RoleName":{
"Fn::Join":[
"-",
[
"localstack-poc",
"local",
"us-east-1",
"lambdaRole"
]
]
}
}
},
"HelloLambdaFunction":{
"Type":"AWS::Lambda::Function",
"Properties":{
"Code":{
"S3Bucket":{
"Ref":"ServerlessDeploymentBucket"
},
"S3Key":"serverless/localstack-poc/local/1549333110291-2019-02-05T02:18:30.291Z/localstack-poc.zip"
},
"FunctionName":"localstack-poc-hello",
"Handler":"handler.hello",
"MemorySize":1024,
"Role":{
"Fn::GetAtt":[
"IamRoleLambdaExecution",
"Arn"
]
},
"Runtime":"python3.6",
"Timeout":6
},
"DependsOn":[
"HelloLogGroup",
"IamRoleLambdaExecution"
]
},
"HelloLambdaVersion7lxGKanE5nEnf91l0NuzeIbvYDLEqsyG73dMlYvIOGY":{
"Type":"AWS::Lambda::Version",
"DeletionPolicy":"Retain",
"Properties":{
"FunctionName":{
"Ref":"HelloLambdaFunction"
},
"CodeSha256":"6Mjv7NuUsRtLWrD6YhKZey2t4KM62BnZ+B8R5Ny/5ZY="
}
},
"HelloEventSourceMappingSQSMyQueue":{
"Type":"AWS::Lambda::EventSourceMapping",
"DependsOn":"IamRoleLambdaExecution",
"Properties":{
"BatchSize":10,
"EventSourceArn":{
"Fn::GetAtt":[
"MyQueue",
"Arn"
]
},
"FunctionName":{
"Fn::GetAtt":[
"HelloLambdaFunction",
"Arn"
]
},
"Enabled":"True"
}
},
"MyQueue":{
"Type":"AWS::SQS::Queue",
"Properties":{
"QueueName":"localstack-poc-queue"
}
}
},
"Outputs":{
"ServerlessDeploymentBucketName":{
"Value":{
"Ref":"ServerlessDeploymentBucket"
}
},
"HelloLambdaFunctionQualifiedArn":{
"Description":"Current Lambda function version",
"Value":{
"Ref":"HelloLambdaVersion7lxGKanE5nEnf91l0NuzeIbvYDLEqsyG73dMlYvIOGY"
}
}
}
}
As per https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html, StartingPosition is only required for Kineses an DynamoDB Streams. Is it possible to modify the code to make StartingPosition optional? I have done this on my local moto deployment and successfully deployed the CloudFormation JSON above. I am happy to create a pull request.
@jaygelman could you please either submit a PR or share the way you patched this? I'm in the same exact spot, where I'm using serverless with a Lambda+SQS, and having the exact same failure from CloudFormation.
@FnTm Change /opt/code/localstack/.venv/lib/python2.7/site-packages/moto/awslambda/models.py by modifying classEventSourceMapping's create_from_cloudformation_json and __init__ :
def __init__(self, spec):
# required
self.function_name = spec['FunctionName']
self.event_source_arn = spec['EventSourceArn']
self.starting_position = spec.get('StartingPosition', 'LATEST')
# optional
self.batch_size = spec.get('BatchSize', 100)
self.enabled = spec.get('Enabled', True)
self.starting_position_timestamp = spec.get('StartingPositionTimestamp',
None)
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json,
region_name):
properties = cloudformation_json['Properties']
spec = {
'FunctionName': properties['FunctionName'],
'EventSourceArn': properties['EventSourceArn']
}
optional_properties = 'BatchSize Enabled StartingPositionTimestamp'.split()
for prop in optional_properties:
if prop in properties:
spec[prop] = properties[prop]
return EventSourceMapping(spec)
Thanks; it looks like we don't support this right now. I'm going to set it as a feature request.
Bump, please! I need this fix. :)
I'm assuming that this will be fixed in #2376
Closing this - #2376 should now be included in 1.3.14
Feel free to open a new issue if something are still missing
Most helpful comment
Thanks; it looks like we don't support this right now. I'm going to set it as a feature request.