1

I'm trying to generate a dynamic aws_db_parameter_group from a map in terraform. I was wondering if what I'm trying to do is even possible. Here is a sample code:

provider "aws" {
...
}

variable "key_values" {
  type = map(string)

  default = {
    "audit_trail" = "db,extended"
    "log_buffer" = "100"
  }
}

resource "aws_db_parameter_group" "test" {
  family = "oracle-ee"

  name = "test"

  dynamic "key_value" {
    for_each = var.key_values
    content {
        name = key_value.key
        value = key_value.value
    }
  }
}

The goal is that for each key, value in my variable, I want to generate a dynamic block with two values. One would be the key name and the second value would be value in the map. I've been reading this: https://www.terraform.io/docs/language/expressions/dynamic-blocks.html

And it looks like it is doable what I'm trying but I can't figure it out. Any suggestion?

Regards,

1 Answer 1

1

According to the documentation, the only possible dynamic block you can use is parameter I'll give you an example below.

resource "aws_db_parameter_group" "default" {
  name = "db-paramgroup-${var.project}-${var.env}"
  family = "mysql${var.engine_version}"

  dynamic "parameter" {
    for_each = var.custom_db_parameters
    content {
      name         = lookup(parameter.value, "name", null)
      value        = lookup(parameter.value, "value", null)
      apply_method = lookup(parameter.value, "apply_method", null)
    }
  }
  tags = var.tags
}

If you need to create multiple aws_db_parameter_groupresources in a dynamic way, you should use a count or for_each to make it work, I'll give you a new example below.


resource "aws_db_parameter_group" "default" {
  count = length(var.parameter_group_name) == 0 ? 1 : 0
  name = "db-paramgroup-${var.project}-${var.env}"
  family = "mysql${var.engine_version}"

  dynamic "parameter" {
    for_each = var.custom_db_parameters
    content {
      name         = lookup(parameter.value, "name", null)
      value        = lookup(parameter.value, "value", null)
      apply_method = lookup(parameter.value, "apply_method", null)
    }
  }
  tags = var.tags
}

in case you need more information about how a count works, you can refer to this link.

In addition, make sure you are using custom_db_parameters values like the following:

custom_db_parameters = [
    {
      name        = "database_parameter_name_one"
      value = "database_parameter_value_one"
      apply_method  = "immediate"

    },
    {
      name        = "database_parameter_name_two"
      value = "database_parameter_value_two"
      apply_method  = "pending-reboot"
    },

]

Make sure to have a proper value for the apply_method key, you have two possible values and it's important to understand if you need to apply it immediately or wait for the next reboot/maintenance window.

Sign up to request clarification or add additional context in comments.

9 Comments

Thank you very much Hugo. I'm having a look at the lookup.
My pleasure, I hope it may help you!
Did this work? I tried the same approach as mentioned above, but the lookup function always returns the default value "immediate".
Yes, this code should work, the lookup built-in function is validating the values you pass through the variable called custom_db_parameters into the for_each parameter, make sure you are passing the right value and then you can get the elements, notice if the value is not there, the lookup function will return a null by default (example above)
Hi, this code used to work but today, when I try, I got an error like this: │ Invalid value for "inputMap" parameter: lookup() requires a map as the first argument. Any idea?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.