Skip to content

Variable unpacking for easy module resource parameter matching #37670

@drewmullen

Description

@drewmullen

Explanation / setup

Say I have a module that allows users to set some specific values on resources. The common approach is to define a variable for each parameter

root module

variable "vpc_region" {}
variable "vpc_cidr" {}
# ... etc

module "vpc" {
   region = var.vpc_region
   cidr   = var.vpc_cidr
}

module

Then inside the module code we map each var to the resource. This also requires redefining the variables

variable "vpc_region" {}
variable "vpc_cidr" {}
# ... etc

resource "aws_vpc" "m" {
  region = var.vpc_region
  cidr_block    = var.vpc_cidr
}

With 2 variables this isnt too bad but when done in reality this can get quite complicated.

Slightly better way

Another option is to use a single variable and then map to the resource parameters in the module.

root module

variable "vpc_attributes" {
  type = object({
    cidr   = string
    region = string
  })
}

module "vpc" {
  vpc_attributes = var.vpc_attributes
}

module

This method reduces the amount of variables you need to define in the module. However this still requires:

  • setting each parameter on the resource
  • handling for null or missing keys
variable "vpc_attributes" {}

resource "aws_vpc" "m" {
  region = var.vpc_attributes["region"]
  cidr_block    = var.vpc_attributes["cidr"]
}

The big idea

What if we had a way of packing terraform variables as known parameter keys of a resource. Then unpack them into the resource in the module code itself. The keys and types must match for this to work.

root module

variable "vpc_attributes" {
  type = object({
    cidr_block   = string
    region = string
    instance_tenancy = string
  })
}

module "vpc" {
   vpc_attributes = var.vpc_attributes
}

module

variable "vpc_attributes" {}

resource "aws_vpc" "m" {
  var.vpc_attributes...
  
  enable_dns_hostnames = true
}

The syntax is expansive the same way most programming languages have a form of variadic functions. Also note that other parameters can be set that are not necessarily in the variable. Also note that the vpc_attributes us using custom object types to enforce the same naming convention as the aws_vpc resource expects.

This aligns nicely with the spirit of variable custom object definitions with default values. Ultimately this would make for cleaner and more maintainable terraform modules.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions