How to accept a block as module argument

Based on this github issue (#3388) and this github issue (#24029) it seems that humans really want to be able to pass blocks to modules as arguments. I know I do.

Based on the later issue it seems @teamterraform is claiming its now possible. Can we get an example?

An example of the use case were trying to get working is

main.tf

module "lambda_suite" {
    source = "../modules/api-gateway-lambda-suite"
    region = var.region
    name = var.name

    function {
        name = "get-products"
        version = data.external.version_map.result.get_products.version
        timeout = 30
    }

    function {
        name = "get-product-availability"
        version = data.external.version_map.result.get_product_availability.version
        environment_variables = {
            AMZ_API_KEY = data.aws_ssm_parameter.amazon_api_key.value
        }
    }

    function {
        name = "generate-checkout-receipt"
        version = data.external.version_map.result.generate_checkout_receipt.version
        layers = [
            local.document_conversion_tools_layer_arn
        ]
     }

variables.tf inside the api-gateway-lambda-suite module

variable function {
  type = list(object({
    name    = string
    version = string
    timeout = optional(number)
    memory  = optional(number)
    handler = optional(string)
    layers  = optional(list(string))
    environment_variables = optional(map(string))
  }))
  default = []
}

My Current Workaround
Instead of passing function blocks, pass the function argument as a list.

function = [{
    name = "abbreviated"
    version = "because_this"
}, {
    name = "is"
    version = "long"
}]

I don’t want to do this. Even terraform itself recommends using blocks over this format in the docs when possible:

we recommend using block syntax for simple cases for readability

Given @teamterraform says here in #24029

A lot has changed since 3338 was closed, and we now have the ability to pass around complex values using a structural type system, allowing one to do exactly as you describe here.

How is this done? If so…

  • please show me how
  • please add to the docs
  • please update the linked issues

Hi @rayepps,

What you’ve learned from the issues is correct: modules can accept complex-typed values as variables, and that is the only way to pass data structures.

Nested block types are a resource/provider thing, not a module thing. Data passes into and out of modules as normal values, which you can then project onto nested blocks within the module if you wish.