SSM 文档中的活动目录 DNS 服务器 IP 地址列表



我正在将我的 0.11 代码转换为 0.12。大多数事情似乎进展顺利,但我真的迷失在 SSM 文档中。

在我的 0.11 代码中,我有以下代码:

resource "aws_ssm_document" "ssm_document" {
name = "ssm_document_${terraform.workspace}${var.addomainsuffix}"
document_type = "Command"
content = <<DOC
{
"schemaVersion": "1.0",
"description": "Automatic Domain Join Configuration",
"runtimeConfig": {
"aws:domainJoin": {
"properties": {
"directoryId": "${aws_directory_service_directory.microsoftad-lab.id}",
"directoryName": "${aws_directory_service_directory.microsoftad-lab.name}",
"dnsIpAddresses": [
"${aws_directory_service_directory.microsoftad-lab.dns_ip_addresses[0]}",
"${aws_directory_service_directory.microsoftad-lab.dns_ip_addresses[1]}"
]
}
}
}
}
DOC
depends_on = ["aws_directory_service_directory.microsoftad-lab"]
}

这工作得相当好。但是,Terraform 0.12不接受此代码,称

此值没有任何索引。

我一直在尝试在网络上查找不同的解决方案,但是我遇到了无数的数据类型问题。例如,我看到的解决方案之一提出了这个建议:

"dnsIpAddresses": [
"${sort(aws_directory_service_directory.oit-microsoftad-lab.dns_ip_addresses)[0]}",
"${sort(aws_directory_service_directory.oit-microsoftad-lab.dns_ip_addresses)[1]}",
]
}

我正在得到

无效文档内容:JSON 格式不正确

这对我来说有点奇怪,因为如果我正在查看跟踪日志,我似乎得到了相对正确的值:

{"Content":"{n    "schemaVersion": "1.0",n    "description": "Automatic Domain Join Configuration",n    "runtimeConfig": {n        "aws:domainJoin": {n            "properties": {n                "directoryId": "d-9967245377",n                "directoryName": "012mig.lab",n                "dnsIpAddresses": [n                    "10.0.0.227",n
"10.0.7.103",n                ]n            }n        }n    }n}n    n","DocumentFormat":"JSON","DocumentType":"Command","Name":"ssm_document_012mig.lab"}

我已经尝试了 concat 和列表将值放在一起,但随后我遇到了数据类型错误。现在,看起来我在这里兜圈子。

有人在这里给我任何方向吗?

Terraform 0.12 具有比 0.11 更严格的类型,并且幕后进行的自动类型强制更少,因此在这里您会遇到这样一个事实,即aws_directory_service_directory资源的dns_ip_addresses属性的输出不是一个列表,而是一个集合:

"dns_ip_addresses": {
Type:     schema.TypeSet,
Elem:     &schema.Schema{Type: schema.TypeString},
Set:      schema.HashString,
Computed: true,
},

Set 不能直接索引,而是必须首先在 0.12 中显式转换为列表。

举个例子:

variable "example_list" {
type = list(string)
default = [
"foo",
"bar",
]
}

output "list_first_element" {
value = var.example_list[0]
}

在此上运行terraform apply将输出以下内容:

Outputs:
list_first_element = foo

但是,如果我们改用 set 变量:

variable "example_set" {
type = set(string)
default = [
"foo",
"bar",
]
}
output "set_first_element" {
value = var.example_set[0]
}

然后尝试运行terraform apply将引发以下错误:

Error: Invalid index
on main.tf line 22, in output "set_foo":
22:   value = var.example_set[0]
This value does not have any indices.

如果我们首先将 set 变量转换为带有tolist的列表,那么它可以工作:

variable "example_set" {
type = set(string)
default = [
"foo",
"bar",
]
}
output "set_first_element" {
value = tolist(var.example_set)[0]
}
Outputs:
set_first_element = bar

请注意,集合的顺序可能与预期的顺序不同(在本例中,按字母顺序排序,而不是按声明顺序排序(。在您的情况下,这不是问题,但在索引时值得考虑,期望元素按照您声明的顺序排列。

这里的另一个可能的选择是,您可以使用jsonencode函数直接将dns_ip_addresses属性编码为 JSON,而不是从输出集或输出列表中构建 JSON 输出:

variable "example_set" {
type = set(string)
default = [
"foo",
"bar",
]
}
output "set_first_element" {
value = jsonencode(var.example_set)
}

运行terraform apply后输出以下内容:

Outputs:
set_first_element = ["bar","foo"]

因此,对于您的特定示例,我们希望执行以下操作:

resource "aws_ssm_document" "ssm_document" {
name = "ssm_document_${terraform.workspace}${var.addomainsuffix}"
document_type = "Command"
content = <<DOC
{
"schemaVersion": "1.0",
"description": "Automatic Domain Join Configuration",
"runtimeConfig": {
"aws:domainJoin": {
"properties": {
"directoryId": "${aws_directory_service_directory.microsoftad-lab.id}",
"directoryName": "${aws_directory_service_directory.microsoftad-lab.name}",
"dnsIpAddresses": ${jsonencode(aws_directory_service_directory.microsoftad-lab.dns_ip_addresses)}
}
}
}
}
DOC
}

请注意,我还删除了不必要的depends_on。如果一个资源从另一个资源进行了插值,则 Terraform 将自动理解需要在引用它之前创建内插的资源。

资源依赖关系文档对此进行了更详细的介绍:

大多数资源依赖关系都是自动处理的。大地形态 分析资源块中的任何表达式以查找对 其他对象,并将这些引用视为隐式排序 创建、更新或销毁资源时的要求。因为 大多数资源的行为依赖于其他资源 参考这些资源的数据,通常不需要手动 指定资源之间的依赖关系。

但是,某些依赖项无法在 中隐式识别 配置。例如,如果 Terraform 必须管理访问控制 策略并采取需要这些策略存在的操作, 访问策略和资源之间存在隐藏的依赖关系 谁的创造取决于它。在这些罕见的情况下,depends_on元参数可以显式指定依赖项。

最新更新