-
Notifications
You must be signed in to change notification settings - Fork 10k
Description
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.