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

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

Terraform dynamic loop to create multiple dynamodb

问题

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

变量声明:

  1. variable "dynamodb_table" {
  2. type = list(object({
  3. table_name = string
  4. billing_mode = string
  5. read_capacity = optional(number)
  6. write_capacity = optional(string)
  7. hash_key = string
  8. ttl_attribute_name = string
  9. ttl_enabled = string
  10. range_key = optional(string)
  11. attribute = object({
  12. name = string
  13. type = string
  14. })
  15. }))
  16. }
  17. variable "global_secondary_indexes" {
  18. description = "Describe a GSI for the table; subject to the normal limits on the number of GSIs, projected attributes, etc."
  19. type = list(object({
  20. index_name = string
  21. index_projection_type = string
  22. index_range_key = string
  23. index_hash_key = string
  24. index_write_capacity = optional(string)
  25. index_read_capacity = optional(string)
  26. index_non_key_attributes = list(string)
  27. }))
  28. default = []
  29. }
  1. dynamodb_table = [
  2. {
  3. table_name = "devops-test-01",
  4. billing_mode = "PAY_PER_REQUEST",
  5. hash_key = "UserId",
  6. range_key = "GameTitle",
  7. ttl_attribute_name = "ttl_attribute_name",
  8. ttl_enabled = "false"
  9. attribute = [
  10. {
  11. name = "UserId",
  12. type = "S"
  13. },
  14. {
  15. name = "GameTitle",
  16. type = "S"
  17. }
  18. ]
  19. },
  20. {
  21. table_name = "devops-test-02",
  22. billing_mode = "PAY_PER_REQUEST",
  23. hash_key = "GameTitle",
  24. ttl_attribute_name = "ttl_attribute_name",
  25. ttl_enabled = "false"
  26. }
  27. ]
  28. global_secondary_indexes = [
  29. {
  30. index_name = "TitleIndex",
  31. index_hash_key = "UserId",
  32. index_range_key = "GameTitle",
  33. index_projection_type = "INCLUDE",
  34. index_non_key_attributes = ["Id"]
  35. }
  36. ]
  37. default_tags = {
  38. "Environment" = "Dev",
  39. "Owner" = "xxx"
  40. }
  1. resource "aws_dynamodb_table" "basic-dynamodb-table" {
  2. for_each = { for key, value in var.dynamodb_table : key => value }
  3. name = each.value.table_name
  4. billing_mode = each.value.billing_mode
  5. read_capacity = each.value.read_capacity
  6. write_capacity = each.value.write_capacity
  7. hash_key = each.value.hash_key
  8. range_key = each.value.range_key
  9. ttl {
  10. attribute_name = each.value.ttl_attribute_name
  11. enabled = each.value.ttl_enabled
  12. }
  13. dynamic "attribute" {
  14. for_each = { for key, value in var.attributes : key => value }
  15. content {
  16. name = attribute.value.name
  17. type = attribute.value.type
  18. }
  19. }
  20. dynamic "global_secondary_index" {
  21. for_each = var.global_secondary_indexes
  22. content {
  23. name = global_secondary_index.value.index_name
  24. hash_key = global_secondary_index.value.index_hash_key
  25. projection_type = global_secondary_index.value.index_projection_type
  26. range_key = lookup(global_secondary_index.value, "index_range_key", null)
  27. read_capacity = lookup(global_secondary_index.value, "index_read_capacity", null)
  28. write_capacity = lookup(global_secondary_index.value, "index_write_capacity", null)
  29. non_key_attributes = lookup(global_secondary_index.value, "index_non_key_attributes", null)
  30. }
  31. }
  32. tags = merge(
  33. var.default_tags,
  34. {
  35. Name = each.value.table_name
  36. })
  37. }

这段代码产生以下错误:

