TIL - Terraform refactor resources without recreation
Today I learned that since v1.1
, you can move Terraform resources into modules
without recreation using moved
block. Refactoring
doc covers such use cases as renaming resources, enabling count
or for_each
and splitting module into multiple modules.
But this doc don’t cover my use case, move one or a bunch of resources in the module. For example, you have AWS SQS resources:
resource "aws_sqs_queue" "queue" {
name = var.queue_name
content_based_deduplication = var.content_based_deduplication
deduplication_scope = var.deduplication_scope
delay_seconds = var.delay_seconds
fifo_queue = var.fifo_queue
fifo_throughput_limit = var.fifo_throughput_limit
kms_data_key_reuse_period_seconds = var.kms_data_key_reuse_period_seconds
kms_master_key_id = var.kms_master_key_id
max_message_size = var.max_message_size
message_retention_seconds = var.message_retention_seconds
policy = var.policy
receive_wait_time_seconds = var.receive_wait_time_seconds
redrive_allow_policy = var.redrive_allow_policy
redrive_policy = var.redrive_policy
visibility_timeout_seconds = var.visibility_timeout_seconds
tags = var.tags
}
And you want to refactor it into your module:
module "queue" {
source = "./modules/sqs/"
content_based_deduplication = var.content_based_deduplication
delay_seconds = var.delay_seconds
env_name = var.env_name
fifo_queue = var.fifo_queue
kms_data_key_reuse_period_seconds = var.kms_data_key_reuse_period_seconds
kms_master_key_id = var.kms_master_key_id
max_message_size = var.max_message_size
message_retention_seconds = var.message_retention_seconds
name = var.queue_name
policy = var.policy
product = var.product
queue_name = var.queue_name
receive_wait_time_seconds = var.receive_wait_time_seconds
redrive_allow_policy = var.redrive_allow_policy
redrive_policy = var.redrive_policy
tags = var.tags
visibility_timeout_seconds = var.visibility_timeout_seconds
}
By default, aws_sqs_queue.queue
will be destroyed and
module.queue.aws_sqs_queue.queue
will be created. You can override this by
using following moved
syntax:
moved {
from = aws_sqs_queue.queue
to = module.queue.aws_sqs_queue.queue
}
But if you’ll try to extract module into separate repository, you will get following error:
│ Error: Cross-package move statement
│
│ on main.tf line 41:
│ 41: moved {
│
│ This statement declares a move to an object declared in external module package "git::https://github.com/user/modules.git?ref=v0.5.5//modules/sqs".
│ Move statements can be only within a single module package.
According to this ticket
Terraform would not have allowed moving into module.x above if the source
address of that call had not been a local path
.
So here’s my action list to refactor such resources into modules:
- Move resources into the local
modules
folder - Define usage of module in the main block instead of plain resources
- Add moved block for every resource, for example:
moved { from = aws_sqs_queue.queue to = module.queue.aws_sqs_queue.queue }
- Run Terraform plan to make sure that resources aren’t recreated
- Apply Terraform plan
- Clean up moved blocks
Comments