Does terraform plan refresh the state?

39 views Asked by At

Let's say that there is a modification in the infrastructure, and you make a change to the resource file to match. When you run a terraform plan will it show that the change needs to be made or not?

I've done this test and it seems to not show a change being made, but wouldn't it need to go and grab that change from the architecture and place that change into state?

The example I'm thinking of is a modification of a tag on some AWS resource.

As a follow up question, what happens if the manual change to the AWS tag occurs after you've run plan but BEFORE you run apply?

2

There are 2 answers

2
Martin Atkins On BEST ANSWER

By default, the planning operation visits each resource instance declared in the configuration or pre-existing in the state snapshot that was current when the plan started, and:

  1. If the resource instance is still declared in the configuration, evaluates the arguments in the resource block to produce an object representing the resource instance's current configuration.
  2. Asks the provider to update Terraform's record of the object to match the current state of the real remote object as closely as possible. In the UI, Terraform calls this "refreshing", and the result is the "prior state".
  3. Asks the provider to compare the prior state with the current configuration and produce a new object that represents how the remote object would need to be changed to match the configuration. Terraform calls this "planning", and the result is the "planned new state".

If you specify the planning option -refresh=false then that effectively disables step 2: the prior state is just whatever was recorded in the state snapshot that was current at the start of the plan, regardless of what might have changed in the remote system.

If you specify the planning option -refresh-only then that effectively disables step 3: Terraform pretends that no changes are required and so applying the plan would just save the "prior state" (the result of refreshing) as the current state in the newly-created state snapshot.

Exactly what it means to "refresh" or "plan" a particular resource type is decided by the provider that resource type belongs to. For example, sometimes a remote API treats something as write-only and so the provider might respond to that by just assuming that the value from the previous state snapshot is still valid. However, in most cases a provider will detect changes made outside of Terraform and report them in step 2, causing them to be taken into account during step 3.

The other wrinkle is that Terraform will only ever refresh a resource instance that already exists in the input state snapshot. If something new was created outside of Terraform, the provider is unlikely to detect it unless it appears as a nested part of some other object that was previously created with this Terraform configuration, or explicitly imported into its state.

1
Guillermo Alvarado On

When you make a modification to your Terraform configuration files to match a change in your infrastructure, and then you run terraform plan, Terraform will analyze the current state of your infrastructure as described in the state file and compare it to the desired state defined in your Terraform configuration files. If Terraform detects any differences between the current state and the desired state, it will show those changes in the plan.

However, if the change was made manually outside of Terraform (for example, modifying a tag directly in the AWS Management Console), Terraform wouldn't be aware of this change until you update its state.

To address your follow-up question:

If a manual change is made to an AWS resource tag after you've run terraform plan but before you've run terraform apply, Terraform will still attempt to apply the changes based on the plan it generated during the last run. If the manual change conflicts with the changes Terraform planned to apply, you may encounter errors or conflicts during the terraform apply process.

To ensure that Terraform is aware of any manual changes made outside of its management, you can use the terraform import command to import the existing resource into the Terraform state. This will reconcile the manually modified resource with Terraform's state, allowing Terraform to manage it going forward.

Here's a general process you might follow:

  1. Make the manual change to the AWS resource tag.

  2. Run terraform import <resource_type>.<resource_name> <resource_id> to import the resource into the Terraform state.

  3. Run terraform plan again to see how Terraform intends to reconcile the manual change with the desired state.

  4. Finally, run terraform apply to apply the changes according to the updated plan.