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

     1  ---
     2  layout: "language"
     3  page_title: "Upgrading to Terraform v0.15"
     4  sidebar_current: "upgrade-guides-0-15"
     5  description: |-
     6    Upgrading to Terraform v0.15
     7  ---
     8  
     9  # Upgrading to Terraform v0.15
    10  
    11  Terraform v0.15 is a major release and so it includes some small changes in
    12  behavior that you may need to consider when upgrading. This guide is intended
    13  to help with 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
    18  [the Terraform Changelog](https://github.com/muratcelep/terraform/blob/v0.15/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 is also not intended as an overview of the new features in
    23  Terraform v0.15. This release includes other enhancements that don't need any
    24  special attention during upgrade, but those are described in the changelog and
    25  elsewhere in the Terraform documentation.
    26  
    27  This guide focuses on changes from v0.14 to v0.15. Terraform supports upgrade
    28  tools and features only for one major release upgrade at a time, so if you are
    29  currently using a version of Terraform prior to v0.14 please upgrade through
    30  the latest minor releases of all of the intermediate versions first, reviewing
    31  the previous upgrade guides for any considerations that may be relevant to you.
    32  
    33  Unlike the previous few Terraform major releases, v0.15's upgrade concerns are
    34  largely conclusions of deprecation cycles left over from previous releases,
    35  many of which already had deprecation warnings in v0.14. If you previously
    36  responded to those while using Terraform v0.14 then you hopefully won't need
    37  to make any special changes to upgrade, although we still recommend reviewing
    38  the content below to confirm, particularly if you see new errors or unexpected
    39  behavior after upgrading from Terraform v0.14.
    40  
    41  -> If you run into any problems during upgrading that are not addressed by the
    42  information in this guide, please feel free to start a topic in
    43  [The Terraform community forum](https://discuss.hashicorp.com/c/terraform-core),
    44  describing the problem you've encountered in enough detail that other readers
    45  may be able to reproduce it and offer advice.
    46  
    47  Upgrade guide sections:
    48  
    49  * [Sensitive Output Values](#sensitive-output-values)
    50  * [Legacy Configuration Language Features](#legacy-configuration-language-features)
    51  * [Alternative (Aliased) Provider Configurations Within Modules](#alternative-provider-configurations-within-modules)
    52  * [Commands Accepting a Configuration Directory Argument](#commands-accepting-a-configuration-directory-argument)
    53  * [Microsoft Windows Terminal Support](#microsoft-windows-terminal-support)
    54  * [Other Minor Command Line Behavior Changes](#other-minor-command-line-behavior-changes)
    55  * [Azure Backend `arm_`-prefixed Arguments](#azure-backend-removed-arguments)
    56  
    57  ## Sensitive Output Values
    58  
    59  Terraform v0.14 previously introduced the ability for Terraform to track and
    60  propagate the "sensitivity" of values through expressions that include
    61  references to sensitive input variables and output values. For example:
    62  
    63  ```hcl
    64  variable "example" {
    65    type      = string
    66    sensitive = true
    67  }
    68  
    69  resource "example" "example" {
    70    # The following value is also treated as sensitive, because it's derived
    71    # from var.example.
    72    name = "foo-${var.example}"
    73  }
    74  ```
    75  
    76  As part of that feature, Terraform also began requiring you to mark an output
    77  value as sensitive if its definition includes any sensitive values itself:
    78  
    79  ```hcl
    80  output "example" {
    81    value = "foo-${var.example}"
    82  
    83    # Must mark this output value as sensitive, because it's derived from
    84    # var.example that is declared as sensitive.
    85    sensitive = true
    86  }
    87  ```
    88  
    89  Terraform v0.15 extends this mechanism to also work for values derived from
    90  resource attributes that the provider has declared as being sensitive.
    91  Provider developers will typically mark an attribute as sensitive if the
    92  remote system has documented the corresponding field as being sensitive, such
    93  as if the attribute always contains a password or a private key.
    94  
    95  As a result of that, after upgrading to Terraform v0.15 you may find that
    96  Terraform now reports some of your output values as invalid, if they were
    97  derived from sensitive attributes without also being marked as sensitive:
    98  
    99  ```
   100  ╷
   101  │ Error: Output refers to sensitive values
   102  │ 
   103  │   on sensitive-resource-attr.tf line 5:
   104  │    5: output "private_key" {
   105  │ 
   106  │ Expressions used in outputs can only refer to sensitive values if the
   107  │ sensitive attribute is true.
   108  ╵
   109  ```
   110  
   111  If you were intentionally exporting a sensitive value, you can address the
   112  error by adding an explicit declaration `sensitive = true` to the output
   113  value declaration:
   114  
   115  ```hcl
   116  output "private_key" {
   117    value     = tls_private_key.example.private_key_pem
   118    sensitive = true
   119  }
   120  ```
   121  
   122  With that addition, if this output value was a root module output value then
   123  Terraform will hide its value in the `terraform plan` and `terraform apply`
   124  output:
   125  
   126  ```
   127  Changes to Outputs:
   128    + private_key = (sensitive value)
   129  ```
   130  
   131  -> **Note:** The declaration of an output value as sensitive must be made
   132  within the module that declares the output, so if you depend on a third-party
   133  module that has a sensitive output value that is lacking this declaration then
   134  you will need to wait for a new version of that module before you can upgrade
   135  to Terraform v0.15.
   136  
   137  The value is only hidden in the main UI, and so the sensitive value
   138  will still be recorded in the state. If you declared this output value in order
   139  to use it as part of integration with other software, you can still retrieve
   140  the cleartext value using commands intended for machine rather than human
   141  consumption, such as `terraform output -json` or `terraform output -raw`:
   142  
   143  ```shellsession
   144  $ terraform output -raw private_key
   145  -----BEGIN RSA PRIVATE KEY-----
   146  MIIEowIBAAKCAQEAoahsvJ1rIxTIOOmJZ7yErs5eOq/Kv9+5l3h0LbxW78K8//Kb
   147  OMU3v8F3h8jp+AB/1zGr5UBYfnYp5ncJm/OTCXLFAHxGibEbRnf1m2A3o0hEaWsw
   148  # (etc...)
   149  ```
   150  
   151  If you consider Terraform's treatment of a sensitive value to be too
   152  conservative and you'd like to force Terraform to treat a sensitive value as
   153  non-sensitive, you can use
   154  [the `nonsensitive` function](/docs/language/functions/nonsensitive.html) to
   155  override Terraform's automatic detection:
   156  
   157  ```hcl
   158  output "private_key" {
   159    # WARNING: Terraform will display this result as cleartext
   160    value = nonsensitive(tls_private_key.example.private_key_pem)
   161  }
   162  ```
   163  
   164  For more information on the various situations where sensitive values can
   165  originate in Terraform, refer to the following sections:
   166  
   167  * [Sensitive Input Variables](/docs/language/values/variables.html#suppressing-values-in-cli-output)
   168  * [Sensitive Resource Attributes](/docs/language/expressions/references.html#sensitive-resource-attributes)
   169  * [Sensitive Output Values](/docs/language/values/outputs.html#sensitive)
   170  
   171  -> **Note:** The new behavior described in this section was previously
   172  available in Terraform v0.14 as the
   173  [language experiment](/docs/language/settings/#experimental-language-features)
   174  `provider_sensitive_attrs`. That experiment has now concluded, so if you were
   175  participating in that experiment then you'll now need to remove the experiment
   176  opt-in from your module as part of upgrading to Terraform v0.15.
   177  
   178  ## Legacy Configuration Language Features
   179  
   180  Terraform v0.12 introduced new syntax for a variety of existing Terraform
   181  language features that were intended to make the language easier to read and
   182  write and, in some cases, to better allow for future changes to the language.
   183  
   184  Many of the old forms remained available but deprecated from v0.12 through to
   185  v0.14, with these deprecations finally concluding in the v0.15 release. Those
   186  who used the `terraform 0.12upgrade` command when upgrading from Terraform v0.11
   187  to v0.12 will have had these updated automatically, but we've summarized the
   188  changes below to help with any remaining legacy forms you might encounter while
   189  upgrading to Terraform v0.15:
   190  
   191  * The built-in functions `list` and `map` were replaced with first-class syntax
   192    `[ ... ]` and `{ ... }` in Terraform v0.12, and we've now removed the
   193    deprecated functions in order to resolve the ambiguity with the syntax used
   194    to declare list and map type constraints inside `variable` blocks.
   195  
   196      If you need to update a module which was using the `list` function, you
   197      can get the same result by replacing `list(...)` with `tolist([...])`.
   198      For example:
   199  
   200      ```diff
   201      - list("a", "b", "c")
   202      + tolist(["a", "b", "c"])
   203      ```
   204  
   205      If you need to update a module which was using the `map` function, you
   206      can get the same result by replacing `map(...)` with `tomap({...})`.
   207      For example:
   208  
   209      ```diff
   210      - map("a", 1, "b", 2)
   211      + tomap({ a = 1, b = 2 })
   212      ```
   213  
   214      The above examples include the type conversion functions `tolist` and
   215      `tomap` to ensure that the result will always be of the same type as
   216      before. However, in most situations those explicit type conversions won't
   217      be necessary because Terraform can infer the necessary type conversions
   218      automatically from context. In those cases, you can just use the
   219      `[ ... ]` or `{ ... }` syntax directly, without a conversion function.
   220  
   221  * In `variable` declaration blocks, the `type` argument previously accepted
   222    v0.11-style type constraints given as quoted strings. This legacy syntax
   223    is removed in Terraform v0.15.
   224  
   225      To update an old-style type constraint to the modern syntax, start by
   226      removing the quotes so that the argument is a bare keyword rather than
   227      a string:
   228  
   229      ```hcl
   230      variable "example" {
   231        type = string
   232      }
   233      ```
   234  
   235      Additionally, if the previous type constraint was either `"list"` or
   236      `"map`", add a type argument to specify the element type of the collection.
   237      Terraform v0.11 typically supported only collections of strings, so in
   238      most cases you can set the element type to `string`:
   239  
   240      ```hcl
   241      variable "example" {
   242        type = list(string)
   243      }
   244  
   245      variable "example" {
   246        type = map(string)
   247      }
   248      ```
   249  
   250  * In `lifecycle` blocks nested inside `resource` blocks, Terraform previously
   251    supported a legacy value `["*"]` for the `ignore_changes` argument, which
   252    is removed in Terraform v0.15.
   253  
   254      Instead, use the `all` keyword to indicate that you wish to ignore changes
   255      to all of the resource arguments:
   256  
   257      ```hcl
   258        lifecycle {
   259          ignore_changes = all
   260        }
   261      ```
   262  
   263  * Finally, Terraform v0.11 and earlier required all non-constant expressions
   264    to be written using string interpolation syntax, even if the result was
   265    not a string. Terraform v0.12 introduced a less confusing syntax where
   266    arguments can accept any sort of expression without any special wrapping,
   267    and so the interpolation-style syntax has been redundant and deprecated
   268    in recent Terraform versions.
   269  
   270    For this particular change we have not made the older syntax invalid, but
   271    we do still recommend updating interpolation-only expressions to bare
   272    expressions to improve readability:
   273  
   274    ```diff
   275    - example = "${var.foo}"
   276    + example = var.foo
   277    ```
   278  
   279    This only applies to arguments where the value is a single expression without
   280    any string concatenation. You must continue to use the `${ ... }` syntax for
   281    situations where you are combining string values together into a larger
   282    string.
   283  
   284    The `terraform fmt` command can detect and repair simple examples of the
   285    legacy interpolation-only syntax, and so we'd recommend running
   286    `terraform fmt` on your modules once you've addressed any of the other
   287    situations above that could block configuration parsing in order to update
   288    your configurations to the typical Terraform language style conventions.
   289  
   290  ## Alternative Provider Configurations Within Modules
   291  
   292  Terraform's provider configuration scheme includes the idea of a "default"
   293  (unaliased) provider configuration along with zero or more alternative
   294  (aliased) provider configurations.
   295  
   296  The `required_providers` block now has a new field for providers to indicate
   297  aliased configuration names, replacing the need for an empty "proxy
   298  configuration block" as a placeholder. In order to declare
   299  [configuration aliases](/docs/language/modules/develop/providers.html#provider-aliases-within-modules), 
   300  add the desired names to the `configuration_aliases` argument for the provider
   301  requirements.
   302  
   303  ```hcl
   304  terraform {
   305    required_providers {
   306      aws = {
   307        source  = "hashicorp/aws"
   308        version = ">= 2.7.0"
   309        configuration_aliases = [ aws.alternate ]
   310      }
   311    }
   312  }
   313  ```
   314  
   315  Warnings will be emitted now where empty configuration blocks are present but
   316  no longer required, though they continue to work unchanged in the 0.15 release.
   317  There are a few cases where existing configurations may return new errors:
   318  
   319  * The `providers` map in a module call cannot override a provider configured
   320    within the module. This is not a supported configuration, but was previously
   321    missed in validation and now returns an error.
   322  
   323  * A provider alias within a module that has no configuration _requires_ a
   324    provider configuration be supplied in the module `providers` map.
   325  
   326  * All entries in the `providers` map in a module call must correspond to a
   327    provider name within the module. Passing in a configuration to an undeclared
   328    provider is now an error.
   329  
   330  ## Commands Accepting a Configuration Directory Argument
   331  
   332  A subset of Terraform's CLI commands have historically accepted a final
   333  positional argument to specify which directory contains the root module of
   334  the configuration, overriding the default behavior of expecting to find it
   335  in the current working directory.
   336  
   337  However, the design of that argument was flawed in a number of ways due to
   338  it being handled at the wrong level of abstraction: it only changed where
   339  Terraform looks for configuration and not any of the other files that Terraform
   340  might search for, and that could therefore violate assumptions that Terraform
   341  configurations might make about the locations of different files, leading
   342  to confusing error messages. It was also not possible to support this usage
   343  pattern across all commands due to those commands using positional arguments
   344  in other ways.
   345  
   346  To address these design flaws, Terraform v0.14 introduced a new global option
   347  `-chdir` which you can use before the subcommand name, causing Terraform to
   348  run the subcommand as if the given directory had been the current working
   349  directory:
   350  
   351  ```shellsession
   352  $ terraform -chdir=example init
   353  ```
   354  
   355  This command causes the Terraform process to actually change its current
   356  working directory to the given directory before launching the subcommand, and
   357  so now any relative paths accessed by the subcommand will be treated as
   358  relative to that directory, including (but not limited to) the following key
   359  directory conventions:
   360  
   361  * As with the positional arguments that `-chdir` replaces, Terraform will look
   362    for the root module's `.tf` and `.tf.json` files in the given directory.
   363  
   364  * The `.tfvars` and `.tfvars.json` files that Terraform automatically searches
   365    for, and any relative paths given in `-var-file` options, will be searched
   366    in the given directory.
   367  
   368  * The `.terraform` directory which Terraform creates to retain the working
   369    directory internal state will appear in the given directory, rather than
   370    the current working directory.
   371  
   372  After treating the v0.14 releases as a migration period for this new behavior,
   373  Terraform CLI v0.15 no longer accepts configuration directories on any
   374  command except `terraform fmt`. (`terraform fmt` is special compared to the
   375  others because it primarily deals with configuration files in isolation,
   376  rather than modules or configurations as a whole.)
   377  
   378  If you built automation which previously relied on overriding the configuration
   379  directory alone, you will need to transition to using the `-chdir` command line
   380  option before upgrading to Terraform v0.15.
   381  
   382  Since the `-chdir` argument behavior is more comprehensive than the positional
   383  arguments it has replaced, you may need to make some further changes in the
   384  event that your automation was relying on the limitations of the old mechanism:
   385  
   386  * If your system depends on the `.terraform` directory being created in the
   387    _real_ current working directory while using a root module defined elsewhere,
   388    you can use the `TF_DATA_DIR` environment variable to specify the absolute
   389    path where Terraform should store its working directory internal state:
   390  
   391      ```bash
   392      TF_DATA_DIR="$PWD/.terraform"
   393      ```
   394  
   395  * If your system uses `.tfvars` or `.tfvars.json` files either implicitly found
   396    or explicitly selected in the current working directory, you must either
   397    move those variables files into the root module directory or specify your
   398    files from elsewhere explicitly using the `-var-file` command line option:
   399  
   400      ```bash
   401      terraform plan -var-file="$PWD/example.tfvars"
   402      ```
   403  
   404  As a special case for backward compatibility, Terraform ensures that the
   405  language expression `path.cwd` will return the _original_ working directory,
   406  before overriding with `-chdir`, so that existing configurations referring to
   407  files in that directory can still work. If you want to refer to files in the
   408  directory given in `-chdir` then you can use `path.root`, which returns the
   409  directory containing the configuration's root module.
   410  
   411  ## Microsoft Windows Terminal Support
   412  
   413  Until the first Windows 10 update, Microsoft Windows had a console window
   414  implementation with an API incompatible with the virtual terminal approach
   415  taken on all other platforms that Terraform supports.
   416  
   417  Previous versions of Terraform accommodated this by using an API translation
   418  layer which could convert a subset of typical virtual terminal sequences into
   419  corresponding Windows Console API function calls, but as a result this has
   420  prevented Terraform from using more complex terminal features such as progress
   421  indicators that update in place, menu prompts, etc.
   422  
   423  Over the course of several updates to Windows 10, Microsoft has introduced
   424  virtual terminal support similar to other platforms and
   425  [now recommends the virtual terminal approach for console application developers](https://docs.microsoft.com/en-us/windows/console/classic-vs-vt).
   426  In response to that recommendation, Terraform v0.15 no longer includes the
   427  terminal API translation layer and consequently it will, by default, produce
   428  incorrectly-formatted output on Windows 8 and earlier, and on non-updated
   429  original retail Windows 10 systems.
   430  
   431  If you need to keep using Terraform on an older version of Windows, there are
   432  two possible workarounds available in the v0.15.0 release:
   433  
   434  * Run Terraform commands using the `-no-color` command line option to disable
   435    the terminal formatting sequences.
   436    
   437      This will cause the output to be unformatted plain text, but as a result
   438      will avoid the output being interspersed with uninterpreted terminal
   439      control sequences.
   440  
   441  * Alternatively, you can use Terraform v0.15.0 in various third-party
   442    virtual terminal implementations for older Windows versions, including
   443    [ConEmu](https://conemu.github.io/), [Cmder](https://cmder.net/),
   444    and [mintty](https://mintty.github.io/).
   445  
   446  Although we have no immediate plans to actively block running Terraform on
   447  older versions of Windows, we will not be able to test future versions of
   448  Terraform on those older versions and so later releases may contain
   449  unintended regressions. We recommend planning an upgrade to a modern Windows
   450  release on any system where you expect to continue using Terraform CLI.
   451  
   452  ## Other Minor Command Line Behavior Changes
   453  
   454  Finally, Terraform v0.15 includes a small number of minor changes to the
   455  details of some commands and command line arguments, as part of a general
   456  cleanup of obsolete features and improved consistency:
   457  
   458  * Interrupting Terraform commands with your operating system's interrupt
   459    signal (`SIGINT` on Unix systems) will now cause Terraform to exit with
   460    a non-successful exit code. Previously it would, in some cases, exit with
   461    a success code.
   462    
   463      This signal is typically sent to Terraform when you press
   464      Ctrl+C or similar interrupt keyboard shortcuts in an interactive terminal,
   465      but might also be used by automation in order to gracefully cancel a
   466      long-running Terraform operation.
   467  
   468  * The `-lock` and `-lock-timeout` options are no longer available for the
   469    `terraform init` command. Locking applies to operations that can potentially
   470    change remote objects, to help ensure that two concurrent Terraform processes
   471    don't try to run conflicting operations, but `terraform init` does not
   472    interact with any providers in order to possibly effect such changes.
   473  
   474      These options didn't do anything in the `terraform init` command before,
   475      and so you can remove them from any automated calls with no change
   476      in behavior.
   477  
   478  * The `-verify-plugins` and `-get-plugins` options to `terraform init` are
   479    no longer available. These have been non-functional since Terraform v0.13,
   480    with the introduction of the new Terraform Registry-based provider installer,
   481    because in practice there are very few operations Terraform can perform which
   482    both require a `terraform init` but can also run without valid provider
   483    plugins installed.
   484  
   485      If you were using these options in automated calls to `terraform init`,
   486      remove them from the command line for compatibility with Terraform v0.15.
   487      There is no longer an option to initialize without installing the
   488      required provider plugins.
   489  
   490  * The `terraform destroy` command no longer accepts the option `-force`. This
   491    was a previous name for the option in earlier Terraform versions, but we've
   492    since adopted `-auto-approve` for consistency with the `terraform apply`
   493    command.
   494  
   495      If you are using `-force` in an automated call to `terraform destroy`,
   496      change to using `-auto-approve` instead.
   497  
   498  ## Azure Backend Removed Arguments
   499  
   500  In an earlier release the `azure` backend changed to remove the `arm_` prefix
   501  from a number of the configuration arguments:
   502  
   503  | Old Name              | New Name          |
   504  |-----------------------|-------------------|
   505  | `arm_client_id`       | `client_id`       |
   506  | `arm_client_secret`   | `client_secret`   |
   507  | `arm_subscription_id` | `subscription_id` |
   508  | `arm_tenant_id`       | `tenant_id`       |
   509  
   510  The old names were previously deprecated, but we've removed them altogether
   511  in Terraform v0.15 in order to conclude that deprecation cycle.
   512  
   513  If you have a backend configuration using the old names then you may see
   514  errors like the following when upgrading to Terraform v0.15:
   515  
   516  ```
   517  ╷
   518  │ Error: Invalid backend configuration argument
   519  │
   520  │ The backend configuration argument "arm_client_id" given on
   521  │ the command line is not expected for the selected backend type.
   522  ╵
   523  ```
   524  
   525  If you see errors like this, rename the arguments in your backend configuration
   526  as shown in the table above and then run the following to re-initialize your
   527  backend configuration:
   528  
   529  ```
   530  terraform init -reconfigure
   531  ```
   532  
   533  The `-reconfigure` argument instructs Terraform to just replace the old
   534  configuration with the new configuration directly, rather than offering to
   535  migrate the latest state snapshots from the old to the new configuration.
   536  Migration would not be appropriate in this case because the old and new
   537  configurations are equivalent and refer to the same remote objects.