【问题标题】:Using fn::split in Serverless yaml configuration not working在无服务器 yaml 配置中使用 fn::split 不起作用
【发布时间】:2021-04-12 11:42:54
【问题描述】:

我正在使用无服务器框架在 AWS 上部署 API。我的serverless.yml 文件中有以下内容:

custom:
  vpcSettings:
    private:
      securityGroupIds:
        private:
          fn::split:
            delimiter: ','
            value: ${env:VPC_SG_ID}

VPC_SG_ID 包含以下字符串:sg-1111111111,sg-222222222,sg-3333333333

但是,在部署应用程序时,我收到以下错误: An error occurred: MyLambdaFunction - Value of property SecurityGroupIds must be of type List of String.

如果我对 SG 列表进行硬编码,它可以正常工作:

custom:
  vpcSettings:
    private:
      securityGroupIds:
        private:
          - "sg-1111111111"
          - "sg-2222222222"
          - "sg-3333333333"

为什么 fn::split 函数没有返回字符串列表?

编辑:

以下配置导致同样的错误

custom:
  vpcSettings:
    private:
      securityGroupIds:
        private:
          Fn::Split:
            - ','
            - ${env:VPC_SG_ID}

【问题讨论】:

  • 以下解决方案是否使用Split from parameter work?
  • @cramix 你是怎么解决这个问题的?

标签: amazon-web-services yaml amazon-cloudformation serverless-framework


【解决方案1】:

如果安全组作为输入参数添加到模板

Parameters:
  VPCSGID:
    Type: String
    Description: Comma separated Security Groups

安全组可以用!Split 分割成

SecurityGroupIds: !Split [",", !Ref VPCSGID]

可以用Fn:Split分割成

SecurityGroupIds: { "Fn::Split": [",", !Ref VPCSGID] }

sam deploy 的参数可以传递为

sam deploy --parameter-overrides 'ParameterKey=VPCSGID,ParameterValue=sg-011111,sg-222222'

【讨论】:

  • 问题是关于“无服务器框架”而不是“SAM”
【解决方案2】:

我正在尝试实现相同的目标,但我很确定您不能在 serverless.yml 中使用 CloudFormation 函数 (Fn::Split)。

替代解决方案 1

通过环境变量传递 YAML 列表/数组对于无服务器来说似乎是不可能的,因为我们无法编写代码来解析来自环境变量的字符串。也许你可以写一个无服务器插件,但我还没有研究过。

我假设您需要能够传递可变长度和任意值的列表,因此以下解决方案可能不适合您。

如果你有已知的值,你可以保留列表in serverless.yml 并选择一个带有 env var 的列表:

custom:
  sgLists:
    list1:
      - sg-11
      - sg-22
    list2:
      - sg-33
      - sg-44
  vpcSettings:
    private:
      securityGroupIds:
        private: ${self:custom.sgLists.${env:LIST_SELECTOR}}

...然后你选择一个列表:

LIST_SELECTOR=list1 sls print
LIST_SELECTOR=list2 sls print

如果您需要任意值,并且您的列表不会太长,那么您可以变得非常 hacky 并将每个列表项设置为 env var:

custom:
  sgLists:
    twoItems:
      - ${env:SG1}
      - ${env:SG2}
    threeItems:
      - ${env:SG1}
      - ${env:SG2}
      - ${env:SG3}
  vpcSettings:
    private:
      securityGroupIds:
        private: ${self:custom.sgLists.${env:LIST_SELECTOR}}

..并将所有内容作为环境变量提供:

LIST_SELECTOR=twoItems SG1=sg-11 SG2=sg-22 sls print
LIST_SELECTOR=threeItems SG1=sg-11 SG2=sg-22 SG3-33 sls print

替代方案 2

您还可以利用无服务器功能来reference properties in other files。您可以创建一个小的 YAML 文件(版本控制会忽略该文件):

cd `dirname "$0"`
cat <<EOF > ../sgConfig.yml
groups:
  - sg-11
  - sg-22
EOF

...然后在您的serverless.yml 中引用该文件:

custom:
  vpcSettings:
    private:
      securityGroupIds:
        private: ${file(./sgConfig.yml):groups}

解释错误信息

我认为您的错误消息是指您在需要 YAML 列表/数组时将 YAML 对象/字典传递到 private 的事实。关键是这与 YAML 语法有关。 Fn::Split 函数是 specific to AWS CloudFormation 的东西,我猜这个函数的“执行”发生在 AWS 基础设施中。

我们可以通过更改您的代码来提供一个列表来测试这个理论:

        private:
          - fn::split: # add the "-" for a list
            delimiter: ','

...然后你会看到类似的错误

Configuration error at 'custom.vpcSettings.private.securityGroupIds.private[0]': should be string

这意味着我们修复了之前的错误,但现在我们遇到了同样的问题,但降了一级,因为 fn::split: 是一个 YAML 对象/字典。您还可以添加另一个列表项,例如:

        private:
          - blah # add this line
          - fn::split:
            delimiter: ','

..您将看到错误消息更改为引用索引[1]。要证明 fn::split 值不特殊,请将其更改为其他值,例如:

        private:
          - blah
          - asdf:  # change this line
            delimiter: ','

...您会看到错误消息没有改变。这是因为 Serverless 不关心 CloudFormation 函数,它只是检查 YAML 模式匹配。

【讨论】:

    猜你喜欢
    • 2019-03-15
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-21
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多