我使用terraform在云中构建我的基础设施(我对terraform还不熟悉)。
我还用terraform创建了一些防火墙规则,需要分配给多个服务器。为此,我在模型中创建了一个名为防火墙的字段。
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/ as变量定义多个防火墙规则?
发布于 2022-02-15 00:28:07
根模块输入变量的定义实际上存在于根模块之外,同样的意义是,当您将值传递给子模块的变量时,您会在调用方的上下文中定义它们,因此它们无法直接访问被调用模块中定义的任何内容。
因为根模块之外没有可以计算表达式的模块,所以根模块输入变量必须始终具有完全恒定的值。根模块变量定义无法直接引用根模块中声明的对象。
但是,通过添加一个间接级别,您可以获得与这里类似的效果:与其让hosts变量直接包含防火墙it,它还可以包含一些只在此配置中有意义的符号名称,每个名称都引用您声明的防火墙。
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经验的人来说不那么令人惊讶。
发布于 2022-02-14 23:47:20
你不能创建动态变量。所以你不可能做你想做的事。相反,您应该创建一个local变量并使用它:
locals {
firewall = [hcloud_firewall.basic.id, hcloud_firewall.ssh.id, hcloud_firewall.webserver.id]
}然后在代码中使用local.firewall代替var.firewall。
https://stackoverflow.com/questions/71119397
复制相似问题