1---
2layout: "language"
3page_title: "Upgrading to Terraform 0.12"
4sidebar_current: "upgrade-guides-0-12"
5description: |-
6  Upgrading to Terraform v0.12
7---
8
9# Upgrading to Terraform v0.12
10
11[Terraform v0.12 is a major release](https://hashicorp.com/blog/terraform-0-1-2-preview)
12focused on configuration language improvements and thus includes some
13changes that you'll need to consider when upgrading. The goal of this guide is
14to cover the most common upgrade concerns and issues.
15
16For most users, upgrading configuration should be completely automatic. Some
17simple configurations will require no changes at all, and most other
18configurations can be prepared by running
19[the automatic upgrade tool](/docs/cli/commands/0.12upgrade.html). Please read on
20for more information and recommendations on the upgrade process.
21
22-> If you are a developer maintaining a provider plugin, please see
23[the documentation on 0.12 compatibility for providers](/docs/extend/terraform-0.12-compatibility.html)
24to learn more about the changes that are required.
25
26
27## Upgrade to Terraform 0.11 first
28
29We strongly recommend completing an upgrade to the latest Terraform v0.11
30release first. This will give you an opportunity to address any changes
31required for the previous major version upgrades separately, rather than
32making multiple changes at once.
33
34In particular, if you are upgrading from a Terraform version prior to v0.9,
35you _must_ first [upgrade to Terraform v0.9](/upgrade-guides/0-9.html) and
36switch to initializing with `terraform init`, because v0.12 no longer includes
37the functionality for automatically migrating from the legacy remote state
38mechanism.
39
40This guide focuses on changes from v0.11 to v0.12. Each previous major release
41has its own upgrade guide, so please consult the other guides (available in the
42navigation) to upgrade step-by-step to v0.11 first.
43
44Terraform v0.11.14 (and any subsequent v0.11 releases) also include some
45additional functionality to help smooth the upgrade, which we will use later
46in this guide.
47
48Prior versions of Terraform are available from
49[the releases server](https://releases.hashicorp.com/terraform/).
50
51## Pre-upgrade Checklist
52
53Terraform v0.11.14 introduced a temporary helper command
54`terraform 0.12checklist`, which analyzes your configuration to detect any
55required steps that will be easier to perform before upgrading.
56
57To use it, first upgrade to [Terraform v0.11.14](https://releases.hashicorp.com/terraform/0.11.14/).
58Then, perform the following steps:
59
60* `terraform init` to ensure your working directory is fully initialized and
61  all required plugins are installed and selected.
62* `terraform apply` to ensure that your real infrastructure and Terraform
63  state are consistent with the current configuration. The instructions
64  produced by the checklist command assume that configuration and state are
65  synchronized.
66* `terraform 0.12checklist` to see if there are any pre-upgrade steps in the
67  checklist.
68
69If all is well, the final command will produce a message like this:
70
71```
72Looks good! We did not detect any problems that ought to be
73addressed before upgrading to Terraform v0.12
74
75This tool is not perfect though, so please check the v0.12 upgrade
76guide for additional guidance, and for next steps:
77    https://www.terraform.io/upgrade-guides/0-12.html
78```
79
80As the message suggests, the next step in that case is to read the remainder
81of this page to prepare for and carry out the upgrade.
82
83However, the checklist command may instead produce a list of one or more tasks
84that we recommend you perform before upgrading to Terraform 0.12, because they
85are easier to perform with a fully-functional Terraform 0.11 than with a
86Terraform 0.12 that has encountered compatibility problems.
87
88The tasks it may suggest you perform could include:
89
90* Upgrading any provider versions that are not compatible with Terraform v0.12.
91  We recommend upgrading to the latest version of each provider before upgrading
92  because that will avoid changing many things in one step.
93* Renaming any resources or provider aliases that have names that start with
94  digits, because that is no longer valid in Terraform 0.12.
95* Upgrading any external modules the configuration uses which themselves have
96  the above problems.
97
98In each case, the tool will give some direction on how to perform the task it
99is suggesting.
100
101The output from `terraform 0.12checklist` is in Markdown format so that it can
102easily be pasted into a Markdown-compatible issue tracker, should you want
103to track the necessary tasks or share the work with other team members.
104
105After all of the tasks are complete, run `terraform 0.12checklist` one more time
106to verify that everything is complete. If so, continue reading the following
107sections to complete the upgrade!
108
109### Addendum: Invalid module names
110
111There is one additional pre-upgrade checklist item that the Terraform team did
112not become aware of until after the release of Terraform v0.11.14, and thus
113cannot be detected automatically by the checklist tool: renaming modules which
114have names that start with digits.
115
116Terraform 0.11 inadvertently tolerated leading-digit names for modules as a
117result of a validation bug, but Terraform 0.12 has corrected that bug and will
118reject such module names. Unfortunately, module names are also recorded in
119state snapshots and so a state snapshot created for a configuration with an
120invalid module name will itself be invalid as far as Terraform 0.12 is
121concerned.
122
123You can address this in a similar way to what the checklist tool suggests for
124invalid resource names and provider aliases:
125
126* Rename the module in your configuration.
127* Use `terraform state mv module.old module.new` _in Terraform 0.11.14_ to
128  update the state to use the new name instead of the old name.
129
130As with all of the pre-upgrade checklist items, be sure to run `terraform apply`
131once more before upgrading in order to ensure that the latest state snapshot is
132synchronized with the latest configuration.
133
134## Upgrading to Terraform 0.12
135
136Before switching to Terraform 0.12, we recommend using Terraform v0.11.14 (or
137any later v0.11 release) to perform one last `terraform init` and
138`terraform apply` to ensure that everything is initialized and synchronized.
139
140Once `terraform apply` shows no changes pending, switch over to a Terraform
141v0.12 release and run `terraform init` again to upgrade the working directory
142metadata to v0.12 format. (Once you've done this, you'll need to delete the
143`.terraform` directory if you wish to return to Terraform v0.11, but no
144real infrastructure or persisted state will be upgraded yet.)
145
146It is possible that your configuration may be using configuration constructs
147that are not Terraform v0.12 compatible and thus require upgrade. In that case,
148`terraform init` will produce the following message:
149
150```
151Terraform has initialized, but configuration upgrades may be needed.
152
153Terraform found syntax errors in the configuration that prevented full
154initialization. If you've recently upgraded to Terraform v0.12, this may be
155because your configuration uses syntax constructs that are no longer valid,
156and so must be updated before full initialization is possible.
157
158Terraform has installed the required providers to support the configuration
159upgrade process. To begin upgrading your configuration, run the following:
160    terraform 0.12upgrade
161
162To see the full set of errors that led to this message, run:
163    terraform validate
164```
165
166As mentioned in the message, Terraform has partially initialized the directory
167just enough to perform the configuration upgrade process, which is described
168in the following section.
169
170We recommend running the configuration upgrade tool even if you do not see
171the above message, because it may detect and fix constructs that are
172syntactically correct but still need some changes to work as expected with
173Terraform v0.12.
174
175## Upgrading Terraform configuration
176
177Terraform v0.12 includes a new command `terraform 0.12upgrade` that will
178read the configuration files for a module written for Terraform 0.11 and
179update them in-place to use the cleaner Terraform 0.12 syntax and also
180adjust for use of features that have changed behavior in the 0.12 Terraform
181language.
182
183Simple configuration files are likely to be understood by Terraform 0.12 as-is,
184because the language is still broadly compatible, but we recommend that everyone
185run the upgrade tool nonetheless. Even if your configuration is already
186compatible, the tool will update your configuration to use the cleaner syntax
187available in Terraform 0.12, which should improve readability.
188
189To run the command, first make sure that your local working directory is synced
190with your version control system so that there are no changes outstanding. This
191will make it easier to review the changes that the upgrade tool is proposing,
192using the diff feature of your version control system.
193
194With a fully-initialized working directory (all necessary providers and child
195modules installed), run `terraform 0.12upgrade` to begin the process. By default
196it will print some information about what it is about to do and prompt for
197confirmation:
198
199```
200This command will rewrite the configuration files in the given directory so
201that they use the new syntax features from Terraform v0.12, and will identify
202any constructs that may need to be adjusted for correct operation with
203Terraform v0.12.
204
205We recommend using this command in a clean version control work tree, so that
206you can easily see the proposed changes as a diff against the latest commit.
207If you have uncommitted changes already present, we recommend aborting this
208command and dealing with them before running this command again.
209
210Would you like to upgrade the module in the current directory?
211```
212
213If you answer yes, the `.tf` and `.tfvars` files in your current working
214directory will be rewritten in-place.
215
216The upgrade tool may also print out warnings about constructs it wasn't able to
217migrate fully automatically; in that case, it will also emit comments into the
218rewritten source files containing the special marker `TF-UPGRADE-TODO`, as
219a prompt for a decision you'll need to make to complete the upgrade.
220
221Once the upgrade tool has successfully completed and you've resolved any
222`TF-UPGRADE-TODO` prompts, use your version control tool to review the proposed
223changes and then run `terraform plan` to see the effect of those changes.
224
225In most cases, `terraform plan` should report that no changes are required,
226because the updated configuration is equivalent to before.
227
228The remaining sections below describe both some common changes that the upgrade
229tool is able to make automatically, and some other upgrade situations that
230the configuration tool may not be able to fully resolve. If you encounter
231any errors during the upgrade or during the subsequent `terraform plan`, the
232sections below may give some additional context for how to proceed.
233
234Once you're happy with the updated configuration, commit it to version control
235in the usual way and apply it with Terraform 0.12.
236
237### Remote state references
238
239The `terraform_remote_state` data source has changed slightly for the v0.12
240release to make all of the remote state outputs available as a single map
241value, rather than as top-level attributes as in previous releases.
242
243In previous releases, a reference to a `vpc_id` output exported by the remote
244state data source might have looked like this:
245
246```hcl
247data.terraform_remote_state.vpc.vpc_id
248```
249
250This value must now be accessed via the new `outputs` attribute:
251
252```hcl
253data.terraform_remote_state.vpc.outputs.vpc_id
254```
255
256The upgrade tool will rewrite remote state references automatically to include
257the additional `outputs` attribute.
258
259Where appropriate, you can also access the outputs attribute directly to
260work with the whole map as a single value:
261
262```hcl
263data.terraform_remote_state.vpc.outputs
264```
265
266Another consideration for `terraform_remote_state` is that this data source must
267be able to parse the latest state snapshot for a separate Terraform
268configuration that may have been updated by a newer version of Terraform.
269To provide flexibility when upgrading decomposed environments that use
270`terraform_remote_state`, Terraform v0.11.14 introduced support for reading
271outputs from the Terraform v0.12 state format, so if you upgrade all of your
272configurations to Terraform v0.11.14 first you can then perform v0.12 upgrades
273of individual configurations in any order, without breaking
274`terraform_remote_state` usage.
275
276Note that the `config` block should now be in the form of an assignment with the `=` sign:
277
278```hcl
279data "terraform_remote_state" "default" {
280  backend = "gcs"
281  config = {
282    bucket = "..."
283  }
284}
285```
286
287### Attributes vs. blocks
288
289Terraform resource configurations consist of both arguments that set
290individual properties of the main object being described, and nested blocks
291which declare zero or more other objects that are modeled as being part of
292their parent. For example:
293
294```hcl
295resource "aws_instance" "example" {
296  instance_type = "t2.micro"
297  ami           = "ami-abcd1234"
298
299  tags = {
300    Name = "example instance"
301  }
302
303  ebs_block_device {
304    device_name = "sda2"
305    volume_type = "gp2"
306    volume_size = 24
307  }
308}
309```
310
311In the above resource, `instance_type`, `ami`, and `tags` are both direct
312arguments of the `aws_instance` resource, while `ebs_block_device` describes
313a separate EBS block device object that is connected to the parent instance.
314
315Due to the design of the configuration language decoder in Terraform v0.11 and
316earlier, it was in many cases possible to interchange the argument syntax
317(with `=`) and the block syntax (with just braces) when dealing with map
318arguments vs. nested blocks. However, this led to some subtle bugs and
319limitations, so Terraform v0.12 now requires consistent usage of argument
320syntax for arguments and nested block syntax for nested blocks.
321
322In return for this new strictness, Terraform v0.12 now allows map keys to be
323set dynamically from expressions, which is a long-requested feature. The
324main difference between a map attribute and a nested block is that a map
325attribute will usually have user-defined keys, like we see in the `tags`
326example above, while a nested block always has a fixed set of supported
327arguments defined by the resource type schema, which Terraform will validate.
328
329The configuration upgrade tool uses the provider's schema to recognize the
330nature of each construct and will select the right syntax automatically. For
331most simple usage, this will just involve adding or removing the equals sign
332as appropriate.
333
334A more complicated scenario is where users found that they could exploit this
335flexibility to -- with some caveats -- dynamically generate nested blocks even
336though this wasn't intentionally allowed:
337
338```hcl
339  # Example of no-longer-supported workaround from 0.11 and earlier
340  ebs_block_device = "${concat(map("device_name", "sda4"), var.extra_block_devices)}"
341```
342
343Terraform v0.12 now includes a first-class feature for dynamically generating
344nested blocks using expressions, using the special `dynamic` block type. The
345above can now be written like this, separating the static block device from
346the dynamic ones:
347
348```hcl
349  ebs_block_device {
350    device_name = "sda4"
351  }
352  dynamic "ebs_block_device" {
353    for_each = var.extra_block_devices
354    content {
355      device_name = ebs_block_device.value.device_name
356      volume_type = ebs_block_device.value.volume_type
357      volume_size = ebs_block_device.value.volume_size
358    }
359  }
360```
361
362The configuration upgrade tool will detect use of the above workaround and
363rewrite it as a `dynamic` block, but it may make non-ideal decisions for how to
364flatten your expression down into static vs. dynamic blocks, so we recommend
365reviewing the generated `dynamic` blocks to see if any simplifications are
366possible.
367
368Terraform v0.12 now also requires that each argument be set only once within
369a particular block, whereas before Terraform would either take the last
370definition or, in some cases, attempt to merge together multiple definitions
371into a list. The upgrade tool does not remove or attempt to consolidate
372any existing duplicate arguments, but other commands like `terraform validate`
373will detect and report these after upgrading.
374
375### Integer vs. Float Number Types
376
377From Terraform v0.12, the Terraform language no longer distinguishes between
378integer and float types, instead just having a single "number" type that can
379represent high-precision floating point numbers. This new type can represent
380any value that could be represented before, plus many new values due to the
381expanded precision.
382
383In most cases this change should not cause any significant behavior change, but
384please note that in particular the behavior of the division operator is now
385different: it _always_ performs floating point division, whereas before it
386would sometimes perform integer division by attempting to infer intent from
387the argument types.
388
389If you are relying on integer division behavior in your configuration, please
390use the `floor` function to obtain the previous result. A common place this
391would arise is in index operations, where the index is computed by division:
392
393```hcl
394  example = var.items[floor(count.index / var.any_number)]
395```
396
397Using a fractional number to index a list will produce an error telling you
398that this is not allowed, serving as a prompt to add `floor`:
399
400```
401Error: Invalid index
402
403The given key does not identify an element in this collection value: indexing a
404sequence requires a whole number, but the given index (0.5) has a fractional
405part.
406```
407
408Unfortunately the automatic upgrade tool cannot apply a fix for this case
409because it does not have enough information to know if floating point or integer
410division was intended by the configuration author, so this change must be made
411manually where needed.
412
413### Referring to List Variables
414
415In early versions of Terraform, before list support became first-class, we
416required using seemingly-redundant list brackets around a single expression
417in order to hint to the language interpreter that a list interpretation was
418desired:
419
420```hcl
421  # Example for older versions of Terraform; not valid for v0.12
422  example = ["${var.any_list}"]
423```
424
425This strange requirement was subsequently lifted after the introduction of
426first-class list support, but we retained compatibility with this older usage
427for a transitional period by including some fixup logic that would detect when
428list brackets contain list expressions and automatically flatten to a single
429list.
430
431As part of implementing the first-class expressions support for v0.12, we needed
432to finally remove that backward-compatibility mechanism to avoid ambiguity
433in the language, so an expression like the above will now produce a list of
434lists and thus produce a type checking error for any argument that was expecting
435a list of some other type.
436
437The upgrade tool is able to recognize most simple usage of this pattern and
438rewrite automatically to just refer to the list directly:
439
440```hcl
441  example = var.any_list
442```
443
444However, an unintended side-effect of this compatibility mechanism was to
445also flatten mixed lists of single-value and list expressions into a single
446list automatically. We didn't intend for this to be a part of the language, but
447in retrospect it was an obvious consequence of how the compatibility mechanism
448was implemented. If you have expressions in your modules that produce a list
449of strings by using list brackets with a mixture of string and list-of-string
450sub-expressions, you will need to rewrite this to explicitly use
451[the `flatten` function](/docs/language/functions/flatten.html)
452to make the special treatment more obvious to the reader:
453
454```hcl
455  example = flatten([
456    "single string",
457    var.any_list,
458  ])
459```
460
461The configuration upgrade tool unfortunately cannot make this change
462automatically, because it doesn't have enough information to know for certain
463which interpretation was intended for a given list.
464
465For complex examples that the upgrade tool is not able to adjust automatically,
466subsequent Terraform operations may produce an error message like the following:
467
468```
469Error: Incorrect attribute value type
470
471  on redundant-list-brackets.tf line 9, in resource "aws_security_group" "foo":
472   9:     cidr_blocks = ["${var.cidr_blocks}"]
473
474Inappropriate value for attribute "cidr_blocks": element 0: string required.
475```
476
477This message is reporting that Terraform has understood this expression as a
478list of lists, and therefore element zero is a list rather than a string. To
479fix the error, remove the redundant list brackets and possibly add a
480`flatten` function call as described above, for more complex cases.
481
482### Reserved Variable Names
483
484In preparation for new features planned for future releases, Terraform 0.12
485reserves some additional names that can no longer be used as input variable
486names for modules. These reserved names are:
487
488* `count`
489* `depends_on`
490* `for_each`
491* `lifecycle`
492* `providers`
493* `source`
494
495When any of these names is used as the label of a `variable` block, Terraform
496will now generate the following error:
497
498```
499Error: Invalid variable name
500
501  on reserved-variable-names.tf line 2, in variable "count":
502   2: variable "count" {
503
504The variable name "count" is reserved due to its special meaning inside module
505blocks.
506```
507
508The upgrade tool cannot automatically adjust for these reserved names, because
509it does not know what new name would be more appropriate. To proceed, you must
510unfortunately rename these input variables and make a new major release of
511the module in question, since renaming input variables is a breaking change.
512
513### Type Constraints on Variables
514
515In Terraform v0.11, variables were documented as accepting only strings, lists
516of strings, and maps of strings. However, in practice Terraform permitted
517lists of lists and lists of maps and other nested structures in some cases,
518even though it was then generally inconvenient to work with those values
519elsewhere in the module due to limitations of the index syntax, `element`
520function, and `lookup` function.
521
522Terraform now allows various [type constraints](/docs/language/expressions/type-constraints.html)
523to be specified, as part of the language's new type system and generalized
524functions and operators. However, because lists and maps of non-string values
525were not officially supported in 0.11, existing configurations do not have
526enough information for the upgrade tool to know what element type was intended.
527It will therefore assume that lists and maps are of strings as documented,
528which will be incorrect for configurations using more complex structures. The
529result will be one of the following error messages:
530
531```
532Error: Invalid default value for variable
533
534  on child_module/example.tf line 4, in variable "example":
535   4:   default = [
536   5:     {
537   6:       "foo" = "bar"
538   7:     },
539   8:   ]
540
541This default value is not compatible with the variable's type constraint:
542element 0: string required.
543```
544
545```
546Error: Invalid value for module argument
547
548  on variables-incorrect-elem-type.tf line 4, in module "child":
549   4:   example = [
550   5:     {
551   6:       "foo" = "bar"
552   7:     },
553   8:   ]
554
555The given value is not suitable for child module variable "example" defined at
556child/child.tf:1,1-19: element 0: string required.
557```
558
559To fix this, change the `type` argument from `list(string)` or `map(string)`
560to a more appropriate [type constraint](/docs/language/expressions/type-constraints.html).
561
562If you're not sure what type constraint to use yet, another option is to
563use the type constraint `any`, which will effectively disable validation and
564allow any value. We recommend using specific types where possible, but selecting
565`any` during upgrade may be preferable, so that the work to select and define
566a more precise type can be saved for a later change at your leisure, once
567upgrading is complete.
568
569### Working with `count` on resources
570
571The `count` feature allows declaration of multiple instances of a particular
572resource constructed from the same configuration. In Terraform v0.11, any
573use of `count` would generally lead to referring to the resource in question
574using the "splat expression" syntax elsewhere in the configuration:
575
576```
577aws_instance.example.*.id[0]
578```
579
580Because `aws_instance.example` itself was not directly referencable in
581Terraform v0.11, the expression system allowed some flexibility in how such
582expressions were resolved. For example, Terraform would treat
583`aws_instance.example.id` as an alias for `aws_instance.example.*.id[0]`.
584
585Terraform v0.12 allows referring to an entire resource as an object value,
586but that required making a decision on what type of value is returned by
587`aws_instance.example`. The new rules are as follows:
588
589* For resources where `count` is _not_ set, a reference like
590  `aws_instance.example` returns a single object, whose attributes can be
591  accessed in the usual way, like `aws_instance.example.id`.
592
593* For resources where `count` _is_ set -- even if the expression evaluates to
594  `1` -- `aws_instance.example` returns a list of objects whose length is
595  decided by the count. In this case `aws_instance.example.id` is an error,
596  and must instead be written as `aws_instance.example[0].id` to access
597  one of the objects before retrieving its `id` attribute value.
598
599The splat syntax is still available and will still be useful in situations
600where a list result is needed, but we recommend updating expressions like
601`aws_instance.example.*.id[count.index]` to instead be
602`aws_instance.example[count.index].id`, which should be easier to read and
603understand for those who are familiar with other languages.
604
605Another consequence of the new handling of `count` is that you can use the
606`length` function directly with references to resources that have `count` set:
607
608```
609length(aws_instance.example)
610```
611
612This replaces the v0.11 special case of `aws_instance.example.count`, which
613can no longer be supported due to `aws_instance.example` being a list.
614
615The upgrade tool will automatically detect references that are inconsistent
616with the `count` setting on the target resource and rewrite them to use the
617new syntax. The upgrade tool will _not_ rewrite usage of splat syntax to
618direct index syntax, because the old splat syntax form is still compatible.
619
620Another `count`-related change is that Terraform now requires `count` to be
621assigned a numeric value, and will not automatically convert a boolean value
622to a number in the interests of clarity. If you wish to use a boolean value
623to activate or deactivate a particular resource, use the conditional operator
624to show clearly how the boolean value maps to a number value:
625
626```hcl
627  count = var.enabled ? 1 : 0
628```
629
630### First-class expressions
631
632Terraform v0.11 and earlier allowed expressions only within interpolation
633sequences, like `"${var.example}"`. Because expressions are such an important
634part of Terraform -- they are the means by which we connect the attributes of
635one resource to the configuration of another -- Terraform v0.12 now allows
636you to use expressions directly when defining most attributes.
637
638```
639  ami = var.ami
640```
641
642The generalization of expression handling also has some other benefits. For
643example, it's now possible to directly construct lists and maps within
644expressions using the normal syntax, whereas in Terraform v0.11 we required
645using the `list` and `map` functions:
646
647```
648  # Old 0.11 example
649  tags = "${merge(map("Name", "example"), var.common_tags)}"
650
651  # Updated 0.12 example
652  tags = merge({ Name = "example" }, var.common_tags)
653```
654
655The automatic upgrade tool will perform rewrites like these automatically,
656making expressions easier to read and understand.
657
658### Default settings in `connection` blocks
659
660Terraform v0.11 and earlier allowed providers to pre-populate certain arguments
661in a `connection` block for use with remote provisioners. Several resource
662type implementations use this to pre-populate `type` as `"ssh"` and `host`
663as one of the IP addresses of the compute instance being created.
664
665While that feature was convenient in some cases, we found that in practice it
666was hard for users to predict how it would behave, since each provider had its
667own rules for whether to prefer public vs. private IP addresses, which network
668interface to use, whether to use IPv4 or IPv6, etc.
669
670It also violated our design principle of "explicit is better than implicit": we
671think it's important that someone who is unfamiliar with a particular Terraform
672configuration (or with Terraform itself) to be able to read the configuration
673and make a good guess as to what it will achieve, and the default connection
674settings feature left an important detail unstated: how do the provisioners
675access the host?
676
677With this in mind, Terraform v0.12 no longer performs any automatic population
678of `connection` blocks. Instead, if you are using any remote provisioners you
679should explicitly set the connection type and the hostname to connect to:
680
681```hcl
682  connection {
683    type = "ssh"
684    host = self.public_ip
685    # ...
686  }
687```
688
689The automatic upgrade tool will detect existing `connection` blocks that are
690lacking these settings within resource types that are known to have previously
691set defaults, and it will write out an expression that approximates whatever
692selection logic the provider was previously doing in its own implementation.
693
694Unfortunately in some cases the provider did not export the result of the
695possibly-rather-complex host selection expression as a single attribute, and so
696for some resource types the generated `host` expression will be quite
697complicated. We recommend reviewing these and replacing them with a simpler
698expression where possible, since you will often know better than Terraform does
699which of the instance IP addresses are likely to be accessible from the host
700where Terraform is running.
701
702### Equality operations must be valid on value and type
703
704In 0.11, `"1"` would compare truthfully against `1`, however, in 0.12,
705values must be equal on both value and type in order to be true. That is, in 0.11
706you would see:
707
708```
709> "1" == 1
710true
711```
712
713and in 0.12:
714
715```
716> "1" == 1
717false
718```
719
720This means special care should be taken if you have any conditionals comparing to say,
721`count.index` where you were previously expecting it to be a string, when it is now a number.
722
723This is a scenario where you would need to update existing 0.11 code to work as you expect in 0.12:
724
725```
726resource "server_instance" "app" {
727    server_status = "${count.index == local.prod_index ? "production" : "standby"}"
728  }
729}
730
731locals {
732  # when migrating to 0.12, be sure to change this value to a number
733  # to ensure expected behavior
734  prod_index = "0"
735}
736```
737
738Also take care that if you have a variable that is a number, but defined as a string,
739the upgrade tool will not change it to a number, so take care to inspect your code:
740
741```
742locals {
743  some_count = "3" # will not be changed to a number after config upgrade
744}
745```
746
747## Upgrades for reusable modules
748
749If you are making upgrades to a reusable module that is consumed by many
750different configurations, you may need to take care with the timing of your
751upgrade and of how you publish it.
752
753We strongly recommend using module versioning, either via a Terraform registry
754or via version control arguments in your module source addresses, to pin
755existing references to the old version of the module and then publish the
756upgraded version under a new version number. If you are using semantic
757versioning, such as in a Terraform registry, the updates made by the upgrade
758tool should be considered a breaking change and published as a new major
759version.
760
761The migration tool will automatically add a `>= 0.12.0` Terraform version
762constraint to indicate that the module has been upgraded to use v0.12-only
763features. By using version constraints, users can gradually update their callers
764to use the newly-upgraded version as they begin to use Terraform v0.12 with
765those modules.
766
767For simpler modules it may be possible to carefully adapt them to be both
7680.11 and 0.12 compatible at the same time, by following the upgrade notes in
769earlier sections and avoiding any v0.12-only features. However, for any module
770using a undocumented workarounds for v0.11 limitations it is unlikely to be
771possible to both update it for Terraform v0.12 and retain v0.11 compatibility
772at the same time, because those undocumented workarounds have been replaced
773with new features in Terraform v0.12.
774
775## Map variables no longer merge when overridden
776
777In prior versions of Terraform, a variable of type `"map"` had a special
778behavior where any value provided via mechanisms such as the `-var` command
779line option would be keywise-merged with any default value associated with
780the variable. This was useful in early versions of Terraform that lacked
781mechanisms for doing such merging explicitly, but since Terraform v0.10
782introduced the concept of local values we consider it preferable to perform
783such merges manually so that they are explicit in configuration:
784
785```
786variable "example_map" {
787  type = map(string)
788  default = {}
789}
790
791locals {
792  default_map_keys = {
793    "a" = "b"
794  }
795  merged_map_keys = merge(local.default_map_keys, var.example_map)
796}
797```
798
799In order to improve the consistency of variable handling across types, the
800map variable merging behavior is removed in Terraform v0.12. Because this
801mechanism was driven by command line options rather than configuration, the
802automatic upgrade tool cannot automatically handle it. If you are relying on
803the merging feature, you must reorganize your configuration to use explicit
804merging like in the above example, or else your default map value will be
805entirely overridden by any explicitly-set value.
806
807## Upgrading `remote` Backend Configuration
808
809Terraform Cloud and Terraform Enterprise users will need
810to run `terraform init -reconfigure` to upgrade to Terraform 0.12.
811
812Terraform provides a message stating that `terraform init` is required; while
813there is no harm in running this command, the next error message will clarify
814that `terraform init -reconfigure` is required.
815
816## Upgrading Sentinel policies
817
818The Terraform Sentinel imports have been updated to work with Terraform 0.12.
819Care has been taken to ensure that the API is as backwards compatible as
820possible and most policies will continue to work without modification. However,
821there are some important changes and certain policies will need to modified.
822
823More information on the changes can be found in our page on [using Sentinel with
824Terraform 0.12](/docs/cloud/sentinel/sentinel-tf-012.html).
825
826It's strongly advised that you test your Sentinel policies after upgrading to
827Terraform 0.12 to ensure they continue to work as expected. [Mock
828generation](/docs/cloud/sentinel/mock.html) has also been updated to
829produce mock data for the Sentinel imports as they appear in Terraform 0.12.
830
831For more information on testing a policy with 0.11 and 0.12 at the same time,
832see the section on [testing a policy with 0.11 and 0.12
833simultaneously](/docs/cloud/sentinel/sentinel-tf-012.html#testing-a-policy-with-0-11-and-0-12-simultaneously).
834