Repository: localstack/localstack

Issue:
Unable to deploy Lambdas with a DynamoDB stream as the event source
With the following serverless.yml file:
```yml
service: localtest

provider:
  name: aws
  runtime: nodejs10.x

functions:
  hello:
    handler: handler.hello
    events:
    - stream:
        type: dynamodb
        arn:
          Fn::GetAtt: [fooTable, StreamArn]

resources:
  Resources:
    fooTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: fooTable
        AttributeDefinitions:
          - AttributeName: foo
            AttributeType: S
        KeySchema:
          - AttributeName: foo
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        StreamSpecification:
          StreamViewType: NEW_AND_OLD_IMAGES

plugins:
- "serverless-localstack"

custom:
  localstack:
    stages:
      - "local"
```
It fails with a generic error (500) on the deployment end and with `:ERROR:localstack.services.cloudformation.cloudformation_starter: Unable to parse and create resource "HelloEventSourceMappingDynamodbFooTable": 'NoneType' object has no attribute 'function_arn'` on the localstack end.
It deploys fine to AWS.


Discussion:

Resolving patch:
diff --git a/localstack/services/cloudformation/cloudformation_starter.py b/localstack/services/cloudformation/cloudformation_starter.py
--- a/localstack/services/cloudformation/cloudformation_starter.py
+++ b/localstack/services/cloudformation/cloudformation_starter.py
@@ -339,6 +339,11 @@ def DynamoDB_Table_get_cfn_attribute(self, attribute_name):
     def DynamoDB2_Table_get_cfn_attribute(self, attribute_name):
         if attribute_name == 'Arn':
             return aws_stack.dynamodb_table_arn(table_name=self.name)
+        elif attribute_name == 'StreamArn':
+            if (self.stream_specification or {}).get('StreamEnabled'):
+                return aws_stack.dynamodb_stream_arn(self.name, 'latest')
+            return None
+        raise UnformattedGetAttTemplateException()
 
     dynamodb2_models.Table.get_cfn_attribute = DynamoDB2_Table_get_cfn_attribute
 
diff --git a/localstack/utils/cloudformation/template_deployer.py b/localstack/utils/cloudformation/template_deployer.py
--- a/localstack/utils/cloudformation/template_deployer.py
+++ b/localstack/utils/cloudformation/template_deployer.py
@@ -29,6 +29,10 @@ def select_attributes(obj, attrs):
     return result
 
 
+def get_bucket_location_config(**kwargs):
+    return {'LocationConstraint': aws_stack.get_region()}
+
+
 # maps resource types to functions and parameters for creation
 RESOURCE_TO_FUNCTION = {
     'S3::Bucket': {
@@ -36,7 +40,8 @@ def select_attributes(obj, attrs):
             'function': 'create_bucket',
             'parameters': {
                 'Bucket': ['BucketName', PLACEHOLDER_RESOURCE_NAME],
-                'ACL': lambda params, **kwargs: convert_acl_cf_to_s3(params.get('AccessControl', 'PublicRead'))
+                'ACL': lambda params, **kwargs: convert_acl_cf_to_s3(params.get('AccessControl', 'PublicRead')),
+                'CreateBucketConfiguration': lambda params, **kwargs: get_bucket_location_config()
             }
         }
     },
diff --git a/localstack/utils/common.py b/localstack/utils/common.py
--- a/localstack/utils/common.py
+++ b/localstack/utils/common.py
@@ -822,12 +822,12 @@ def generate_ssl_cert(target_file=None, overwrite=False, random=False, return_co
     key_file_content = key_file.getvalue().strip()
     file_content = '%s\n%s' % (key_file_content, cert_file_content)
     if target_file:
+        key_file_name = '%s.key' % target_file
+        cert_file_name = '%s.crt' % target_file
         # check existence to avoid permission denied issues:
         # https://github.com/localstack/localstack/issues/1607
         if not os.path.exists(target_file):
             save_file(target_file, file_content)
-            key_file_name = '%s.key' % target_file
-            cert_file_name = '%s.crt' % target_file
             save_file(key_file_name, key_file_content)
             save_file(cert_file_name, cert_file_content)
             TMP_FILES.append(target_file)


Test patch: