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