Skip to main content
  1. Posts/

The Best Terraform Feature Yet?

William Collins
Author
William Collins
Building at the intersection of cloud, automation, and AI. Host of The Cloud Gambit podcast.
Table of Contents

Optional attributes for object type constraints is almost here! I’ve been waiting for this feature to come along for a while. I have tested it extensively in -alpha, and I can confidently confirm that it is a game changer. This feature is long in the making, being discussed as far back as this thread in 2018. Today, it is now in beta, so the official release could be any day now. Let’s demonstrate how this is useful and build some common AWS infrastructure.

Why it is Useful
#

Before this feature, you could resort to using tricks to make arguments in object variables optional. This usually included providing a null value for optional parameters and then doing some fancy lookup or conditional like so:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
variable "some_var" {
  type = object({
    name          = string
    description   = string
  }
  default = {
    name          = "william",
    description   = null
    
  })
}

locals {
  description = lookup(var.some_var, "description", "no_description") == "no_description" ? null : var.some_var
}

Now, we can make that individual attribute optional without any hackery involved. The first thing to know here is that when setting optional(string) without a default value as shown below, the default value is null.

1
2
3
4
5
6
variable "some_var" {
  type = object({
    name          = string
    description   = optional(string)
  })
}

While having the default value automatically set to null is helpful, it only solves half of the problem. What happens if we have a scenario where we still want to provide a value in the logic, even if one isn’t supplied at runtime? Then we can set a default value with a second argument like this:

1
2
3
4
5
6
variable "some_var" {
  type = object({
    name          = string
    description   = optional(string, "Can't stand Monopoly")
  })
}

Building some Infrastructure in AWS
#

This feature comes in handy when building complex data types. Let’s look at something as simple as building an AWS VPC. Your organization could be using VPC IPAM but may still need the option to pass in custom CIDRs at runtime. Or, other standard defaults may need to be set if not provided at runtime. Take the following example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
variable "vpc" {
  description = "Default VPC object"

  type = object({
    name                  = string
    cidr_block            = optional(string)
    ipv4_ipam_pool_id     = optional(string)
    ipv4_netmask_length   = optional(number)
    enable_dns_support    = optional(bool, true)
    enable_dns_hostnames  = optional(bool, false)
    instance_tenancy      = optional(string, "default")
  })

}

If only the cidr_block attribute is provided at runtime, then the IPAM attributes will be nullified. This simplifies our resource configuration as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
resource "aws_vpc" "vpc" {
  cidr_block            = var.vpc.cidr_block
  ipv4_ipam_pool_id     = var.vpc.ipv4_ipam_pool_id
  ipv4_netmask_length   = var.vpc.ipv4_netmask_length
  enable_dns_support    = var.vpc.enable_dns_support
  enable_dns_hostnames  = var.vpc.enable_dns_hostnames
  instance_tenancy      = var.vpc.instance_tenancy

  tags = {
    Name = var.vpc.name
  }

}

Test it Yourself!
#

Want to start testing? Grab v1.3.0-beta1 and setup your versions.tf like this:

1
2
3
4
terraform {
  required_version = ">= 1.3.0"
  experiments      = [module_variable_optional_attrs]
}

Conclusion
#

AWS VPC is a simple example. This feature really shines when building reusable infrastructure-as-code for Network Firewall or even Network ACLs. Anything that simplifies something and reduces or eliminates any hacks required to reach a logical outcome is super valuable. Great work finally driving this one home HashiCorp.

Related

Intro To Terraform Modules With AWS

Effectively automating infrastructure is no longer a luxury but a staple in the enterprise move through future transformation. I wrote a blog recently about using Terraform with Packer together, and wanted to take this thought further with breaking down Terraform Modules and getting well connected with Terraform Cloud. I recently put together a simple module for building base infrastructure in AWS for the purpose of testing Alkira Network Cloud. Let’s dive in!

Terraforming Alkira and Fortinet is Multicloud Bliss

There is a reason why enterprises prefer the best-of-breed approach to connect and secure their network and intellectual property. Alkira announced its integration with Fortinet at AWS re:Inforce in July, and this is a perfect example of the best in action. As anyone that reads my blog knows, I have an automation first approach to everything. Alkira’s Terraform Provider is Fortinet ready, so let’s take it for a spin!

Importing Infrastructure With Azure Terrafy

Anyone that has worked in tech knows that building greenfield is much easier than dragging along brownfield environments through a roller-coaster they aren’t ready for. Tools like Terraform make infrastructure-as-code a breeze, but what about all that infrastructure you already have provisioned? April Edwards, Cloud Advocate at Microsoft, recently posted a blog about Azure Terrafy, a new tool in preview which aims to simplify the process. You can find the original blog here. Let’s take it for a spin!