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!
Top comments (2)
Hi Welcome to the DEV Community!
This is such an awesome post! I have not yet used the removed block myself or had time to play with it yet, but this post has definitely given me some great insight into the workings of this newfeature.
Thank you :)
Thank you! I still have not had a chance to play with it now that it is released. It definitely adds a more controlled approach versus running the CLI.
For the section where I did a remove and an import, I believe the moved block will eventually support moving from one provider to another, not sure if this is available in 1.8 or will be a later version based on what I am reading from the release notes.