Dissecting Serverless Stacks (III)

Thumbnail

Dissecting Serverless Stacks (III)

The third post of this series showed how to make IAM statements an external file, so we can deploy that one but still work with the sls command. It still involved commenting out things in the configuration, so this post will show how to solve that issue.

When we are thinking about writing a Serverless project which can be deployed “all-in-one” or in some two-step process, we are basically discussion an “if/then/else” scenario. If we use the sls deploy command normally, it should work like any other SLS project. But if we add some option, it should react differently (like skipping the external IAM stack). On a first glance, SLS does not offer such a mechanic. But let’s see how we can make it work nonetheless

Command line options

You can define your own command line switches, which are called “options” in the Serverless Framework. These switches can then be referenced via a $(opt:name) statement:

custom:
  deployment_option: $(opt:deployment, 'standard')

If we include this block in our serverless.yml file, we define a command line option and its standard value. So basically this could be sls deploy or sls deploy --deployment standard. Or we could supply a different value. During the previous blog post of this series, we also learned that we can use references like $(custom.deployment_option) in our file to reference parts of the file.

So how can we implement different cases? The answer lies in something which can be considered a mapping and then a “double-reference”:

custom:
  deployment_option: $(opt:deployment, 'standard')
  imports:
    standard: $(file:iam.yaml)
    no_includes: ""
    
# ... other parts of the file ...

resources:
  - ${self:custom.imports.${self:custom.deployment_option}}
  - Description: ${self:functions.fancy.description}

This looks confusing at first, so let us have a closer look:

  • When we supply no --deployment option, the $(custom.deployment_option) reference will be standard. In that case, our reference will equal ${self.custom.imports.standard) and the content of this is the content of $(file:iam.yaml) - so our IAM stack.

  • But if we pass --deployment no_includes instead, the reference will equal ${self.custom.imports.no_includes}, which is just an empty string. While sls deploy will throw a warning about that, it will still result in the IAM stack not being included.

So in short: with sls deploy we have the IAM stack included, with sls deploy --deployment no_includes we will not have it included.