Terraform - 模板插值无效

Terraform - Invalid template interpolation value

我正在尝试使用 terraform 通过 AWS Cloudformation 创建一个 AnomalySubscription。 基于:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalysubscription.html

当我测试 Terraform 计划时,我收到:

│ Error: Invalid template interpolation value


│     │ each.value.NotificationsEmail is tuple with 1 element
│
│ Cannot include the given value in a string template: string required.

resource.tf

resource "aws_cloudformation_stack" "anomaly_detection" {
  name = "${var.StackName}${each.value.Key}"

  for_each = { for i in local.anomalies : "${i.Key}" => i }

  template_body = <<EOF
  AWSTemplateFormatVersion: "2010-09-09"
  Description: Cost Anomaly Detection
  Resources:
    CostExplorer:
      Type: AWS::CE::AnomalySubscription
      Properties:
        Frequency: DAILY
        MonitorArnList: [!Ref CostExplorerServiceAnomalyMonitor]
        Subscribers: ${each.value.NotificationsEmail}
        SubscriptionName: DailyAnomalySubscription
        Threshold: ${each.value.Threshold}

EOF
}
locals {
  anomalies = flatten([
    for k, v in var.Anomalies : [
        {
          Key                    = k
          Type                   = v.Type
          NotificationsEmail     = v.NotificationsEmail
          Threshold              = v.Threshold
        }
    ]
  ])
}
Anomalies = {
  Subscription = {
    Type  = "Daily"
    Threshold = 500
    NotificationsEmail = [
      {
        Type = "EMAIL"
        Address = "test@xyz.com"
      },
      {
        Type = "EMAIL"
        Address = "test2@xyz.com"
      }]
  }
}

基于: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ce-anomalysubscription-subscriber.html

    NotificationsEmail = [
      {
        Type = "EMAIL"
        Address = "test@xyz.com"
      },
      {
        Type = "EMAIL"
        Address = "test2@xyz.com"
      }]

heredoc 结构始终是字符串,这就是为什么 terraform 抱怨它无法插入元组的原因。

由于您在 heredoc 中实际提供的是 YAML 文档,因此您可以使用 jsonencode.

将您的元组编码为 YAML

为什么JSON编码?正如文档中所指出的,YAML 只是 JSON:

的超集

yamlencode always uses YAML's "block style" for mappings and sequences, unless the mapping or sequence is empty. To generate flow-style YAML, use jsonencode instead: YAML flow-style is a superset of JSON syntax.

来源:https://www.terraform.io/docs/language/functions/yamlencode.html


给出一个简化的:

variable "NotificationsEmail" {
  default = {
    Type = "EMAIL"
    Address = "test2@xyz.com"
  }
}

output "test" {
  value = <<EOF
  AWSTemplateFormatVersion: "2010-09-09"
  Description: Cost Anomaly Detection
  Resources:
    CostExplorer:
      Type: AWS::CE::AnomalySubscription
      Properties:
        Frequency: DAILY
        MonitorArnList: [!Ref CostExplorerServiceAnomalyMonitor]
        Subscribers: ${jsonencode(var.NotificationsEmail)}
        SubscriptionName: DailyAnomalySubscription
  EOF
}

这会产生预期的结果:

AWSTemplateFormatVersion: "2010-09-09"
Description: Cost Anomaly Detection
Resources:
  CostExplorer:
    Type: AWS::CE::AnomalySubscription
    Properties:
      Frequency: DAILY
      MonitorArnList: [!Ref CostExplorerServiceAnomalyMonitor]
      Subscribers: {"Address":"test2@xyz.com","Type":"EMAIL"}
      SubscriptionName: DailyAnomalySubscription

这是一个完全有效的 YAML 文档。