使用下面的代码时,当 tfvars 列表只有一个资源时,我能够成功创建资源。当它拥有多个资源时,它无法创建计划。 在测试过程中,我还注意到,如果两个 资源在 settings 下具有相似的配置(键),则会生成计划。
在以下示例中,由于将“always_on”添加到第二个资源,计划失败。有什么办法可以解决这个问题吗?
提供商:AzureRM 3.98.0,terraform 版本 - 1.7.5
错误:给定值对于变量“appservicelist”无效:集合元素无法统一。
env.auto.tfvars
appservicelist = {
appsvc1 = {
appsvcname = "appsvctest01"
rgname = "appsvcrg01"
settings = {
site_config = {
minimum_tls_version = "1.2"
http2_enabled = true
application_stack = {
java_version = "17"
}
}
}
},
appsvc2 = {
appsvcname = "appsvctest02"
rgname = "appsvcrg02"
settings = {
site_config = {
minimum_tls_version = "1.2"
http2_enabled = true
always_on = true
application_stack = {
java_version = "17"
}
}
}
}
}
main.tf
module "appservice" {
for_each = var.appservicelist
source = "./modules/appservice"
appsvcname = each.value.appsvcname
rgname = each.value.rgname
settings = each.value.settings
}
变量.tf
variables "appservicelist" {
type = map(object({
appsvcname = string
rgname = string
settings = any
}) )
}
./modules/appservice/main.tf
resource "azurerm_linux_web_app" "appservice" {
name = var.appsvcname
rgname = var.rgname
dynamic "site_config" {
for_each = lookup(var.settings, "site_config", {}) != {} ? [1] : []
content {
always_on = lookup(var.settings.site_config, "always_on", false)
http2_enabled = lookup(var.settings.site_config, "http2_enabled", false)
minimum_tls_version = lookup(var.settings.site_config, "http2_enabled", null)
...
...
}
dynamic "application_stack" {
for_each = lookup(var.settings.site_config, "application_stack" {}) != {} ? [1] : []
content {
java_version = lookup(var.settings.site_config.application_stack, "java_version", null)
}
}
}
}
./modules/appservice/variables.tf
variables "appsvcname" {}
variables "rgname" {}
variables "settings" {
type = any
default = {}
}
在单个命令中创建多个资源 - Terraform。
您遇到的问题是由 Terraforms 处理地图中的
any
类型引起的,尤其是当项目之间的对象结构不同时。在您的 tfvars
文件中,每个应用程序服务在其 settings
映射中包含不同的键。当 Terraform 尝试将集合合并为一种统一类型时,这种差异会导致错误。
不要对
any
类型使用 settings
,而是选择利用具有默认值的可选属性的结构化但适应性强的方法。此外,验证所有可选设置是否在动态块中得到正确管理,并且在没有指定值的情况下应用默认值。
我尝试了演示 terraform 配置作为测试用例,并且能够满足成功部署多个资源的要求。
我的文件结构:
├── main.tf
├── variables.tf
├── terraform.tfvars
└── modules
├── appservice
├── main.tf
├── variables.tf
main.tf(根):
provider "azurerm" {
features {}
}
module "appservice" {
for_each = var.appservicelist
source = "./modules/appservice"
appsvcname = each.value.appsvcname
rgname = each.value.rgname
settings = each.value.settings
service_plan_id = each.value.service_plan_id
location = each.value.location
}
变量.tf
variable "appservicelist" {
type = map(object({
appsvcname = string
rgname = string
location = string
service_plan_id = string
settings = object({
site_config = object({
minimum_tls_version = string
http2_enabled = bool
always_on = optional(bool)
application_stack = object({
java_version = string
java_server = string
java_server_version = string
})
})
})
}))
}
terraform.tfvars:
appservicelist = {
appsvc1 = {
appsvcname = "appvksvctest01"
rgname = "appvksvcrg01"
location = "East US"
service_plan_id = "/subscriptions/sub_ID/resourceGroups/vinay-rg/providers/Microsoft.Web/serverFarms/vk-plan-id-1"
settings = {
site_config = {
minimum_tls_version = "1.2"
http2_enabled = true
always_on = false
application_stack = {
java_version = "11"
java_server = "TOMCAT"
java_server_version = "9.0"
}
}
}
},
appsvc2 = {
appsvcname = "appvksvctest02"
rgname = "appvksvcrg02"
location = "West US"
service_plan_id = "/subscriptions/sub_ID/resourceGroups/vinay-rg/providers/Microsoft.Web/serverFarms/vk-plan-id-2"
settings = {
site_config = {
minimum_tls_version = "1.2"
http2_enabled = true
always_on = false
application_stack = {
java_version = "11"
java_server = "TOMCAT"
java_server_version = "9.0"
}
}
}
}
}
模块/appservice/main.tf
modules/appservice/main.tfresource "azurerm_linux_web_app" "appservice" {
name = var.appsvcname
resource_group_name = var.rgname
location = var.location
service_plan_id = var.service_plan_id
site_config {
always_on = lookup(var.settings.site_config, "always_on", false)
http2_enabled = var.settings.site_config.http2_enabled
minimum_tls_version = var.settings.site_config.minimum_tls_version
dynamic "application_stack" {
for_each = var.settings.site_config.application_stack != null ? [var.settings.site_config.application_stack] : []
content {
java_version = application_stack.value.java_version
java_server = application_stack.value.java_server
java_server_version = application_stack.value.java_server_version
}
}
}
}
output "app_service_name" {
value = azurerm_linux_web_app.appservice.name
}
模块/appservice/variable.tf
variable "appsvcname" {
type = string
}
variable "rgname" {
type = string
}
variable "location" {
type = string
}
variable "service_plan_id" {
type = string
}
variable "settings" {
type = object({
site_config = object({
minimum_tls_version = string
http2_enabled = bool
always_on = optional(bool)
application_stack = object({
java_version = string
java_server = string
java_server_version = string
})
})
})
}
注意:确保您的应用程序部署位于应用程序服务计划的同一区域中
部署成功: