如何在serverless.yml文件中添加条件?

13

我正在使用serverless框架部署api网关。我不想在每个服务器中应用VPC。是否有一种方法可以根据阶段名称添加以下配置?

provider:
  name: aws
  runtime: nodejs12.x

...

endpointType: PRIVATE
vpcEndpointIds:
    -  'Fn::ImportValue': 'api-gateway-endpoint'
resourcePolicy:
    - Effect: Deny
...
3个回答

17

在 serverless.yml 中,有几种条件部署的方式。其中一些比其他方法更脆弱,并且每种方法都有其优缺点,但以下是我收集到的方法列表:

使用变量控制条件

注意:我们使用自定义的正则表达式变量语法来区分 Serverless 变量和 cloudformation 变量语法。以下所有代码片段都使用了这种修改后的语法:

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}

使用条件操作

设置CloudFormation条件语句

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"]]

使用Cloudformation条件语句

如果你的条件有两个选项,可以这样书写:

# 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 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

奇怪的条件性技巧(如果您决定实施它们,请仔细阅读文档)

有条件地部署大量资源

使用Serverless通过环境变量设置的字符串,有选择地部署整个资源文件。

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

这也是通过条件语句切换多个资源部署的一种方式。 conditional_file_A.yaml 可以包含您要切换部署的所有资源,而 conditional_file_B.yaml 可以包含一个空的 Resources 列表(如果您不想从无服务器端收到“文件未找到”警告)。请保留 HTML 标签。
Resources:

在buildspec.yml文件或将被发送到CloudFormation(参数存储文件等)的.json文件中使用无服务器变量

如果您想有条件地修改将作为一些CloudFormation键的值发送部署的.json或.yml文件(例如为参数存储部署.json文件,或提交CodePipeline的buildspec.yml文件),则实际上不能在这些外部文件中使用${}无服务器语法。这是因为无服务器使用其自己的方法从外部文件调用Key/Values时会产生混淆

为了在这些文件中使用Serverless Variables,您可以使它们成为.txt扩展名,只要实际文件格式为正确的.json或.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)}}

谢谢,那真的很有帮助。只是想指出,serverless.yml 现在需要为变量条件值提供回退选项,所以 enabled: ${self:custom.scheduleEnabled.${self:custom.stage}} 变成了 enabled: ${self:custom.scheduleEnabled.${self:custom.stage}, false} - undefined

9
你可以查看以下答案:基于stage的条件serverless.yml? 因此,你会得到类似以下内容:
resources:
    Conditions:
        IsProd:
          Fn::Equals:
            - ${opt:stage}
            - prod  

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

3

另外,还有一个“Serverless Plugin Ifelse”插件可供选择

添加插件:

plugins:  
  - serverless-plugin-ifelse

然后添加您的条件:

custom:
.....
....

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

查看更多信息 Serverless插件if-else


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接