3

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?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Krzysztof Madej
  • 32,704
  • 10
  • 78
  • 107
  • 2
    Coincidentally there was a now deleted question a few days ago about this, so will put the relevant comment again here: this is not possible in HCL2 syntax, and the way this is implemented in resource and data blocks is with the schema in the SDK, which is not available for modules. – Matthew Schuchard Nov 19 '21 at 13:36
  • What a shame :( But well, thanks for answering. Please can you post it as an reply. I would prefer to keep this online so it would be beneficial for other person who may have this question. – Krzysztof Madej Nov 19 '21 at 13:48
  • Coincidentally someone else also wanted the opposite recently (convert from a block in a resource to a `list(object)`. Anyway, the schema for a block would have a `Elem` of `Map` where the type is `Map` or `Set` in SDKv1, but now in v2 these are arguments and the `Elem` must be a nested resource schema. Note that the schema documentation examples on the TF website have not been updated for this yet. – Matthew Schuchard Nov 19 '21 at 14:22
  • Also, are you requesting I write up an answer for this? Sorry; it is unclear. – Matthew Schuchard Nov 19 '21 at 14:23
  • Yeah. After all this is answer for my question. – Krzysztof Madej Nov 19 '21 at 14:27

1 Answers1

4

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).

Matthew Schuchard
  • 25,172
  • 3
  • 47
  • 67