Today we've released OpenTofu v1.12.0, collecting together several months of work from the OpenTofu community, including several new features.
The following are highlights from the new release:
- Dynamic
prevent_destroy: Theprevent_destroyargument in a resource's lifecycle block can now refer to other symbols within the same module, such as input variables. - Improved provider checksum handling:
tofu initnow automatically includes a full set of checksums for all platforms using bothzh:andh1:hashes, reducing the need for manually runningtofu providers lock. - Simultaneous output formats: The new
-json-into=FILENAMECLI option allows saving machine-readable output to a separate file while still producing human-readable output in the terminal. - New
destroylifecycle meta-argument: The newdestroy = falselifecycle option for managed resources allows removing an object from the state without first destroying the remote object. - Provider installer performance: Provider installation now performs concurrent requests for faster
tofu initcompletion when many providers are needed.
For full details on the changes in this release, refer to the OpenTofu v1.12.0 release notes.
There are also some deprecations that might be relevant to you:
prevent_destroy can now be set dynamically​
The prevent_destroy lifecycle argument for managed resources tells OpenTofu that it should return an error if the plan for a particular object involves destroying it. Authors tend to use this feature for infrastructure objects that whose deletion would cause large disruption, or when faithfully recreating that object would require manual action outside of OpenTofu such as restoring a backup.
Unfortunately this setting previously required making a static decision that's hard-coded into the configuration, which is annoying for shared modules that might be used in multiple different environments that have different needs. For example, it's common to want to make it very hard to destroy a production database while still allowing the equivalent database in a development environment to be easily replaced when necessary.
OpenTofu v1.12.0 now allows prevent_destroy to be defined dynamically in terms of other values available elsewhere in the same module. For example:
variable "prevent_destroy_database" {
type = bool
default = true
}
resource "example_database" "example" {
# ...
lifecycle {
prevent_destroy = var.prevent_destroy_database
}
}
A module containing the above would prevent deletion of the database by default, but when used in a development environment you could set prevent_destroy_database = false in the module block to disable that constraint.
This is the first of several other lifecycle-related settings we're hoping to make more dynamic in future versions of OpenTofu. We started with this one because the design questions for it had relatively straightforward answers. The others each have their own design challenges we need to overcome, and if you're interested you can find out more in the umbrella issue #1329.
Provider Checksum Improvements​
The default provider installation behavior in OpenTofu is designed to mostly "just work" by getting the needed providers installed and making the necessary changes to the dependency lock file, but in previous versions friction appeared for any teams using many of the non-default installation settings such as the shared provider plugin cache, or local mirrors of upstream providers.
For OpenTofu v1.12, OpenTofu Registry now provides a full set of official checksums in all of the checksum formats needed by other installation methods. This means that after running tofu init the dependency lock file will immediately have all of the information required to successfully use a global plugin cache directory and to verify matching packages served from a local mirror, without needing to run tofu providers lock separately.
The tofu providers lock command is now needed only in the situation for which it was originally intended: populating the dependency lock file with the official checksums from origin registries on systems where tofu init has been reconfigured to use an alternative installation source. As long as your CLI configuration allows tofu init to install providers directly from OpenTofu Registry (which is the default), it will record the full set of checksums automatically.
The first time you run tofu init after upgrading, you will find additional entries were added to the hashes argument in your dependency lock file, all of which should use the h1: prefix. This is the hashing scheme that previous versions of OpenTofu could only calculate locally, but OpenTofu v1.12 can now prepopulate all of these hashes at once on first install in addition to the zh: hashes that were already included by previous versions of OpenTofu.
Simultaneous Human-readable and Machine-readable Output​
Many OpenTofu commands support both human-oriented UI output and machine-readable JSON output, but previously those commands could be run with only one or the other. This was bothersome for those implementing alternative UIs in terms of the machine-readable output because it meant they would need to implement all possible features of the UI before their tool could actually be used.
OpenTofu v1.12.0 introduces a new option -json-into=FILENAME, which produces the same output format that -json would have produced but sends that output to the given filename instead of to the standard output stream. The OpenTofu UI output then appears on the standard output stream as normal, so that software interpreting the JSON output can behave as just a supplement to the normal UI rather than a complete replacement.
For commands that produce streaming JSON output describing a series of ongoing events, you can optionally specify the path to an operating system IPC object such as a named pipe or a /dev/fd/N special device node so that your software can consume that JSON output concurrently with OpenTofu's execution, such as if you want to update a web UI or terminal UI responsively to report ongoing progress.
Download and Install​
You can download OpenTofu v1.12.0 directly from our GitHub releases page, install it using your preferred package manager, or use our official Docker images.
For more information, refer to our installation guides.
Deprecation Notices​
WinRM for Provisioners is Now Deprecated​
Some of the Go libraries that OpenTofu uses for WinRM connection support in provisioners have become unmaintained over time, and so unfortunately we are phasing out support for WinRM in OpenTofu starting with deprecation warnings in this release.
If your configuration includes a connection block with type = "winrm" then OpenTofu v1.12 will warn that this connection type is deprecated, but provisioning should otherwise still work as it did before.
We intend to remove WinRM support completely in the forthcoming OpenTofu v1.13 series, and so if you are currently relying on WinRM support we recommend that you begin planning to migrate to using OpenSSH for Windows instead.
Phasing Out Support for 32-bit CPU Architectures​
We are also planning to stop producing official releases for 32-bit CPU architectures (386 and arm) in a future version of OpenTofu. Support for 64-bit architectures (amd64 and arm64) is unaffected.
OpenTofu v1.12 does not include any changes to CPU support yet, but we expect that the official builds in the forthcoming v1.13 series will begin producing warnings when running on 32-bit CPU architectures, before we stop producing those packages altogether in a future release series.
If you are currently running OpenTofu on a 32-bit CPU architecture we recommend beginning to plan migration to a 64-bit architecture instead. If you don't expect to be able to complete that migration at some point in the next year, please tell us about your situation in issue #3912.