给定的值不适用于在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:

  1. variable "dynamodb_table" {
  2. type = list(object({
  3. table_name = string
  4. billing_mode = string
  5. read_capacity = optional(number)
  6. write_capacity = optional(string)
  7. hash_key = string
  8. ttl_attribute_name = string
  9. ttl_enabled = string
  10. range_key = optional(string)
  11. attribute = object({
  12. name = string
  13. type = string
  14. })
  15. }))
  16. }
  17. variable "global_secondary_indexes" {
  18. description = "Describe a GSI for the table; subject to the normal limits on the number of GSIs, projected attributes, etc."
  19. type = list(object({
  20. index_name = string
  21. index_projection_type = string
  22. index_range_key = string
  23. index_hash_key = string
  24. index_write_capacity = optional(string)
  25. index_read_capacity = optional(string)
  26. index_non_key_attributes = list(string)
  27. }))
  28. default = []
  29. }
  1. dynamodb_table = [
  2. {
  3. table_name = "devops-test-01",
  4. billing_mode = "PAY_PER_REQUEST",
  5. hash_key = "UserId",
  6. range_key = "GameTitle",
  7. ttl_attribute_name = "ttl_attribute_name",
  8. ttl_enabled = "false"
  9. attribute = [
  10. {
  11. name = "UserId"
  12. type = "S"
  13. },
  14. {
  15. name = "GameTitle"
  16. type = "S"
  17. }
  18. ]
  19. },
  20. {
  21. table_name = "devops-test-02",
  22. billing_mode = "PAY_PER_REQUEST",
  23. hash_key = "GameTitle",
  24. ttl_attribute_name = "ttl_attribute_name",
  25. ttl_enabled = "false"
  26. }
  27. ]
  28. global_secondary_indexes = [
  29. {
  30. index_name = "TitleIndex"
  31. index_hash_key = "UserId"
  32. index_range_key = "GameTitle"
  33. index_projection_type = "INCLUDE"
  34. index_non_key_attributes = ["Id"]
  35. }
  36. ]
  37. default_tags = {
  38. "Environment" = "Dev",
  39. "Owner" = "xxx"
  40. }
  1. resource "aws_dynamodb_table" "basic-dynamodb-table" {
  2. for_each = { for key, value in var.dynamodb_table : key => value }
  3. name = each.value.table_name
  4. billing_mode = each.value.billing_mode
  5. read_capacity = each.value.read_capacity
  6. write_capacity = each.value.write_capacity
  7. hash_key = each.value.hash_key
  8. range_key = each.value.range_key
  9. ttl {
  10. attribute_name = each.value.ttl_attribute_name
  11. enabled = each.value.ttl_enabled
  12. }
  13. dynamic "attribute" {
  14. for_each = { for key, value in var.attributes : key => value }
  15. content {
  16. name = attribute.value.name
  17. type = attribute.value.type
  18. }
  19. }
  20. dynamic "global_secondary_index" {
  21. for_each = var.global_secondary_indexes
  22. content {
  23. name = global_secondary_index.value.index_name
  24. hash_key = global_secondary_index.value.index_hash_key
  25. projection_type = global_secondary_index.value.index_projection_type
  26. range_key = lookup(global_secondary_index.value, "index_range_key", null)
  27. read_capacity = lookup(global_secondary_index.value, "index_read_capacity", null)
  28. write_capacity = lookup(global_secondary_index.value, "index_write_capacity", null)
  29. non_key_attributes = lookup(global_secondary_index.value, "index_non_key_attributes", null)
  30. }
  31. }
  32. tags = merge(
  33. var.default_tags,
  34. {
  35. Name = each.value.table_name
  36. })
  37. }

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 文件中的代码部分如下:

  1. variable "dynamodb_table" {
  2. type = list(object({
  3. table_name = string
  4. billing_mode = string
  5. hash_key = string
  6. ttl_attribute_name = string
  7. ttl_enabled = string
  8. attribute = list(object({
  9. name = string
  10. type = string
  11. }))
  12. }))
  13. default = [
  14. {
  15. table_name = "devops-test-01",
  16. billing_mode = "PAY_PER_REQUEST",
  17. hash_key = "UserId",
  18. ttl_attribute_name = "ttl_attribute_name",
  19. ttl_enabled = "false",
  20. attribute = [
  21. {
  22. name = "UserId",
  23. type = "S"
  24. },
  25. {
  26. name = "GameTitle",
  27. type = "S"
  28. }
  29. ]
  30. },
  31. {
  32. table_name = "devops-test-02",
  33. billing_mode = "PAY_PER_REQUEST",
  34. hash_key = "GameTitle",
  35. ttl_attribute_name = "ttl_attribute_name",
  36. ttl_enabled = "false",
  37. attribute = [
  38. {
  39. name = "UserId",
  40. type = "S"
  41. },
  42. {
  43. name = "GameTitle",
  44. type = "S"
  45. }
  46. ]
  47. }
  48. ]
  49. }
  50. variable "global_secondary_indexes" {
  51. description = "Describe a GSI for the table; subject to the normal limits on the number of GSIs, projected attributes, etc."
  52. type = list(object({
  53. index_name = string
  54. index_projection_type = string
  55. index_range_key = string
  56. index_hash_key = string
  57. index_non_key_attributes = list(string)
  58. }))
  59. default = [
  60. {
  61. index_name = "TitleIndex",
  62. index_hash_key = "UserId",
  63. index_range_key = "GameTitle",
  64. index_projection_type = "INCLUDE",
  65. index_non_key_attributes = ["Id"]
  66. }
  67. ]
  68. }
  69. variable "default_tags" {
  70. default = {
  71. "Environment" = "Dev",
  72. "Owner" = "xxx"
  73. }
  74. }

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

  1. resource "aws_dynamodb_table" "basic-dynamodb-table" {
  2. for_each = { for key, value in var.dynamodb_table : value.table_name => value }
  3. name = each.value.table_name
  4. billing_mode = each.value.billing_mode
  5. read_capacity = lookup(each.value, "read_capacity", null)
  6. write_capacity = lookup(each.value, "write_capacity", null)
  7. hash_key = each.value.hash_key
  8. range_key = lookup(each.value, "range_key", null)
  9. ttl {
  10. attribute_name = each.value.ttl_attribute_name
  11. enabled = each.value.ttl_enabled
  12. }
  13. dynamic "attribute" {
  14. for_each = { for key, value in each.value.attribute : key => value }
  15. content {
  16. name = attribute.value.name
  17. type = attribute.value.type
  18. }
  19. }
  20. dynamic "global_secondary_index" {
  21. for_each = var.global_secondary_indexes
  22. content {
  23. name = global_secondary_index.value.index_name
  24. hash_key = global_secondary_index.value.index_hash_key
  25. projection_type = global_secondary_index.value.index_projection_type
  26. range_key = lookup(global_secondary_index.value, "index_range_key", null)
  27. read_capacity = lookup(global_secondary_index.value, "index_read_capacity", null)
  28. write_capacity = lookup(global_secondary_index.value, "index_write_capacity", null)
  29. non_key_attributes = lookup(global_secondary_index.value, "index_non_key_attributes", null)
  30. }
  31. }
  32. tags = merge(
  33. var.default_tags,
  34. {
  35. Name = each.value.table_name
  36. })
  37. }

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

  1. resource "aws_kinesis_stream" "example" {
  2. for_each = aws_dynamodb_table.basic-dynamodb-table
  3. name = "${each.key}_table_stream"
  4. shard_count = 1
  5. }
  6. resource "aws_dynamodb_kinesis_streaming_destination" "example" {
  7. for_each = aws_dynamodb_table.basic-dynamodb-table
  8. stream_arn = aws_kinesis_stream.example[each.key].arn
  9. table_name = each.key
  10. }
