【问题标题】:Pass a CloudFormation YAML list via a JSON string parameter通过 JSON 字符串参数传递 CloudFormation YAML 列表
【发布时间】:2021-09-10 16:41:12
【问题描述】:

我正在尝试将现有负载均衡器导入 CloudFormation 堆栈。监听器必须指定为 YAML 列表,但列表(数组)或对象没有 CloudFormation 参数类型,因此 YAML 列表的参数必须是字符串。这导致以下 CloudFormation 错误

属性Listeners的值必须是List类型

使用 CLI 设置侦听器的字符串参数值 -

aws elb describe-load-balancers --load-balancer-names $ELB_DNS_NAME --query 'LoadBalancerDescriptions[0].ListenerDescriptions[].Listener' | jq --compact-output '.' | sed -e 's/"/\\"/g'

请注意,上述命令生成的 JSON 已转义。我怀疑这是问题的根本原因。

[
...
    {
        "ParameterKey": "ElbListeners",
        "ParameterValue": "[{\"Protocol\":\"TCP\",\"LoadBalancerPort\":443,\"InstanceProtocol\":\"TCP\",\"InstancePort\":31672},{\"Protocol\":\"TCP\",\"LoadBalancerPort\":80,\"InstanceProtocol\":\"TCP\",\"InstancePort\":30545}]"
    },
...
]

CloudFormation 似乎没有提供任何取消转义字符串参数的方法,因此以下模板失败。

AWSTemplateFormatVersion: 2010-09-09
Resources:
  ...
  IngressLoadBalancer:
    Type: AWS::ElasticLoadBalancing::LoadBalancer
    DeletionPolicy: Delete
    Properties: 
      Listeners: !Ref ElbListeners
      LoadBalancerName: !Ref ElbName


Parameters:
  ...
  ElbListeners:
    Type: String
    Description: Listeners for the load balancer
    Default: ""
  ElbName:
    Type: String
    Description: Name of the load balancer
    Default: ""

将生成的 JSON 中的引号替换为参数文件中的 ${quote},然后将 ${quote} 替换为使用 !Sub 的引号失败。 !Sub 的第一个输入似乎不能是 !Ref ParameterName

我不知道会有多少侦听器,因此在模板中硬编码侦听器列表并为端口/协议传递多个参数是不可行的。

如何将 YAML 列表作为 JSON 字符串参数传递?

【问题讨论】:

  • 愚蠢的问题:我对 YAML 没有那么丰富的经验,但是如果模板是在 YAML 中,那么侦听器列表不能/不应该在 YAML 中吗?请参阅此处并向下滚动到 YAML 示例:docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…
  • 我查看了文档。我不相信它实际上是在期待一个 JSON 字符串。它需要一个“类型:听众列表”docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…。因此,即使您可以做到,我认为在 YAML 中传递 JSON 字符串也不会成功。我是否可以为侦听器的每个值建议一个逗号分隔列表,然后为每种类型使用参数。然后使用 Fn::Select。这当然假设您有已知数量的侦听器,因为没有 for 循环逻辑。
  • @TimBassett - 是的,这就是问题所在。这不是与负载均衡器相关的问题,而是与 CloudFormation 相关的问题,其中正在导入的资源恰好是负载均衡器。 CloudFormation 资源 AWS::ElasticLoadBalancing::LoadBalancer 需要一个 YAML 侦听器列表。但是,CloudFormation 似乎没有提供可以通过参数传递 YAML 列表的机制。参数的类型非常有限,只留下String 作为一个可行的选项。我正在寻找解决该问题的方法。
  • 您是否有已知数量的听众,或者它是可变的?
  • 通常是两个(80 和 443),但不能保证。因此需要传递整个列表,而不是传递给每个侦听器的一部分。

标签: yaml amazon-cloudformation


【解决方案1】:

您可以获取 ElbListeners 参数的内容,然后将其插入模板中,然后将其从您的参数中删除。生成的模板如下所示:

AWSTemplateFormatVersion: 2010-09-09
Resources:
  ...
  IngressLoadBalancer:
    Type: AWS::ElasticLoadBalancing::LoadBalancer
    DeletionPolicy: Delete
    Properties: 
      Listeners:
        - Protocol: TCP
          LoadBalancerPort: 443
          InstanceProtocol: TCP
          InstancePort: 31672
        - Protocol: TCP
          LoadBalancerPort: 80
          InstanceProtocol: TCP
          InstancePort: 30545
      LoadBalancerName: !Ref ElbName


Parameters:
  ...
  ElbName:
    Type: String
    Description: Name of the load balancer
    Default: ""

【讨论】:

  • Listeners(YAML 列表)的值在部署 CloudFormation 模板之前是未知的,因此必须通过参数 (JSON) 传递。我寻求答案的难题是如何将 YAML 列表作为 JSON 字符串传递?
  • 你不能真正传入复杂的对象。您需要自己传递各个值。作为替代方案,您可以编译您的对象,将其提交给 S3,然后使用 AWS::Include 转换将其引入您的模板。
  • 谢谢,这是可能的,但我的保留是,它会使已经过于复杂的将现有资源导入堆栈的过程更加复杂。 CloudFormaiton 与 ARM 模板相比有多么有限,这让我感到非常震惊,因为这将是微不足道的。
猜你喜欢
  • 2019-02-05
  • 1970-01-01
  • 2016-10-26
  • 1970-01-01
  • 2018-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多