Search code examples
amazon-web-servicesterraformconditional-statementsamazon-rds

Terraform conditional option_settings in a dynamic option block


When using RDS option_groups, there are some options that require option_settings and some that don't. Terraform throws an error if the option_settings block is included with an option that doesn't use option settings, and terraform apply fails. I have a module that accepts a map of objects for RDS instances, including their option groups/options/option_settings. Within this is a resource that has an option that requires the option settings to be omitted (S3_INTEGRATION option). Below is the option_group resource block code being used:

resource "aws_db_option_group" "main" {
  for_each = {
    for name, rds in var.main : name => rds
    if rds.option_group_name != ""
  }
  name                     = each.value["option_group_name"]
  option_group_description = "Terraform Option Group"
  engine_name              = each.value["engine"]
  major_engine_version     = each.value["major_engine_version"]

  dynamic "option" {
    for_each = each.value["options"]
    content {
      option_name = option.key

      option_settings {
        name  = option.value["option_name"]
        value = option.value["option_value"]
      }
    }
  }
}

Is there a way to make the option_settings block creation in an option conditional to circumvent this?


Solution

  • Terraform supports nested dynamic blocks too, which in my understanding is something that you are looking for.

    Hashicorp documentation on Nested Dynamic Blocks: https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks#multi-level-nested-block-structures

    You can modify your aws_db_option_group module with the below code and make your option_settings optional for the module. It will work only when the values are supplied(but it also depends on the typing of the variable if its flexible).

    If you are already using Terraform version >= 1.3 then you also can use optional object type attributes already.

    Hashicorp documentations : https://www.hashicorp.com/blog/terraform-1-3-improves-extensibility-and-maintainability-of-terraform-modules

    resource "aws_db_option_group" "main" {
      for_each = {
        for name, rds in var.main : name => rds
        if rds.option_group_name != ""
      }
      name                     = each.value["option_group_name"]
      option_group_description = "Terraform Option Group"
      engine_name              = each.value["engine"]
      major_engine_version     = each.value["major_engine_version"]
    
      dynamic "option" {
        for_each = each.value["options"]
        content {
          option_name = option.key
    
          dynamic "option_settings" {
            for_each = option.value["option_settings"]
    
            content {
              name  = option_settings.key
              value = option_settings.value
            }
            ## Uncomment if you find this better and remove the above content block.
            # content {
            #   name  = option_settings.value["name"]
            #   value = option_settings.value["value"]
            # }
          }
        }
      }
    }
    

    Hope it helps.