Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I put condition in serverless.yml file?

I am using serverless framework to deploy api gateway. I don't want to apply VPC to every stage in serverless. Is there a way for me to add below configuration based on stage name?

provider:
  name: aws
  runtime: nodejs12.x

...

endpointType: PRIVATE
vpcEndpointIds:
    -  'Fn::ImportValue': 'api-gateway-endpoint'
resourcePolicy:
    - Effect: Deny
...
like image 690
Joey Yi Zhao Avatar asked Jan 15 '21 04:01

Joey Yi Zhao


People also ask

How do I use environment variables in serverless yml?

To reference environment variables, use the ${env:SOME_VAR} syntax in your serverless. yml configuration file. It is valid to use the empty string in place of SOME_VAR . This looks like " ${env:} " and the result of declaring this in your serverless.

How do I refer a property in serverless yml ML file?

Reference Properties In serverless. yml , use the ${self:someProperty} syntax in your serverless. yml . This functionality is recursive, so you can go as deep in the object tree as you want.

What is service in serverless Yaml?

Service. service: app. The service is simply the name of your project. Since Serverless lets us deploy a project in multiple stages (prod, dev, staging…), CloudFormation stacks will contain both the service name and the stage: app-prod , app-dev , etc.

What is serverless yml?

The serverless.yml is the heart of a serverless application. This file describes the entire application infrastructure, all the way from the programming language to resource access. The primary section of this YAML file is the provider.

How do I use self reference in yml serverless?

Reference Properties In serverless.yml To self-reference properties in serverless.yml, use the $ {self:someProperty} syntax in your serverless.yml. someProperty can contain the empty string for a top-level self-reference or a dotted attribute reference to any depth of attribute, so you can go as shallow or deep in the object tree as you want.

How do I reference a YAML file in serverless?

You can reference properties in other YAML or JSON files. To reference properties in other YAML files use the $ {file (./myFile.yml):someProperty} syntax in your serverless.yml configuration file. Files need to be referenced by relative paths, which should not reach out beyond project directory (by default service directory).

How do I reference environment variables in a yml file?

Referencing Environment Variables To reference environment variables, use the $ {env:SOME_VAR} syntax in your serverless.yml configuration file. It is valid to use the empty string in place of SOME_VAR.


Video Answer


3 Answers

There are a few ways to do conditional deployments in serverless.yml, some are more brittle than others and there are pros/cons to each but here is a list of methods I have collected:

Variables to control conditionals

NOTE: We use a custom regex variable syntax to separate Serverless variables from cloudformation variable syntax. All of the following snippets use this modified syntax:

provider:
  name: aws
  # Changes serverless variable to ${{}} double curly braces
  variableSyntax: "\\${{([ ~:a-zA-Z0-9._\\'\",\\-\\/\\(\\)]+?)}}"

Serverless Custom Variables

custom:
  scheduleEnabled:
    dev: true
    stage: true
    prod: true

# Then In lambda function declaration
    events:
      - schedule:
          name: MyScheduleName
          description: SomeDescription
          rate: cron(0/5 * * * ? *)
          # Use custom variable and the serverless `stage` supplied 
          # via your deployment command to choose whether this feature is enabled
          enabled: ${self:custom.scheduleEnabled.${self:custom.stage}} 
          input: {"_keepwarm": true}

Using Conditional Operations

Setting up CloudFormation Conditionals

resources:
  - Conditions:
      # True if they are equal ==
      MyCondition: [!Equals ["${{env:SOMETHING}}","SOME_STRING"]]
      # True if they are not equal !=
      MyConditionTwo: !Not [!Equals ["${{env:SOMETHING_ELSE}}","SOME_OTHER_STRING"]]
      # Using a custom serverless variable
      IsProd: [!Equals ["${{self:provider.stage}}","prod"]]

Using Cloudformation Conditionals

If your conditional has two options, you can write it as:

# If true choose X, if False choose Y
Source:
  Type: !If
    - MyCondition # Conditional Name
    - GITHUB # If condition is true
    - GITHUB_ENTERPRISE # if condition is false

If your conditional is something you want to toggle ON or OFF, you can write it as:

# If True do nothing, If False choose X
MyCodebuildSetup:
  Type: "AWS::CodeBuild::Project"
  VpcConfig: !If
    - MyCondition # Condition Name
    - !Ref AWS::NoValue # If True, AWS will not attach a VPC Config
    - VpcId: <My_VPC_ID> # If False, Use this VPC Config
      Subnets:
        - <my_VPC_Subnet>
      SecurityGroupIds:
        - <my_VPC_security_group

Weird Conditional Hacks (document usage well if you decide to implement them)

Conditionally deploying a large series of resources

Using Serverless to selectively deploy entire files of resources using strings set via environment variables.

resources:
  - ${{file(some_dir/conditional_file_${{env:MY_CONDITION}}.yml)}}

This is also a way to toggle deployment of many resources via conditionals.

conditional_file_A.yaml can contain all the resources you toggle deployment of, while conditional_file_B.yaml can contain an empty Resources list (If you don't want a "file not found" warning from serverless:

Resources:

Using Serverless Variables in buildspec.yml files or .json files that will be sent to cloudformation (parameter store files, etc)

If you want to conditionally modify a .json or .yml file that will be sent deployed as a value for some CloudFormation key (such as deploying a .json file for parameter store, or submitting buildspec.yml files for CodePipeline), you can't actually use ${} serverless syntax in these external files. This is because serverless gets confused with it's own method of calling Key/Values from external files.

In order to use Serverless Variables in these files, you can make them .txt extensions as long as the actual file is formatted as proper .json or .yml

Source:
  Type: CODEPIPELINE
  # This file can't have any serverless variables in it
  BuildSpec: ${{file(my_buildspec_file.yml)}}
Source:
  Type: CODEPIPELINE
  # This file CAN have serverless variables because it is 
  # interpreted by serverless as a .txt, the variables
  # are resolved and then it is sent to cloudformation as a string anyway
  BuildSpec: ${{file(my_buildspec_file_yaml_formatted.txt)}}
like image 54
noxasaxon Avatar answered Oct 22 '22 09:10

noxasaxon


You may check the following answers: Conditional serverless.yml based on stage?

Therefore, you get something like:

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

    Resources:
        SomeIAMRole:
            Type: AWS::IAM::Role
            Condition: IsProd
            Properties:
                etc
                etc
like image 31
elbik Avatar answered Oct 22 '22 09:10

elbik


Alternatively, there is a Serverless Plugin Ifelse

Add the plugin:

plugins:  
  - serverless-plugin-ifelse

and then add your conditions:

custom:
.....
....

  serverlessIfElse:
    - If: '"${opt:stage}" == "production"'    
      Set:
        functions.helloWorld.cors: true

see more info Serveless plugin if-else

like image 2
ramamoorthy_villi Avatar answered Oct 22 '22 09:10

ramamoorthy_villi