2
votes

Does anyone know if it is possible to have a Terraform script that uses multiple provider versions?

For example azurerm version 2.0.0 to create one resource, and 1.4.0 for another? I tried specifying the providers, as documented here: https://www.terraform.io/docs/configuration/providers.html

However it doesn't seem to work as it tries to resolve a single provider that fullfills both 1.4.0 and 2.0.0. It errors like:

No provider "azurerm" plugins meet the constraint "=1.4.0,=2.0.0".

I'm asking this because we have a large Terraform codebase and I would like to migrate bits by bits if doable.

There used to be a similar question raised, here: Terraform: How to install multiple versions of provider plugins? But it got no valid answer

2
You can migrate module by module, since your provider version would/should be specified in the root config. That would make this possible. The only issue would be state maintenance.Matt Schuchard

2 Answers

0
votes

No you cannot do what you want. Terraform expects your constraint to match one plugin version as eluded to in:

Plugin Names and Versions

If multiple versions of a plugin are installed, Terraform will use the newest version that meets the configuration's version constraints.

So your constraint cannot be parsed to match anyone plugin, hence the error

0
votes

How to use multiple version of the same Terraform provider

This allowed us a smooth transition from helm2 to helm3, while enabling new deployments to use helm3 right away, therefore reducing the accumulation of tech debt.

Of course you can do the same for most providers

How we've solved this

So the idea is to download a specific version of our provider (helm 0.10.6 in my case) and move it to one of the filesystem mirrors terraform uses by default. The key part is the renaming of our plugin binary. In the zip we can find terraform-provider-helm_v0.10.6, but we rename it to terraform-provider-helm2_v0.10.6

PLUGIN_PATH=/usr/share/terraform/plugins/registry.terraform.io/hashicorp/helm2/0.10.6/linux_amd64
mkdir -p $PLUGIN_PATH
curl -sLo_ 'https://releases.hashicorp.com/terraform-provider-helm/0.10.6/terraform-provider-helm_0.10.6_linux_amd64.zip'
unzip -p _ 'terraform-provider-helm*' > ${PLUGIN_PATH}/terraform-provider-helm2_v0.10.6
rm _
chmod 755 ${PLUGIN_PATH}/terraform-provider-helm2_v0.10.6

Then when we declare our two provider plugins

We can use hashicorp/helm2 plugin from the filesystem mirror, and let terraform directly download the latest hashicorp/helm provider, which uses helm3

terraform {
  required_providers {
    helm2 = {
      source = "hashicorp/helm2"
    }
    helm = {
      source = "hashicorp/helm"
      version = ">= 2.0.0"
    }
  }
}
# you will find the doc here https://registry.terraform.io/providers/hashicorp/helm/0.10.6/docs
provider "helm2" {
  install_tiller = false
  namespace      = "kube-system"

  kubernetes {
    ...
  }
}

# you will find the doc at latest version https://registry.terraform.io/providers/hashicorp/helm/latest/docs
provider "helm" {
  kubernetes {
    ...
  }
}

When initializing terraform, you will find that

- Finding latest version of hashicorp/helm...
- Finding latest version of hashicorp/helm2...

- Installing hashicorp/helm v2.0.2...
- Installed hashicorp/helm v2.0.2 (signed by HashiCorp)
- Installing hashicorp/helm2 v0.10.6...
- Installed hashicorp/helm2 v0.10.6 (unauthenticated)

Using it

Its pretty straightforward from this point. By default, helm resources will pick our updated helm provider at v2.0.2. You must explicitly use provider = helm2 for old resources (helm_repositoryand helm_releases in our case). Once migrated, you can remove it to use the default helm provider.