The ambiguous export/import of resources between cross AWS stacks using serverless ('' o)
Tags: aws, javascript, serverless
Published: 2019-12-03 13:31:48

SO i exported my resources from stack A and i wanna use it in Stack B and precisely i wanna pass it to my lambda function …mmm what to do

Will first i've tried what the aws console saying about this 
U can have a quick look its kinda helpful to understand the basic principles behind the cross stack shared resources :

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html

Unfortunately this is didn't work for me so i checked the 2nd option which is trying to list all exported resources(variables)  inside my cloudformation stack using the aws sdk inside my lambda and you could do that using the following code


const aws = require('aws-sdk')

var params = {
    NextToken: ''
};
var cloudformation = new AWS.CloudFormation();
cloudformation.listExports(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else     console.log("cloudformation ",data);           // successful response
});



But this was a bad solution too much things to display and too much thing to expose 

![..mm what is next](https://media.giphy.com/media/oOTTyHRHj0HYY/giphy.gif)


So what would be the right way to do that ?
 
First let me explain the situation we are importing resources called UserPool that is being exported to the cloud formation from another repo and another stack

Like this
.
.

userPool:
  production:
    Fn::ImportValue :  yourProjectName-production-UserPool
  staging:
    Fn::ImportValue :  yourProjectName-staging-UserPool
  other:
    Fn::ImportValue :  yourProjectName-dev-UserPool
.
.


This is located in file cognito.yml and inside our serverless.yml we have a custom variable to reference it.

Like this


.
.
userPool: ${file(./config/resources/cognito.yml):userPool}
.
.

Now, the problem was to be able to pass this user pool id to a Lambda function
To do some stuff there

The api was defined in the serverless.yml file as following, and using the static pool id was working probaly
.
.
 list-owners:
    memorySize: 1024
    timeout: 5
    environment:
     COGNITO_POOL_ID: ‘static_pool_id’
    handler: src/api/get-owners.list
    alarms:
      - errorOccur
    events:
     - http:
          path: ‘/path’
          method: get
          cors:
            origin: '*'
            headers: ${self:custom.list-headers}
            allowCredentials: false
          authorizer: ${self:custom.authorizer}
.
.
Now if use what the aws console suggested in the documentation it will the environment should look like this
 environment:
     COGNITO_POOL_ID: Fn::ImportValue: userPool //sharedValueToImport

But this will return you an object value like this [object object]

And the reason is because the different levels  of the objects inside the .yml file

So the solution was to define a short hand to my cognito.yml file inside my custom functions

So inside the serverless.yml

And under custom i added 

userPoolExportKey: ${file(./config/resources/cognito.yml):userPoolExportKey}

And when on the api that I wanted to pass it the cognito pool id based on the environment 

I used it this way

list-owners:
 memorySize: 1024
 timeout: 5
 environment:
   COGNITO_POOL: ${cf:${self:custom.userPoolExportKey.${self:provider.stage}, self:custom.userPoolExportKey.other}}
 handler: src/api/get-owners.list
 alarms:
   - errorOccur
 events:
  - http:
       path: owners
       method: get
       cors:
         origin: '*'
         headers: ${self:custom.list-headers}
         allowCredentials: false
       authorizer: ${self:custom.authorizer}

And  inside the Lambda handler, you can get the COGNITO_POOL  from process.env.COGNITO_POOL