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 = "test@xyz.com"
},
{
Type = "EMAIL"
Address = "test2@xyz.com"
}]
}
}
NotificationsEmail = [
{
Type = "EMAIL"
Address = "test@xyz.com"
},
{
Type = "EMAIL"
Address = "test2@xyz.com"
}]
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, usejsonencode
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 = "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
}
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":"test2@xyz.com","Type":"EMAIL"}
SubscriptionName: DailyAnomalySubscription
Which is a perfectly valid YAML document.