Terraform动态循环以创建多个DynamoDB。

huangapple go评论59阅读模式
英文:

Terraform dynamic loop to create multiple dynamodb

问题

我正在尝试创建一个动态方法来创建多个DynamoDB表格,每个表格都有自己的属性。我尝试使用动态块、列表对象等for循环,但无法为每个表格迭代属性。目标是一次性创建具有不同属性和每个表格的全局索引的多个表格。我有以下结构的terraform.tfvars和main.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 = 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
      })

    }

这段代码产生以下错误:

给定的值不适用于在variable.tf:6,1-26中声明的var.dynamodb_table:element 0:需要对象。

英文:

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

答案1

得分: 2

你没有分享你的 attributes 变量,但我已经在 dynamodb_table 变量中使用了 attributes

你的主要问题是 dynamodb_table 变量中的 attribute 属性是必需的,但你没有在 devops-test-02 表中为它提供任何值。

variables.tf 文件中的代码部分如下:

variable "dynamodb_table" {
  type = list(object({
    table_name   = string
    billing_mode = string
    hash_key           = string
    ttl_attribute_name = string
    ttl_enabled        = string
    attribute = list(object({
      name = string
      type = string
    }))
  }))
  default = [
    {
      table_name         = "devops-test-01",
      billing_mode       = "PAY_PER_REQUEST",
      hash_key           = "UserId",
      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_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
  })
}

更新 2023-01-17:在 DynamoDB 表中添加了 Kinesis 流目标资源。

resource "aws_kinesis_stream" "example" {
  for_each = aws_dynamodb_table.basic-dynamodb-table

  name        = "${each.key}_table_stream"
  shard_count = 1
}

resource "aws_dynamodb_kinesis_streaming_destination" "example" {
    for_each = aws_dynamodb_table.basic-dynamodb-table
    
    stream_arn = aws_kinesis_stream.example[each.key].arn   
    table_name = each.key
}
英文:

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
  })
}

UPDATE 2023-01-17
Add Kinesis streaming destination resource to dynamodb tables.

resource "aws_kinesis_stream" "example" {
  for_each = aws_dynamodb_table.basic-dynamodb-table

  name        = "${each.key}_table_stream"
  shard_count = 1
}

resource "aws_dynamodb_kinesis_streaming_destination" "example" {
    for_each = aws_dynamodb_table.basic-dynamodb-table
    
    stream_arn = aws_kinesis_stream.example[each.key].arn   
    table_name = each.key
}

huangapple
  • 本文由 发表于 2023年1月9日 16:13:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75054589.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定