Terraform - 集合元素无法统一

问题描述 投票:0回答:1

使用下面的代码时,当 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 = {}
}
azure terraform terraform-provider-azure
1个回答
0
投票

在单个命令中创建多个资源 - 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
      })
    })
  })
}

注意:确保您的应用程序部署位于应用程序服务计划的同一区域中

部署成功:

enter image description here

enter image description here

enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.