Latest in branch 1.2
1.2.9
Released 07 Sep 2022
(3 years ago)
SoftwareTerraform
Version1.2
Status
End of life
Initial release1.2.0
18 May 2022
(4 years ago)
Latest release1.2.9
07 Sep 2022
(3 years ago)
End of security fixes08 Mar 2023
(Ended 3 years, 3 months ago)
Release noteshttps://github.com/hashicorp/terraform/blob/v1.2/CHANGELOG.md
Source codehttps://github.com/hashicorp/terraform/tree/v1.2
Documentationhttps://developer.hashicorp.com/terraform/docs
Downloadhttps://releases.hashicorp.com/terraform/
Terraform 1.2 ReleasesView full list

What Is New in Terraform 1.2

Terraform 1.2 introduces several key enhancements focused on improving the module development experience and providing finer control over data handling. The most significant additions are the replace_triggered_by lifecycle argument and the new moved configuration block.

Category Key Changes
New Features moved block, replace_triggered_by lifecycle, optional object attributes
Enhancements Cloud integration improvements, extended functions (startswith, endswith), terraform_data managed resource
Deprecations terraform 0.11 and earlier compatibility, certain provisioner behaviors

How does the moved block simplify refactoring?

The new moved block is a declarative way to record resource or module instance address changes in your configuration. This is a game-changer for refactoring because it tells Terraform to treat the new address as if it were always there, preserving the existing object in state instead of destroying and recreating it.

In practice, you add a moved block to your configuration to explain where a resource used to live. This is far cleaner than using the terraform state mv command, as the intent is now documented directly in the code for your whole team to see.

moved {
  from = aws_instance.old_name
  to   = aws_instance.new_name
}

What can I control with replace_triggered_by?

The replace_triggered_by lifecycle argument lets you force a resource to be replaced based on changes in other parts of your infrastructure. You can point it to a list of references from attributes of other resources, a resource's self attributes, or even a list of instance addresses.

This is useful for managing implicit dependencies that Terraform can't automatically detect. For example, you can force an EC2 instance to be replaced whenever its underlying AMI is updated, even if the AMI ID is fetched dynamically by a data source.

lifecycle {
  replace_triggered_by = [
    data.aws_ami.example.id
  ]
}

How do optional object attributes improve modules?

Optional attributes in object type constraints make module input variable schemas much more flexible. You can now define an object type where certain attributes are optional instead of required, allowing users to omit them when calling your module.

This matters because it removes the need to specify dummy values for attributes you don't care about. It makes modules cleaner to use and more closely mirrors the optional arguments you find in resource blocks.

variable "example" {
  type = object({
    name    = string
    enabled = optional(bool, true)
    tags    = optional(map(string))
  })
}

What cloud integrations were enhanced?

Terraform 1.2 includes deeper integration with Terraform Cloud, particularly for the CLI-driven run workflow. The authentication process for terraform login was improved to support automatically generating a credentials token when using TFC as a host.

These updates streamline the developer experience when working in a CI/CD pipeline or any automated environment where manual token handling is cumbersome. It's about reducing friction for teams that use Terraform Cloud as their collaboration backend.

FAQ

Does the moved block actually run a terraform state mv command?
No. The moved block is a configuration-time declaration, not a command. When you run terraform plan, it analyzes these blocks and internally updates the state file to reflect the new address before creating the execution plan.

Can I use replace_triggered_by with any expression?
No. The argument only accepts references to specific objects: resources, data sources, or a list of instance addresses. You cannot use arbitrary expressions, function calls, or literal values, as it needs to track specific dependencies.

What happens if I use both a moved block and terraform state mv?
You should generally choose one method. The moved block is the preferred, declarative approach. If you use both, Terraform will see the state was already moved by the command and the block may become a no-op, but it's best to avoid the confusion.

Are there any new functions besides startswith and endswith?
Not in this release. The main function additions are startswith and endswith, which provide convenient string prefix and suffix checks that were previously missing from the interpolation language.

Is the terraform_data resource a replacement for null_resource?
It serves a similar purpose but is integrated into the core lifecycle. terraform_data is a managed resource that stores a value, useful for triggering provisioners on other resources without the need for the null_resource community anti-pattern.

Releases In Branch 1.2

VersionRelease date
1.2.907 Sep 2022
(3 years ago)
1.2.824 Aug 2022
(3 years ago)
1.2.710 Aug 2022
(3 years ago)
1.2.627 Jul 2022
(3 years ago)
1.2.513 Jul 2022
(3 years ago)
1.2.429 Jun 2022
(3 years ago)
1.2.315 Jun 2022
(3 years ago)
1.2.201 Jun 2022
(4 years ago)
1.2.123 May 2022
(4 years ago)
1.2.018 May 2022
(4 years ago)
1.2.0-rc211 May 2022
(4 years ago)
1.2.0-rc104 May 2022
(4 years ago)
1.2.0-beta127 Apr 2022
(4 years ago)
1.2.0-alpha2022041313 Apr 2022
(4 years ago)
1.2.0-alpha-2022032828 Mar 2022
(4 years ago)