skip to Main Content

I’ve the following variable:

variable "mymap" {
  type = map(string)
  default = {
    "key1" = "val1"
    "key2" = "val2"
  }
}

I am trying to expand this to create individual parameters in this resource:

resource "aws_elasticache_parameter_group" "default" {
  name   = "cache-params"
  family = "redis2.8"

  parameter {
    name  = "activerehashing"
    value = "yes"
  }

  parameter {
    name  = "min-slaves-to-write"
    value = "2"
  }
}

My desired state for this example would be:

resource "aws_elasticache_parameter_group" "default" {
  name   = "cache-params"
  family = "redis2.8"

  parameter {
    name  = "key1"
    value = "val1"
  }

  parameter {
    name  = "key2"
    value = "val2"
  }
}

I don’t see this supported explicitly in the docs; am I even taking the correct approach to doing this?

(I’m mainly looking at leveraging ‘dynamic’ and ‘for_each’ keywords, but haven’t been able to have success)

2

Answers


  1. To achieve the desired state, you would have to do a couple of things. One could be to use dynamic meta-argument [1] with for_each [2]. The code would have to be changed to the following:

    resource "aws_elasticache_parameter_group" "default" {
      name   = "cache-params"
      family = "redis2.8"
    
      dynamic "parameter" {
        for_each = var.mymap
        content {
          name  = parameter.value.name
          value = parameter.value.value
        }
      }
    }
    

    However, you would also have to adjust the variable:

    variable "mymap" {
      type        = map(map(string))
      description = "Map of parameters for Elasticache."
    
      default = {
        "parameter1" = {
          "value" = "value1"
          "name"  = "name1"
        }
      }
    }
    

    Then, you can define the values for the variable mymap in a tfvars file (e.g., terraform.tfvars) like this:

    mymap = {
      "parameter1" = {
        "name"  = "activerehashing"
        "value" = "yes"
      }
      "parameter2" = {
        "name"  = "min-slaves-to-write"
        "value" = "2"
      }
    }
    

    [1] https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks

    [2] https://developer.hashicorp.com/terraform/language/meta-arguments/for_each

    Login or Signup to reply.
  2. You can use a dynamic block to dynamically declare zero or more nested configuration blocks based on a collection.

    resource "aws_elasticache_parameter_group" "default" {
      name   = "cache-params"
      family = "redis2.8"
    
      dynamic "parameter" {
        for_each = var.mymap
        content {
          name  = parameter.key
          value = parameter.value
        }
      }
    }
    

    The above tells Terraform to generate one parameter block for each element of var.varmap, and to populate the name and value arguments of each generated block based on the key and value from each map element respectively.

    The parameter symbol inside the content block represents the current element of the collection. This symbol is by default named after the block type being generated, which is why it was named parameter in this case. It’s possible to override that generated name using an additional iterator argument in the dynamic block, but that’s necessary only if you are generating multiple levels of nesting where a nested block type has the same name as its container.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search