Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reference CF resources attributes in serverless.yml #3426

Closed
mthenw opened this issue Mar 30, 2017 · 13 comments
Closed

Reference CF resources attributes in serverless.yml #3426

mthenw opened this issue Mar 30, 2017 · 13 comments

Comments

@mthenw
Copy link
Contributor

mthenw commented Mar 30, 2017

This is a Feature Proposal

Description

Let say I have a service that uses RDS MySQL DB

service: test

provider:
  name: aws
  environment:
    DB_ADDR: ???

functions:
  createUser:
    handler: index.create

resources:
  Resources: 
    DBCluster:
      Type: AWS::RDS::DBCluster
      Properties:
        Engine: aurora
        ...

The problem is that I cannot use return values from this resource and use it in function/service config. AWS::RDS::DBCluster has two return attributes Endpoint.Address & Endpoint.Port. Right now the only way is to copy/paste this value. It's a huge blocker for automated deployments.

Maybe something like ${self:resources.DBCluster.Endpoint.Address}?

@HyperBrain
Copy link
Member

Did you try to set the environment variable as GetAtt ?

environment:
  DB_ADDR:
    Fn::GetAtt:
      - DBCluster
      - Endpoint.Address

@mfulgo
Copy link

mfulgo commented Oct 18, 2018

This is an old ticket (and can probably be closed), but I found this helpful.

If you're trying to reference a parameter that you define in your resource, you can use the variable substitution:

functions:
  myFunction:
    ...
    environment:
      QUEUE_NAME: ${self:resources.Resources.MyQueue.Properties.QueueName}
...
resources:
  Resources:
    MyQueue:
      ...
      Properties:
        QueueName: MyQueuesName

If you need to access one of the resource's outputs (like its ARN), you can use the the Fn::GetAtt: as mentioned above.

@exoego
Copy link
Contributor

exoego commented Dec 9, 2018

Can this be resolved by Referencing CloudFormation Outputs and closed?
https://serverless.com/framework/docs/providers/aws/guide/variables/#reference-cloudformation-outputs

@dschep
Copy link
Contributor

dschep commented Dec 10, 2018

I don't thinks so @exoego. He's using cfn references within the same stack, not exports.

@pmuens
Copy link
Contributor

pmuens commented Feb 6, 2019

Don't we have the ${cf:} variable support which should make that work?

@dschep
Copy link
Contributor

dschep commented Feb 6, 2019

@pmuens that syntax is for interacting with stack exports

@henning
Copy link
Contributor

henning commented Nov 22, 2019

I also need to do something like that.
The difference is, that I don't want to set an environment variable (which actually works), but I want to set a cors origin to the value of a cloudfront distribution that i set up in the resources.

            origins:
              - http://localhost:3000
              - http://127.0.0.1:3000
              - Fn::GetAtt: [ FrontendCloudfront, DomainName ]

but it errors out with:

$ sls -s preview deploy
Serverless: Generating requirements.txt from Pipfile...
Serverless: Parsed requirements.txt from Pipfile in /Users/henning/project/.serverless/requirements.txt...
Serverless: Installing requirements from /Users/henning/project/.serverless/requirements/requirements.txt ...
Serverless: Running ...
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Injecting required Python packages to package...
 
  Type Error ---------------------------------------------
 
  TypeError: str.replace is not a function
      at /usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/cors.js:125:32
      at Array.map (<anonymous>)
      at AwsCompileApigEvents.regexifyWildcards (/usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/cors.js:125:17)
      at AwsCompileApigEvents.generateCorsResponseTemplate (/usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/cors.js:131:31)
      at AwsCompileApigEvents.generateCorsIntegrationResponses (/usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/cors.js:117:22)
      at /usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/cors.js:73:42
      at /usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:4905:15
      at baseForOwn (/usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:2990:24)
      at /usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:4874:18
      at Function.forEach (/usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:9342:14)
      at AwsCompileApigEvents.compileCors (/usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/cors.js:8:7)
      at AwsCompileApigEvents.tryCatcher (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/util.js:16:23)
      at Promise._settlePromiseFromHandler (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:547:31)
      at Promise._settlePromise (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:604:18)
      at Promise._settlePromise0 (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:649:10)
      at Promise._settlePromises (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:729:18)
      at _drainQueueStep (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:93:12)
      at _drainQueue (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:86:9)
      at Async._drainQueues (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:102:5)
      at Immediate.Async.drainQueues [as _onImmediate] (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:15:14)
      at processImmediate (internal/timers.js:439:21)
      at process.topLevelDomainCallback (domain.js:130:23)
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information ---------------------------
     Operating System:          darwin
     Node Version:              12.13.1
     Framework Version:         1.58.0
     Plugin Version:            3.2.5
     SDK Version:               2.2.1
     Components Core Version:   1.1.2
     Components CLI Version:    1.4.0

