Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing destroy of resources when refactoring Terraform to use indices

When I was just starting to use Terraform, I more or less naively declared resources individually, like this:

resource "aws_cloudwatch_log_group" "image1_log" {
  name              = "${var.image1}-log-group"
  tags              = module.tagging.tags
}

resource "aws_cloudwatch_log_group" "image2_log" {
  name              = "${var.image2}-log-group"
  tags              = module.tagging.tags
}

 resource "aws_cloudwatch_log_stream" "image1_stream" {
   name           = "${var.image1}-log-stream"
   log_group_name = aws_cloudwatch_log_group.image1_log.name
 }

 resource "aws_cloudwatch_log_stream" "image2_stream" {
   name           = "${var.image2}-log-stream"
   log_group_name = aws_cloudwatch_log_group.image2_log.name
 }

Then, 10-20 different log groups later, I realized this wasn't going to work well as infrastructure grew. I decided to define a variable list:

variable "image_names" {
  type = list(string)
  default = [
    "image1",
    "image2"
  ]
}

Then I replaced the resources using indices:

resource "aws_cloudwatch_log_group" "service-log-groups" {
  name              = "${element(var.image_names, count.index)}-log-group"
  count             = length(var.image_names)
  tags              = module.tagging.tags
}

resource "aws_cloudwatch_log_stream" "service-log-streams" {
  name              = "${element(var.image_names, count.index)}-log-stream"
  log_group_name    = aws_cloudwatch_log_group.service-log-groups[count.index].name
  count             = length(var.image_names)
}

The problem here is that when I run terraform apply, I get 4 resources to add, 4 resources to destroy. I tested this with an old log group, and saw that all my logs were wiped (obviously, since the log was destroyed).

The names and other attributes of the log groups/streams are identical- I'm simply refactoring the infrastructure code to be more maintainable. How can I maintain my existing log groups without deleting them yet still refactor my code to use lists?

like image 818
Yu Chen Avatar asked Sep 13 '25 05:09

Yu Chen


1 Answers

You'll need to move the existing resources within the Terraform state.

Try running terraform show to get the strings under which the resources are stored, this will be something like [module.xyz.]aws_cloudwatch_log_group.image1_log ...

You can move it with terraform state mv [module.xyz.]aws_cloudwatch_log_group.image1_log '[module.xyz.]aws_cloudwatch_log_group.service-log-groups[0]'. You can choose which index to assign to each resource by changing [0] accordingly.

Delete the old resource definition for each moved resource, as Terraform would otherwise try to create a new group/stream.

Try it with the first import and check with terraform plan if the resource was moved correctly...

Also check if you need to choose some index for the image_names list jsut to be sure, but I think that won't be necessary.

like image 72
rflume Avatar answered Sep 15 '25 20:09

rflume