github.com/hugorut/terraform@v1.1.3/website/docs/language/upgrade-guides/0-14.mdx (about) 1 --- 2 page_title: Upgrading to Terraform v0.14 3 description: Upgrading to Terraform v0.14 4 --- 5 6 # Upgrading to Terraform v0.14 7 8 Terraform v0.14 is a major release and so it includes some small changes in 9 behavior that you may need to consider when upgrading. This guide is intended 10 to help with 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 15 [the Terraform Changelog](https://github.com/hugorut/terraform/blob/v0.14/CHANGELOG.md). 16 After reviewing this guide, we recommend reviewing the Changelog to check for 17 specific notes about less-commonly-used features. This guide is also not 18 intended as an overview of the new features in Terraform v0.14. This release 19 includes other enhancements that don't need any special attention during 20 upgrade, but those are described in the changelog and elsewhere in the 21 Terraform documentation. 22 23 This guide focuses on changes from v0.13 to v0.14. Terraform supports upgrade 24 tools and features only for one major release upgrade at a time, so if you are 25 currently using a version of Terraform prior to v0.13 please upgrade through 26 the latest minor releases of all of the intermediate versions first, reviewing 27 the previous upgrade guides for any considerations that may be relevant to you. 28 29 In particular, Terraform v0.14 no longer includes the `terraform 0.13upgrade` 30 command for automatically inserting 31 [provider requirements](/language/providers/requirements) 32 into existing modules, and the automatic mechanisms to upgrade legacy provider 33 references in the Terraform state. You will need to successfully complete a 34 `terraform apply` at least once under Terraform v0.13 before upgrading an 35 existing configuration to Terraform v0.14. 36 37 -> If you run into any problems during upgrading that are not addressed by the 38 information in this guide, please feel free to start a topic in 39 [The Terraform community forum](https://discuss.hashicorp.com/c/terraform-core), 40 describing the problem you've encountered in enough detail that other readers 41 may be able to reproduce it and offer advice. 42 43 Upgrade guide sections: 44 45 * [Before You Upgrade](#before-you-upgrade) 46 * [Provider Dependency Lock File](#provider-dependency-lock-file) 47 * [Concise Terraform Plan Output](#concise-terraform-plan-output) 48 * [Sensitive Values in Plan Output](#sensitive-values-in-plan-output) 49 * [Other important workflow changes](#other-important-workflow-changes) 50 51 ## Before You Upgrade 52 53 Terraform v0.14 does not support legacy Terraform state snapshot formats from 54 prior to Terraform v0.13, so before upgrading to Terraform v0.14 you _must_ 55 have successfully run `terraform apply` at least once with Terraform v0.13 56 so that it can complete its state format upgrades. 57 58 When upgrading between major releases, we always recommend ensuring that you 59 can run `terraform plan` and see no proposed changes on the previous version 60 first, because otherwise pending changes can add additional unknowns into the 61 upgrade process. Terraform v0.14 has the additional requirement of running 62 `terraform apply`, as described above, because that allows Terraform v0.13 to 63 commit the result of its automatic state format upgrades. 64 65 ## Provider Dependency Lock File 66 67 In Terraform v0.13 and earlier, the `terraform init` command would always 68 install the newest version of any provider in the configuration that would 69 meet the configured version constraints. 70 71 That meant that unless the configuration author manually entered _exact_ 72 version constraints (for a particular version alone), a later provider release 73 could potentially cause a change in behavior for an existing configuration even 74 though the configuration itself had not changed. 75 76 We believe that, as far as possible, the behavior of a configuration that has 77 already been written and tested should remain consistent unless it is 78 intentionally changed by its author, and that intentional changes should be 79 represented in files that can be included in a version control system and 80 code review process. 81 82 To better meet that goal, Terraform v0.14 introduces a new 83 [dependency lock file](/language/files/dependency-lock), 84 which Terraform will generate automatically after running `terraform init` 85 in the same directory as your configuration's root module. This file includes 86 the specific version numbers selected for each provider, and also includes 87 the package checksums for the selected version to help ensure that the 88 provider packages you depend on are not changed in-place upstream, 89 whether accidentally or maliciously. 90 91 This new behavior is designed so that for most users it will not require 92 a significant change in workflow. After running `terraform init` for the 93 first time after upgrading you will find a new file `.terraform.lock.hcl` 94 in your root module directory, and `terraform init` will automatically read 95 and respect the entries in that file on future runs with no additional action 96 on your part. We strongly recommend that you commit this file to your version 97 control system, but if you do not then Terraform's behavior will be very similar to 98 the old v0.13 behavior. 99 100 There are some situations that require some further consideration though, 101 and those are discussed in the following sections. 102 103 ### Opting out of dependency locking 104 105 We understand that not all teams share our belief that upgrades should always 106 be represented as changes to the code in a version control repository. Those 107 teams may have previously intentionally used a non-exact version constraint 108 for one or more providers in order to automatically adopt any future provider 109 releases and then make any necessary configuration changes in retrospect. 110 111 You can continue with a model similar to the v0.13 behavior after upgrading 112 to v0.14 by placing `.terraform.lock.hcl` in your version control system's 113 "ignore" file, such as `.gitignore` for Git. In that case, Terraform will 114 see the lock file in the same way as the internal index that Terraform v0.13 115 would generate under the `.terraform` directory, preserving the selections 116 only with in a particular working directory until you delete the file. 117 118 With that said, we do recommend that teams consider carefully the benefits 119 of a persistent lock file, and make a considered decision about which path 120 to take. We believe that a lock file under version control will be the best 121 choice for most teams, because we've seen this pattern used successfully in 122 many other programming language ecosystems. 123 124 ### In-house providers and internal mirrors 125 126 Terraform v0.13 introduced a new hierarchical namespace for providers, which 127 was an important pre-requisite for introducing a dependency lock file in 128 v0.14 which can support a mixture of official, partner, community and in-house 129 providers in a single configuration. 130 131 If you followed the advice from the Terraform v0.13 upgrade guide about 132 [assigning your in-house providers their own unique source addresses](/language/upgrade-guides/0-13#in-house-providers), 133 and you're distributing your in-house providers to Terraform through one of 134 the documented mechanisms, Terraform should handle selecting a version and 135 recording its checksums in the same way for all of the providers you use. 136 137 However, the full functionality of the lock file does depend on some 138 information only available from a real provider registry, so there are some 139 special considerations for providers installed from either filesystem or 140 network mirrors: 141 142 * Mirror sources don't provide package checksums that are signed by the original 143 provider distributor, so by default `terraform init` will record only the 144 checksum for the provider package on the platform you are currently using. 145 146 For example, if you run `terraform init` on a macOS system and then commit 147 the lock file, a collegue running `terraform init` on a Linux system may 148 encounter a checksum error, because the mirror-based installation was only 149 able to safely record the checksum for the package it actually installed. 150 151 This problem doesn't arise for installation from a provider registry because 152 the registry can provide signed checksums for all packages for a particular 153 provider version, across all supported platforms. 154 155 If you use mirrors exclusively in your environment and you use Terraform 156 across a mixture of platforms then, in addition to making sure that your 157 mirrors include packages for all of the necessary platforms, you may choose 158 to use 159 [the new `terraform providers lock` command](/cli/commands/providers/lock) 160 to pre-enter the required lock file entries for all of the platforms you 161 intend to use. 162 163 * Terraform expects a particular version of a provider to have identical 164 package checksums across all installation methods you work with in your 165 team. 166 167 For example, if you use direct installation from Terraform registries in 168 your development environment but you use a mirror in your production 169 automation, you must ensure that the packages available for a particular 170 provider version in your mirror are identical to the official packages 171 in the origin registry. 172 173 If your internal mirrors intentionally have different packages than are 174 available upstream, you must either use your internal mirrors consistently 175 (so Terraform never uses or verifies an official package) or you must 176 publish your own builds so that Terraform can understand your intent for 177 them to be distinct. 178 179 If you are only making minor or temporary changes to a provider, such as 180 building for a platform that Terraform doesn't official support or including 181 a bugfix patch that isn't yet in an upstream release, the simplest answer 182 is to number your local build with semantic versioning _build metadata_, 183 such as `v2.1.0+companyname.1` where `v2.1.0` is the upstream release you 184 derived yours from, `companyname` is a short mnemonic for your organization, 185 and `.1` is an internal build id that you can potentially increment if 186 you need to make ongoing new builds from the same upstream version. 187 188 If you are making more substantial changes to a provider, such as adding 189 entirely new features that your modules depend on, it may be better to 190 instead publish the provider under a separate namespace you control, such 191 as publishing a fork of `hashicorp/aws` as `companyname/aws` in the public 192 registry or `tf.example.com/companyname/aws` for in-house distribution only. 193 This is a more drastic approach in that Terraform will understand your 194 release as an entirely separate provider, but it also allows your modules 195 to clearly indicate that they depend on the features of your fork rather 196 than the features of the upstream release. 197 198 In both cases the dependency lock file will see your releases as distinct 199 from the upstream ones and thus expect the two to have a different set of 200 checksums each. 201 202 ### External module dependencies are not locked 203 204 Although we do hope to eventually include a means to lock version selections 205 for external modules in addition to providers, this new capability is limited 206 only to providers in Terraform v0.14. 207 208 Terraform modules have a different approach to distribution and versioning than 209 Terraform providers, with many different supported installation methods that 210 each require careful consideration in designing a dependency locking mechanism. 211 212 If you wish to lock your module dependencies then for now you must continue 213 to use the same strategy as for v0.13 and earlier: specify exact version 214 constraints for modules distributed via a module registry, or use the 215 source-type-specific mechanisms to lock to a particular version of module 216 packages retrieved directly using other protocols. 217 218 Note that Terraform also does not currently track checksums for external 219 module dependencies. If you are concerned about the possibility of external 220 modules being altered in-place without your knowledge, we recommend using 221 modules only from sources directly under your control, such as a private 222 Terraform module registry. 223 224 ### The local provider cache directory 225 226 As an implementation detail of automatic provider installation, Terraform 227 has historically unpacked auto-installed plugins under the local cache 228 directory in `.terraform/plugins`. That directory was only intended for 229 Terraform's internal use, but unfortunately due to a miscommunication within 230 our team it was inadvertently documented as if it were a "filesystem mirror" 231 directory that you could place local providers in to upload them to 232 Terraform Cloud. 233 234 Unfortunately the implementation details have changed in Terraform v0.14 in 235 order to move the authority for provider version selection to the new dependency 236 lock file, and so manually placing extra plugins into that local cache directory 237 is no longer effective in Terraform v0.14. 238 239 We've included a heuristic in `terraform init` for Terraform v0.14 which should 240 detect situations where you're relying on an unofficial provider manually 241 installed into the cache directory and generate a warning like the following: 242 243 ``` 244 Warning: Missing provider is in legacy cache directory 245 246 Terraform supports a number of local directories that can serve as automatic 247 local filesystem mirrors, but .terraform/plugins is not one of them because 248 Terraform v0.13 and earlier used this directory to cache copies of provider 249 plugins retrieved from elsewhere. 250 251 If you intended to use this directory as a filesystem mirror for 252 tf.example.com/awesomecorp/happycloud, place it instead in the following 253 directory: 254 terraform.d/plugins/tf.example.com/awesomecorp/happycloud/1.1.0/linux_amd64 255 ``` 256 257 The error message suggests using the `terraform.d` directory, which is a 258 local search directory originally introduced in Terraform v0.10 in order to 259 allow sending bundled providers along with your configuration up to Terraform 260 Cloud. The error message assumes that use-case because it was for Terraform 261 Cloud in particular that this approach was previously mis-documented. 262 263 If you aren't intending to upload the provider plugin to Terraform Cloud as 264 part of your configuration, we recommend instead installing to one of 265 [the other implied mirror directories](/cli/config/config-file#implied-local-mirror-directories), 266 or you can explicitly configure some 267 [custom provider installation methods](/cli/config/config-file#provider-installation) 268 if your needs are more complicated. 269 270 ## Concise Terraform Plan Output 271 272 In Terraform v0.11 and earlier, the output from `terraform plan` was designed 273 to show only the subset of resource instance attributes that had actually 274 changed compared to the prior state. 275 276 Although that made the output very concise, we heard from several users that 277 the lack of context in the output had led to some misunderstandings that in 278 turn caused production outages. We know that reviewing a Terraform plan can 279 be a point of anxiety for those working on production infrastructure, so we 280 responded to that feedback in Terraform v0.12 by having the plan output 281 instead show the full context of each resource instance that has a planned 282 action, and then use extra annotations (`+`, `-`, `~`) to mark the specific 283 attributes that will change. 284 285 Based on further feedback since the v0.12 release, we understand that the 286 new detailed output has been very overwhelming for resource types that have 287 a large number of attributes or deeply nested block structures. Terraform v0.14 288 introduces a new compromise that aims to still address the concern about 289 context while allowing better focus on the parts of each object that are 290 changing. 291 292 For this initial release, Terraform will omit from the plan output any 293 attribute that has not changed, with the exception of a number of attribute 294 names whose values often contain human-recognizable identifying information. 295 When attributes or blocks are omitted, Terraform will always include a summary 296 of what isn't included, to avoid ambiguity with an argument merely being unset. 297 298 This is intended as an incremental step to improve the worst cases of verbose 299 output in Terraform v0.12 and v0.13, but the compromises we made here may not 300 be suitable for all situations. If you'd like to retain the fully-verbose 301 output from Terraform v0.13, you can temporarily re-enable it by setting the 302 environment variable `TF_X_CONCISE_DIFF=0` when you run Terraform. 303 304 If you choose to opt out of the new concise mode, please 305 [open a feature request issue](https://github.com/hugorut/terraform/issues/new?labels=enhancement%2C+new&template=feature_request.md) 306 to let us know what you found lacking in the new output. We intend to continue 307 iterating on the design tradeoffs here to find the best compromise to suit 308 the needs of most users. We expect to remove the opt-out environment variable 309 in Terraform v0.15. 310 311 ## Sensitive Values in Plan Output 312 313 In Terraform v0.13 and earlier, Terraform allowed provider authors to mark 314 certain resource type attributes as being "sensitive", and similarly allowed 315 module authors to mark certain output values as "sensitive". Terraform would 316 then show the placeholder string `(sensitive value)` in the plan output, 317 instead of the actual value. 318 319 Terraform v0.14 introduces a more extensive version of that behavior where 320 Terraform will track when you write an expression whose result is derived 321 from a 322 [sensitive input variable](/language/values/outputs#sensitive-suppressing-values-in-cli-output) or 323 [sensitive output value](/language/values/variables#suppressing-values-in-cli-output), 324 and so after upgrading to Terraform v0.14 you may find that more values are 325 obscured in the Terraform plan output than would have been in Terraform v0.13. 326 327 If a sensitive value (either derived from a sensitive input variable or a sensitive output variable) is used in another module output, that output must be marked `sensitive` as well to be explicit about this data being passed through Terraform: 328 329 ```terraform 330 variable "foo" { 331 sensitive = true 332 } 333 334 output "bar" { 335 value = var.foo 336 # sensitive must be true when referencing a sensitive input variable 337 sensitive = true 338 } 339 ``` 340 341 There is also experimental behavior that will extend this sensitivity-awareness to attributes providers define as sensitive. You can enable this feature by activating the experiment in the `terraform` block: 342 343 ``` 344 terraform { 345 experiments = [provider_sensitive_attrs] 346 } 347 ``` 348 349 If you enable this experiment, attributes that are defined by a given _provider_ as sensitive will have the same sensitivity-tracking behavior as sensitive input values and outputs. For example, the [`vault_generic_secret`](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/data-sources/generic_secret) data source has an attribute `data` that is sensitive according to this provider's schema. 350 351 ``` 352 # mod/main.tf 353 354 terraform { 355 experiments = [provider_sensitive_attrs] 356 } 357 358 data "vault_generic_secret" "foobar" { 359 path = "secret/foobar" 360 } 361 362 output "token" { 363 value = vault_generic_secret.foobar.data["token"] 364 # a error will display if sensitive = true is not here 365 } 366 ``` 367 368 If you do not add `sensitive = true` to the output referencing that sensitive attribute, you will get an error: 369 370 ``` 371 Error: Output refers to sensitive values 372 373 on mod/main.tf line 6: 374 6: output "token" { 375 376 Expressions used in outputs can only refer to sensitive values if the 377 sensitive attribute is true. 378 ``` 379 380 For this feature we've taken the approach that it's better to be conservative 381 and obscure _potentially-sensitive_ values at the expense of potentially also 382 obscuring some values that aren't sensitive. Unfortunately this means that 383 if you've written a module in a generic or dynamic way then Terraform may 384 over-generalize which values are sensitive, leading to less helpful plan output. 385 386 Due to the security implications of this feature, Terraform offers no direct 387 way to opt out of this change. However, the obscuring of these values is done 388 at the UI layer only and so you can still access the raw values, if needed, 389 by saving your plan to an plan file and then asking Terraform to present it 390 in machine-readable JSON format: 391 392 ``` 393 terraform plan -out=tfplan 394 terraform show -json tfplan 395 ``` 396 397 Please note that the binary file `tfplan` and the JSON output produced from it 398 can both include cleartext representations of sensitive values, so writing 399 these to disk on a multi-user system or viewing the JSON output on-screen 400 may cause those values to become visible to others. 401 402 Sensitive values are also still saved in state snapshots stored in your 403 configured backend. Use the access control and audit mechanisms offered by 404 the remote system to control who can access that data. 405 406 ## Other Important Workflow Changes 407 408 ### Terraform Output Formatting 409 410 We've modified the formatting of `terraform output` to match the formatting of `terraform show`. 411 412 We consider the console output of Terraform human readable; specifically designed and optimized for operators and practitioners to review themselves. As a result we occasionally (maybe even regularly) intend to tweak that output to help improve consistency, clarity, actionability and more. 413 414 If you rely on `terraform output` in automation, please use `terraform output -json`.