Terraform: 0.13: upgrading from 0.12 leads to duplicate providers being downloaded

Created on 7 Aug 2020  ยท  9Comments  ยท  Source: hashicorp/terraform

Terraform Version

Terraform 0.13 (building from master - commit 796eba95da9d230cdbb3617027b8036aa08f086d)

Terraform Configuration Files

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "test" {
  name     = "tom-dev2"
  location = "west europe"

  tags = {
    version = "0.13"
  }
}

Expected Behavior

When upgrading from an existing statefile created with Terraform 0.12 to Terraform 0.13 - when the statefile hasn't yet been upgraded for Terraform 0.12 (and the config hasn't been changed) - running terraform init should download the single version of each provider necessary to be used - in this case AzureRM v2.22.0.

Actual Behavior

Terraform downloads two different versions of the Azure Provider, one unaliased version and one aliased version:

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of -/azurerm...
- Finding latest version of hashicorp/azurerm...
- Installing -/azurerm v2.22.0...
- Installed -/azurerm v2.22.0 (signed by HashiCorp)
- Installing hashicorp/azurerm v2.22.0...
- Installed hashicorp/azurerm v2.22.0 (signed by HashiCorp)

Steps to Reproduce

Starting with Terraform 0.12:

$ ./terraform version
Terraform v0.12.29

$ ./terraform init

Initializing the backend...

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "azurerm" (hashicorp/azurerm) 2.22.0...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.azurerm: version = "~> 2.22"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

