Home > Net >  Terraform - Invalid template interpolation value
Terraform - Invalid template interpolation value

Time:12-08

I'm trying to use terraform to create an AnomalySubscription with AWS Cloudformation. Based on: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ce-anomalysubscription.html

When I tested Terraform plan, I'm receiving:

│ 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 = "[email protected]"
      },
      {
        Type = "EMAIL"
        Address = "[email protected]"
      }]
  }
}

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

    NotificationsEmail = [
      {
        Type = "EMAIL"
        Address = "[email protected]"
      },
      {
        Type = "EMAIL"
        Address = "[email protected]"
      }]

CodePudding user response:

An heredoc structure is always a string, this is why terraform complains that it cannot interpolate your tuple.

Since what you are actually feeding in the heredoc is YAML document, you can encode your tuple to YAML using jsonencode.

Why JSON encode? As pointed in the documentation, YAML is just a superset of 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.

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


Given a simplified:

variable "NotificationsEmail" {
  default = {
    Type = "EMAIL"
    Address = "[email protected]"
  }
}

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
}

This yields the expected:

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

Which is a perfectly valid YAML document.

  • Related