Conditional serverless.yml based on stage?

aws

#1

I need to make it so a certain scheduled events do not run unless they are running on our prod stage. Is there any syntax that cam be used in serverless.yml to make it so it automatically checks this when running. For instance something like

enabled : ${opt:stage == prod}

Thanks!


Conditionally deploy endpoints?
#2

Conditional logic isn’t supported.

If you know all of the environments you’re deploying to then you could do something like:

custom:
  enabled:
    dev: false
    prod: true

enabled: ${self:custom.enabled.${opt:stage, self:provider.stage}}

#3

Fantastic! Not conditional, but that works great for our case as we have 3 set stage names. Thanks for the help!


#4

@buggy @DJHoltkamp you can totally do conditions in serverless .yml, and mappings too!

resources:
  Mappings:
    config:
      global:
        key: value
      dev:
        AuroraInstanceSize: db.t2.small
      test:
        AuroraInstanceSize: db.t2.small
      qa:
        AuroraInstanceSize: db.t2.small
      prod:
        AuroraInstanceSize: db.t2.medium
      

  Conditions:
    IsProd:
      Fn::Equals:
        - ${opt:stage}
        - prod  

   Resources:
      SomeIAMRole:
         Type: AWS::IAM::Role
         Condition: IsProd
         Properties:
            etc
            etc

#5

@ezeeetm You can simulate conditional logic in serverless.yml by placing the stage name into the path for a variable then defining the value for every possible stage. I’ve written about that many times including the solution I provided here. It’s good enough for most people but it’s not the same as IF x THEN y ELSE z conditional logic.

CloudFormation is more flexible but it only helps you if you need the conditional logic in the CloudFormation template generated by Serverless. If you need the conditional logic as part of running the Serverless command (for example the plugins to include) then you need to use the stage in the path trick.


#6

Building on the solution by @buggy. If you don’t know all the environments you will be deploying to you could do something like this:

custom:
  enabled:
    dev: true
    prod: true
    other: false

enabled: ${self:custom.enabled.${opt:stage}, self.enabled.other}

So the other stage become all other stages apart from dev and prod


#7

Perfect, just what I was looking for :+1:


#8

I was responding more to this. Cloudformation conditional logic is supported, and (as you say) a bit more flexible than the variable replacement provided by sls. I follow a ‘write once run everywhere’ highly parameterized pattern for my infrastructure code, so sometimes I have 30 or more params for a given stack…cfn mappings and conditions are really the best way to handle that kind of parameterizations.

to be fair, I came to sls from many years of cfn, so I view sls more as a tool for making it easier to work with cfn, while others who came to sls first might just look at cfn as ‘the poo that sls spits out’, and prefer to stay in native sls as much as possible, which makes sense.


#9

@alechewitt
Not sure what is happening in your example…

Is the “self.enabled.other” part a typo?
Should it not be…
"${self:custom.enabled.other}"

also… I didn’t know it was legit to set vars outside of “custom”?


#10

@iDVB apologies for the late reply.

I was writing out the case where you want dev and prod to be enabled but all other stages to be disabled.

With your configuration looking something like this:

custom:
  enabled:
    dev: true
    prod: true
    other: false

enabled: ${self:custom.enabled.${opt:stage}, self.enabled.other}

If you deployed to a stage called uat then self:custom.enabled.${opt:stage} gets evaluated as self:custom.enabled.uat which does not exist. Therefore it will use the default value of self.enabled.other, which is false.

I wrote it like this because in some situations you might not know all the different stages you are going to be deploying to ahead of time. Therefore you can fallback onto a default value.