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).