github.com/hugorut/terraform@v1.1.3/website/docs/language/upgrade-guides/0-13.mdx (about)

     1  ---
     2  page_title: Upgrading to Terraform v0.13
     3  description: Upgrading to Terraform v0.13
     4  ---
     5  
     6  # Upgrading to Terraform v0.13
     7  
     8  Terraform v0.13 is a major release and thus includes some changes that
     9  you'll need to consider when upgrading. This guide is intended to help with
    10  that process.
    11  
    12  The goal of this guide is to cover the most common upgrade concerns and
    13  issues that would benefit from more explanation and background. The exhaustive
    14  list of changes will always be the
    15  [Terraform Changelog](https://github.com/hugorut/terraform/blob/main/CHANGELOG.md).
    16  After reviewing this guide, we recommend reviewing the Changelog to check for
    17  specific notes about less-commonly-used features.
    18  
    19  This guide focuses on changes from v0.12 to v0.13. Terraform supports upgrade
    20  tools and features only for one major release upgrade at a time, so if you are
    21  currently using a version of Terraform prior to v0.12 please upgrade through
    22  the latest minor releases of all of the intermediate versions first, reviewing
    23  the previous upgrade guides for any considerations that may be relevant to you.
    24  
    25  In particular, Terraform v0.13 no longer includes the `terraform 0.12upgrade`
    26  command for automatically migrating module source code from v0.11 to v0.12
    27  syntax. If your modules are written for v0.11 and earlier you may need to
    28  upgrade their syntax using the latest minor release of Terraform v0.12 before
    29  using Terraform v0.13.
    30  
    31  -> If you run into any problems during upgrading that are not addressed by the
    32  information in this guide, please feel free to start a topic in
    33  [The Terraform community forum](https://discuss.hashicorp.com/c/terraform-core),
    34  describing the problem you've encountered in enough detail that other readers
    35  may be able to reproduce it and offer advice.
    36  
    37  Upgrade guide sections:
    38  
    39  * [Before You Upgrade](#before-you-upgrade)
    40  * [Explicit Provider Source Locations](#explicit-provider-source-locations)
    41  * [New Filesystem Layout for Local Copies of Providers](#new-filesystem-layout-for-local-copies-of-providers)
    42    * [Special considerations for in-house providers](#in-house-providers)
    43  * [Destroy-time provisioners may not refer to other resources](#destroy-time-provisioners-may-not-refer-to-other-resources)
    44  * [Data resource reads can no longer be disabled by `-refresh=false`](#data-resource-reads-can-no-longer-be-disabled-by-refresh-false)
    45  * [Frequently Asked Questions](#frequently-asked-questions)
    46  
    47  ## Before You Upgrade
    48  
    49  When upgrading between major releases, we always recommend ensuring that you
    50  can run `terraform plan` and see no proposed changes on the previous version
    51  first, because otherwise pending changes can add additional unknowns into the
    52  upgrade process.
    53  
    54  For this upgrade in particular, completing the upgrade will require running
    55  `terraform apply` with Terraform 0.13 after upgrading in order to apply some
    56  upgrades to the Terraform state, and we recommend doing that with no other
    57  changes pending.
    58  
    59  ## Explicit Provider Source Locations
    60  
    61  Prior versions of Terraform have supported automatic provider installation only
    62  for providers packaged and distributed by HashiCorp. Providers built by the
    63  community have previously required manual installation by extracting their
    64  distribution packages into specific local filesystem locations.
    65  
    66  Terraform v0.13 introduces a new hierarchical namespace for providers that
    67  allows specifying both HashiCorp-maintained and community-maintained providers
    68  as dependencies of a module, with community providers distributed from other
    69  namespaces on [Terraform Registry](https://registry.terraform.io/) or from a
    70  third-party provider registry.
    71  
    72  In order to establish the hierarchical namespace, Terraform now requires
    73  explicit source information for any providers that are not HashiCorp-maintained,
    74  using a new syntax in the `required_providers` nested block inside the
    75  `terraform` configuration block:
    76  
    77  ```hcl
    78  terraform {
    79    required_providers {
    80      azurerm = {
    81        # The "hashicorp" namespace is the new home for the HashiCorp-maintained
    82        # provider plugins.
    83        #
    84        # source is not required for the hashicorp/* namespace as a measure of
    85        # backward compatibility for commonly-used providers, but recommended for
    86        # explicitness.
    87        source  = "hashicorp/azurerm"
    88        version = "~> 2.12"
    89      }
    90      newrelic = {
    91        # source is required for providers in other namespaces, to avoid ambiguity.
    92        source  = "newrelic/newrelic"
    93        version = "~> 2.1.1"
    94      }
    95    }
    96  }
    97  ```
    98  
    99  If you are using providers that now require an explicit source location to be
   100  specified, `terraform init` will produce an error like the following:
   101  
   102  ```
   103  Error: Failed to install providers
   104  
   105  Could not find required providers, but found possible alternatives:
   106  
   107    hashicorp/datadog -> terraform-providers/datadog
   108    hashicorp/fastly -> terraform-providers/fastly
   109  
   110  If these suggestions look correct, upgrade your configuration with the
   111  following command:
   112      terraform 0.13upgrade
   113  ```
   114  
   115  As mentioned in the error message, Terraform v0.13 includes an automatic
   116  upgrade command
   117  [`terraform 0.13upgrade`](/cli/commands/0.13upgrade)
   118  that is able to automatically generate source addresses for unlabelled
   119  providers by consulting the same lookup table that was previously used for
   120  Terraform v0.12 provider installation. This command will automatically modify
   121  the configuration of your current module, so you can use the features of your
   122  version control system to inspect the proposed changes before committing them.
   123  
   124  We recommend running `terraform 0.13upgrade` even if you don't see the message,
   125  because it will generate the recommended explicit source addresses for
   126  providers in the "hashicorp" namespace.
   127  
   128  For more information on declaring provider dependencies, see
   129  [Provider Requirements](/language/providers/requirements).
   130  That page also includes some guidance on how to write provider dependencies
   131  for a module that must remain compatible with both Terraform v0.12 and
   132  Terraform v0.13; the `terraform 0.13upgrade` result includes a conservative
   133  version constraint for Terraform v0.13 or later, which you can weaken to
   134  `>= 0.12.26` if you follow the guidelines in
   135  [v0.12-Compatible Provider Requirements](/language/providers/requirements#v0-12-compatible-provider-requirements).
   136  
   137  Each module must declare its own set of provider requirements, so if you have
   138  a configuration which calls other modules then you'll need to run this upgrade
   139  command for each module separately.
   140  [The `terraform 0.13upgrade documentation`](/cli/commands/0.13upgrade)
   141  includes an example of running the upgrade process across all directories under
   142  a particular prefix that contain `.tf` files using some common Unix command line
   143  tools, which may be useful if you want to upgrade all modules in a single
   144  repository at once.
   145  
   146  After you've added explicit provider source addresses to your configuration,
   147  run `terraform init` again to re-run the provider installer.
   148  
   149  -> **Action:** Either run [`terraform 0.13upgrade`](/cli/commands/0.13upgrade) for each of your modules, or manually update the provider declarations to use explicit source addresses.
   150  
   151  The upgrade tool described above only updates references in your configuration.
   152  The Terraform state also includes references to provider configurations which
   153  need to be updated to refer to the correct providers.
   154  
   155  Terraform will automatically update provider configuration references in the
   156  state the first time you run `terraform apply` after upgrading, but it relies
   157  on information in the configuration to understand which provider any
   158  existing resource belongs to, and so you must run `terraform apply` at least
   159  once (and accept any changes it proposes) before removing any `resource` blocks
   160  from your configuration after upgrading.
   161  
   162  If you are using Terraform Cloud or Terraform Enterprise with the VCS-driven
   163  workflow (as opposed to CLI-driven runs), refer to
   164  [The UI- and VCS-driven Run Workflow](/cloud-docs/run/ui) to learn how
   165  to manually start a run after you select a Terraform v0.13 release for your
   166  workspace.
   167  
   168  If you remove a `resource` block (or a `module` block for a module that
   169  contains `resource` blocks) before the first `terraform apply`, you may see
   170  a message like this reflecting that Terraform cannot determine which provider
   171  configuration the existing object ought to be managed by:
   172  
   173  ```
   174  Error: Provider configuration not present
   175  
   176  To work with null_resource.foo its original provider configuration at
   177  provider["registry.terraform.io/-/aws"] is required, but it has been removed.
   178  This occurs when a provider configuration is removed while objects created by
   179  that provider still exist in the state. Re-add the provider configuration to
   180  destroy aws_instance.example, after which you can remove the provider
   181  configuration again.
   182  ```
   183  
   184  In this specific upgrade situation the problem is actually the missing
   185  `resource` block rather than the missing `provider` block: Terraform would
   186  normally refer to the configuration to see if this resource has an explicit
   187  `provider` argument that would override the default strategy for selecting
   188  a provider. If you see the above after upgrading, re-add the resource mentioned
   189  in the error message until you've completed the upgrade.
   190  
   191  -> **Action:** After updating all modules in your configuration to use the new provider requirements syntax, run `terraform apply` to create a new state snapshot containing the new-style provider source addresses that are now specified in your configuration.
   192  
   193  ## New Filesystem Layout for Local Copies of Providers
   194  
   195  As part of introducing the hierarchical provider namespace discussed in the
   196  previous section, Terraform v0.13 also introduces a new hierarchical directory
   197  structure for manually-installed providers in the local filesystem.
   198  
   199  If you use local copies of official providers or if you use custom in-house
   200  providers that you have installed manually, you will need to adjust your local
   201  directories to use the new directory structure.
   202  
   203  The previous layout was a single directory per target platform containing
   204  various executable files named with the prefix `terraform-provider`, like
   205  `linux_amd64/terraform-provider-google_v2.0.0`. The new expected location for the
   206  Google Cloud Platform provider for that target platform within one of the local
   207  search directories would be the following:
   208  
   209  ```
   210  registry.terraform.io/hashicorp/google/2.0.0/linux_amd64/terraform-provider-google_v2.0.0
   211  ```
   212  
   213  The `registry.terraform.io` above is the hostname of the registry considered
   214  to be the origin for this provider. The provider source address
   215  `hashicorp/google` is a shorthand for `registry.terraform.io/hashicorp/google`,
   216  and the full, explicit form is required for a local directory.
   217  
   218  Note that the version number given as a directory name must be written _without_
   219  the "v" prefix that tends to be included when a version number is used as part
   220  of a git branch name. If you include that prefix, Terraform will not recognize
   221  the directory as containing provider packages.
   222  
   223  As before, the recommended default location for locally-installed providers
   224  is one of the following, depending on which operating system you are running
   225  Terraform under:
   226  
   227  * Windows: `%APPDATA%\terraform.d\plugins`
   228  * All other systems: `~/.terraform.d/plugins`
   229  
   230  Terraform v0.13 introduces some additional options for customizing where
   231  Terraform looks for providers in the local filesystem. For more information on
   232  those new options, see [Provider Installation](/cli/config/config-file#provider-installation).
   233  
   234  If you use only providers that are automatically installable from Terraform
   235  provider registries but still want to avoid Terraform re-downloading them from
   236  registries each time, Terraform v0.13 includes
   237  [the `terraform providers mirror` command](/cli/commands/providers/mirror)
   238  which you can use to automatically populate a local directory based on the
   239  requirements of the current configuration file:
   240  
   241  ```
   242  terraform providers mirror ~/.terraform.d/plugins
   243  ```
   244  
   245  -> **Action:** If you use local copies of official providers rather than installing them automatically from Terraform Registry, adopt the new expected directory structure for your local directory either by running `terraform providers mirror` or by manually reorganizing the existing files.
   246  
   247  ### In-house Providers
   248  
   249  If you use an in-house provider that is not available from an upstream registry
   250  at all, after upgrading you will see an error similar to the following:
   251  
   252  ```
   253  - Finding latest version of hashicorp/happycloud...
   254  
   255  Error: Failed to install provider
   256  
   257  Error while installing hashicorp/happycloud: provider registry
   258  registry.terraform.io does not have a provider named
   259  registry.terraform.io/hashicorp/happycloud
   260  ```
   261  
   262  Terraform assumes that a provider without an explicit source address belongs
   263  to the "hashicorp" namespace on `registry.terraform.io`, which is not true
   264  for your in-house provider. Instead, you can use any domain name under your
   265  control to establish a _virtual_ source registry to serve as a separate
   266  namespace for your local use. For example:
   267  
   268  ```
   269  terraform.example.com/awesomecorp/happycloud/1.0.0/linux_amd64/terraform-provider-happycloud_v1.0.0
   270  ```
   271  
   272  You can then specify explicitly the requirement for that in-house provider
   273  in your modules, using the requirement syntax discussed in the previous section:
   274  
   275  ```hcl
   276  terraform {
   277    required_providers {
   278      happycloud = {
   279        source  = "terraform.example.com/awesomecorp/happycloud"
   280        version = "1.0.0"
   281      }
   282    }
   283  }
   284  ```
   285  
   286  If you wish, you can later run your own Terraform provider registry at the
   287  specified hostname as an alternative to local installation, without any further
   288  modifications to the above configuration. However, we recommend tackling that
   289  only after your initial upgrade using the new local filesystem layout.
   290  
   291  -> **Action:** If you use in-house providers that are not installable from a provider registry, assign them a new source address under a domain name you control and update your modules to specify that new source address.
   292  
   293  If your configuration using one or more in-house providers has existing state
   294  snapshots that include resources belonging to those providers, you'll also need
   295  to perform a one-time migration of the provider references in the state, so
   296  Terraform can understand them as belonging to your in-house providers rather
   297  than to providers in the public Terraform Registry. If you are in this
   298  situation, `terraform init` will produce the following error message after
   299  you complete the configuration changes described above:
   300  
   301  ```
   302  Error: Failed to install legacy providers required by state
   303  
   304  Found unresolvable legacy provider references in state. It looks like these
   305  refer to in-house providers. You can update the resources in state with the
   306  following command:
   307  
   308      terraform state replace-provider registry.terraform.io/-/happycloud terraform.example.com/awesomecorp/happycloud
   309  ```
   310  
   311  Provider source addresses starting with `registry.terraform.io/-/` are a special
   312  way Terraform marks legacy addresses where the true namespace is unknown.
   313  For providers that were automatically-installable in Terraform 0.12, Terraform
   314  0.13 can automatically determine the new addresses for these using a lookup
   315  table in the public Terraform Registry, but for in-house providers you will
   316  need to provide the appropriate mapping manually.
   317  
   318  The `terraform state replace-provider` subcommand allows re-assigning provider
   319  source addresses recorded in the Terraform state, and so we can use this
   320  command to tell Terraform how to reinterpret the "legacy" provider addresses
   321  as properly-namespaced providers that match with the provider source addresses
   322  in the configuration.
   323  
   324  ~> **Warning:** The `terraform state replace-provider` subcommand, like all of the `terraform state` subcommands, will create a new state snapshot and write it to the configured backend. After the command succeeds the latest state snapshot will use syntax that Terraform v0.12 cannot understand, so you should perform this step only when you are ready to permanently upgrade to Terraform v0.13.
   325  
   326  ```
   327  terraform state replace-provider 'registry.terraform.io/-/happycloud' 'terraform.example.com/awesomecorp/happycloud'
   328  ```
   329  
   330  The command above asks Terraform to update any resource instance in the state
   331  that belongs to a legacy (non-namespaced) provider called "happycloud" to
   332  instead belong to the fully-qualified source address
   333  `terraform.example.com/awesomecorp/happycloud`.
   334  
   335  Whereas the configuration changes for provider requirements are made on a
   336  per-module basis, the Terraform state captures data from throughout the
   337  configuration (all of the existing module instances) and so you only need to
   338  run `terraform state replace-provider` once per configuration.
   339  
   340  Running `terraform init` again after completing this step should cause
   341  Terraform to attempt to install `terraform.example.com/awesomecorp/happycloud`
   342  and to find it in the local filesystem directory you populated in an earlier
   343  step.
   344  
   345  -> **Action:** If you use in-house providers that are not installable from a provider registry and your existing state contains resource instances that were created with any of those providers, use the `terraform state replace-provider` command to update the state to use the new source addressing scheme only once you are ready to commit to your v0.13 upgrade. (Terraform v0.12 cannot parse a state snapshot that was created by this command.)
   346  
   347  ## Destroy-time provisioners may not refer to other resources
   348  
   349  Destroy-time provisioners allow introducing arbitrary additional actions into
   350  the destroy phase of the resource lifecycle, but in practice the design of this
   351  feature was flawed because it created the possibility for a destroy action
   352  of one resource to depend on a create or update action of another resource,
   353  which often leads either to dependency cycles or to incorrect behavior due to
   354  unsuitable operation ordering.
   355  
   356  In order to retain as many destroy-time provisioner capabilities as possible
   357  while addressing those design flaws, Terraform v0.12.18 began reporting
   358  deprecation warnings for any `provisioner` block setting `when = destroy` whose
   359  configuration refers to any objects other than `self`, `count`, and `each`.
   360  
   361  Addressing the flaws in the destroy-time provisioner design was a pre-requisite
   362  for new features in v0.13 such as module `depends_on`, so Terraform v0.13
   363  concludes the deprecation cycle by making such references now be fatal errors:
   364  
   365  ```
   366  Error: Invalid reference from destroy provisioner
   367  
   368  Destroy-time provisioners and their connection configurations may only
   369  reference attributes of the related resource, via 'self', 'count.index',
   370  or 'each.key'.
   371  
   372  References to other resources during the destroy phase can cause dependency
   373  cycles and interact poorly with create_before_destroy.
   374  ```
   375  
   376  Some existing modules using resource or other references inside destroy-time
   377  provisioners can be updated by placing the destroy-time provisioner inside a
   378  `null_resource` resource and copying any data needed at destroy time into
   379  the `triggers` map to be accessed via `self`:
   380  
   381  ```hcl
   382  resource "null_resource" "example" {
   383    triggers = {
   384      instance_ip_addr = aws_instance.example.private_ip
   385    }
   386  
   387    provisioner "remote-exec" {
   388      when = destroy
   389  
   390      connection {
   391        host = self.triggers.instance_ip_addr
   392        # ...
   393      }
   394  
   395      # ...
   396    }
   397  }
   398  ```
   399  
   400  In the above example, the `null_resource.example.triggers` map is effectively
   401  acting as a temporary "cache" for the instance's private IP address to
   402  guarantee that a value will be available when the provisioner runs, even if
   403  the `aws_instance.example` object itself isn't currently available.
   404  The provisioner's `connection` configuration can refer to that value via
   405  `self`, whereas referring directly to `aws_instance.example.private_ip` in that
   406  context is forbidden.
   407  
   408  [Provisioners are a last resort](/language/resources/provisioners/syntax#provisioners-are-a-last-resort),
   409  so we recommend avoiding both create-time and destroy-time provisioners wherever
   410  possible. Other options for destroy-time actions include using `systemd` to
   411  run commands within your virtual machines during shutdown or using virtual
   412  machine lifecycle hooks provided by your chosen cloud computing platform,
   413  both of which can help ensure that the shutdown actions are taken even if the
   414  virtual machine is terminated in an unusual way.
   415  
   416  -> **Action:** If you encounter the "Invalid reference from destroy provisioner" error message after upgrading, reorganize your destroy-time provisioners to depend only on self-references, and consider other approaches if possible to avoid using destroy-time provisioners at all.
   417  
   418  ## Data resource reads can no longer be disabled by `-refresh=false`
   419  
   420  In Terraform v0.12 and earlier, Terraform would read the data for data
   421  resources during the "refresh" phase of `terraform plan`, which is the same
   422  phase where Terraform synchronizes its state with any changes made to
   423  remote objects.
   424  
   425  An important prerequisite for properly supporting `depends_on` for both
   426  data resources and modules containing data resources was to change the data
   427  resource lifecycle to now read data during the _plan_ phase, so that
   428  dependencies on managed resources could be properly respected.
   429  
   430  If you were previously using `terraform plan -refresh=false` or
   431  `terraform apply -refresh=false` to disable the refresh phase, you will find
   432  that under Terraform 0.13 this will continue to disable synchronization of
   433  managed resources (declared with `resource` blocks) but will no longer
   434  disable the reading of data resources (declared with `data` blocks).
   435  
   436  ~> Updating the data associated with data resources is crucial to producing an
   437  accurate plan, and so there is no replacement mechanism in Terraform v0.13
   438  to restore the previous behavior.
   439  
   440  ## Frequently Asked Questions
   441  
   442  ### Why do I see `-/provider` during init?
   443  
   444  Provider source addresses starting with `registry.terraform.io/-/` are a special
   445  way Terraform marks legacy addresses where the true namespace is unknown. For
   446  providers that were automatically-installable in Terraform 0.12, Terraform 0.13
   447  can automatically determine the new addresses for these using a lookup table in
   448  the public Terraform Registry. That lookup table is accessed by using the
   449  special namespace `-`.
   450  
   451  When you run `init`, terraform generates a list of required providers based on
   452  both the configuration and state. Legacy-style providers - such as providers in
   453  a statefile written with Terraform v0.12 - don't have a namespace, so terraform
   454  uses the placeholder namespace `-` to query the registry. That is why you may
   455  see output like this during your first `init`:
   456  
   457  ```
   458  - Finding latest version of -/null...
   459  - Finding latest version of -/random...
   460  - Finding latest version of hashicorp/null...
   461  - Finding latest version of hashicorp/random...
   462  ```
   463  
   464  Terraform found providers `null` and `random` in the statefile without a
   465  namespace. Terraform _also_ found `hashicorp/null` and `hashicorp/random` in the
   466  configuration files. Providers in configuration are automatically assumed to be
   467  default (HashiCorp) providers, while providers found in state are first looked
   468  up in the registry.
   469  
   470  While this does not cause any problems for Terraform, it has been confusing. You
   471  may circumvent this by using the `terraform state replace-provider` subcommand
   472  to tell Terraform exactly what provider addresses are required in state.
   473  Continuing from the example above, the following commands tell Terraform the
   474  source address for the `null` and `random` providers:
   475  
   476  ```
   477  terraform state replace-provider -- -/random registry.terraform.io/hashicorp/random
   478  terraform state replace-provider -- -/null registry.terraform.io/hashicorp/null
   479  ```
   480  
   481  If you are seeing these messages with errors, and are using in-house or
   482  locally-installed providers, please see the section on [in-house providers](#in-house-providers).