Repository: localstack/localstack

Issue:
Outputted Resources Not Available For Import
We are in the process of reorganizing our Lambda functions into a monorepo and utilizing shared resources (ApiGateway, IAM, S3) and want to us localstack to help with local development of our platform.  Unfortunately, we have seemed to run into a pretty big roadblock.

We are trying to share a single ApiGateway among multiple services.  We have a root service that defines and outputs the resource:

```yaml
resources:
  Resources:
    SharedGateway:
      Type: AWS::ApiGateway::RestApi
      Properties:
        Name: SharedGateway
  Outputs:
    apiGatewayRestApiId:
      Value:
        Ref: SharedGateway
      Export:
        Name: ${self:custom.stage}-SharedGateway-restApiId
    apiGatewayRestApiRootResourceId:
      Value:
        Fn::GetAtt:
          - SharedGateway
          - RootResourceId
      Export:
        Name: ${self:custom.stage}-SharedGateway-rootResourceId
```

When we deploy this function, the gateway is created as expected:

```json
❯ awslocal cloudformation describe-stacks                                                                                                                                                 
{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:us-east-1:000000000000:stack/root-service-local/380b2980-3d1f-49a7-8a8e-f455574dd463",
            "Parameters": [],
            "Tags": [
                {
                    "Value": "local",
                    "Key": "STAGE"
                }
            ],
            "Outputs": [
                {
                    "OutputKey": "ServerlessDeploymentBucketName",
                    "OutputValue": "root-service-local-ServerlessDeploymentBucket-V42VYOBG30M1"
                },
                {
                    "ExportName": "local-SharedGateway-restApiId",
                    "OutputKey": "apiGatewayRestApiId",
                    "OutputValue": "6lmwod0qxv"
                },
                {
                    "ExportName": "local-SharedGateway-rootResourceId",
                    "OutputKey": "apiGatewayRestApiRootResourceId",
                    "OutputValue": "1cgu6jfibl"
                }
            ],
            "CreationTime": "2010-07-27T22:28:28Z",
            "StackName": "root-service-local",
            "NotificationARNs": [],
            "StackStatus": "UPDATE_COMPLETE",
            "DisableRollback": false
        }
    ]
}
```

We are then importing the values into another service:

```yaml
provider:
  name: aws
  runtime: nodejs12.x
  region: ${opt:region, 'us-east-1'}
  apiGateway: 
    restApiId:
      'Fn::ImportValue': ${self:custom.stage}-SharedGateway-restApiId
    restApiRootResourceId:
      'Fn::ImportValue': ${self:custom.stage}-SharedGateway-rootResourceId
```

The issue arises when we attempt to deploy this service locally:

`ServerlessError: No export named local-SharedGateway-rootResourceId found.`

Sure enough, the shared gateway is not listed in the cloudformation exports:

```json
❯ awslocal cloudformation list-exports                                                                                                                                                    
{
    "Exports": []
}
```

Is this supported by Localstack?  Has anyone successfully shared resources between Lambda functions?  I feel that I am missing something simple...


Discussion:
Any news on it? It really looks like a simple issue.

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
@@ -1,5 +1,6 @@
 import sys
 import json
+import types
 import logging
 import traceback
 import six
@@ -18,7 +19,7 @@
 from moto.cloudwatch import models as cw_models
 from moto.cloudformation import parsing, responses
 from boto.cloudformation.stack import Output
-from moto.cloudformation.models import FakeStack
+from moto.cloudformation.models import FakeStack, cloudformation_backends
 from moto.cloudformation.exceptions import ValidationError, UnformattedGetAttTemplateException
 from localstack import config
 from localstack.constants import DEFAULT_PORT_CLOUDFORMATION_BACKEND, TEST_AWS_ACCOUNT_ID, MOTO_ACCOUNT_ID
@@ -404,6 +405,23 @@ def parse_output(output_logical_id, output_json, resources_map):
         """
         responses.DESCRIBE_STACKS_TEMPLATE = responses.DESCRIBE_STACKS_TEMPLATE.replace(find, replace)
 
+    # Patch CloudFormationBackend.update_stack method in moto
+
+    def make_cf_update_stack(cf_backend):
+        cf_update_stack_orig = cf_backend.update_stack
+
+        def cf_update_stack(self, *args, **kwargs):
+            stack = cf_update_stack_orig(*args, **kwargs)
+            # update stack exports
+            self._validate_export_uniqueness(stack)
+            for export in stack.exports:
+                self.exports[export.name] = export
+            return stack
+        return types.MethodType(cf_update_stack, cf_backend)
+
+    for region, cf_backend in cloudformation_backends.items():
+        cf_backend.update_stack = make_cf_update_stack(cf_backend)
+
     # Patch DynamoDB get_cfn_attribute(..) method in moto
 
     def DynamoDB_Table_get_cfn_attribute(self, attribute_name):


Test patch: