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
...
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.
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.
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.
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.
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.
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).
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.
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:
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._\\'\",\\-\\/\\(\\)]+?)}}"
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}
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"]]
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
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:
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)}}
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With