What Is New in Terraform 1.1
Terraform 1.1 introduces major workflow enhancements, particularly around refactoring and module authoring. The headline feature is the ability to move resources into and out of child modules without destroying and recreating them.
| Category | Key Changes |
|---|---|
| New Features | Cross-module moved blocks, optional object type attributes |
| Improvements | Enhanced terraform console, Cloud state encryption, Provider-defined functions (experimental) |
| Bug Fixes | Numerous fixes for the Terraform CLI, core, and built-in providers |
| Deprecations | Deprecation notices for various arguments and attributes in the AWS and AzureRM providers |
How does Terraform 1.1 improve refactoring?
The biggest win is the introduction of cross-module moved blocks. This lets you refactor your code by moving resources between modules without the pain of destroying and recreating the underlying infrastructure. You just declare the move in your configuration and Terraform handles the rest.
In practice, this is a game-changer for evolving complex configurations over time. You can now extract a group of resources into a new module or collapse a module back into the root, all while preserving the state. This makes large-scale code maintenance significantly less risky.
Example
# Moving a resource from the root module to a child module
moved {
from = aws_instance.example
to = module.example_module.aws_instance.example
}
What new capabilities were added for module authors?
Module authors get a powerful new tool with optional object type attributes. You can now define an object type where certain attributes are not mandatory, giving consumers of your module more flexibility.
This matters because it removes a previous rigidity in object type definitions. Before, every attribute in an object had to be set. Now you can create more nuanced and user-friendly module interfaces that can accommodate a wider range of use cases without requiring complex workarounds.
Example
variable "example" {
type = object({
required = string
optional = optional(string)
})
}
What enhancements were made to the Terraform CLI?
The terraform console command received a major upgrade, now supporting all of the Terraform language's built-in functions, operators, and type conversion capabilities. It's no longer just for simple expressions.
This turns the console into a proper sandbox for testing and debugging complex logic. You can now prototype entire expressions, test function combinations, and validate your assumptions interactively before writing them into your configuration files.
Are there any experimental features to try?
Yes, Terraform 1.1 includes an experimental feature for provider-defined functions. This allows providers to expose custom functions, extending the Terraform language itself with capabilities specific to that provider's domain.
This is experimental, so it's not for production yet, but it opens up exciting possibilities. Imagine a cloud provider offering a function to dynamically calculate optimal instance sizes or network configurations directly within your HCL.
FAQ
Can I use moved blocks to rename a resource?
Yes, absolutely. The moved block syntax is designed for both moving resources to different modules and for renaming resources within the same module. It's a unified mechanism for any refactoring that changes a resource's address in the state.
Do optional object attributes change my existing modules?
No, this is a purely additive feature. Your existing module variable definitions will continue to work exactly as before. You only need to use the optional() modifier when you want to define new, non-required attributes.
Is the state encryption for cloud backends automatic?
No, it's an opt-in feature. For supported backends like Terraform Cloud, you must explicitly enable and configure encryption using the backend's specific settings. Your existing state files remain unchanged until you enable this feature.
What happens if I remove a moved block?
Once Terraform has processed a moved block and updated the state, the block can be safely removed from your configuration. The state now remembers the new address, so the block is only needed to perform the initial state update.
How stable are the provider-defined functions?
They are explicitly marked as experimental in this release. The syntax and behavior could change in future versions based on feedback. It's great for testing and providing feedback to providers, but avoid using them for critical production workloads until they are stabilized.