如何让Terraform数据模板文件识别数值类型?
I’ve run into this exact snag before working with Terraform and ECR lifecycle policies—template_file treats all variables as strings, which triggers JSON validation failures because ECR expects the countNumber field to be a numeric value, not a quoted string. Here are two straightforward fixes to resolve this:
Solution 1: Use jsonencode in Your Template File
The quickest fix is to wrap your numeric variables with Terraform’s jsonencode function in your lifecycle policy JSON template. This ensures numeric values render as unquoted numbers in the final output, while string values (like ${env}) stay properly formatted with quotes.
Update your lifecyclePolicyApp.json like this:
{ "rules": [ { "rulePriority": 1, "description": "Expire untagged images older than ${max_untagged_images} days", "selection": { "tagStatus": "untagged", "countType": "sinceImagePushed", "countUnit": "days", "countNumber": ${jsonencode(max_untagged_images)} }, "action": { "type": "expire" } }, { "rulePriority": 2, "description": "Expire tagged images of ${env}, older than ${max_tagged_images} days", "selection": { "tagStatus": "tagged", "countType": "imageCountMoreThan", "countNumber": ${jsonencode(max_tagged_images)}, "tagPrefixList": ["${env}"] }, "action": { "type": "expire" } } ] }
Notice we removed quotes around the numeric variables and wrapped them with jsonencode(). When rendered, this will output raw numbers (e.g., 30 instead of "30"), which ECR accepts without validation errors.
Solution 2: Switch to the templatefile Function (Recommended for Terraform 0.12+)
The data "template_file" resource is legacy—Terraform 0.12 and newer recommend using the built-in templatefile function instead. This function preserves variable types natively, so you won’t need extra encoding for numeric values.
First, remove your data "template_file" resources and update your aws_ecr_lifecycle_policy to use templatefile directly:
resource "aws_ecr_lifecycle_policy" "lifecycle" { count = length(aws_ecr_repository.repo) repository = aws_ecr_repository.repo[count.index].name depends_on = [aws_ecr_repository.repo] policy = var.policy_type == "app" ? templatefile("lifecyclePolicyApp.json", { max_untagged_images = var.max_untagged_images max_tagged_images = var.max_tagged_images env = var.env }) : templatefile("lifecyclePolicyInfra.json", { # Add your infrastructure policy variables here }) }
Then adjust your original lifecyclePolicyApp.json by removing quotes around the numeric variables—templatefile will render them as numbers automatically:
{ "rules": [ { "rulePriority": 1, "description": "Expire untagged images older than ${max_untagged_images} days", "selection": { "tagStatus": "untagged", "countType": "sinceImagePushed", "countUnit": "days", "countNumber": ${max_untagged_images} }, "action": { "type": "expire" } }, { "rulePriority": 2, "description": "Expire tagged images of ${env}, older than ${max_tagged_images} days", "selection": { "tagStatus": "tagged", "countType": "imageCountMoreThan", "countNumber": ${max_tagged_images}, "tagPrefixList": ["${env}"] }, "action": { "type": "expire" } } ] }
This approach is cleaner and aligns with modern Terraform best practices.
Either solution will fix the numeric type mismatch and let your ECR lifecycle policy validate successfully.
内容的提问来源于stack exchange,提问作者shadow

