A Guide for Terraform Versioning in Infrastructure-as-Code Management
Tags: webdev
Published: 2023-11-24 16:34:11

The Hashicorp Terraform infrastructure-as-code (IaC) tool has been in existence for nearly a decade, and it continues to gain greater relevance. Notably, just a couple of months back, Google released its [Infrastructure Manager cloud resource provisioning system](https://cloud.google.com/blog/products/management-tools/introducing-infrastructure-manager-powered-by-terraform), which includes the ability to manage the deployment of Terraform configurations into cloud environments operated by Google. IaC is becoming a fundamental part of modern IT, and Terraform has been growing rapidly with it.

Terraform is an excellent tool, especially with its multi-cloud support, large ecosystem, and integration with DevOps practices. However, it can also be the source of issues. In particular, updating to a newer Terraform version can result in changes that may impair the operation of an organization’s IaC.

**The need for Terraform Versioning**

It is understandable why many tend to instinctively update their Terraform to the latest version. The newest versions of software usually come with new functions and features. They are also updated to address issues found in the older versions. Additionally, regular software updating is one of the most oft-repeated tips in cybersecurity, so refusing to urgently upgrade is rather counterintuitive.

However, when it comes to Terraform, version updates should be handled carefully. The upgrade may provide new functions as well as new data sources and resources to take advantage of, but there is also the possibility that it may result in dysfunction. The new version may bring about functionality modifications. It may also change or supplant arguments that have worked well in the previous version. These can cause the configuration to fail, leading to an unsuccessful Terraform plan.

To ensure a seamless shift into the new version, [there is a need for Terraform Versioning](https://www.env0.com/blog/tutorial-how-to-manage-terraform-versioning), the process of controlling and specifying the versions of Terraform configurations and other elements involved in an IaC project. This is crucial to maintain the consistency of IaC and support collaboration in infrastructure management and deployment. It also ensures control over the Terraform Core executable, the plugins installed by the provider, as well as the modules.

**Deciding on the need to upgrade**

The choice of what version to upgrade to depends on the existing policies and supported options of an organization. For example, if an organization regularly uses additional open-source tools, it would be inappropriate to upgrade to Terraform v1.6, because this version comes with the new Business Source License, which is incompatible with open-source.

In most cases, it is advisable to continue using the minor version release that was used at the time a Terraform configuration was deployed. Switching to a major version release usually does not yield significant benefits and may expose the organization to unnecessary risks. Note: A minor version release comes with new features and enhancements but without breaking changes. In contrast, a major release entails significant modifications, deprecation of features, and potentially breaking changes.

However, for those who are writing a new configuration for deployment, it is recommended to use the most recent stable version of Terraform, from Terraform Core to the modules and provider plugins. 
To find details about the latest Terraform releases, [consult this official Terraform registry](https://registry.terraform.io/browse/providers). It provides a comprehensive listing of all releases, including those officially released by HashiCorp, those from partner providers, and community submissions. To determine the current Terraform version being used, one quick way to do it is to input the following command into the terminal.

> terraform version
Terraform v1.5.5
on windows_amd64

**Implementing Terraform version constraints**

As suggested earlier, the latest version of Terraform may not always be the best for an organization because of the latter’s requirements, policies, and supported options. To avoid instances where an incompatible version is downloaded and deployed, it helps to set up version constraints.
Terraform version constraints ensure that only the versions that are compatible with existing configurations and organizational policies are installed. These constraints are created with the following syntax.

= "1.1.1" # Equals the exact version 1.0.1
= "> 1.0" # Greater than version 1.0
= "<= 3.5" # Less than or equal to version 3.5

Multiple constraints may be combined as long as they are separated by commas. For example, a constraint that prevents the installation of any version greater than or equal to 1.5 and less than 2.0 will be stated as follows:

= ">= 1.5, < 2.0" # Greater than or equal to 2.0 and less than 3.0

If a constrained version is installed, an error message will be displayed. This error message will indicate the exact violation. It is not advisable to update or modify the constraint to suit the version that is being installed because it can lead to unexpected behaviors.

**Basic Terraform upgrading processes**

Terraform versioning covers three main elements. These are Terraform Core, the provider plugins, and the modules. Here’s an overview of their respective upgrading processes.
When it comes to upgrading Terraform Core, the process is relatively easy. It is mainly about replacing the local executable with the preferred version, which can be downloaded from the [official available releases](https://releases.hashicorp.com/terraform/) of HashiCorp’s website. A package manager may be used to do the Core upgrade. To maintain several local versions of Terraform Core, the tfswitch or tfenv tools may be employed.

The process of updating the Terraform provider plugins is a bit complex. It starts with the identification of providers in a Terraform configuration using the "terraform providers" command. Next, the Terraform configuration is initialized, which downloads provider plugins in the process and also generates a lock file. The lock file contains constraints and version information indicated by the provider to make sure that only the exact version is used. To proceed with the upgrade,  the “-upgrade” flag has to be used with the “terraform init” command.

For the Terraform modules, versioning may or may not be supported. It depends on the source of the module. Those that come from public or private registries usually support the version argument, which is in line with the syntax used for "required_version" and "required_providers." As such, a version may be specified with the source URL included as a ref query string field, which can be pointed to a valid reference such as a tag, branch, or hash. This means that the ref points to an exact version, not a range.

**Ensuring IaC stability and consistency**

Terraform versioning can be a complex process but it has to be done to make sure that an organization’s Infrastructure-as-Code implementation is consistent and stable. It is important to plan a versioning strategy to proceed smoothly and without issues. The key steps center on the versioning of Terraform Core, the provider plugins, and the modules. To ensure that only the suitable versions are employed, version constraints have to be set. Also, it is advisable to upgrade one thing at a time and thoroughly read release notes to monitor breaking changes.