$ ./terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.test will be created
  + resource "azurerm_resource_group" "test" {
      + id       = (known after apply)
      + location = "westeurope"
      + name     = "tom-dev2"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_resource_group.test: Creating...
azurerm_resource_group.test: Creation complete after 1s [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tom-dev2]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

$ ./terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

azurerm_resource_group.test: Refreshing state... [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tom-dev2]

------------------------------------------------------------------------

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.

at this point - I delete the .terraform folder (as we recommend) then continue with Terraform 0.13 (building from master - commit 796eba95da9d230cdbb3617027b8036aa08f086d):

$ rm -rf .terraform/

$ terraform version
Terraform v0.13.0-dev

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of -/azurerm...
- Finding latest version of hashicorp/azurerm...
- Installing -/azurerm v2.22.0...
- Installed -/azurerm v2.22.0 (signed by HashiCorp)
- Installing hashicorp/azurerm v2.22.0...
- Installed hashicorp/azurerm v2.22.0 (signed by HashiCorp)

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, we recommend adding version constraints in a required_providers block
in your configuration, with the constraint strings suggested below.

* -/azurerm: version = "~> 2.22.0"
* hashicorp/azurerm: version = "~> 2.22.0"

  1 provider "azurerm" {
Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

$ terraform apply
azurerm_resource_group.test: Refreshing state... [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tom-dev2]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

$ tree .terraform/
.terraform/
โ””โ”€โ”€ plugins
    โ”œโ”€โ”€ registry.terraform.io
    โ”‚ย ย  โ”œโ”€โ”€ -
    โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ azurerm
    โ”‚ย ย  โ”‚ย ย      โ””โ”€โ”€ 2.22.0
    โ”‚ย ย  โ”‚ย ย          โ””โ”€โ”€ darwin_amd64
    โ”‚ย ย  โ”‚ย ย              โ””โ”€โ”€ terraform-provider-azurerm_v2.22.0_x5
    โ”‚ย ย  โ””โ”€โ”€ hashicorp
    โ”‚ย ย      โ””โ”€โ”€ azurerm
    โ”‚ย ย          โ””โ”€โ”€ 2.22.0
    โ”‚ย ย              โ””โ”€โ”€ darwin_amd64
    โ”‚ย ย                  โ””โ”€โ”€ terraform-provider-azurerm_v2.22.0_x5
    โ””โ”€โ”€ selections.json

10 directories, 3 files

$ terraform apply
azurerm_resource_group.test: Refreshing state... [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tom-dev2]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # azurerm_resource_group.test will be updated in-place
  ~ resource "azurerm_resource_group" "test" {
        id       = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tom-dev2"
        location = "westeurope"
        name     = "tom-dev2"
      ~ tags     = {
          + "version" = "0.13"
        }
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_resource_group.test: Modifying... [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tom-dev2]
azurerm_resource_group.test: Modifications complete after 2s [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tom-dev2]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

at this point, deleting the .terraform folder and re-running terraform init downloads only a single provider:

$ rm -rf .terraform/

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/azurerm...
- Installing hashicorp/azurerm v2.22.0...
- Installed hashicorp/azurerm v2.22.0 (signed by HashiCorp)

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, we recommend adding version constraints in a required_providers block
in your configuration, with the constraint strings suggested below.

* hashicorp/azurerm: version = "~> 2.22.0"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
โœ” ~/code/src/tmp/resource-group
18:07 $ tree .terraform/
.terraform/
โ””โ”€โ”€ plugins
    โ”œโ”€โ”€ registry.terraform.io
    โ”‚ย ย  โ””โ”€โ”€ hashicorp
    โ”‚ย ย      โ””โ”€โ”€ azurerm
    โ”‚ย ย          โ””โ”€โ”€ 2.22.0
    โ”‚ย ย              โ””โ”€โ”€ darwin_amd64
    โ”‚ย ย                  โ””โ”€โ”€ terraform-provider-azurerm_v2.22.0_x5
    โ””โ”€โ”€ selections.json

6 directories, 2 files

Based on the fact we can run an apply, this doesn't appear to be a blocking issue - but I believe that Terraform Core should be detecting these are duplicate providers with an older statefile.

bug confirmed v0.13 working as designed

Most helpful comment

Went back and re-read the previous post (I'm not missing any required providers) it is coming from the state file.

Running the command terraform state replace-provider registry.terraform.io/-/github registry.terraform.io/hashicorp/github resolved this for me.

All 9 comments

Hi, thanks for opening this up! This is an expected behavior:

Terraform parses both the state and configuration to get a list of required providers. When it encounters a state written in v0.12, there isn't an FQN for the providers, just a type name, so it uses the default "legacy" namespace "-". That's where you see "-/azurerm". This is a shorthand for the special registry "aliases" table. We do this so terraform v0.13 can find providers in both the hashicorp and terraform-providers namespace during the upgrade from v0.12 to v0.13.

When parsing the configuration, on the other hand, terraform assumes any provider that doesn't have an explicit source is in the default "hashicorp" namespace, which is a behavior we've commited to in v0.13.

As far as terraform knows, -/azurerm and hashicorp/azurerm are two different providers. It's confusing, but the big implication of the provider source attribute is that you can have any number of providers with the same type name, and the FQN is required to tell them apart.

If this behavior is causing issues for any users, it can be avoided by using the terraform state replace-providers command to update the v0.12 state to include full FQNs for all the providers. The currently functionality - -/azurerm - was designed so that we did not need to require users run a separate state upgrade tool or have 0.13upgrade modify _state_ before the initial (v0.13) apply.

Glad to have found this issue already as I was getting confused. For me it caused some confusion b/c I've got a provider explicitly pinned yet a newer version was being downloaded with -. Because of a compatibility issue in the provider I ended up with errors attempting to run a plan.

Initializing provider plugins...
- Using previously-installed hashicorp/github v2.9.0
- Using previously-installed -/github v2.9.2

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, we recommend adding version constraints in a required_providers block
in your configuration, with the constraint strings suggested below.

* -/github: version = "~> 2.9.2"

with this in my versions.tf

```
terraform {
required_version = ">= 0.13"

required_providers {
// "internal" repo support was added in 2.9.0 and then reverted in 2.9.1 to include in a 3.0.0 release instead
github = {
source = "hashicorp/github"
version = "2.9.0"
}
}
}

For what it's worth, even removing the local .terraform dir I'm still seeing this issue. (Using TFC for backend).

Initializing provider plugins...
- Finding hashicorp/github versions matching "2.9.0, 2.9.0, 2.9.0, 2.9.0, 2.9.0, 2.9.0, 2.9.0, 2.9.0, 2.9.0"...
- Finding latest version of -/github...
- Installing hashicorp/github v2.9.0...
- Installed hashicorp/github v2.9.0 (signed by HashiCorp)
- Installing -/github v2.9.2...
- Installed -/github v2.9.2 (signed by HashiCorp)

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, we recommend adding version constraints in a required_providers block
in your configuration, with the constraint strings suggested below.

* -/github: version = "~> 2.9.2"

Terraform has been successfully initialized!

I was running into a similar issue and thought I had everything correctly with required_providers in the modules I was pulling in, but I was still not having any luck fixing the problem. Then I ran terraform providers which shows a nice tree of where the various provider paths are coming from and I spotted exactly where I had missed putting a required_providers with a source.

Went back and re-read the previous post (I'm not missing any required providers) it is coming from the state file.

Running the command terraform state replace-provider registry.terraform.io/-/github registry.terraform.io/hashicorp/github resolved this for me.

I'm going to close this as working as expected, but if this continues to be an issue that comes up for folks we can consider some kind of enhancement or docs work to prompt people to run terraform state replace-provider.

Yes, it is _very_ confusing when the config has pinned an upper bound on the provider version, but a newer version gets pulled in and used by the provider reference in the state.

@danieldreier Some documentation update might be helpful. I assume people who google would find this issue as well, but a 2 sentence pointer to update provider references somewhere in the migration/upgrade doc would not hurt? Thanks!

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zeninfinity picture zeninfinity  ยท  3Comments

larstobi picture larstobi  ยท  3Comments

pawelsawicz picture pawelsawicz  ยท  3Comments

rjinski picture rjinski  ยท  3Comments

shanmugakarna picture shanmugakarna  ยท  3Comments