Home > Software design >  Terraform dynamic loop to create multiple dynamodb
Terraform dynamic loop to create multiple dynamodb

Time:01-10

I'm trying to create a dynamic method to create multiple dynamodb tables with their own attributes. I tried for loops with dynamic blocks, list objects, etc but was not able to iterate attributes for each table. The goal is to have multiple tables with different attributes and global indexes for each table in one go. I have terraform.tfvars and main.tf with the following structure:

Variable declaration:

variable "dynamodb_table" {
  type = list(object({
    table_name         = string
    billing_mode       = string
    read_capacity      = optional(number)
    write_capacity     = optional(string)
    hash_key           = string
    ttl_attribute_name = string
    ttl_enabled        = string
    range_key          = optional(string)
    attribute = object({
      name = string
      type = string
    })
  }))
}

variable "global_secondary_indexes" {
  description = "Describe a GSI for the table; subject to the normal limits on the number of GSIs, projected attributes, etc."
  type = list(object({
    index_name               = string
    index_projection_type    = string
    index_range_key          = string
    index_hash_key           = string
    index_write_capacity     = optional(string)
    index_read_capacity      = optional(string)
    index_non_key_attributes = list(string)
  }))

  default = []
}
dynamodb_table = [
      {
        table_name   = "devops-test-01",
        billing_mode = "PAY_PER_REQUEST",
        hash_key           = "UserId",
        range_key          = "GameTitle",
        ttl_attribute_name = "ttl_attribute_name",
        ttl_enabled        = "false"
        attribute = [
          {
            name = "UserId"
            type = "S"
          },
          {
            name = "GameTitle"
            type = "S"
          }
        ]
      },
      {
        table_name   = "devops-test-02",
        billing_mode = "PAY_PER_REQUEST",
        hash_key           = "GameTitle",
        ttl_attribute_name = "ttl_attribute_name",
        ttl_enabled        = "false"
      }
    ]

    global_secondary_indexes = [
      {
        index_name               = "TitleIndex"
        index_hash_key           = "UserId"
        index_range_key          = "GameTitle"
        index_projection_type    = "INCLUDE"
        index_non_key_attributes = ["Id"]
      }

    ]

    default_tags = {
      "Environment" = "Dev",
      "Owner"       = "xxx"
    }
resource "aws_dynamodb_table" "basic-dynamodb-table" {
      for_each       = { for key, value in var.dynamodb_table : key => value }
      name           = each.value.table_name
      billing_mode   = each.value.billing_mode
      read_capacity  = each.value.read_capacity
      write_capacity = each.value.write_capacity
      hash_key       = each.value.hash_key
      range_key      = each.value.range_key
      ttl {
        attribute_name = each.value.ttl_attribute_name
        enabled        = each.value.ttl_enabled
      }

      dynamic "attribute" {

        for_each = { for key, value in var.attributes : key => value }
        content {
          name = attribute.value.name
          type = attribute.value.type
        }
      }

      dynamic "global_secondary_index" {
        for_each = var.global_secondary_indexes
        content {
          name               = global_secondary_index.value.index_name
          hash_key           = global_secondary_index.value.index_hash_key
          projection_type    = global_secondary_index.value.index_projection_type
          range_key          = lookup(global_secondary_index.value, "index_range_key", null)
          read_capacity      = lookup(global_secondary_index.value, "index_read_capacity", null)
          write_capacity     = lookup(global_secondary_index.value, "index_write_capacity", null)
          non_key_attributes = lookup(global_secondary_index.value, "index_non_key_attributes", null)
        }
      }


      tags = merge(
        var.default_tags,
        {
          Name = each.value.table_name
      })

    }

This code produces the following error:

The given value is not suitable for var.dynamodb_table declared at variable.tf:6,1-26: element 0: attribute │ "attribute": object required

CodePudding user response:

You did not share your attributes variable but I have used attributes in dynamodb_table variable.

Your main problem is attribute property in dynamodb_table variable is requeired but you did not provide any value for it in devops-test-02 table values.


variables.tf

variable "dynamodb_table" {
  type = list(object({
    table_name   = string
    billing_mode = string
    // read_capacity      = optional(number)
    //write_capacity     = optional(string)
    hash_key           = string
    ttl_attribute_name = string
    ttl_enabled        = string
    //range_key          = optional(string)
    attribute = list(object({
      name = string
      type = string
    }))
  }))
  default = [
    {
      table_name         = "devops-test-01",
      billing_mode       = "PAY_PER_REQUEST",
      hash_key           = "UserId",
      range_key          = "GameTitle",
      ttl_attribute_name = "ttl_attribute_name",
      ttl_enabled        = "false"
      attribute = [
        {
          name = "UserId"
          type = "S"
        },
        {
          name = "GameTitle"
          type = "S"
        }
      ]
    },
    {
      table_name         = "devops-test-02",
      billing_mode       = "PAY_PER_REQUEST",
      hash_key           = "GameTitle",
      ttl_attribute_name = "ttl_attribute_name",
      ttl_enabled        = "false"
      attribute = [
        {
          name = "UserId"
          type = "S"
        },
        {
          name = "GameTitle"
          type = "S"
        }
      ]
    }
  ]
}

variable "global_secondary_indexes" {
  description = "Describe a GSI for the table; subject to the normal limits on the number of GSIs, projected attributes, etc."
  type = list(object({
    index_name            = string
    index_projection_type = string
    index_range_key       = string
    index_hash_key        = string
    //index_write_capacity     = optional(string)
    //index_read_capacity      = optional(string)
    index_non_key_attributes = list(string)
  }))

  default = [
    {
      index_name               = "TitleIndex"
      index_hash_key           = "UserId"
      index_range_key          = "GameTitle"
      index_projection_type    = "INCLUDE"
      index_non_key_attributes = ["Id"]
    }
  ]
}

variable "default_tags" {
  default = {
    "Environment" = "Dev",
    "Owner"       = "xxx"
  }
}

dynamodb.tf

resource "aws_dynamodb_table" "basic-dynamodb-table" {
  for_each       = { for key, value in var.dynamodb_table : value.table_name => value }
  name           = each.value.table_name
  billing_mode   = each.value.billing_mode
  read_capacity  = lookup(each.value, "read_capacity", null)
  write_capacity = lookup(each.value, "write_capacity", null)
  hash_key       = each.value.hash_key
  range_key      = lookup(each.value, "range_key", null)
  ttl {
    attribute_name = each.value.ttl_attribute_name
    enabled        = each.value.ttl_enabled
  }

  dynamic "attribute" {
    for_each = { for key, value in each.value.attribute : key => value }
    content {
      name = attribute.value.name
      type = attribute.value.type
    }
  }

  dynamic "global_secondary_index" {
    for_each = var.global_secondary_indexes
    content {
      name               = global_secondary_index.value.index_name
      hash_key           = global_secondary_index.value.index_hash_key
      projection_type    = global_secondary_index.value.index_projection_type
      range_key          = lookup(global_secondary_index.value, "index_range_key", null)
      read_capacity      = lookup(global_secondary_index.value, "index_read_capacity", null)
      write_capacity     = lookup(global_secondary_index.value, "index_write_capacity", null)
      non_key_attributes = lookup(global_secondary_index.value, "index_non_key_attributes", null)
    }
  }


  tags = merge(
    var.default_tags,
    {
      Name = each.value.table_name
  })
}
  • Related