Terraform lookup函数未默认返回null致Azure函数应用部署报错
问题:Terraform配置Azure函数应用栈时参数冲突报错
尝试用Terraform的lookup函数根据输入指定Azure Web应用栈,执行terraform plan时触发参数冲突错误,提示application_stack块中仅能指定一个栈参数。预期java_version返回null(手动设置null时可正常运行),但当前lookup写法导致node_version与java_version同时被指定,需排查问题原因。
报错信息
terraform plan ╷ │ Error: Invalid combination of arguments │ │ with azurerm_windows_function_app.example, │ on functionapp.tf line 67, in resource "azurerm_windows_function_app" "example": │ 67: application_stack { │ │ "site_config.0.application_stack.0.powershell_core_version": only one of │ `site_config.0.application_stack.0.dotnet_version,site_config.0.application_stack.0.java_version,site_config.0.application_stack.0.node_version,site_config.0.application_stack.0.powershell_core_version,site_config.0.application_stack.0.use_custom_runtime` │ can be specified, but `site_config.0.application_stack.0.java_version,site_config.0.application_stack.0.node_version` were specified.
原Terraform代码
variable "applicationstack" { type = string default = "node" } variable "stack_version" { type = map default ={ node = "~14" java = "8" } } resource "azurerm_resource_group" "example" { name = "eus-s-test-rg-01" location = "eastus" } resource "azurerm_storage_account" "example" { name = "eusperftestjs01" resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location account_tier = "Standard" account_replication_type = "LRS" } resource "azurerm_service_plan" "example" { name = "example-app-service-plan" resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location os_type = "Windows" sku_name = "Y1" } resource "azurerm_windows_function_app" "example" { name = "eus-perf-test-js-01" resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location storage_account_name = azurerm_storage_account.example.name storage_account_access_key = azurerm_storage_account.example.primary_access_key service_plan_id = azurerm_service_plan.example.id site_config { application_stack { node_version = lookup(var.stack_version,var.applicationstack,null) java_version = lookup(var.stack_version,var.applicationstack,null) } } }
解决方案
问题核心不是lookup语法错误,而是你同时显式声明了node_version和java_version两个参数——哪怕它们的值是null,Terraform依然会将这两个参数传递给Azure资源,而Azure的函数应用资源不允许同时指定多个栈版本参数。
方法1:使用动态块(推荐,扩展性好)
通过Terraform的动态块,仅生成对应栈类型的版本参数:
resource "azurerm_windows_function_app" "example" { name = "eus-perf-test-js-01" resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location storage_account_name = azurerm_storage_account.example.name storage_account_access_key = azurerm_storage_account.example.primary_access_key service_plan_id = azurerm_service_plan.example.id site_config { dynamic "application_stack" { for_each = [var.applicationstack] content { (application_stack.value)_version = lookup(var.stack_version, application_stack.value, null) } } } }
- 动态块会根据
var.applicationstack的值,仅生成对应栈的版本参数(比如指定node时,只会生成node_version = "~14",不会出现java_version参数) - 后续新增栈类型(如dotnet)时,只需在
stack_version变量中添加对应值,无需修改资源配置
方法2:条件判断显式赋值
如果栈类型较少,也可以用条件判断单独控制每个参数的赋值:
resource "azurerm_windows_function_app" "example" { name = "eus-perf-test-js-01" resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location storage_account_name = azurerm_storage_account.example.name storage_account_access_key = azurerm_storage_account.example.primary_access_key service_plan_id = azurerm_service_plan.example.id site_config { application_stack { node_version = var.applicationstack == "node" ? lookup(var.stack_version, "node", null) : null java_version = var.applicationstack == "java" ? lookup(var.stack_version, "java", null) : null } } }
这种方式需要为每个栈类型单独写条件判断,适合栈类型固定的场景。
内容的提问来源于stack exchange,提问作者Uday Kiran
相关产品推荐
相关产品推荐

