365 lines
19 KiB
Plaintext
365 lines
19 KiB
Plaintext
---
|
|
page_title: 'Command: plan'
|
|
description: >-
|
|
The terraform plan command creates an execution plan with a preview of the
|
|
changes that Terraform will make to your infrastructure.
|
|
---
|
|
|
|
# Command: plan
|
|
|
|
The `terraform plan` command creates an execution plan, which lets you preview
|
|
the changes that Terraform plans to make to your infrastructure. By default,
|
|
when Terraform creates a plan it:
|
|
|
|
* Reads the current state of any already-existing remote objects to make sure
|
|
that the Terraform state is up-to-date.
|
|
* Compares the current configuration to the prior state and noting any
|
|
differences.
|
|
* Proposes a set of change actions that should, if applied, make the remote
|
|
objects match the configuration.
|
|
|
|
> **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.
|
|
|
|
The plan command alone will not actually carry out the proposed changes, and
|
|
so you can use this command to check whether the proposed changes match what
|
|
you expected before you apply the changes or share your changes with your
|
|
team for broader review.
|
|
|
|
If Terraform detects that no changes are needed to resource instances or to
|
|
root module output values, `terraform plan` will report that no actions need
|
|
to be taken.
|
|
|
|
If you are using Terraform directly in an interactive terminal and you expect
|
|
to apply the changes Terraform proposes, you can alternatively run
|
|
[`terraform apply`](/cli/commands/apply) directly. By default, the "apply" command
|
|
automatically generates a new plan and prompts for you to approve it.
|
|
|
|
You can use the optional `-out=FILE` option to save the generated plan to a
|
|
file on disk, which you can later execute by passing the file to
|
|
[`terraform apply`](/cli/commands/apply) as an extra argument. This two-step workflow
|
|
is primarily intended for when
|
|
[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).
|
|
|
|
If you run `terraform plan` without the `-out=FILE` option then it will create
|
|
a _speculative plan_, which is a description of the effect of the plan but
|
|
without any intent to actually apply it.
|
|
|
|
In teams that use a version control and code review workflow for making changes
|
|
to real infrastructure, developers can use speculative plans to verify the
|
|
effect of their changes before submitting them for code review. However, it's
|
|
important to consider that other changes made to the target system in the
|
|
meantime might cause the final effect of a configuration change to be different
|
|
than what an earlier speculative plan indicated, so you should always re-check
|
|
the final non-speculative plan before applying to make sure that it still
|
|
matches your intent.
|
|
|
|
## Usage
|
|
|
|
Usage: `terraform plan [options]`
|
|
|
|
The `plan` subcommand looks in the current working directory for the root module
|
|
configuration.
|
|
|
|
Because the plan command is one of the main commands of Terraform, it has
|
|
a variety of different options, described in the following sections. However,
|
|
most of the time you should not need to set any of these options, because
|
|
a Terraform configuration should typically be designed to work with no special
|
|
additional options for routine work.
|
|
|
|
The remaining sections on this page describe the various options:
|
|
|
|
* **[Planning Modes](#planning-modes)**: There are some special alternative
|
|
planning modes that you can use for some special situations where your goal
|
|
is not just to change the remote system to match your configuration.
|
|
* **[Planning Options](#planning-options)**: Alongside the special planning
|
|
modes, there are also some options you can set in order to customize the
|
|
planning process for unusual needs.
|
|
* **[Resource Targeting](#resource-targeting)** is one particular
|
|
special planning option that has some important caveats associated
|
|
with it.
|
|
* **[Other Options](#other-options)**: These change the behavior of the planning
|
|
command itself, rather than customizing the content of the generated plan.
|
|
|
|
## Planning Modes
|
|
|
|
The previous section describes Terraform's default planning behavior, which
|
|
changes the remote system to match the changes you make to
|
|
your configuration. Terraform has two alternative planning modes, each of which creates a plan with a different intended outcome. These options are available for both `terraform plan` and [`terraform apply`](/cli/commands/apply).
|
|
|
|
* **Destroy mode:** creates a plan whose goal is to destroy all remote objects
|
|
that currently exist, leaving an empty Terraform state. This can be useful
|
|
for situations like transient development environments, where the managed
|
|
objects cease to be useful once the development task is complete.
|
|
|
|
Activate destroy mode using the `-destroy` command line option.
|
|
|
|
* **Refresh-only mode:** creates a plan whose goal is only to update the
|
|
Terraform state and any root module output values to match changes made to
|
|
remote objects outside of Terraform. This can be useful if you've
|
|
intentionally changed one or more remote objects outside of the usual
|
|
workflow (e.g. while responding to an incident) and you now need to reconcile
|
|
Terraform's records with those changes.
|
|
|
|
Activate refresh-only mode using the `-refresh-only` command line option.
|
|
|
|
In situations where we need to discuss the default planning mode that Terraform
|
|
uses when none of the alternative modes are selected, we refer to it as
|
|
"Normal mode". Because these alternative modes are for specialized situations
|
|
only, some other Terraform documentation only discusses the normal planning
|
|
mode.
|
|
|
|
The planning modes are all mutually-exclusive, so activating any non-default
|
|
planning mode disables the "normal" planning mode, and you can't use more than
|
|
one alternative mode at the same time.
|
|
|
|
-> **Note:** In Terraform v0.15 and earlier, the `-destroy` option is
|
|
supported only by the `terraform plan` command, and not by the
|
|
`terraform apply` command. To create and apply a plan in destroy mode in
|
|
earlier versions you must run [`terraform destroy`](/cli/commands/destroy).
|
|
|
|
-> **Note:** The `-refresh-only` option is available only in Terraform v0.15.4
|
|
and later.
|
|
|
|
> **Hands-on:** Try the [Use Refresh-Only Mode to Sync Terraform State](https://learn.hashicorp.com/tutorials/terraform/refresh) tutorial on HashiCorp Learn.
|
|
|
|
## Planning Options
|
|
|
|
In addition to alternate [planning modes](#planning-modes), there are several options that can modify planning behavior. These options are available for both `terraform plan` and [`terraform apply`](/cli/commands/apply).
|
|
|
|
- `-refresh=false` - Disables the default behavior of synchronizing the
|
|
Terraform state with remote objects before checking for configuration changes. This can make the planning operation faster by reducing the number of remote API requests. However, setting `refresh=false` causes Terraform to ignore external changes, which could result in an incomplete or incorrect plan. You cannot use `refresh=false` in refresh-only planning mode because it would effectively disable the entirety of the planning operation.
|
|
|
|
- `-replace=ADDRESS` - Instructs Terraform to plan to replace the
|
|
resource instance with the given address. This is helpful when one or more remote objects have become degraded, and you can use replacement objects with the same configuratation to align with immutable infrastructure patterns. Terraform will use a "replace" action if the specified resource would normally cause an "update" action or no action at all. Include this option multiple times to replace several objects at once. You cannot use `-replace` with the `-destroy` option, and it is only available from Terraform v0.15.2 onwards. For earlier versions, use [`terraform taint`](/cli/commands/taint) to achieve a similar result.
|
|
|
|
- `-target=ADDRESS` - Instructs Terraform to focus its planning efforts only
|
|
on resource instances which match the given address and on any objects that
|
|
those instances depend on.
|
|
|
|
-> **Note:** Use `-target=ADDRESS` in exceptional circumstances only, such as recovering from mistakes or working around Terraform limitations. Refer to [Resource Targeting](#resource-targeting) for more details.
|
|
|
|
- `-var 'NAME=VALUE'` - Sets a value for a single
|
|
[input variable](/language/values/variables) declared in the
|
|
root module of the configuration. Use this option multiple times to set
|
|
more than one variable. Refer to
|
|
[Input Variables on the Command Line](#input-variables-on-the-command-line) for more information.
|
|
|
|
- `-var-file=FILENAME` - Sets values for potentially many
|
|
[input variables](/language/values/variables) declared in the
|
|
root module of the configuration, using definitions from a
|
|
["tfvars" file](/language/values/variables#variable-definitions-tfvars-files).
|
|
Use this option multiple times to include values from more than one file.
|
|
|
|
There are several other ways to set values for input variables in the root
|
|
module, aside from the `-var` and `-var-file` options. Refer to
|
|
[Assigning Values to Root Module Variables](/language/values/variables#assigning-values-to-root-module-variables) for more information.
|
|
|
|
### Input Variables on the Command Line
|
|
|
|
You can use the `-var` command line option to specify values for
|
|
[input variables](/language/values/variables) declared in your
|
|
root module.
|
|
|
|
However, to do so will require writing a command line that is parsable both
|
|
by your chosen command line shell _and_ Terraform, which can be complicated
|
|
for expressions involving lots of quotes and escape sequences. In most cases
|
|
we recommend using the `-var-file` option instead, and write your actual values
|
|
in a separate file so that Terraform can parse them directly, rather than
|
|
interpreting the result of your shell's parsing.
|
|
|
|
To use `-var` on a Unix-style shell on a system like Linux or macOS we
|
|
recommend writing the option argument in single quotes `'` to ensure the
|
|
shell will interpret the value literally:
|
|
|
|
```
|
|
terraform plan -var 'name=value'
|
|
```
|
|
|
|
If your intended value also includes a single quote then you'll still need to
|
|
escape that for correct interpretation by your shell, which also requires
|
|
temporarily ending the quoted sequence so that the backslash escape character
|
|
will be significant:
|
|
|
|
```
|
|
terraform plan -var 'name=va'\''lue'
|
|
```
|
|
|
|
When using Terraform on Windows, we recommend using the Windows Command Prompt
|
|
(`cmd.exe`). When you pass a variable value to Terraform from the Windows
|
|
Command Prompt, use double quotes `"` around the argument:
|
|
|
|
```
|
|
terraform plan -var "name=value"
|
|
```
|
|
|
|
If your intended value includes literal double quotes then you'll need to
|
|
escape those with a backslash:
|
|
|
|
```
|
|
terraform plan -var "name=va\"lue"
|
|
```
|
|
|
|
PowerShell on Windows cannot correctly pass literal quotes to external programs,
|
|
so we do not recommend using Terraform with PowerShell when you are on Windows.
|
|
Use Windows Command Prompt instead.
|
|
|
|
The appropriate syntax for writing the variable value is different depending
|
|
on the variable's [type constraint](/language/expressions/type-constraints).
|
|
The primitive types `string`, `number`, and `bool` all expect a direct string
|
|
value with no special punctuation except that required by your shell, as
|
|
shown in the above examples. For all other type constraints, including list,
|
|
map, and set types and the special `any` keyword, you must write a valid
|
|
Terraform language expression representing the value, and write any necessary
|
|
quoting or escape characters to ensure it will pass through your shell
|
|
literally to Terraform. For example, for a `list(string)` type constraint:
|
|
|
|
```
|
|
# Unix-style shell
|
|
terraform plan -var 'name=["a", "b", "c"]'
|
|
|
|
# Windows Command Prompt (do not use PowerShell on Windows)
|
|
terraform plan -var "name=[\"a\", \"b\", \"c\"]"
|
|
```
|
|
|
|
Similar constraints apply when setting input variables using environment
|
|
variables. For more information on the various methods for setting root module
|
|
input variables, see
|
|
[Assigning Values to Root Module Variables](/language/values/variables#assigning-values-to-root-module-variables).
|
|
|
|
### Resource Targeting
|
|
|
|
> **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.
|
|
|
|
You can use the `-target` option to focus Terraform's attention on only a
|
|
subset of resources.
|
|
You can use [resource address syntax](/cli/state/resource-addressing)
|
|
to specify the constraint. Terraform interprets the resource address as follows:
|
|
|
|
* If the given address identifies one specific resource instance, Terraform
|
|
will select that instance alone. For resources with either `count` or
|
|
`for_each` set, a resource instance address must include the instance index
|
|
part, like `aws_instance.example[0]`.
|
|
|
|
* If the given address identifies a resource as a whole, Terraform will select
|
|
all of the instances of that resource. For resources with either `count`
|
|
or `for_each` set, this means selecting _all_ instance indexes currently
|
|
associated with that resource. For single-instance resources (without
|
|
either `count` or `for_each`), the resource address and the resource instance
|
|
address are identical, so this possibility does not apply.
|
|
|
|
* If the given address identifies an entire module instance, Terraform will
|
|
select all instances of all resources that belong to that module instance
|
|
and all of its child module instances.
|
|
|
|
Once Terraform has selected one or more resource instances that you've directly
|
|
targeted, it will also then extend the selection to include all other objects
|
|
that those selections depend on either directly or indirectly.
|
|
|
|
This targeting capability is provided for exceptional circumstances, such
|
|
as recovering from mistakes or working around Terraform limitations. It
|
|
is _not recommended_ to use `-target` for routine operations, since this can
|
|
lead to undetected configuration drift and confusion about how the true state
|
|
of resources relates to configuration.
|
|
|
|
Instead of using `-target` as a means to operate on isolated portions of very
|
|
large configurations, prefer instead to break large configurations into
|
|
several smaller configurations that can each be independently applied.
|
|
[Data sources](/language/data-sources) can be used to access
|
|
information about resources created in other configurations, allowing
|
|
a complex system architecture to be broken down into more manageable parts
|
|
that can be updated independently.
|
|
|
|
## Other Options
|
|
|
|
The `terraform plan` command also has some other options that are related to
|
|
the input and output of the planning command, rather than customizing what
|
|
sort of plan Terraform will create. These commands are not necessarily also
|
|
available on `terraform apply`, unless otherwise stated in the documentation
|
|
for that command.
|
|
|
|
The available options are:
|
|
|
|
* `-compact-warnings` - Shows any warning messages in a compact form which
|
|
includes only the summary messages, unless the warnings are accompanied by
|
|
at least one error and thus the warning text might be useful context for
|
|
the errors.
|
|
|
|
* `-detailed-exitcode` - Returns a detailed exit code when the command exits.
|
|
When provided, this argument changes the exit codes and their meanings to
|
|
provide more granular information about what the resulting plan contains:
|
|
* 0 = Succeeded with empty diff (no changes)
|
|
* 1 = Error
|
|
* 2 = Succeeded with non-empty diff (changes present)
|
|
|
|
* `-input=false` - Disables Terraform's default behavior of prompting for
|
|
input for root module input variables that have not otherwise been assigned
|
|
a value. This option is particularly useful when running Terraform in
|
|
non-interactive automation systems.
|
|
|
|
* `-json` - Enables the [machine readable JSON UI][machine-readable-ui] output.
|
|
This implies `-input=false`, so the configuration must have no unassigned
|
|
variable values to continue.
|
|
|
|
[machine-readable-ui]: /internals/machine-readable-ui
|
|
|
|
* `-lock=false` - Don't hold a state lock during the operation. This is
|
|
dangerous if others might concurrently run commands against the same
|
|
workspace.
|
|
|
|
* `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`,
|
|
instructs Terraform to retry acquiring a lock for a period of time before
|
|
returning an error. The duration syntax is a number followed by a time
|
|
unit letter, such as "3s" for three seconds.
|
|
|
|
* `-no-color` - Disables terminal formatting sequences in the output. Use this
|
|
if you are running Terraform in a context where its output will be
|
|
rendered by a system that cannot interpret terminal formatting.
|
|
|
|
* `-out=FILENAME` - Writes the generated plan to the given filename in an
|
|
opaque file format that you can later pass to `terraform apply` to execute
|
|
the planned changes, and to some other Terraform commands that can work with
|
|
saved plan files.
|
|
|
|
Terraform will allow any filename for the plan file, but a typical
|
|
convention is to name it `tfplan`. **Do not** name the file with a suffix
|
|
that Terraform recognizes as another file format; if you use a `.tf` suffix
|
|
then Terraform will try to interpret the file as a configuration source
|
|
file, which will then cause syntax errors for subsequent commands.
|
|
|
|
The generated file is not in any standard format intended for consumption
|
|
by other software, but the file _does_ contain your full configuration,
|
|
all of the values associated with planned changes, and all of the plan
|
|
options including the input variables. If your plan includes any sort of
|
|
sensitive data, even if obscured in Terraform's terminal output, it will
|
|
be saved in cleartext in the plan file. You should therefore treat any
|
|
saved plan files as potentially-sensitive artifacts.
|
|
|
|
* `-parallelism=n` - Limit the number of concurrent operations as Terraform
|
|
[walks the graph](/internals/graph#walking-the-graph). Defaults
|
|
to 10.
|
|
|
|
For configurations using
|
|
[the `local` backend](/language/settings/backends/local) only,
|
|
`terraform plan` accepts the legacy command line option
|
|
[`-state`](/language/settings/backends/local#command-line-arguments).
|
|
|
|
### Passing a Different Configuration Directory
|
|
|
|
Terraform v0.13 and earlier accepted an additional positional argument giving
|
|
a directory path, in which case Terraform would use that directory as the root
|
|
module instead of the current working directory.
|
|
|
|
That usage was deprecated in Terraform v0.14 and removed in Terraform v0.15.
|
|
If your workflow relies on overriding the root module directory, use
|
|
[the `-chdir` global option](/cli/commands/#switching-working-directory-with-chdir)
|
|
instead, which works across all commands and makes Terraform consistently look
|
|
in the given directory for all files it would normally read or write in the
|
|
current working directory.
|
|
|
|
If your previous use of this legacy pattern was also relying on Terraform
|
|
writing the `.terraform` subdirectory into the current working directory even
|
|
though the root module directory was overridden, use
|
|
[the `TF_DATA_DIR` environment variable](/cli/config/environment-variables#tf_data_dir)
|
|
to direct Terraform to write the `.terraform` directory to a location other
|
|
than the current working directory.
|