terraform

Terraform 1.3 Improves Extensibility and Maintainability of Terraform Modules

Now generally available, HashiCorp Terraform 1.3 introduces optional object type attributes with defaults, and enhancements to moved blocks, improving extensibility and maintainability of Terraform modules.

We’re excited to announce the release of HashiCorp Terraform 1.3, now immediately available for download as well as for use in HashiCorp Terraform Cloud. Terraform is widely adopted as the standard for multi-cloud provisioning and automation for individuals and teams at any scale. This release introduces optional object type attributes with defaults, and expands the capabilities of moved blocks. These changes improve the extensibility and maintainability of Terraform modules and help users to more easily refactor a Terraform code base as it grows.

»Optional Object Type Attributes with Defaults

Terraform variables support a feature known as type constraints. This argument allows module authors to validate the type of value supplied to input variables. In more complex scenarios, there may be a need to group multiple values into a single variable. A common solution in these scenarios is to use the object type, which is a collection of named attributes that each have their own type.

To support this approach even further, the community proposed a feature that would allow marking an object’s named attributes as optional. This feature was added to Terraform 0.14 under experimental support and eventually became one of the most upvoted community GitHub issues.

As a result of that community support, Terraform 1.3 graduates the optional object type attribute feature from experimental status and adds the ability to set a default value. The benefit of this feature is to provide module authors a way to extend their modules to handle more complex use cases using the object type without forcing module consumers to provide values for attributes that are not relevant to their work.

Below is an example of using the optional object type attribute with a default value when defining a variable as "ingress_rules":

variable "ingress_rules" {
  type = list(object({
    port = number,
    description = optional(string),
    protocol = optional(string, "tcp"),
  }))
}
variable "ingress_rules" {
  type = list(object({
    port = number,
    description = optional(string),
    protocol = optional(string, "tcp"),
  }))
}

You can apply the following values to this variable:

rules = [
  { port = 80, description = "web" },
  { port = 53, protocol = "udp" }
]
rules = [
  { port = 80, description = "web" },
  { port = 53, protocol = "udp" }
]

The resulting variable value will be:

[
  {
    port = 80,
    description = "web",
    protocol = "tcp",
  },
  {
    port = 53,
    description = null,
    protocol = "udp",
  }
]
[
  {
    port = 80,
    description = "web",
    protocol = "tcp",
  },
  {
    port = 53,
    description = null,
    protocol = "udp",
  }
]

»Improvements to moved Blocks

The moved block, introduced as part of Terraform 1.1, provided a programmatic method for refactoring resources within a Terraform configuration file. This update removed the dependency on using terraform state mv, which was manual, error-prone, and would often lose the context of refactor operations to the command line history. There was one limitation with the initial release of the moved block: they only supported refactoring moves if they were between modules within the same local path.

Terraform 1.3 improves moved blocks by adding the ability to refactor resources to third-party and separately sourced modules. This includes modules sourced from the Terraform Registry, a private registry in Terraform Cloud, or any of the other options available through the source argument.

Below is an example of using the moved block to refactor a resource into a module sourced from Terraform Cloud’s private registry:

moved {
  from = aws_instance.hashiapp
  to   = module.web-server-aws.aws_instance.hashiapp
}

module "web-server-aws" {
  source  = "app.terraform.io/TPMM-Org/web-server-aws"
  version = "1.0.1"

  prefix        = var.prefix
  region        = var.region
  key_name      = var.key_name
  instance_type = var.instance_type
}
moved {
  from = aws_instance.hashiapp
  to   = module.web-server-aws.aws_instance.hashiapp
}
 
module "web-server-aws" {
  source  = "app.terraform.io/TPMM-Org/web-server-aws"
  version = "1.0.1"
 
  prefix        = var.prefix
  region        = var.region
  key_name      = var.key_name
  instance_type = var.instance_type
}

»Getting Started with Terraform 1.3

For more details, please see the full HashiCorp Terraform 1.3 changelog. This release wouldn't have been possible without all of the great community feedback we've received via GitHub issues, as well as continued feedback from our customers. Thank you!


Sign up for the latest HashiCorp news