I am creating some resources using the for_each method on Terraform version 0.14.15. The resource has an attirbute, input_parameters that takes a string in JSON format as its value. I am defining this value in a map variable utilizing separate objects. The value I am specifying as a string in JSON format, and I am getting an error upon execution that I need to declare a string. Any insight on fixing this error would be helpful. Below is how I have my resource and variable declared.
Resource
resource "aws_config_config_rule" "managed_rules" {
for_each = var.managed_rules
name = each.value.name
description = each.value.description
input_parameters = each.value.input_parameters
source {
owner = each.value.owner
source_identifier = each.value.source_identifier
}
depends_on = [aws_config_configuration_recorder.config_recorder]
}
Variable
variable "managed_rules" {
type = map(object({
name = string
description = string
owner = string
source_identifier = string
# Is there a variable for strings in JSON format?
input_parameters = string
}))
default = {
"1" = {
name = "alb-http-to-https-redirection-check"
description = "Checks whether HTTP to HTTPS redirection is configured on all HTTP listeners of Application Load Balancers. The rule is NON_COMPLIANT if one or more HTTP listeners of Application Load Balancer do not have HTTP to HTTPS redirection configured."
owner = "AWS"
source_identifier = "ALB_HTTP_TO_HTTPS_REDIRECTION_CHECK"
input_parameters = {
"MaximumExecutionFrequency" : "TwentyFour_Hours",
}
}
Error
This default value is not compatible with the variable's type constraint:
element "2": attribute "input_parameters": string required.
After updating code with jsonencode function and changing input_parameters to any, this is the error:
This default value is not compatible with the variable's type constraint:
collection elements cannot be unified.
You have a couple things going on here:
input_parameters to be a JSON-encoded stringSo (2) and (3) are conflicting. At some point, you have to convert your object into a JSON string. You can either do that before passing it in as an input variable, or change your input variable to accept objects and convert the object to JSON when providing it to the resource.
I'd choose the second option because it's more intuitive to pass the object into the module instead of a string. So, try this:
resource "aws_config_config_rule" "managed_rules" {
for_each = var.managed_rules
name = each.value.name
description = each.value.description
input_parameters = jsonencode(each.value.input_parameters)
source {
owner = each.value.owner
source_identifier = each.value.source_identifier
}
depends_on = [aws_config_configuration_recorder.config_recorder]
}
variable "managed_rules" {
type = map(object({
name = string
description = string
owner = string
source_identifier = string
# Is there a variable for strings in JSON format?
input_parameters = any
}))
default = {
"1" = {
name = "alb-http-to-https-redirection-check"
description = "Checks whether HTTP to HTTPS redirection is configured on all HTTP listeners of Application Load Balancers. The rule is NON_COMPLIANT if one or more HTTP listeners of Application Load Balancer do not have HTTP to HTTPS redirection configured."
owner = "AWS"
source_identifier = "ALB_HTTP_TO_HTTPS_REDIRECTION_CHECK"
input_parameters = {
"MaximumExecutionFrequency" : "TwentyFour_Hours",
}
}
Note that I've used jsonencode in the resource's input_parameters and I've changed the variable type for that field to any (so it will accept an object of any structure).
To add to Jordan's answer. I Had a similar concern when trying to add a json policy to a module.
I used the any object type in place of the string object type.
Here's how I fixed it:
Module main.tf
resource "aws_ecr_repository_policy" "main" {
repository = var.repository_name
policy = var.repository_policy
}
Module variables.tf
variable "repository_name" {
type = string
description = "Name of the repository."
}
variable "repository_policy" {
type = any
description = "The policy document. This is a JSON formatted string."
}
Resource Creation main.tf
# ECR Repository for container images
module "ecr_repository_1" {
source = "../../../../modules/aws/ecr-repository"
ecr_repository_name = var.ecr_repository_name.1
image_tag_mutability = var.image_tag_mutability
image_scan_on_push = var.image_scan_on_push
tag_environment = local.tag_environment
tag_terraform = local.tag_terraform.true
}
# ECR Repository policies
module "ecr_repository_policy_1" {
source = "../../../../modules/aws/ecr-repository-policy"
repository_name = var.ecr_repository_name.1
repository_policy = var.repository_policy.1
}
Resource creation variables.tf
variable "ecr_repository_name" {
type = map(string)
description = "Name of the repository."
default = {
"1" = "my-backend-api"
}
}
variable "image_tag_mutability" {
type = string
description = "The tag mutability setting for the repository. Must be one of: MUTABLE or IMMUTABLE. Defaults to MUTABLE."
default = "MUTABLE"
}
variable "image_scan_on_push" {
type = bool
description = "Indicates whether images are scanned after being pushed to the repository (true) or not scanned (false)."
default = true
}
variable "repository_policy" {
type = any
description = "The policy document. This is a JSON formatted string."
default = {
"1" = <<EOF
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "new policy",
"Effect": "Allow",
"Principal": "*",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
"ecr:DescribeRepositories",
"ecr:GetRepositoryPolicy",
"ecr:ListImages",
"ecr:DeleteRepository",
"ecr:BatchDeleteImage",
"ecr:SetRepositoryPolicy",
"ecr:DeleteRepositoryPolicy"
]
}
]
}
EOF
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With