分配地图(TF 0.11)时,Terraform中何时需要等号(=)

时间:2019-08-13 12:53:37

标签: terraform

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

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

使用=

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

没有=

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

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

2 个答案:

答案 0 :(得分:2)

在Terraform语言中,有两种截然不同的结构,在通常情况下,它们的语法看上去非常相似。

需要映射的参数

Terraform中的参数是一个单一的名称/值对,提供者在其中指定(在资源类型模式中)期望的值类型。您可以按照自己喜欢的方式随意创建该期望类型的值,无论是文字值还是复杂表达式。

参数语法通常为:

  name = value

如果将特定参数定义为 map ,则可以使用一种文字值来设置它,例如:

 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)

通常来说,您可以使用任何结果为具有预期元素类型的映射的expression

在Terraform 0.11中,所有这些非文字示例都需要使用模板插值语法${ ... }进行呈现,但是原理仍然相同。

嵌套块

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

嵌套块语法遵循与顶级resourcevariableterraform等块的语法相同的约定:

  block_type "label" {
    nested_argument = value
  }

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

由于块语法和映射文字语法都使用大括号{ },因此它们在配置上具有相似的外观,但是它们与Terraform的含义完全不同。使用块语法,可以期望块的内容具有固定的结构,该结构具有一组特定的参数名称和由资源类型架构决定的嵌套块类型。使用map参数,您可以自由选择所需的任何映射键(根据提供者或远程系统可能在Terraform架构之外施加的任何验证规则)。

认识到差异

不幸的是,今天提供程序的文档通常对于每个参数或嵌套块的确切使用方式都含糊不清,有时甚至忽略了预期的参数类型。主要提供者的代码库非常大,因此,由于它们是由许多不同的人写了几年的书,并且对文件的持续改进只能逐渐发生,因此它们的文件质量参差不齐。

话虽如此,提供者文档在嵌套块的描述中通常会使用“嵌套块”或“块类型”一词,并且会在页面上的其他位置引用一些定义,以确切说明哪些参数和嵌套块属于该块内部。如果文档指出特定参数是一个映射,或者暗示键是自由格式的,则表明它是一个需要映射值的参数。另一个线索是,块类型名称通常是单数名词(因为每个块描述一个对象),而采用map和其他集合的参数通常使用复数名词。

如果您发现文档中关于特定名称是嵌套块类型还是自变量模棱两可的特定情况,则在提供者的存储库中为其打开一个问题以帮助改善文档可能会有所帮助。 Terraform的文档页面在页脚中有一个“编辑此页面”链接,您可以使用它在适当的存储库中提出简单(仅单页)编辑作为请求请求。

有关这些概念的详细说明,请参见文档Arguments and Blocks部分。

答案 1 :(得分:1)

混乱来自terraform使用的hcl语言的行为。该功能在terraform中的文档记录不是很好,但是...在hcl中,您可以通过使用重复块来定义列表,这是像aws_route_table这样的资源如何定义内联路由的,例如

resource "aws_route_table" "r" {
  vpc_id = "${aws_vpc.default.id}"

  route {
    cidr_block = "10.0.1.0/24"
    gateway_id = "${aws_internet_gateway.main.id}"
  }

  route {
    ipv6_cidr_block        = "::/0"
    egress_only_gateway_id = "${aws_egress_only_internet_gateway.foo.id}"
  }

  tags = {
    Name = "main"
  }
}

等同于

resource "aws_route_table" "r" {
  vpc_id = "${aws_vpc.default.id}"

  route = [
    {
      cidr_block = "10.0.1.0/24"
      gateway_id = "${aws_internet_gateway.main.id}"
    },
    {
      ipv6_cidr_block        = "::/0"
      egress_only_gateway_id = "${aws_egress_only_internet_gateway.foo.id}"
    }
  ]

  tags = {
    Name = "main"
  }
}

您要确保在为某物分配值时使用=,并且在使用列表时仅使用重复块语法。另外,根据我的经验,我建议在单个资源可用时不要使用内联。

在回购的readme中可以找到关于hcl的非常有限的文档。