Setting an environment variable with the exact same construct works without problems, though.

I dont get why using getAtt for an environment var works, and using it for filling in a cors origin doesn't...

@mckennajones
Copy link

@mthenw did you ever find a clean solution to this problem?

@mthenw
Copy link
Contributor Author

mthenw commented Nov 27, 2019

@mckennajones not really :)

@cryptiklemur
Copy link

The Fn::GetAtt: doesn't seem to work anymore?

I'm getting this error: Configuration warning at 'provider.environment.SQS_QUEUE_URL': unsupported configuration format

service: test

provider:
  name: aws
  environment:
    SQS_QUEUE_URL:
      Fn::GetAtt:
        - NewSQSQueue
        - Arn

functions:
  createUser:
    handler: index.create

resources:
  Resources:
    NewSQSQueue:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: "queue-${opt:stage, self:provider.stage}.fifo"
        FifoQueue: true

@medikoo
Copy link
Contributor

medikoo commented Oct 9, 2020

Closing, as I believe it's possible now either by using CF intrinsic functions, or simply relying on ${self:resources.Resources..} vars resolution (for shorter, more maintainable path we may also define reusable part in custom and refer to it in both places via ${self:custom... })

@mthenw If I miss something, please explain in more detail.

@aequasi I believe issue you were having was addressed with #8307

@medikoo medikoo closed this as completed Oct 9, 2020
@iamhosseindhv
Copy link

iamhosseindhv commented Sep 5, 2022

Just to expand on @mfulgo 's answer, in a serverless.ts config file (and not .yaml), this would look something like:

provider: {
    // ...
    iam: {
      role: {
        statements: [
          {
            Effect: 'Allow',
            Action: ['your:action'],
            Resource: { 'Fn::GetAtt': ['NotificationsQueue', 'Arn'] }, // <-- this
          },
        ],
      },
    },
  }



resources: {
    Resources: {
      NotificationsQueue: {
        Type: 'AWS::SQS::Queue',
        // ...
      },
    },
  },

@relaxdiego
Copy link

Note that none of the previously proposed solutions/workarounds work if one needs to use the Ref function.

For example, given the following resource in serverless.yml

resources:
  Resources:
    SomeQueue:
      Type: AWS::SQS::Queue
      ...

Attempting to reference the above within the same serverless.yml via the following methods will not work:

provider:
  environment:
    SOME_ENV_VAR: !Ref SomeQueue  # Doesn't work; Treated as string literal.
    ...
provider:
  environment:
    SOME_ENV_VAR: Ref: SomeQueue  # Doesn't work; Treated as string literal.
    ...
provider:
  environment:
    SOME_ENV_VAR: { "Ref": "SomeQueue" }  # Doesn't work; Treated as string literal.
    ...
params:
  production:
    sqs_queue_url: !Ref SomeQueue  # Doesn't work; Treated as string literal.
    ...

provider:
  environment:
    SOME_ENV_VAR: "${param:sqs_queue_url}"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests