如何处理动态块的空列表
How to handle empty list for dynamic block
这是关于 Azure 资源的,app_service,但我认为这是一个更一般的 HCL 问题……
您可以使用动态块将 IP 限制指定给 app_service,例如
locals {
ip_addresses = [ "192.168.250.1" ]
}
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}
resource "azurerm_app_service_plan" "example" {
name = "example-appserviceplan"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
sku {
tier = "Standard"
size = "S1"
}
}
resource "azurerm_app_service" "example" {
name = "example-app-service"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
app_service_plan_id = azurerm_app_service_plan.example.id
site_config {
dotnet_framework_version = "v4.0"
scm_type = "LocalGit"
}
app_settings = {
"SOME_KEY" = "some-value"
}
connection_string {
name = "Database"
type = "SQLServer"
value = "Server=some-server.mydomain.com;Integrated Security=SSPI"
}
dynamic "ip_restriction" {
for_each = toset(local.ip_addresses)
content {
ip_address = each.value
}
}
}
但是,要删除限制,您需要将 ip_restriction 显式分配给空列表,即
resource "azurerm_app_service" "example" {
...
ip_restriction = []
}
我看不到如何有条件地执行此操作 - 如果我制作两个资源并有条件地使用这些资源,我的 app_service 将是 created/destroyed,而我需要就地更新它。
这是一种特殊的 terraform
语法,称为 Attributes as Blocks. Resource arguments defined using nested block syntax implicitly define a fixed collection of objects,因此为了指定零个对象,我们应该明确设置空列表。而且这两种形式不能混用。
话虽如此,terraform
也支持参数语法(尽管他们建议在简单情况下使用块语法以提高可读性):
example = [
for name in var.names: {
foo = name
}
]
恐怕动态块在使用条件表达式时不支持空列表。阅读更多参考 here.
经过我的验证,当 var.some_variable
设置为 null
时,像 for_each = var.some_variable == "" ? [] : [1]
这样的条件表达式不起作用,但是当 for_each = var.some_variable
和 var.some_variable
设置为 null
.
因此,在这种情况下,作为@rkm 的回答,您可以使用 for
循环,就像我的这个工作示例一样。
variable "ip_restrictions" {
default = [
# {
# ip_address = "1.1.1.1/32"
# virtual_network_subnet_id = null
# subnet_id = null
# name = "aaa"
# priority = 110
# action = "Allow"
# },
# {
# ip_address = "2.2.2.2/32"
# virtual_network_subnet_id = null
# subnet_id = null
# name = "bbb"
# priority = 112
# action = "Allow"
# },
]
}
resource "azurerm_app_service" "example" {
name = "nn-example-app-service"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
app_service_plan_id = azurerm_app_service_plan.example.id
site_config {
ip_restriction = [
for s in var.ip_restrictions :
{
ip_address = s.ip_address
virtual_network_subnet_id = s.virtual_network_subnet_id
subnet_id = s.subnet_id
name = s.name
priority = s.priority
action = s.action
}
]
}
}
这是关于 Azure 资源的,app_service,但我认为这是一个更一般的 HCL 问题……
您可以使用动态块将 IP 限制指定给 app_service,例如
locals {
ip_addresses = [ "192.168.250.1" ]
}
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}
resource "azurerm_app_service_plan" "example" {
name = "example-appserviceplan"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
sku {
tier = "Standard"
size = "S1"
}
}
resource "azurerm_app_service" "example" {
name = "example-app-service"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
app_service_plan_id = azurerm_app_service_plan.example.id
site_config {
dotnet_framework_version = "v4.0"
scm_type = "LocalGit"
}
app_settings = {
"SOME_KEY" = "some-value"
}
connection_string {
name = "Database"
type = "SQLServer"
value = "Server=some-server.mydomain.com;Integrated Security=SSPI"
}
dynamic "ip_restriction" {
for_each = toset(local.ip_addresses)
content {
ip_address = each.value
}
}
}
但是,要删除限制,您需要将 ip_restriction 显式分配给空列表,即
resource "azurerm_app_service" "example" {
...
ip_restriction = []
}
我看不到如何有条件地执行此操作 - 如果我制作两个资源并有条件地使用这些资源,我的 app_service 将是 created/destroyed,而我需要就地更新它。
这是一种特殊的 terraform
语法,称为 Attributes as Blocks. Resource arguments defined using nested block syntax implicitly define a fixed collection of objects,因此为了指定零个对象,我们应该明确设置空列表。而且这两种形式不能混用。
话虽如此,terraform
也支持参数语法(尽管他们建议在简单情况下使用块语法以提高可读性):
example = [
for name in var.names: {
foo = name
}
]
恐怕动态块在使用条件表达式时不支持空列表。阅读更多参考 here.
经过我的验证,当 var.some_variable
设置为 null
时,像 for_each = var.some_variable == "" ? [] : [1]
这样的条件表达式不起作用,但是当 for_each = var.some_variable
和 var.some_variable
设置为 null
.
因此,在这种情况下,作为@rkm 的回答,您可以使用 for
循环,就像我的这个工作示例一样。
variable "ip_restrictions" {
default = [
# {
# ip_address = "1.1.1.1/32"
# virtual_network_subnet_id = null
# subnet_id = null
# name = "aaa"
# priority = 110
# action = "Allow"
# },
# {
# ip_address = "2.2.2.2/32"
# virtual_network_subnet_id = null
# subnet_id = null
# name = "bbb"
# priority = 112
# action = "Allow"
# },
]
}
resource "azurerm_app_service" "example" {
name = "nn-example-app-service"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
app_service_plan_id = azurerm_app_service_plan.example.id
site_config {
ip_restriction = [
for s in var.ip_restrictions :
{
ip_address = s.ip_address
virtual_network_subnet_id = s.virtual_network_subnet_id
subnet_id = s.subnet_id
name = s.name
priority = s.priority
action = s.action
}
]
}
}