'Terraform aws dynamodb item - preparation of data
I'm trying to load data into a dynamodb table from input variables. I'm using locals to manipulate the input data into the correct shape for loading into my table. What seems like a simple thing has
My Variable definition:
variable "templates" {
description = "List of templates available to be used by notifications."
type = list(object({
description = string
html_part = string
text_part = string
template_id = string
subject = string
substitutions = list(object({
name = string
default = string
required = bool
}))
}))
default = []
}
Initialising that variable:
templates = [{
template_id = "TestNotification1"
subject = "This is a test"
description = "Test notification 1"
html_part = <<EOT
<html>
<body>
{{test}} This {{test1}} is {{test2}} the HTML Part
</body>
</html>
EOT
text_part = "This is a test"
substitutions = [{
default = "test"
required = true
name = "test1"
}
]
}]
My attempt to convert the variables into a dynamodb item entry. This is where my problem is.
locals {
templates = tomap([for template in var.templates :
{
"TemplateId": { "S": "${template.template_id}"},
"Type": { "S": "STANDARD"},
"TemplateDescription": { "S": "${template.description}"},
"Subject": { "S": "${template.subject}"},
"HtmlPart": { "S": "${replace(template.html_part,"\n","")}"},
"TextPart": { "S": "${template.text_part}"},
"Substitutions":[for substitution in template.substitutions : {
"Name" : { "S": "${substitution.name}"},
"Required" : { "S": "${substitution.required}"},
"DefaultValue" : { "S": "${substitution.default}"}
}
]
}
])
}
This produces the following error:
Invalid value for "v" parameter: cannot convert tuple to map of any single type.
Loading into dynamodb table (obviously not getting that far):
resource "aws_dynamodb_table_item" "templates" {
table_name = aws_dynamodb_table.default_template_table.name
hash_key = "TemplateId"
for_each = local.templates
item = each.value
}
If I didn't have to do the substitions I could have something like this which works, but I can't figure out how to include my substitutions in this?:
locals {
templates = toset([for template in var.templates :
<<ITEM
{
"TemplateId": { "S": "${template.template_id}"},
"Type": { "S": "STANDARD"},
"TemplateDescription": { "S": "${template.description}"},
"Subject": { "S": "${template.subject}"},
"HtmlPart": { "S": "${replace(template.html_part,"\n","")}"},
"TextPart": { "S": "${template.text_part}"}
}
ITEM
])
}
Solution 1:[1]
I've solved this. The solution is to jsonencode the whole json object and use the dynamodb L and M Attribute Type for my list of substituion objects.
Note the cannot unmarshall array error appeared to be related to not using the correct Attribute type for an array when inserting into DDB. I found this post useful: How can I store an array into dynamoDB table
locals {
templates = toset([for template in var.templates :
jsonencode({
"TemplateId": { "S": "${template.template_id}"},
"Type": { "S": "STANDARD"},
"TemplateDescription": { "S": "${template.description}"},
"Subject": { "S": "${template.subject}"},
"HtmlPart": { "S": "${replace(template.html_part,"\n","")}"},
"TextPart": { "S": "${template.text_part}"},
"Substitutions":{"L": [for substitution in template.substitutions : {
"M" : {
"Name" : { "S": "${substitution.name}"},
"DefaultValue" : { "S": "${substitution.default}"}
}
}] }
})
])
Solution 2:[2]
You can add Substitutions to your second form using jsonencode:
templates = toset([for template in var.templates :
<<ITEM
{
"TemplateId": { "S": "${template.template_id}"},
"Type": { "S": "STANDARD"},
"TemplateDescription": { "S": "${template.description}"},
"Subject": { "S": "${template.subject}"},
"HtmlPart": { "S": "${replace(template.html_part,"\n","")}"},
"TextPart": { "S": "${template.text_part}"},
"Substitutions":${jsonencode([for substitution in template.substitutions : {
"Name" : { "S": "${substitution.name}"},
"Required" : { "S": "${substitution.required}"},
"DefaultValue" : { "S": "${substitution.default}"}
}])}
}
ITEM
])
But this is unlikely to work anyway, as TF can't process such a complex data structure and you will end up with cannot unmarshal array error. The issue has been already reported in TF several times, e.g. here.
Thus you have to simplify your templates items to be regular flat maps, not nested, or use local-exec to populate your dynamodb table.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | user1148920 |
| Solution 2 | Marcin |
