github.com/hugorut/terraform@v1.1.3/website/docs/cli/commands/plan.mdx (about) 1 --- 2 page_title: 'Command: plan' 3 description: >- 4 The terraform plan command creates an execution plan with a preview of the 5 changes that Terraform will make to your infrastructure. 6 --- 7 8 # Command: plan 9 10 The `terraform plan` command creates an execution plan, which lets you preview 11 the changes that Terraform plans to make to your infrastructure. By default, 12 when Terraform creates a plan it: 13 14 * Reads the current state of any already-existing remote objects to make sure 15 that the Terraform state is up-to-date. 16 * Compares the current configuration to the prior state and noting any 17 differences. 18 * Proposes a set of change actions that should, if applied, make the remote 19 objects match the configuration. 20 21 > **Hands-on:** Try the [Terraform: Get Started](https://learn.hashicorp.com/collections/terraform/aws-get-started?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) collection on HashiCorp Learn. 22 23 The plan command alone will not actually carry out the proposed changes, and 24 so you can use this command to check whether the proposed changes match what 25 you expected before you apply the changes or share your changes with your 26 team for broader review. 27 28 If Terraform detects that no changes are needed to resource instances or to 29 root module output values, `terraform plan` will report that no actions need 30 to be taken. 31 32 If you are using Terraform directly in an interactive terminal and you expect 33 to apply the changes Terraform proposes, you can alternatively run 34 [`terraform apply`](/cli/commands/apply) directly. By default, the "apply" command 35 automatically generates a new plan and prompts for you to approve it. 36 37 You can use the optional `-out=FILE` option to save the generated plan to a 38 file on disk, which you can later execute by passing the file to 39 [`terraform apply`](/cli/commands/apply) as an extra argument. This two-step workflow 40 is primarily intended for when 41 [running Terraform in automation](https://learn.hashicorp.com/tutorials/terraform/automate-terraform?in=terraform/automation&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS). 42 43 If you run `terraform plan` without the `-out=FILE` option then it will create 44 a _speculative plan_, which is a description of the effect of the plan but 45 without any intent to actually apply it. 46 47 In teams that use a version control and code review workflow for making changes 48 to real infrastructure, developers can use speculative plans to verify the 49 effect of their changes before submitting them for code review. However, it's 50 important to consider that other changes made to the target system in the 51 meantime might cause the final effect of a configuration change to be different 52 than what an earlier speculative plan indicated, so you should always re-check 53 the final non-speculative plan before applying to make sure that it still 54 matches your intent. 55 56 ## Usage 57 58 Usage: `terraform plan [options]` 59 60 The `plan` subcommand looks in the current working directory for the root module 61 configuration. 62 63 Because the plan command is one of the main commands of Terraform, it has 64 a variety of different options, described in the following sections. However, 65 most of the time you should not need to set any of these options, because 66 a Terraform configuration should typically be designed to work with no special 67 additional options for routine work. 68 69 The remaining sections on this page describe the various options: 70 71 * **[Planning Modes](#planning-modes)**: There are some special alternative 72 planning modes that you can use for some special situations where your goal 73 is not just to change the remote system to match your configuration. 74 * **[Planning Options](#planning-options)**: Alongside the special planning 75 modes, there are also some options you can set in order to customize the 76 planning process for unusual needs. 77 * **[Resource Targeting](#resource-targeting)** is one particular 78 special planning option that has some important caveats associated 79 with it. 80 * **[Other Options](#other-options)**: These change the behavior of the planning 81 command itself, rather than customizing the content of the generated plan. 82 83 ## Planning Modes 84 85 The section above described Terraform's default planning behavior, which is 86 intended for changing the remote system to match with changes you've made to 87 your configuration. 88 89 Terraform has two alternative planning modes, each of which creates a plan with 90 a different intended outcome: 91 92 * **Destroy mode:** creates a plan whose goal is to destroy all remote objects 93 that currently exist, leaving an empty Terraform state. This can be useful 94 for situations like transient development environments, where the managed 95 objects cease to be useful once the development task is complete. 96 97 Activate destroy mode using the `-destroy` command line option. 98 99 * **Refresh-only mode:** creates a plan whose goal is only to update the 100 Terraform state and any root module output values to match changes made to 101 remote objects outside of Terraform. This can be useful if you've 102 intentionally changed one or more remote objects outside of the usual 103 workflow (e.g. while responding to an incident) and you now need to reconcile 104 Terraform's records with those changes. 105 106 Activate refresh-only mode using the `-refresh-only` command line option. 107 108 In situations where we need to discuss the default planning mode that Terraform 109 uses when none of the alternative modes are selected, we refer to it as 110 "Normal mode". Because these alternative modes are for specialized situations 111 only, some other Terraform documentation only discusses the normal planning 112 mode. 113 114 The planning modes are all mutually-exclusive, so activating any non-default 115 planning mode disables the "normal" planning mode, and you can't use more than 116 one alternative mode at the same time. 117 118 -> **Note:** In Terraform v0.15 and earlier, the `-destroy` option is 119 supported only by the `terraform plan` command, and not by the 120 `terraform apply` command. To create and apply a plan in destroy mode in 121 earlier versions you must run [`terraform destroy`](/cli/commands/destroy). 122 123 -> **Note:** The `-refresh-only` option is available only in Terraform v0.15.4 124 and later. 125 126 > **Hands-on:** Try the [Use Refresh-Only Mode to Sync Terraform State](https://learn.hashicorp.com/tutorials/terraform/refresh) tutorial on HashiCorp Learn. 127 128 ## Planning Options 129 130 In addition to the planning _modes_ described above, there are also several 131 additional options that can modify details of the behavior of the planning 132 step. 133 134 When you use `terraform apply` without passing it a saved plan file, it 135 incorporates the `terraform plan` command functionality and so the planning 136 options in this section, along with the planning mode selection options in 137 the previous section, are also available with the same meanings on 138 `terraform apply`. 139 140 * `-refresh=false` - Disables the default behavior of synchronizing the 141 Terraform state with remote objects before checking for configuration changes. 142 143 This option can potentially make the planning operation faster by reducing 144 the number of remote API requests, but it comes at the expense of having 145 Terraform not take into account any changes that might've happened outside 146 of Terraform, and thus the resulting plan may not be complete or correct. 147 148 This option is not available in the "refresh only" planning mode, because 149 it would effectively disable the entirety of the planning operation in that 150 case. 151 152 * `-replace=ADDRESS` - Instructs Terraform to plan to replace the single 153 resource instance with the given address. If the given instance would 154 normally have caused only an "update" action, or no action at all, then 155 Terraform will choose a "replace" action instead. 156 157 You can use this option if you have learned that a particular remote object 158 has become degraded in some way. If you are using immutable infrastructure 159 patterns then you may wish to respond to that by replacing the 160 malfunctioning object with a new object that has the same configuration. 161 162 This option is allowed only in the normal planning mode, so this option 163 is incompatible with the `-destroy` option. 164 165 The `-replace=...` option is available only from Terraform v0.15.2 onwards. 166 For earlier versions, you can achieve a similar effect (with some caveats) 167 using [`terraform taint`](/cli/commands/taint). 168 169 * `-target=ADDRESS` - Instructs Terraform to focus its planning efforts only 170 on resource instances which match the given address and on any objects that 171 those instances depend on. 172 173 This command is for exceptional use only. See 174 [Resource Targeting](#resource-targeting) 175 below for more information. 176 177 * `-var 'NAME=VALUE'` - Sets a value for a single 178 [input variable](/language/values/variables) declared in the 179 root module of the configuration. Use this option multiple times to set 180 more than one variable. For more information see 181 [Input Variables on the Command Line](#input-variables-on-the-command-line), 182 below. 183 184 * `-var-file=FILENAME` - Sets values for potentially many 185 [input variables](/language/values/variables) declared in the 186 root module of the configuration, using definitions from a 187 ["tfvars" file](/language/values/variables#variable-definitions-tfvars-files). 188 Use this option multiple times to include values from more than one file. 189 190 There are several other ways to set values for input variables in the root 191 module, aside from the `-var` and `-var-file` options. For more information, 192 see 193 [Assigning Values to Root Module Variables](/language/values/variables#assigning-values-to-root-module-variables). 194 195 ### Input Variables on the Command Line 196 197 You can use the `-var` command line option to specify values for 198 [input variables](/language/values/variables) declared in your 199 root module. 200 201 However, to do so will require writing a command line that is parsable both 202 by your chosen command line shell _and_ Terraform, which can be complicated 203 for expressions involving lots of quotes and escape sequences. In most cases 204 we recommend using the `-var-file` option instead, and write your actual values 205 in a separate file so that Terraform can parse them directly, rather than 206 interpreting the result of your shell's parsing. 207 208 To use `-var` on a Unix-style shell on a system like Linux or macOS we 209 recommend writing the option argument in single quotes `'` to ensure the 210 shell will interpret the value literally: 211 212 ``` 213 terraform plan -var 'name=value' 214 ``` 215 216 If your intended value also includes a single quote then you'll still need to 217 escape that for correct interpretation by your shell, which also requires 218 temporarily ending the quoted sequence so that the backslash escape character 219 will be significant: 220 221 ``` 222 terraform plan -var 'name=va'\''lue' 223 ``` 224 225 When using Terraform on Windows, we recommend using the Windows Command Prompt 226 (`cmd.exe`). When you pass a variable value to Terraform from the Windows 227 Command Prompt, use double quotes `"` around the argument: 228 229 ``` 230 terraform plan -var "name=value" 231 ``` 232 233 If your intended value includes literal double quotes then you'll need to 234 escape those with a backslash: 235 236 ``` 237 terraform plan -var "name=va\"lue" 238 ``` 239 240 PowerShell on Windows cannot correctly pass literal quotes to external programs, 241 so we do not recommend using Terraform with PowerShell when you are on Windows. 242 Use Windows Command Prompt instead. 243 244 The appropriate syntax for writing the variable value is different depending 245 on the variable's [type constraint](/language/expressions/type-constraints). 246 The primitive types `string`, `number`, and `bool` all expect a direct string 247 value with no special punctuation except that required by your shell, as 248 shown in the above examples. For all other type constraints, including list, 249 map, and set types and the special `any` keyword, you must write a valid 250 Terraform language expression representing the value, and write any necessary 251 quoting or escape characters to ensure it will pass through your shell 252 literally to Terraform. For example, for a `list(string)` type constraint: 253 254 ``` 255 # Unix-style shell 256 terraform plan -var 'name=["a", "b", "c"]' 257 258 # Windows Command Prompt (do not use PowerShell on Windows) 259 terraform plan -var "name=[\"a\", \"b\", \"c\"]" 260 ``` 261 262 Similar constraints apply when setting input variables using environment 263 variables. For more information on the various methods for setting root module 264 input variables, see 265 [Assigning Values to Root Module Variables](/language/values/variables#assigning-values-to-root-module-variables). 266 267 ### Resource Targeting 268 269 > **Hands-on:** Try the [Target resources](https://learn.hashicorp.com/tutorials/terraform/resource-targeting?in=terraform/state&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn. 270 271 You can use the `-target` option to focus Terraform's attention on only a 272 subset of resources. 273 You can use [resource address syntax](/cli/state/resource-addressing) 274 to specify the constraint. Terraform interprets the resource address as follows: 275 276 * If the given address identifies one specific resource instance, Terraform 277 will select that instance alone. For resources with either `count` or 278 `for_each` set, a resource instance address must include the instance index 279 part, like `aws_instance.example[0]`. 280 281 * If the given address identifies a resource as a whole, Terraform will select 282 all of the instances of that resource. For resources with either `count` 283 or `for_each` set, this means selecting _all_ instance indexes currently 284 associated with that resource. For single-instance resources (without 285 either `count` or `for_each`), the resource address and the resource instance 286 address are identical, so this possibility does not apply. 287 288 * If the given address identifies an entire module instance, Terraform will 289 select all instances of all resources that belong to that module instance 290 and all of its child module instances. 291 292 Once Terraform has selected one or more resource instances that you've directly 293 targeted, it will also then extend the selection to include all other objects 294 that those selections depend on either directly or indirectly. 295 296 This targeting capability is provided for exceptional circumstances, such 297 as recovering from mistakes or working around Terraform limitations. It 298 is _not recommended_ to use `-target` for routine operations, since this can 299 lead to undetected configuration drift and confusion about how the true state 300 of resources relates to configuration. 301 302 Instead of using `-target` as a means to operate on isolated portions of very 303 large configurations, prefer instead to break large configurations into 304 several smaller configurations that can each be independently applied. 305 [Data sources](/language/data-sources) can be used to access 306 information about resources created in other configurations, allowing 307 a complex system architecture to be broken down into more manageable parts 308 that can be updated independently. 309 310 ## Other Options 311 312 The `terraform plan` command also has some other options that are related to 313 the input and output of the planning command, rather than customizing what 314 sort of plan Terraform will create. These commands are not necessarily also 315 available on `terraform apply`, unless otherwise stated in the documentation 316 for that command. 317 318 The available options are: 319 320 * `-compact-warnings` - Shows any warning messages in a compact form which 321 includes only the summary messages, unless the warnings are accompanied by 322 at least one error and thus the warning text might be useful context for 323 the errors. 324 325 * `-detailed-exitcode` - Returns a detailed exit code when the command exits. 326 When provided, this argument changes the exit codes and their meanings to 327 provide more granular information about what the resulting plan contains: 328 * 0 = Succeeded with empty diff (no changes) 329 * 1 = Error 330 * 2 = Succeeded with non-empty diff (changes present) 331 332 * `-input=false` - Disables Terraform's default behavior of prompting for 333 input for root module input variables that have not otherwise been assigned 334 a value. This option is particularly useful when running Terraform in 335 non-interactive automation systems. 336 337 * `-json` - Enables the [machine readable JSON UI][machine-readable-ui] output. 338 This implies `-input=false`, so the configuration must have no unassigned 339 variable values to continue. 340 341 [machine-readable-ui]: /internals/machine-readable-ui 342 343 * `-lock=false` - Don't hold a state lock during the operation. This is 344 dangerous if others might concurrently run commands against the same 345 workspace. 346 347 * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, 348 instructs Terraform to retry acquiring a lock for a period of time before 349 returning an error. The duration syntax is a number followed by a time 350 unit letter, such as "3s" for three seconds. 351 352 * `-no-color` - Disables terminal formatting sequences in the output. Use this 353 if you are running Terraform in a context where its output will be 354 rendered by a system that cannot interpret terminal formatting. 355 356 * `-out=FILENAME` - Writes the generated plan to the given filename in an 357 opaque file format that you can later pass to `terraform apply` to execute 358 the planned changes, and to some other Terraform commands that can work with 359 saved plan files. 360 361 Terraform will allow any filename for the plan file, but a typical 362 convention is to name it `tfplan`. **Do not** name the file with a suffix 363 that Terraform recognizes as another file format; if you use a `.tf` suffix 364 then Terraform will try to interpret the file as a configuration source 365 file, which will then cause syntax errors for subsequent commands. 366 367 The generated file is not in any standard format intended for consumption 368 by other software, but the file _does_ contain your full configuration, 369 all of the values associated with planned changes, and all of the plan 370 options including the input variables. If your plan includes any sort of 371 sensitive data, even if obscured in Terraform's terminal output, it will 372 be saved in cleartext in the plan file. You should therefore treat any 373 saved plan files as potentially-sensitive artifacts. 374 375 * `-parallelism=n` - Limit the number of concurrent operations as Terraform 376 [walks the graph](/internals/graph#walking-the-graph). Defaults 377 to 10. 378 379 For configurations using 380 [the `local` backend](/language/settings/backends/local) only, 381 `terraform plan` accepts the legacy command line option 382 [`-state`](/language/settings/backends/local#command-line-arguments). 383 384 ### Passing a Different Configuration Directory 385 386 Terraform v0.13 and earlier accepted an additional positional argument giving 387 a directory path, in which case Terraform would use that directory as the root 388 module instead of the current working directory. 389 390 That usage was deprecated in Terraform v0.14 and removed in Terraform v0.15. 391 If your workflow relies on overriding the root module directory, use 392 [the `-chdir` global option](/cli/commands/#switching-working-directory-with-chdir) 393 instead, which works across all commands and makes Terraform consistently look 394 in the given directory for all files it would normally read or write in the 395 current working directory. 396 397 If your previous use of this legacy pattern was also relying on Terraform 398 writing the `.terraform` subdirectory into the current working directory even 399 though the root module directory was overridden, use 400 [the `TF_DATA_DIR` environment variable](/cli/config/environment-variables#tf_data_dir) 401 to direct Terraform to write the `.terraform` directory to a location other 402 than the current working directory.