github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/website/upgrade-guides/0-13.html.markdown (about)

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