如何在 terraform 中使用输出 id 作为变量?
How to use output ids in terraform as variable?
我使用 Terraform 在云中构建我的基础设施(我是 Terraform 的新手)。
我还使用 terraform 创建了一些防火墙规则,我需要将其分配给多个服务器。为此,我在我的模型中创建了一个名为 firewall 的字段。
Variables.tf
variable "hosts" {
type = map(object({
name = string
serverType = string
serverImage = string
serverLocation = string
serverKeepDisk = bool
serverBackup = bool
ip = string
volume = bool
volumeName = string
volumeSize = number
volumeFormat = string
volumeAutomount = bool
volumeDeleteProtection = bool
floating = bool
firewall = list(string) <--- this thing here!
}))
}
Terraform.tfvars
"myServer01" = {
name = "s01"
serverType = "cx11"
serverImage = "ubuntu-20.04"
serverLocation = "fsn1"
serverKeepDisk = false
serverBackup = false
ip = "192.168.0.12"
volume = true
volumeName = "data"
volumeSize = 100
volumeFormat = "ext4"
volumeAutomount = false
volumeDeleteProtection = false
floating = false
firewall = [hcloud_firewall.basic.id, hcloud_firewall.ssh.id, hcloud_firewall.webserver.id] <-- I define here variables of the firewalls I need to assign to this specific server
},
main.tf
resource "hcloud_server" "default" {
for_each = var.hosts
name = each.value.name
server_type = each.value.serverType
image = each.value.serverImage
location = each.value.serverLocation
user_data = file("userdata.yml")
keep_disk = each.value.serverKeepDisk
backups = each.value.serverBackup
ssh_keys = [hcloud_ssh_key.default.id]
firewall_ids = each.value.firewall
错误:
│ Error: Variables not allowed
│
│ on terraform.tfvars line 71:
│ 71: firewall = [hcloud_firewall.basic.id, hcloud_firewall.ssh.id, hcloud_firewall.webserver.id]
│
│ Variables may not be used here.
如何在 Terraform 中通过 ID/ 作为变量定义多个防火墙规则?
您不能创建动态变量。所以不可能做你想做的事。相反,您应该创建一个 local
变量并改用它:
locals {
firewall = [hcloud_firewall.basic.id, hcloud_firewall.ssh.id, hcloud_firewall.webserver.id]
}
然后在代码中使用 local.firewall
代替 var.firewall
。
根模块输入变量的定义有效地存在于根模块之外,在同样的意义上,当您将值传递给子模块的变量时,您在 caller[= 的上下文中定义它们28=],因此他们无法直接访问被调用模块中定义的任何内容。
因为根模块之外没有模块可以计算其中的表达式,所以根模块输入变量必须始终具有完全恒定的值。根模块变量定义无法直接引用根模块内声明的对象。
但是,您可以通过添加间接级别获得与此处预期的效果类似的效果:不是让 hosts
变量直接包含防火墙 ID,而是可以包含一些符号名称,这些符号名称具有表示仅在此配置中,每个都指您声明的防火墙之一。
variable "hosts" {
type = map(object({
name = string
serverType = string
serverImage = string
serverLocation = string
serverKeepDisk = bool
serverBackup = bool
ip = string
volume = bool
volumeName = string
volumeSize = number
volumeFormat = string
volumeAutomount = bool
volumeDeleteProtection = bool
floating = bool
firewall_names = set(string)
}))
}
locals {
firewall_ids = {
basic = hcloud_firewall.basic.id
ssh = hcloud_firewall.ssh.id
webserver = hcloud_firewall.webserver.id
}
}
resource "hcloud_server" "default" {
for_each = var.hosts
name = each.value.name
server_type = each.value.serverType
image = each.value.serverImage
location = each.value.serverLocation
user_data = file("userdata.yml")
keep_disk = each.value.serverKeepDisk
backups = each.value.serverBackup
ssh_keys = [hcloud_ssh_key.default.id]
firewall_ids = [
for name in each.value.firewall_names : local.firewall_ids[name]
]
}
在您的 terraform.tfvars
文件中,您可以使用符号名称间接指定这些对象,而不是直接引用模块内的对象:
hosts = {
"myServer01" = {
name = "s01"
serverType = "cx11"
serverImage = "ubuntu-20.04"
serverLocation = "fsn1"
serverKeepDisk = false
serverBackup = false
ip = "192.168.0.12"
volume = true
volumeName = "data"
volumeSize = 100
volumeFormat = "ext4"
volumeAutomount = false
volumeDeleteProtection = false
floating = false
firewall_names = ["basic", "ssh", "webserver"]
}
}
请注意,惯用的 Terraform 样式是使用全部小写的属性名称,并用下划线分隔单词,例如 server_type
而不是 serverType
。 Terraform 当然会同时接受两者,但是使用传统风格可能会使您的模块对具有 Terraform 经验的人来说不那么令人惊讶。
我使用 Terraform 在云中构建我的基础设施(我是 Terraform 的新手)。
我还使用 terraform 创建了一些防火墙规则,我需要将其分配给多个服务器。为此,我在我的模型中创建了一个名为 firewall 的字段。
Variables.tf
variable "hosts" {
type = map(object({
name = string
serverType = string
serverImage = string
serverLocation = string
serverKeepDisk = bool
serverBackup = bool
ip = string
volume = bool
volumeName = string
volumeSize = number
volumeFormat = string
volumeAutomount = bool
volumeDeleteProtection = bool
floating = bool
firewall = list(string) <--- this thing here!
}))
}
Terraform.tfvars
"myServer01" = {
name = "s01"
serverType = "cx11"
serverImage = "ubuntu-20.04"
serverLocation = "fsn1"
serverKeepDisk = false
serverBackup = false
ip = "192.168.0.12"
volume = true
volumeName = "data"
volumeSize = 100
volumeFormat = "ext4"
volumeAutomount = false
volumeDeleteProtection = false
floating = false
firewall = [hcloud_firewall.basic.id, hcloud_firewall.ssh.id, hcloud_firewall.webserver.id] <-- I define here variables of the firewalls I need to assign to this specific server
},
main.tf
resource "hcloud_server" "default" {
for_each = var.hosts
name = each.value.name
server_type = each.value.serverType
image = each.value.serverImage
location = each.value.serverLocation
user_data = file("userdata.yml")
keep_disk = each.value.serverKeepDisk
backups = each.value.serverBackup
ssh_keys = [hcloud_ssh_key.default.id]
firewall_ids = each.value.firewall
错误:
│ Error: Variables not allowed
│
│ on terraform.tfvars line 71:
│ 71: firewall = [hcloud_firewall.basic.id, hcloud_firewall.ssh.id, hcloud_firewall.webserver.id]
│
│ Variables may not be used here.
如何在 Terraform 中通过 ID/ 作为变量定义多个防火墙规则?
您不能创建动态变量。所以不可能做你想做的事。相反,您应该创建一个 local
变量并改用它:
locals {
firewall = [hcloud_firewall.basic.id, hcloud_firewall.ssh.id, hcloud_firewall.webserver.id]
}
然后在代码中使用 local.firewall
代替 var.firewall
。
根模块输入变量的定义有效地存在于根模块之外,在同样的意义上,当您将值传递给子模块的变量时,您在 caller[= 的上下文中定义它们28=],因此他们无法直接访问被调用模块中定义的任何内容。
因为根模块之外没有模块可以计算其中的表达式,所以根模块输入变量必须始终具有完全恒定的值。根模块变量定义无法直接引用根模块内声明的对象。
但是,您可以通过添加间接级别获得与此处预期的效果类似的效果:不是让 hosts
变量直接包含防火墙 ID,而是可以包含一些符号名称,这些符号名称具有表示仅在此配置中,每个都指您声明的防火墙之一。
variable "hosts" {
type = map(object({
name = string
serverType = string
serverImage = string
serverLocation = string
serverKeepDisk = bool
serverBackup = bool
ip = string
volume = bool
volumeName = string
volumeSize = number
volumeFormat = string
volumeAutomount = bool
volumeDeleteProtection = bool
floating = bool
firewall_names = set(string)
}))
}
locals {
firewall_ids = {
basic = hcloud_firewall.basic.id
ssh = hcloud_firewall.ssh.id
webserver = hcloud_firewall.webserver.id
}
}
resource "hcloud_server" "default" {
for_each = var.hosts
name = each.value.name
server_type = each.value.serverType
image = each.value.serverImage
location = each.value.serverLocation
user_data = file("userdata.yml")
keep_disk = each.value.serverKeepDisk
backups = each.value.serverBackup
ssh_keys = [hcloud_ssh_key.default.id]
firewall_ids = [
for name in each.value.firewall_names : local.firewall_ids[name]
]
}
在您的 terraform.tfvars
文件中,您可以使用符号名称间接指定这些对象,而不是直接引用模块内的对象:
hosts = {
"myServer01" = {
name = "s01"
serverType = "cx11"
serverImage = "ubuntu-20.04"
serverLocation = "fsn1"
serverKeepDisk = false
serverBackup = false
ip = "192.168.0.12"
volume = true
volumeName = "data"
volumeSize = 100
volumeFormat = "ext4"
volumeAutomount = false
volumeDeleteProtection = false
floating = false
firewall_names = ["basic", "ssh", "webserver"]
}
}
请注意,惯用的 Terraform 样式是使用全部小写的属性名称,并用下划线分隔单词,例如 server_type
而不是 serverType
。 Terraform 当然会同时接受两者,但是使用传统风格可能会使您的模块对具有 Terraform 经验的人来说不那么令人惊讶。