Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 如何使用for循环来发射Terraform中的对象列表?_Loops_Terraform - Fatal编程技术网

Loops 如何使用for循环来发射Terraform中的对象列表?

Loops 如何使用for循环来发射Terraform中的对象列表?,loops,terraform,Loops,Terraform,我有一个变量定义为 variable "ssh_permit" { type = list(object({ name = string, ip = string })) default = [ { name = "alice" ip = "1.1.1.1" }, { name = "bob" ip = "2.2.2.2&quo

我有一个变量定义为

variable "ssh_permit" {
  type = list(object({ name = string, ip = string }))
  default = [
    {
      name = "alice"
      ip = "1.1.1.1"
    },
    {
      name = "bob"
      ip = "2.2.2.2"
    },
  ]
}
我正在尝试使用
for
循环,将此值后处理到可以指定给的对象中

然而,我得到:

Error: Incorrect attribute value type

  on test.tf line 81, in resource "azurerm_network_security_group" "foo_nsg":
  81:   security_rule = [for idx, rule in var.ssh_permit: {
  82:       name = "allow-${rule.name}"
  83:       priority = 100 + idx
  84:       direction = "Inbound"
  85:       access = "Allow"
  86:       protocol = "TCP"
  87:       source_address_prefix = rule.ip
  88:       source_port_range = "*"
  89:       destination_address_prefix = "*"
  90:       destination_port_range = "22"
  91:     } ]
    |----------------
    | var.ssh_permit is list of object with 2 elements

Inappropriate value for attribute "security_rule": element 0: attributes
"description", "destination_address_prefixes",
"destination_application_security_group_ids", "destination_port_ranges",
"source_address_prefixes", "source_application_security_group_ids", and
"source_port_ranges" are required.
就像Terraform忽略了一个事实,那就是那里有一个for循环。是的,
var.ssh\u-permit
是一个包含2个元素的对象列表,但它会被转换为
安全性\u-element
的相应对象


(我把它用于动态块语法,但出于这个问题的目的,我想忽略它,因为我还试图学习
循环的TF语法。它似乎在这里可以工作,所以我想理解为什么不可以。)

安全规则
是块,而不是属性。因此,您不能使用

security_rule = 
它必须通过定义,正如您所指出的,它是有效的


示例=
的第二个链接用于属性,而不是块。

此故障报告为
安全规则提供的第一个元素值不符合此参数的类型约束

根据错误消息,此参数似乎需要具有各种属性的对象列表,包括错误消息中列出的所有属性。因此,使该结果与类型一致的一种方法是将所有这些额外属性设置为
null
,以便对象具有兼容的类型,但仍然不填充这些属性:

  security_rule = [
    for idx, rule in var.ssh_permit: {
      name                                       = "allow-${rule.name}"
      priority                                   = 100 + idx
      direction                                  = "Inbound"
      access                                     = "Allow"
      protocol                                   = "TCP"
      source_address_prefix                      = rule.ip
      source_port_range                          = "*"
      destination_address_prefix                 = "*"
      destination_port_range                     = "22"
      description                                = null
      destination_address_prefixes               = null
      destination_application_security_group_ids = null
      destination_port_ranges                    = null
      source_address_prefixes                    = null
      source_application_security_group_ids      = null
      source_port_ranges                         = null
    }
  ]

上述表达式应使结果具有合适的类型,尽管提供程序可以自由地在类型检查之外附加附加的验证约束,因此它可能不会考虑<代码> null >代码>对于所有这些属性都是一个合适的值。


您提到了
dynamic
块,因此我希望您在这里有一个潜在的问题,即为什么通常不需要在块中将参数设置为
null
,但在这个表达式中却需要这样做

这是因为Terraform语言中的块是一种特殊的语言结构,而不是普通的值,因此它具有一些将其与值区分开来的额外功能,包括特定参数可以是可选的,并且块可以包含嵌套的块。嵌套块是Terraform特有的一种语言结构,因为它使用的是一种声明式风格,读起来像是对所需结果的描述,而不像典型的计算机程序

但是,每当看到
security\u rule=
语法时,您就是在给参数赋值。Terraform中的值更像通用编程语言中的典型值,尤其是每个值都有一个类型。通过在这里使用
{…}
语法,您已经构建了一个对象类型的值。请注意,“对象”实际上不是类型本身,而是具有属性的类型的子类别,类似于在一些通用编程语言中,“对象”只是指任何类的实例,而类本身就是类型

不过,Terraform语言的一个不太传统的特征是,它有一个结构类型系统,这意味着对象类型完全由它们的形状(它们具有什么属性)定义,而不是像您在其他语言中看到的那样由“类名”定义。资源参数具有,该参数说明允许在其中分配哪些类型的值

提供程序中此
security\u规则
参数的定义似乎将其声明为具有以下类型约束(尽管提供程序定义的类型约束在语言本身中不直接可见):

(我可能没有完全正确地理解这一点;我只是根据我们到目前为止在这个问题上讨论的内容进行猜测,而不是参考文档。)

Terraform通过检查对象类型是否至少具有类型约束中定义的属性来确定对象类型是否满足对象类型约束。在您的案例中,类型检查失败,因为您提供的对象缺少类型约束中的某些属性


我认为对于这个
security\u规则
参数,这里有一个额外的细节值得一提。虽然提供者开发人员似乎忘记了将其作为文档记录,但我认为这个参数在提供者模式中被标记为使用遗留,这是Terraform支持的一个特殊垫片,允许向后兼容某些情况,其中提供者设计依赖Terraform v0.11中的配置验证错误,这些错误已经修复


我不会在这里包括所有关于属性作为块模式的特殊情况,因为它们只适用于一些特殊的旧提供程序设计,它们已经在文档页面中进行了详细描述,但是我想提到它,因为我认为使用该模式的参数与典型的资源类型参数相比,会导致其行为有点混乱/不一致。

这是一个非常详细的答案,感谢您的写作!我没有注意到错误中的属性实际上与我提供的属性不同。“你提到了动态块,所以我想你在这里有一个潜在的问题,为什么在块中通常不需要将参数设置为null,但在这个表达式中你却这样做了。”-我确实这样做了,在我阅读了之前的部分答案后,感谢你回答我的后续问题!
list(object({
  name                                       = string
  priority                                   = number
  direction                                  = string
  access                                     = string
  protocol                                   = string
  source_address_prefix                      = string
  source_port_range                          = string
  destination_address_prefix                 = string
  destination_port_range                     = string
  description                                = string
  destination_address_prefixes               = list(string)
  destination_application_security_group_ids = list(string)
  destination_port_ranges                    = list(string)
  source_address_prefixes                    = list(string)
  source_application_security_group_ids      = list(string)
  source_port_ranges                         = list(string)
}))