在无服务器 yaml 配置中使用 fn::split 不起作用
Posted
技术标签:
【中文标题】在无服务器 yaml 配置中使用 fn::split 不起作用【英文标题】:Using fn::split in Serverless yaml configuration not working 【发布时间】: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 你是怎么解决这个问题的? 【参考方案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 模式匹配。
【讨论】:
以上是关于在无服务器 yaml 配置中使用 fn::split 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
在无服务器框架中创建可用于 Lambda 函数的 RDS 实例
如何在 cloudformation yaml 中配置路由规则?
如何使用 spring boot + .yaml 创建配置文件?