Passing Boolean values from CLI into serverless.yml


#1

Hi everyone,
I have a question regarding passing variables from the CLI. As far as I can see so far they seem to be interpreted as strings, is there any way a variable could be interpreted as a boolean?
my serverless.yml looks something like like this:

...
functions:

  poll_queue:
    ....
    events:
      - schedule:
          rate: rate(1 minute)
          enabled: ${opt:poll_enabled}

...

and I want to be able to do this:
serverless deploy --poll_enabled false
and
serverless deploy --poll_enabled true
however I think the variable is interpreted as a string and is therefore always enables the schedule


#2

I just ran into the exact same issue. @alechewitt did you (or anyone else) manage to find a solution for this?


#3

I’m in the same situation.
There is a closed-without-fix issue from v0.5 about this: https://github.com/serverless/serverless/issues/672


#4

My situation is this:
I need to set a boolean variable so that in our CI/CD builds, custom.dockerizePip is set to false.

The following does not work because the environment variable value is interpreted as a string, so any value will be interpreted as true.

custom:
  pythonRequirements:
    dockerizePip: ${env:DOCKERIZE_PIP}

and if the variable is not set, serverless complains thus:
A valid environment variable to satisfy the declaration 'env:DOCKERIZE_PIP' could not be found.

The following also does not work, because a boolean literal cannot appear as a default value:

custom:
  pythonRequirements:
    dockerizePip: ${env:DOCKERIZE_PIP, false}

Invalid variable reference syntax for variable false. You can only reference env vars, options, & files. You can check our docs for more info.

So here is my workaround. Externally, the environment variable DOCKERIZE_PIP is either set (for true) or not set for false. If it is not set, we default to a special custom variable ‘false’ to work around the inability to use a boolean literal as a default.

custom:
  false: false
  pythonRequirements:
    dockerizePip: ${env:DOCKERIZE_PIP, self:custom.false}

#5

@guyc thats a cool workaround but doesnt seem to work for me? Running serverless ^1.28.0


#6

That’s odd. Here’s a minimum serverless.yml file to demonstrate, maybe this will help. This test used sls version 1.31.

service: boolean-test
provider: 
 name: aws
custom:
  false: false
  test: ${env:BOOLEAN_TEST, self:custom.false}

With BOOLEAN_TEST not set:

$ sls --state dev print

service: boolean-test
provider:
  name: aws
custom:
  'false': false
  test: false

set the environment variable:

BOOLEAN_TEST=anything sls --state dev print
service: boolean-test
provider:
  name: aws
custom:
  'false': false
  test: anything

The value set to test is a string, but (at least for dockerizePip) it seems to be interpreted as a true value.


#7

Oh cool, I didnt know about sls --state dev print thats really helpful!

Ye so it looks like my variables are correct (booleans) as you mention:

  cacheInstitutions:
    handler: src/operations/cacheInstitutions/cacheInstitutions.main
    events:
      - schedule: null
        rate: rate(1 day)
        enabled: false

But for some reason the enabled: false doesnt work… perhaps because the null is there? Not sure why its there, this is it in my serverless.yml

cacheInstitutions:
    handler: src/operations/cacheInstitutions/cacheInstitutions.main
    events: 
      - schedule: 
        rate: rate(1 day)
        enabled: ${self:custom.enableSchedules}

Oh wait… is it because there is a space after schedule: ? jeeze thats a gotcha if thats the case…

Ah… its the indenting on schedule… Wow… I hate yml…

For future reference this is the correct structure:

cacheInstitutions:
    handler: src/operations/cacheInstitutions/cacheInstitutions.main
    events: 
      - schedule:
          rate: rate(1 day)
          enabled: ${self:custom.enableSchedules}

note: two indents for rate: and enabled:

… but now for some reason serverless deploy still doesnt set the cloudwatch trigger for the lambda to false? Any suggestions?


#8

It would be helpful to see how ${self:custom.enableSchedules} is assigned.

Here’s an example that very closely mirrors your use case…

service: boolean-test
provider: 
 name: aws
custom:
  false: false

functions:
  cacheInstitutions:
    handler: src/operations/cacheInstitutions/cacheInstitutions.main
    events:
      - schedule:
          rate: rate(1 day)
          enabled: ${env:BOOLEAN_TEST, self:custom.false}

Generate without setting BOOLEAN_TEST:

sls package
cat .serverless/cloudformation-template-update-stack.json 

look for this section in the cloudformation script. Note that State is “DISABLED”

"CacheInstitutionsEventsRuleSchedule1": {
  "Type": "AWS::Events::Rule",
  "Properties": {
    "ScheduleExpression": "rate(1 day)",
    "State": "DISABLED",
    "Targets": [
      {
        "Arn": {
          "Fn::GetAtt": [
            "CacheInstitutionsLambdaFunction",
            "Arn"
          ]
        },
        "Id": "cacheInstitutionsSchedule"
      }
    ]
  }
},

Generate with BOOLEAN_TEST set:

BOOLEAN_TEST=1 sls package
cat .serverless/cloudformation-template-update-stack.json 

and now State is “ENABLED”. Hooray!

"CacheInstitutionsEventsRuleSchedule1": {
  "Type": "AWS::Events::Rule",
  "Properties": {
    "ScheduleExpression": "rate(1 day)",
    "State": "ENABLED",
    "Targets": [
      {
        "Arn": {
          "Fn::GetAtt": [
            "CacheInstitutionsLambdaFunction",
            "Arn"
          ]
        },
        "Id": "cacheInstitutionsSchedule"
      }
    ]
  }
},

#9

@guyc hey thanks for your reply and thanks for the tips about sls package again really useful!

I did as you mentioned and indeed can replicate your results in .serverless/cloudformation-template-update-stack.json but if you then go ahead and deploy it seems like the stack’s cloud-watch enabled state doesnt change:

Oh… wait… if I then click on it, it then says Status: Disabled on the next page!

So I guess it is working! Jeeze AWS has a confusing interface :stuck_out_tongue:

Thanks again for all your help there!