Terraform aws dynamodb 项目 - 数据准备

Terraform aws dynamodb item - preparation of data

我正在尝试从输入变量将数据加载到 dynamodb table。我正在使用 locals 将输入数据处理成正确的形状,以便加载到我的 table 中。看似简单的事情却有

我的变量定义:

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 = []
}

正在初始化该变量:

  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"
    }
    ]
  }]

我尝试将变量转换为 dynamodb 项目条目。这就是我的问题所在。

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}"}
  }
]
}

  ])
}

这会产生以下错误:

Invalid value for "v" parameter: cannot convert tuple to map of any single type.

正在加载到 dynamodb table(显然没有那么远):

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
}

如果我不需要做替换,我可以有类似这样的东西,但我不知道如何在其中包含我的替换?:

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
  ])
}

您可以使用 jsonencode:

Substitutions 添加到您的第二个表单
    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
  ])
  

但这不太可能奏效,因为 TF 无法处理如此复杂的数据结构,您最终会遇到 cannot unmarshal array 错误。该问题已在 TF 中多次报告,例如here.

因此您必须将 templates 项目简化为常规平面图,而不是嵌套,或者使用 local-exec 填充您的 dynamodb table。

我已经解决了这个问题。解决方案是 json 对整个 json 对象进行编码,并为我的替换对象列表使用 dynamodb L 和 M 属性类型。

注意 cannot unmarshall array 错误似乎与插入 DDB 时未使用正确的数组属性类型有关。我发现这个 post 很有用:

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}"}
    }
   }] }

})
  
  ])