liveBook · Manning

Resource replacement

As explained in Terraform in Depth: Infrastructure as Code with Terraform and OpenTofu

Resource replacement is the lifecycle behavior in which changing a resource attribute causes the existing object to be destroyed and recreated.

Resource replacement destroys an existing Terraform object and creates a fresh one instead of updating it in place. It is useful when infrastructure has been corrupted or manually changed and needs a clean instance. section 5.3.2

Replacement can be deliberate or forced by a resource attribute. Terraform represents infrastructure as a dependency graph, so replacing one object may cascade through dependent resources; plans identify these cases with a forces replacement warning. section 5.7.2 section 12.6.1

Replacing a selected resource

Preview a targeted replacement with terraform plan -replace 'tls_private_key.child_key["charilie.example.com"]'. Review the resulting plan before applying it: one selected private key can cause three resources to be destroyed and recreated. Quote the address so the shell does not misinterpret it. section 5.3.2

Use replacement safely by:

  • Reviewing every planned replacement and investigating preserved resources that are unexpectedly recreated. section 5.7.2
  • Checking dependency scope with terraform graph when downstream effects are unclear. section 5.7.2
  • Reducing unnecessary dependency chains and considering lifecycle ignore_changes when a specific attribute should not trigger replacement. section 5.7.2
Listing 5.4 Replace plan execution
$ terraform plan -replace 'tls_private_key.child_key[
"charilie.example.com"]'                                                 #1
 
tls_private_key.child_key["example.com"]: Refreshing state...              #2
[id=938ed55a0b4b79de19515e4786ef132bb74a0d61]                            #2
tls_private_key.child_key["charilie.example.com"]: Refreshing state...     #2
[id=c3aa6b04762e95df38fe3db11a844e3c5461dfa9]                            #2
tls_private_key.ca_key: Refreshing state...                                #2
[id=044212e8419b555765ab31e0ba95a82618668b40]                            #2
tls_private_key.child_key["bravo.example.com"]: Refreshing state...        #2
[id=d0ab07eef6f7c558ac18ab7693221b9b628dc90d]                            #2
tls_self_signed_cert.ca_cert: Refreshing state...                          #2
[id=69838284311976884473259975997369053150]                              #2
tls_cert_request.child_request["charilie.example.com"]: Refreshing state...#2
[id=8e90ba484854ed7477646b4a15c3f1a56a1f66f2]                            #2
tls_cert_request.child_request["bravo.example.com"]: Refreshing state...   #2
[id=e5c98bec8c2df7f52f5d232d862b6ad16d492c96]                            #2
tls_cert_request.child_request["example.com"]: Refreshing state...         #2
[id=35c5f93644b2aa5c801319a3db024a3da11148e4]                            #2
tls_locally_signed_cert.child_certificate["bravo.example.com"]:            #2
Refreshing state... [id=294785322744421134703580347777726746148]         #2
tls_locally_signed_cert.child_certificate["example.com"]:                  #2
Refreshing state... [id=4660488490603684127476228986009749958]           #2
tls_locally_signed_cert.child_certificate["charilie.example.com"]:         #2
Refreshing state... [id=24813774051315396104451485743251799830]          #2
 
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement                                    #3
 
Terraform will perform the following actions:
 
  # tls_cert_request.child_request["charilie.example.com"] must 
be replaced                                                              #4
-/+ resource "tls_cert_request" "child_request" {                          #5
      ~ cert_request_pem = <<-EOT                                          #6
            -----BEGIN CERTIFICATE REQUEST-----
            MIHaMIGKAgEAMDMxGzAZBgNVBAoTElRlcnJhZm9ybSBpbiBEZXB0aDEUMBIGA1UE
            AxMLZXhhbXBsZS5jb20wTjAQBgcqhkjOPQIBBgUrgQQAIQM6AASXBlt4uRJnsB6G
            cmmDisA8EcP/2XWMGJqTuD4kA/tzc9fpu7xnqTJl3jYD5AgxGizFdxsFhtIslKAA
            MAoGCCqGSM49BAMCAz8AMDwCHB59NX3D7M4JTazjlpOdjbcEmidilx2/01570oYC
            HCaps8M9e/vnlWgzKdXlhYpWddyvCG7upMiLMoo=
            -----END CERTIFICATE REQUEST-----
        EOT -> (known after apply)
      ~ id               = "8e90ba484854ed7477646b4a15c3f1a56a1f66f2" -> 
(known after apply)
      ~ key_algorithm    = "ECDSA" -> (known after apply)
      ~ private_key_pem  = (sensitive value) # forces replacement
 
        # (1 unchanged block hidden)                                       #7
    }
 
  # tls_locally_signed_cert.child_certificate["charilie.example.com"] must 
be replaced
-/+ resource "tls_locally_signed_cert" "child_certificate" {
      ~ truncated attribute list
    }
 
  # tls_private_key.child_key["charilie.example.com"] will be replaced, as 
requested                                                                #8
-/+ resource "tls_private_key" "child_key" {
      ~ truncated attribute list
    }
 
Plan: 3 to add, 0 to change, 3 to destroy.                                 #9
 
────────────────────────────────────────────────────────────────────────────
 
Note: You didn't use the -out option to save this plan, so Terraform can't #10
guarantee to take exactly these actions if you run "terraform apply" now.
#1 The replace flag lets us specify a resource to destroy and re-create.
#2 Terraform is running the refresh here.
#3 For this plan, we have the re-create action.
#4 Although this isn’t the resource we specified, it has to be replaced as part of our change.
#5 The -/+ signifies that this resource is being re-created.
#6 The tilde lets us know that this value is going to change.
#7 Terraform hides anything that will remain the same. Since we aren’t changing the subject block it gets hidden.
#8 This is the resource we wanted to replace. It’s at the bottom of the plan because it’s the first action to take place.
#9 The summary includes the resources erased and the ones created.
#10 We didn’t save this to disk so Terraform is giving us this warning again.

Inspect the annotated plan listing to follow refresh operations and the consequences of targeting one TLS private key. section 5.3.2

How Terraform in Depth: Infrastructure as Code with Terraform and OpenTofu covers it

How deep it goes
Explains planned replacement, dependency cascades, lifecycle mitigation, and provider schema decisions, but not provider implementation details.
Examples
Uses corrupted databases, manually changed virtual machines, TLS keys and certificates, and ECDSA-to-ED25519 algorithm changes.
What you can do after
Diagnose replacement cascades, preview targeted recreation with terraform plan -replace, and identify attributes causing unexpected replacements.
How it connects
Connects replacement to Terraform plans, dependency graphs, lifecycle meta-parameters, ignore_changes, resource schemas, and provider resources.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Terraform in Depth: Infrastructure as Code with Terraform and OpenTofu. The section links point to the parts of the book it draws on.