英文:

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

  1. variable "dynamodb_table" {
  2. type = list(object({
  3. table_name = string
  4. billing_mode = string
  5. // read_capacity = optional(number)
  6. //write_capacity = optional(string)
  7. hash_key = string
  8. ttl_attribute_name = string
  9. ttl_enabled = string
  10. //range_key = optional(string)
  11. attribute = list(object({
  12. name = string
  13. type = string
  14. }))
  15. }))
  16. default = [
  17. {
  18. table_name = "devops-test-01",
  19. billing_mode = "PAY_PER_REQUEST",
  20. hash_key = "UserId",
  21. range_key = "GameTitle",
  22. ttl_attribute_name = "ttl_attribute_name",
  23. ttl_enabled = "false"
  24. attribute = [
  25. {
  26. name = "UserId"
  27. type = "S"
  28. },
  29. {
  30. name = "GameTitle"
  31. type = "S"
  32. }
  33. ]
  34. },
  35. {
  36. table_name = "devops-test-02",
  37. billing_mode = "PAY_PER_REQUEST",
  38. hash_key = "GameTitle",
  39. ttl_attribute_name = "ttl_attribute_name",
  40. ttl_enabled = "false"
  41. attribute = [
  42. {
  43. name = "UserId"
  44. type = "S"
  45. },
  46. {
  47. name = "GameTitle"
  48. type = "S"
  49. }
  50. ]
  51. }
  52. ]
  53. }
  54. variable "global_secondary_indexes" {
  55. description = "Describe a GSI for the table; subject to the normal limits on the number of GSIs, projected attributes, etc."
  56. type = list(object({
  57. index_name = string
  58. index_projection_type = string
  59. index_range_key = string
  60. index_hash_key = string
  61. //index_write_capacity = optional(string)
  62. //index_read_capacity = optional(string)
  63. index_non_key_attributes = list(string)
  64. }))
  65. default = [
  66. {
  67. index_name = "TitleIndex"
  68. index_hash_key = "UserId"
  69. index_range_key = "GameTitle"
  70. index_projection_type = "INCLUDE"
  71. index_non_key_attributes = ["Id"]
  72. }
  73. ]
  74. }
  75. variable "default_tags" {
  76. default = {
  77. "Environment" = "Dev",
  78. "Owner" = "xxx"
  79. }
  80. }

