如何用块构建 Terraform 模块

How to build terraform module with blocks

我想构建一个语法如下的模块:

module "order_module" {

  service {
    name ="some-name"
  }

  lambda {
    name = "some-lambda-name"
  }

}

理想情况下,我希望能够以这种方式提供多种服务和功能:

module "order_module" {

  service {
    name ="some-name"
  }

  service {
    name ="some-name-1"
  }

  lambda {
    name = "some-lambda-name"
  }

  lambda {
    name = "some-lambda-name-2"
  }

  lambda {
    name = "some-lambda-name-3"
  }
}

有了变量,我可以做到这一点:

module "order_module" {

  service = {
    name ="some-name"
  }

  lambda = {
    name = "some-lambda-name"
  }
}

然而,当我想提供更多服务时,我需要将它们放在一个列表中:

module "order_module" {

  service = [{
    name ="some-name"
  },
  {
    name ="some-name-2"
  }]

  lambda = {
    name = "some-lambda-name"
  }
}

我没有找到用块构建模块的方法。本机资源有这个:

resource "azurerm_key_vault" "lab" {
  name                = "${var.app_name}${var.env_name}vault${random_id.lab.dec}"
  location            = azurerm_resource_group.lab.location
  resource_group_name = azurerm_resource_group.lab.name
  tenant_id           = data.azurerm_client_config.lab.tenant_id

  sku_name = "standard"

  access_policy {
    tenant_id = data.azurerm_client_config.lab.tenant_id
    object_id = data.external.lab.result.objectId

    key_permissions = []

    secret_permissions = [
      "list",
      "set",
      "get",
      "delete"
    ]
  }
}

access_policy 以上。是否可以通过此类块向模块提供参数?

HCL2 语法的 Terraform DSL 当前不允许 Terraform 模块声明块中的嵌套块。这可以在 module block syntax documentation 中得到证实。语法架构的文档指定块中只允许使用参数。

resourcedata 块中嵌套块的实现是使用 Terraform 提供程序 SDK。不可能在提供程序中实现不同的模块模式,所以这就是为什么使用当前工具不可能的原因。在 SDK 版本 1 中,嵌套块的相应架构为:

Type: schema.TypeMap, // or schema.TypeSet
Elem: &schema.Schema{
  Type: schema.TypeString,
},

从 SDK 版本 2 开始,此架构现在对应于 Map 类型的参数。我的猜测是,这部分是为了允许在复杂类型中指定参数及其类型。这是通过将架构更改为:

为嵌套块实现的
Type: schema.TypeSet,
Elem: &schema.Resource{...}

其中 Elem 现在是嵌套的 schema.Resource,这允许此规范。以前的模式(现在对应于参数)现在对任意键值对更有用,例如资源中的 tags某些参数的 Map 类型参数的嵌套块)。

Terraform 核心 Go 代码需要更新以允许在模块块声明的 HCL2 语法中嵌套块。

另请注意,在撰写本文时此架构的文档尚未针对 SDK v2 进行更新,应将其视为对应于 v1(这就是我在开头引用 v1 行为的原因)。