Krzysztof Madej
Krzysztof Madej

Reputation: 40603

How to build terraform module with blocks

I want to build a module with syntax as follows:

module "order_module" {

  service {
    name ="some-name"
  }

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

}

Ideally I want to be able to provide multiple service and functions in this way:

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"
  }
}

With variables I can do this:

module "order_module" {

  service = {
    name ="some-name"
  }

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

However when I want to provide more services I need to put them in a list:

module "order_module" {

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

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

I didn't find a way to build modules with block. A native resources have this:

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 above. Is this possible to provide parameters to module via such blocks?

Upvotes: 6

Views: 2496

Answers (1)

Matthew Schuchard
Matthew Schuchard

Reputation: 28749

Nested blocks in Terraform module declaration blocks are currently not allowed in the Terraform DSL of the HCL2 syntax. This can be confirmed in the module block syntax documentation. The documentation for the syntax schema specifies only arguments are allowed in the block.

The implementation for nested blocks in resource and data blocks is with the Terraform provider SDK. It is not possible to implement a different module schema within a provider, so this is why it is not possible with current tooling. In SDK version 1, the corresponding schema for a nested block was:

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

As of version 2 of the SDK, this schema now corresponds to arguments of type Map. My speculation is that this was partially to allow specifying the arguments and their types within a complex type. This was implemented for nested blocks by changing the schema to:

Type: schema.TypeSet,
Elem: &schema.Resource{...}

where the Elem is now a nested schema.Resource, which allows for this specification. The previous schema (now corresponding to arguments) is now more useful for arbitrary key-value pairs, such as for tags in resources (note this is also probably why updates in Terraform providers and recently in Packer caused a syntax change from nested blocks to arguments of type Map for certain parameters).

The Terraform core Go code would need to be updated to allow nested blocks within the HCL2 syntax of module block declarations.

Note also that the documentation for this schema at the time of this writing has not been updated for SDK v2, and should be read as corresponding to v1 (which is why I reference the v1 behavior at the beginning).

Upvotes: 4

Related Questions