无法创建嵌套动态块

tle*_*ibo 5 terraform

我有一组 9 条安全组规则,需要将其应用于 4 个不同的源。我想将其构建为一个模块,因此不需要多次复制/粘贴同一块,我只需将端口和源作为变量传递即可。

我尝试创建一个模块,该模块可以for_each在动态块中获取端口,并传递源,因为我未能为源count提供额外的动态块。for_each

模块/sg/main.tf

resource "aws_security_group" "test" {
  name = "test2"
  count = length(var.groups)
  vpc_id = var.vpc_id


  dynamic "ingress_tcp" {
    for_each = var.tcp_ports
    content {
      from_port = ingress_tcp.value
      to_port = ingress_tcp.value
      protocol = "tcp"
      security_groups = [var.groups[*].id]
    }
  }
  dynamic "ingress_udp" {
    for_each = var.udp_ports
    content {
      from_port = ingress_udp.value
      to_port = ingress_udp.value
      protocol = "udp"
      security_groups = [var.groups[*].id]
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

主.tf

module "rules" {
  source = "./module/sg"
  vpc_id = var.vpc_id
  name = "tomer-test"
  tcp_ports = var.tcp_ports
  udp_ports = var.udp_ports
  groups = [var.groups[*].id]
}
Run Code Online (Sandbox Code Playgroud)

变量.tf

variable "groups" {
  description = "source groups"
  type = "list"
  default  = [{
    name = "Enforcement-STG",
    id = "sg-c9db2183abcd"
  },
    {
      name = "Managment-STG",
      id = "sg-b0e71dfa123"
  }]
}

variable "name" {
  type = string
}
variable "vpc_id" {
  type = string
  default = ""
}
variable "tcp_ports" {
  description = "tcp ports to open"
  default = [514,1514, 11514, 12514, 6514]
}
variable "udp_ports" {
  description = "tcp ports to open"
  default = [514,1514, 11514, 12514]
}
Run Code Online (Sandbox Code Playgroud)

我接受输出来为每个源组构建一组规则,但根模块无法调用该模块。我目前收到的错误是

terraform plan

Error: Unsupported block type

  on module/sg/main.tf line 7, in resource "aws_security_group" "test":
   7:   dynamic "ingress_tcp" {

Blocks of type "ingress_tcp" are not expected here.


Error: Unsupported block type

  on module/sg/main.tf line 16, in resource "aws_security_group" "test":
  16:   dynamic "ingress_udp" {

Blocks of type "ingress_udp" are not expected here.
Run Code Online (Sandbox Code Playgroud)

Mar*_*ins 5

正如错误消息所示,您在此处尝试的内容无效,因为ingress_tcp不是aws_security_group资源内预期的块类型。此嵌套块类型的正确名称是ingress

resource "aws_security_group" "test" {
  count = length(var.groups)

  name = "test2"
  vpc_id = var.vpc_id

  dynamic "ingress" {
    for_each = var.tcp_ports
    content {
      from_port       = ingress.value
      to_port         = ingress.value
      protocol        = "tcp"
      security_groups = var.groups[*].id
    }
  }

  dynamic "ingress" {
    for_each = var.udp_ports
    content {
      from_port       = ingress.value
      to_port         = ingress.value
      protocol        = "udp"
      security_groups = var.groups[*].id
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您使用 Terraform 0.12.6 或更高版本,您可能更喜欢使用 resourcesfor_each而不是 来编写count此内容,如下所示:

resource "aws_security_group" "test" {
  for_each = { for g in var.groups : g.name => g }

  name = "test2-${each.key}"
  vpc_id = var.vpc_id

  dynamic "ingress" {
    for_each = var.tcp_ports
    content {
      from_port       = ingress.value
      to_port         = ingress.value
      protocol        = "tcp"
      security_groups = var.groups[*].id
    }
  }

  dynamic "ingress" {
    for_each = var.udp_ports
    content {
      from_port       = ingress.value
      to_port         = ingress.value
      protocol        = "udp"
      security_groups = var.groups[*].id
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这将产生与您的示例类似的结果count,但会生成地址类似aws_security_group.test["Enforcement-STG"]而不是 的实例aws_security_group.test[0],这意味着当您var.groups将来添加和删除元素时,Terraform 将能够确定哪个实例与每个元素对应,并且仅添加/删除需要个别实例。

这种基于映射的资源可能也更容易在配置中的其他地方使用,因为您将能够轻松找到每个符号组名称的特定安全组。