首页 > 解决方案 > 分配地图时 Terraform 何时需要等号 (=) (TF 0.11)

问题描述

我无法通过任何其他方法解决这个问题,所以我不得不在这里问这个......

在将地图分配给 Terraform 0.11 中的值时,使用等号 (=) 背后的逻辑是什么。

与 =

resource "pseude_resource" "pseudo_name" {
  value = {
    key1 = value1
    key2 = value2
  }
}

没有 =

resource "pseude_resource" "pseudo_name" {
  value {
    key1 = value1
    key2 = value2
  }
}

使用数组 ([]) 时似乎需要 =,但使用地图时不需要。这背后的原因是什么,到底为什么?可以省略吗?

标签: terraform

解决方案


在 Terraform 语言中,有两种不同的结构,它们在常见情况下具有非常相似的语法。

期望映射的参数

Terraform 中的参数是单个名称/值对,其中提供者规定(在资源类型模式中)它期望的值类型。您可以以任何您喜欢的方式自由创建该预期类型的​​值,无论是作为文字值还是作为复杂表达式。

参数语法通常是:

  name = value

如果将特定参数定义为映射,那么您可以设置它的一种方法是使用文字值,如下所示:

 tags = {
   Name = "foo bar baz"
 }

...但您也可以使用对与地图类型兼容的其他值的引用:

  # Tags are the same as on some other VPC object
  tags = aws_vpc.example.tags

...或者您可以使用内置的 Terraform 函数将地图组合在一起:

  tags = merge(local.default_tags, var.override_tags)

一般来说,您可以使用任何表达式,其结果是具有预期元素类型的映射。

在 Terraform 0.11 中,这些非文字示例都需要以模板插值语法呈现${ ... },但原理是相同的。

嵌套块

虽然参数为嵌入其块的对象设置了一些特定的配置设置,但嵌套块语法通常声明存在与嵌入块的对象相关的另一个对象。有时这确实是一个单独的物理对象,例如作为与安全组关联的规则,有时它是一个更具概念性的“对象”,例如versioning其中aws_s3_bucket将版本控制功能建模为单独的“对象”,因为它的存在会激活该功能。

嵌套块语法遵循与顶级resource, variable, terraform, etc 块的语法相同的约定:

  block_type "label" {
    nested_argument = value
  }

每种块类型都会有它所期望的固定数量的标签,在许多情况下根本就没有标签。因为每个块代表一个单独对象的声明,块结构更加僵化,必须始终遵循上面的形状;在这种情况下,不可能使用任意表达式,因为 Terraform 想要在其静态验证阶段验证每个块内部是否具有正确的参数。

因为块语法和地图文字语法都使用大括号{ },所以它们在配置中具有相似的外观,但它们的含义与 Terraform 完全不同。使用块语法,您可以期望块的内容具有固定的结构,其中包含一组特定的参数名称和由资源类型模式决定的嵌套块类型。使用 map 参数,您可以自由选择您喜欢的任何映射键(受提供者或远程系统可能在 Terraform 模式之外强加的任何验证规则的约束)。

认识到差异

不幸的是,今天提供者的文档对于每个参数或嵌套块应该如何使用通常含糊其辞,有时甚至省略了参数的预期类型。主要的供应商是非常大的代码库,因此他们的文档质量参差不齐,因为它们是由许多不同的人在几年内编写的,并且对文档的持续改进只能逐渐发生。

话虽如此,提供者文档通常会在对嵌套块的描述中使用“嵌套块”或“块类型”这两个词,并且会在页面上的其他地方引用一些定义,以确定哪些参数和嵌套块属于在那个街区里面。如果文档声明特定参数是映射或暗示键是自由格式的,则表明它是期望映射值的参数。另一个线索是块类型名称通常是单数名词(因为每个块描述一个对象),而采用映射和其他集合的参数通常使用复数名词。

如果您发现文档对于特定名称是嵌套块类型还是参数不明确的特定情况,则在提供者的存储库中为其打开问题以帮助改进文档可能会有所帮助。Terraform 的文档页面在页脚中有一个“编辑此页面”链接,您可以使用该链接在适当的存储库中提出简单(仅单页)编辑作为拉取请求。

这些概念的详细解释在文档部分Arguments and Blocks中。


推荐阅读