dynamodb.tf

  1. resource "aws_dynamodb_table" "basic-dynamodb-table" {
  2. for_each = { for key, value in var.dynamodb_table : value.table_name => value }
  3. name = each.value.table_name
  4. billing_mode = each.value.billing_mode
  5. read_capacity = lookup(each.value, "read_capacity", null)
  6. write_capacity = lookup(each.value, "write_capacity", null)
  7. hash_key = each.value.hash_key
  8. range_key = lookup(each.value, "range_key", null)
  9. ttl {
  10. attribute_name = each.value.ttl_attribute_name
  11. enabled = each.value.ttl_enabled
  12. }
  13. dynamic "attribute" {
  14. for_each = { for key, value in each.value.attribute : key => value }
  15. content {
  16. name = attribute.value.name
  17. type = attribute.value.type
  18. }
  19. }
  20. dynamic "global_secondary_index" {
  21. for_each = var.global_secondary_indexes
  22. content {
  23. name = global_secondary_index.value.index_name
  24. hash_key = global_secondary_index.value.index_hash_key
  25. projection_type = global_secondary_index.value.index_projection_type
  26. range_key = lookup(global_secondary_index.value, "index_range_key", null)
  27. read_capacity = lookup(global_secondary_index.value, "index_read_capacity", null)
  28. write_capacity = lookup(global_secondary_index.value, "index_write_capacity", null)
  29. non_key_attributes = lookup(global_secondary_index.value, "index_non_key_attributes", null)
  30. }
  31. }
  32. tags = merge(
  33. var.default_tags,
  34. {
  35. Name = each.value.table_name
  36. })
  37. }

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

  1. resource "aws_kinesis_stream" "example" {
  2. for_each = aws_dynamodb_table.basic-dynamodb-table
  3. name = "${each.key}_table_stream"
  4. shard_count = 1
  5. }
  6. resource "aws_dynamodb_kinesis_streaming_destination" "example" {
  7. for_each = aws_dynamodb_table.basic-dynamodb-table
  8. stream_arn = aws_kinesis_stream.example[each.key].arn
  9. table_name = each.key
  10. }

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:

确定