Decided to test out the new state block which looks to be released in v1.7.
Stemmed from this request in the hashi forums.
https://discuss.hashicorp.com/t/request-for-testing-removed-block/60511
For now, you can find some documentation and usage here:
https://github.com/hashicorp/terraform/pull/34339/commits/9af31fb5ce8fe983fc212390659215cf6501c85d
At this point it looks like a holy trinity of state blocks will be finished - import, moved, and now removed.
I conducted a simple test, and similar to import and move, additional feature support has been added.
Also looks like there will be an additional lifecycle argument which support this -- in this case it was destroy = false. This argument is required per docs.
The
lifecycle
block is required. Thedestroy
argument determines whether Terraform will attempt to destroy the objects managed by the module or not. A value offalse
means that Terraform will remove the resources from state without destroying them.
Creating then removing local_file from state
Created a simple module which only creates one local file resource.
For this release, I downloaded the latest beta version.
https://releases.hashicorp.com/terraform/1.7.0-beta1/
My initial setup:
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "2.4.0"
}
}
}
resource "local_file" "file" {
filename = "${path.module}/destination"
source = "${path.module}/source"
}
Ran an init + apply:
local_file.file: Refreshing state... [id=5291767cb169477c0a03c53439ec85c8dc3aaf46]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# local_file.file will be created
+ resource "local_file" "file" {
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./destination"
+ id = (known after apply)
+ source = "./source"
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
local_file.file: Creating...
local_file.file: Creation complete after 0s [id=5291767cb169477c0a03c53439ec85c8dc3aaf46]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Updated the file to remove the local_file resource and added removed block. I'm guessing lifecycle + destroy is a new argument.
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "2.4.0"
}
}
}
# resource "local_file" "file" {
# filename = "${path.module}/destination"
# source = "${path.module}/source"
# }
removed {
from = local_file.file
lifecycle {
destroy = false
}
}
Ran an apply and received the expected feedback.
local_file.file: Refreshing state... [id=5291767cb169477c0a03c53439ec85c8dc3aaf46]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
Terraform will perform the following actions:
# local_file.file will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "local_file" "file" {
- content_base64sha256 = "N+FgMd5soTK/NPAhWpf9OwVevfnr6DOVhD8CTislQ5s=" -> null
- content_base64sha512 = "/uaHo4s7YXkWFCLPOobf2izKhUbZtBKmlE3fnEfjM5kFzN4MAC4e8IK+Yl6QlbuqBPnpiI36dGCgtCX/7lVBCw==" -> null
- content_md5 = "f352cac61c815fe9d44770e65345367d" -> null
- content_sha1 = "5291767cb169477c0a03c53439ec85c8dc3aaf46" -> null
- content_sha256 = "37e16031de6ca132bf34f0215a97fd3b055ebdf9ebe83395843f024e2b25439b" -> null
- content_sha512 = "fee687a38b3b6179161422cf3a86dfda2cca8546d9b412a6944ddf9c47e3339905ccde0c002e1ef082be625e9095bbaa04f9e9888dfa7460a0b425ffee55410b" -> null
- directory_permission = "0777" -> null
- file_permission = "0777" -> null
- filename = "./destination" -> null
- id = "5291767cb169477c0a03c53439ec85c8dc3aaf46" -> null
- source = "./source" -> null
}
Plan: 0 to add, 0 to change, 0 to destroy.
╷
│ Warning: Some objects will no longer be managed by Terraform
│
│ If you apply this plan, Terraform will discard its tracking information for the following objects, but it will not delete them:
│ - local_file.file
│
│ After applying this plan, Terraform will no longer manage these objects. You will need to import them into Terraform to manage them again.
╵
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Let us try something a bit different.
In this case, I will be creating an ECR resource via the AWS provider, then deleting that resource from state and importing the resource to the AWS Cloud Control provider.
Why? Cause my friend @drewmullen wanted me to try this.
Set up my configuration. Commented out the AWSCC resource for now.
terraform {
required_providers {
awscc = {
source = "hashicorp/awscc"
version = "0.66.0"
}
aws = {
source = "hashicorp/aws"
version = "5.29.0"
}
}
}
resource "aws_ecr_repository" "this" {
name = "delete-test"
image_tag_mutability = "MUTABLE"
image_scanning_configuration {
scan_on_push = true
}
}
# resource "awscc_ecr_repository" "this" {
# repository_name = "delete-test"
# image_tag_mutability = "MUTABLE"
# image_scanning_configuration = {
# scan_on_push = true
# }
# }
Ran an apply.
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_ecr_repository.this will be created
+ resource "aws_ecr_repository" "this" {
+ arn = (known after apply)
+ id = (known after apply)
+ image_tag_mutability = "MUTABLE"
+ name = "delete-test"
+ registry_id = (known after apply)
+ repository_url = (known after apply)
+ tags_all = (known after apply)
+ image_scanning_configuration {
+ scan_on_push = true
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_ecr_repository.this: Creating...
aws_ecr_repository.this: Creation complete after 1s [id=delete-test]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Ok, resource is now created. For the next step, I will add a removed block and add an import block. I will also comment out (remove) the previous AWS ECR resource from code.
terraform {
required_providers {
awscc = {
source = "hashicorp/awscc"
version = "0.66.0"
}
aws = {
source = "hashicorp/aws"
version = "5.29.0"
}
}
}
# resource "aws_ecr_repository" "this" {
# name = "delete-test"
# image_tag_mutability = "MUTABLE"
# image_scanning_configuration {
# scan_on_push = true
# }
# }
removed {
from = aws_ecr_repository.this
lifecycle {
destroy = false
}
}
import {
id = "delete-test"
to = awscc_ecr_repository.this
}
resource "awscc_ecr_repository" "this" {
repository_name = "delete-test"
image_tag_mutability = "MUTABLE"
image_scanning_configuration = {
scan_on_push = true
}
}
After updating, received the following results:
awscc_ecr_repository.this: Preparing import... [id=delete-test]
aws_ecr_repository.this: Refreshing state... [id=delete-test]
awscc_ecr_repository.this: Refreshing state... [id=delete-test]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# aws_ecr_repository.this will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "aws_ecr_repository" "this" {
- arn = "arn:aws:ecr:us-east-1:634211456147:repository/delete-test" -> null
- id = "delete-test" -> null
- image_tag_mutability = "MUTABLE" -> null
- name = "delete-test" -> null
- registry_id = "634211456147" -> null
- repository_url = "634211456147.dkr.ecr.us-east-1.amazonaws.com/delete-test" -> null
- tags = {} -> null
- tags_all = {} -> null
- encryption_configuration {
- encryption_type = "AES256" -> null
}
- image_scanning_configuration {
- scan_on_push = true -> null
}
}
# awscc_ecr_repository.this will be updated in-place
# (imported from "delete-test")
~ resource "awscc_ecr_repository" "this" {
arn = "arn:aws:ecr:us-east-1:634211456147:repository/delete-test"
+ empty_on_delete = (known after apply)
encryption_configuration = {
encryption_type = "AES256"
}
id = "delete-test"
image_scanning_configuration = {
scan_on_push = true
}
image_tag_mutability = "MUTABLE"
+ lifecycle_policy = (known after apply)
repository_name = "delete-test"
+ repository_policy_text = (known after apply)
repository_uri = "634211456147.dkr.ecr.us-east-1.amazonaws.com/delete-test"
+ tags = (known after apply)
}
Plan: 1 to import, 0 to add, 1 to change, 0 to destroy.
╷
│ Warning: Some objects will no longer be managed by Terraform
│
│ If you apply this plan, Terraform will discard its tracking information for the following objects, but it will not delete them:
│ - aws_ecr_repository.this
│
│ After applying this plan, Terraform will no longer manage these objects. You will need to import them into Terraform to manage them again.
╵
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
awscc_ecr_repository.this: Importing... [id=delete-test]
awscc_ecr_repository.this: Import complete [id=delete-test]
Wrapping up
Nice feature that was added, especially for beginning terraformers. I've never enjoyed dealing with state, but this provides a much more controlled option.
I assume features such as for_each and other meta arguments are still not available, I haven't dug into the terraform code to confirm what is and isn't available. I think just recently import now accepts for_each and provider arguments.
Thanks to @danquack and @drewmullen for the review and ideas!