Joey Yi Zhao
Joey Yi Zhao

Reputation: 42644

How can I use conditional configuration in serverless.yml for lambda?

I need to configure a lambda via serverless.yml to use different provision concurrency for different environments. Below is my lambda configuration:

 myLambda:
   handler: src/lambdas
   name: myLambda
   provisionedConcurrency: ${self:custom.pc}

...

custom:
  pc: ${env:PC}

The value PC is loaded from environment variable. It works for values greater than 0 but I can't set a value 0 in one environment. What I want to do is to disable provision concurrency in dev environment.

I have read through this doc https://forum.serverless.com/t/conditional-serverless-yml-based-on-stage/1763/3 but it doesn't seem to help in my case.

How can I set provisionedConcurrency conditional based on environment?

Upvotes: 5

Views: 7280

Answers (4)

Farley
Farley

Reputation: 1498

Method 1: Stage-based variables via default values

This is a fairly simple trick by using a cascading value variable. The first value is the one you want, the second one being a default, or fallback value. Also called cascading variables.

// serverless.yml
provider:
  stage: "dev"

custom:
  provisionedConcurrency:
    live: 100
    staging: 50
    other: 10

 myLambda:
   handler: src/lambdas
   name: myLambda
   provisionedConcurrency: ${self:custom.provisionedConcurrency.${self:provider.stage}, self:custom.provisionedConcurrency.other}

This above with stage set to dev will default to "other" value of 10, but if you set stage via serverless deploy --stage live then it will use the live value of 100.

See here for more details: https://www.serverless.com/framework/docs/providers/aws/guide/variables#syntax

Method 2: Asynchonous Value via Javascript

You can use an js include and put your conditional logic there. It's called "asynchronous value support". Basically, this allows you to put logic in a javascript file which you include and it can return different values depending on various things (like, what AWS account you're on, or if certain variables are set, or whatever). Basically, it allows you to do this...

provisionedConcurrency: ${file(./detect_env.js):get_provisioned_concurrency}

Which works if you create a javascript file in this folder called detect_env.js, and it has the contents similar to...

module.exports.get_provisioned_concurrency = () => {
  if ("put logic to detect which env you are deploying to, eg for live") {
    return Promise.resolve('100');
  } else {
    // Otherwise fallback to 10
    return Promise.resolve('10');
  }
}

For more info see: https://www.serverless.com/framework/docs/providers/aws/guide/variables#with-a-new-variables-resolver

I felt I had to reply here even though this was asked months ago because none of the answers were even remotely close to the right answer and I really felt sorry for the author or anyone who lands here.

Upvotes: 5

Adunin
Adunin

Reputation: 9

Just using a variable with a null value for dev environments during on deploy/package and SLS will skip this property:

provisionedConcurrency: ${self:custom.variables.provisionedConcurrency}

Upvotes: 0

Tobin
Tobin

Reputation: 2018

For really sticky problems, I find it's useful to go to the Cloudformation script instead and use the Cloudformation Intrinsic Functions.

For this case, if you know all the environments you could use Fn::FindInMap

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

Or if it's JUST production which needs 0 then you could use the conditional Fn::If and a boolean Condition test in the Cloudformation template to test if environment equals production, use 0, else use the templated value from SLS.

Potential SLS:

resources:
  Conditions:
    UseZero: !Equals ["production", ${provider.stage}]
  Resources:
    myLambda:
      ProvisionedConcurrency: !If [UseZero, 0, ${self:custom.pc}]

You can explicitly remove the ProvisionedConcurrency property as well if you want:

resources:
  Conditions:
    UseZero: !Equals ["production", ${provider.stage}]
  Resources:
    myLambda:
      ProvisionedConcurrency: !If [UseZero, AWS::NoValue, ${self:custom.pc}]

Edit: You can still use SLS to deploy; it simply compiles into a Cloudformation JSON template which you can explicitly modify with the SLS resources field.

Upvotes: 1

Gareth McCumskey
Gareth McCumskey

Reputation: 1540

The Serverless Framework provides a really useful dashboard tool with a feature called Parameters. Essentially what it lets you do is connect your service to it then you can set different values for different stages and then use those values in your serverless.yml with syntax like ${param:VARAIBLE_NANE_HERE} and it gets replaced at deploy time with the right value for whatever stage you are currently deploying. Super handy. There are also a bunch of other features in the dashboard such as monitoring and troubleshooting.

You can find out more about Parameters at the official documentation here: https://www.serverless.com/framework/docs/guides/parameters/

And how to get started with the dashboard here: https://www.serverless.com/framework/docs/guides/dashboard#enabling-the-dashboard-on-existing-serverless-framework-services

Upvotes: 0

Related Questions