How to keep resource address after using count condition

Hi support,
We already have resources created for all of dev, qa, and prod environments. Now we want to destroy dev and qa instances, but keep prod ones. So, I added condition
count = contains(["dev", "qa"], var.environment) ? 0 : 1

module "elastic_deployment_monitoring_legacy" {
  count                  = contains(["dev", "qa"], var.environment) ? 0 : 1
  source                 = "../elastic-ec-deployment"
  name_override          = "${local.longname}-es-legacy-monitoring"
  deployment_template_id = "azure-storage-optimized"
....

OK, the dev and qa instances will be destroyed. but it will create a new prod instance. I looked at the terraform output. seems the address will be changed. the new resource address becomes xxxxx_legacy[0]. The old address is xxxxx_legacy.

How can I avoid creating new resource and still keep the existing one?

# module.stack.module.elastic_deployment_monitoring_legacy.ec_deployment.this will be destroyed
  # (because module.stack.module.elastic_ec_deployment_monitoring_legacy is not in configuration)
  - resource "ec_deployment" "this" {
      - alias                      = "prod-es-legacy-monitoring" -> null
      - deployment_template_id     = "azure-storage-optimized" -> null
      - elasticsearch              = {
          - autoscale      = true -> null
          - cloud_id       = "prod-es-legacy-monitoring:ZWFzdHVzLmF6dXJlLmVsYXN0aWMtY2xvdWQuY29tOjQ0MyRlMTczMzY5MDM4ZWM0ZGJiOTI1YmE2NzE1MGFhZWI2MCQ3MGMzNDZkOThkMWI0ZjRhOTYwMWY3Y2Y4MjA1YzRmNg==" -> null
          - cold           = {
              - autoscaling                           = {
                  - max_size          = "60g" -> null
                  - max_size_resource = "memory" -> null
                } -> null
              - instance_configuration_id             = "azure.es.datacold.edsv4" -> null
              - instance_configuration_version        = 1 -> null
              - latest_instance_configuration_id      = "azure.es.datacold.edsv4" -> null
              - latest_instance_configuration_version = 1 -> null
              - node_roles                            = [
                  - "data_cold",
                  - "remote_cluster_client",
                ] -> null
              - size                                  = "0g" -> null
              - size_resource                         = "memory" -> null
              - zone_count                            = 3 -> null
            } -> null
          - config         = {
              - plugins = [] -> null
            } -> null
          - coordinating   = {
              - autoscaling                           = {} -> null
              - instance_configuration_id             = "azure.es.coordinating.fsv2" -> null
              - instance_configuration_version        = 2 -> null
              - latest_instance_configuration_id      = "azure.es.coordinating.fsv2" -> null
              - latest_instance_configuration_version = 2 -> null
              - node_roles                            = [
                  - "ingest",
                  - "remote_cluster_client",
                ] -> null
              - size                                  = "0g" -> null
              - size_resource                         = "memory" -> null
              - zone_count                            = 3 -> null
            } -> null
          - frozen         = {
              - autoscaling                           = {
                  - max_size          = "120g" -> null
                  - max_size_resource = "memory" -> null
                } -> null
              - instance_configuration_id             = "azure.es.datafrozen.edsv4" -> null
              - instance_configuration_version        = 1 -> null
              - latest_instance_configuration_id      = "azure.es.datafrozen.edsv4" -> null
              - latest_instance_configuration_version = 1 -> null
              - node_roles                            = [
                  - "data_frozen",
                ] -> null
              - size                                  = "0g" -> null
              - size_resource                         = "memory" -> null
              - zone_count                            = 3 -> null
            } -> null
          - hot            = {
              - autoscaling                           = {
                  - max_size          = "120g" -> null
                  - max_size_resource = "memory" -> null
                } -> null
              - instance_configuration_id             = "azure.es.datahot.edsv4" -> null
              - instance_configuration_version        = 1 -> null
              - latest_instance_configuration_id      = "azure.es.datahot.edsv4" -> null
              - latest_instance_configuration_version = 1 -> null
              - node_roles                            = [
                  - "data_content",
                  - "data_hot",
                  - "ingest",
                  - "remote_cluster_client",
                  - "transform",
                ] -> null
              - size                                  = "8g" -> null
              - size_resource                         = "memory" -> null
              - zone_count                            = 3 -> null
            } -> null
        
          - master         = {
              - autoscaling                           = {} -> null
              - instance_configuration_id             = "azure.es.master.fsv2" -> null
              - instance_configuration_version        = 2 -> null
              - latest_instance_configuration_id      = "azure.es.master.fsv2" -> null
              - latest_instance_configuration_version = 2 -> null
              - node_roles                            = [
                  - "master",
                  - "remote_cluster_client",
                ] -> null
              - size                                  = "4g" -> null
              - size_resource                         = "memory" -> null
              - zone_count                            = 3 -> null
            } -> null
          - ml             = {
              - autoscaling                           = {
                  - max_size          = "60g" -> null
                  - max_size_resource = "memory" -> null
                  - min_size          = "0g" -> null
                  - min_size_resource = "memory" -> null
                } -> null
              - instance_configuration_id             = "azure.es.ml.fsv2" -> null
              - instance_configuration_version        = 1 -> null
              - latest_instance_configuration_id      = "azure.es.ml.fsv2" -> null
              - latest_instance_configuration_version = 1 -> null
              - node_roles                            = [
                  - "ml",
                  - "remote_cluster_client",
                ] -> null
              - size                                  = "0g" -> null
              - size_resource                         = "memory" -> null
              - zone_count                            = 3 -> null
            } -> null
          - ref_id         = "main-elasticsearch" -> null
          - region         = "azure-eastus" -> null
          - resource_id    = "xxxxxxx" -> null
          - snapshot       = {
              - enabled = true -> null
            } -> null
          - trust_account  = [
              - {
                  - account_id = "xxxxxxx" -> null
                  - trust_all  = true -> null
                },
            ] -> null
          - trust_external = [] -> null
          - warm           = {
              - autoscaling                           = {
                  - max_size          = "120g" -> null
                  - max_size_resource = "memory" -> null
                } -> null
             
              - node_roles                            = [
                  - "data_warm",
                  - "remote_cluster_client",
                ] -> null
              - size                                  = "2g" -> null
              - size_resource                         = "memory" -> null
              - zone_count                            = 3 -> null
            } -> null
        } -> null
      - elasticsearch_password     = (sensitive value) -> null
      - elasticsearch_username     = "elastic" -> null
      - id                         = "xxxxxxx" -> null
      - migrate_to_latest_hardware = true -> null
      - name                       = "prod-az-es-legacy-monitoring" -> null
      
      - request_id                 = "" -> null
     
      - traffic_filter             = [] -> null
      - version                    = "8.13.4" -> null
    }

  # module.stack.module.elastic_deployment_monitoring_legacy[0].ec_deployment.this will be created
  + resource "ec_deployment" "this" {
      + alias                      = (known after apply)
      + deployment_template_id     = "azure-storage-optimized"
      + elasticsearch              = {
          + autoscale      = true
          + cloud_id       = (known after apply)
          + cold           = {
              + autoscaling                           = {
                  + autoscale            = (known after apply)
                  + max_size             = (known after apply)
                  + max_size_resource    = (known after apply)
                  + min_size             = (known after apply)
                  + min_size_resource    = (known after apply)
                  + policy_override_json = (known after apply)
                }
              + instance_configuration_id             = (known after apply)
              + instance_configuration_version        = (known after apply)
              + latest_instance_configuration_id      = (known after apply)
              + latest_instance_configuration_version = (known after apply)
              + node_roles                            = (known after apply)
              + node_type_data                        = (known after apply)
              + node_type_ingest                      = (known after apply)
              + node_type_master                      = (known after apply)
              + node_type_ml                          = (known after apply)
              + size                                  = (known after apply)
              + size_resource                         = "memory"
              + zone_count                            = 3
            }
          + config         = {
              + plugins = []
            }
          + coordinating   = {
              + autoscaling                           = {
                  + autoscale            = (known after apply)
                  + max_size             = (known after apply)
                  + max_size_resource    = (known after apply)
                  + min_size             = (known after apply)
                  + min_size_resource    = (known after apply)
                  + policy_override_json = (known after apply)
                }
              + instance_configuration_id             = (known after apply)
              + instance_configuration_version        = (known after apply)
              + latest_instance_configuration_id      = (known after apply)
              + latest_instance_configuration_version = (known after apply)
              + node_roles                            = (known after apply)
              + node_type_data                        = (known after apply)
              + node_type_ingest                      = (known after apply)
              + node_type_master                      = (known after apply)
              + node_type_ml                          = (known after apply)
              + size                                  = "0g"
              + size_resource                         = "memory"
              + zone_count                            = 3
            }
          + frozen         = {
              + autoscaling                           = {
                  + autoscale            = (known after apply)
                  + max_size             = (known after apply)
                  + max_size_resource    = (known after apply)
                  + min_size             = (known after apply)
                  + min_size_resource    = (known after apply)
                  + policy_override_json = (known after apply)
                }
              + instance_configuration_id             = (known after apply)
              + instance_configuration_version        = (known after apply)
              + latest_instance_configuration_id      = (known after apply)
              + latest_instance_configuration_version = (known after apply)
              + node_roles                            = (known after apply)
              + node_type_data                        = (known after apply)
              + node_type_ingest                      = (known after apply)
              + node_type_master                      = (known after apply)
              + node_type_ml                          = (known after apply)
              + size                                  = "0g"
              + size_resource                         = "memory"
              + zone_count                            = 3
            }
          + hot            = {
              + autoscaling                           = {
                  + autoscale            = (known after apply)
                  + max_size             = (known after apply)
                  + max_size_resource    = (known after apply)
                  + min_size             = (known after apply)
                  + min_size_resource    = (known after apply)
                  + policy_override_json = (known after apply)
                }
              + instance_configuration_id             = (known after apply)
              + instance_configuration_version        = (known after apply)
              + latest_instance_configuration_id      = (known after apply)
              + latest_instance_configuration_version = (known after apply)
              + node_roles                            = (known after apply)
              + node_type_data                        = (known after apply)
              + node_type_ingest                      = (known after apply)
              + node_type_master                      = (known after apply)
              + node_type_ml                          = (known after apply)
              + size                                  = (known after apply)
              + size_resource                         = "memory"
              + zone_count                            = 3
            }
          + http_endpoint  = (known after apply)
          + https_endpoint = (known after apply)
          + master         = {
              + autoscaling                           = {
                  + autoscale            = (known after apply)
                  + max_size             = (known after apply)
                  + max_size_resource    = (known after apply)
                  + min_size             = (known after apply)
                  + min_size_resource    = (known after apply)
                  + policy_override_json = (known after apply)
                }
              + instance_configuration_id             = (known after apply)
              + instance_configuration_version        = (known after apply)
              + latest_instance_configuration_id      = (known after apply)
              + latest_instance_configuration_version = (known after apply)
              + node_roles                            = (known after apply)
              + node_type_data                        = (known after apply)
              + node_type_ingest                      = (known after apply)
              + node_type_master                      = (known after apply)
              + node_type_ml                          = (known after apply)
              + size                                  = (known after apply)
              + size_resource                         = "memory"
              + zone_count                            = 3
            }
          + ml             = {
              + autoscaling                           = {
                  + autoscale            = (known after apply)
                  + max_size             = (known after apply)
                  + max_size_resource    = (known after apply)
                  + min_size             = (known after apply)
                  + min_size_resource    = (known after apply)
                  + policy_override_json = (known after apply)
                }
              + instance_configuration_id             = (known after apply)
              + instance_configuration_version        = (known after apply)
              + latest_instance_configuration_id      = (known after apply)
              + latest_instance_configuration_version = (known after apply)
              + node_roles                            = (known after apply)
              + node_type_data                        = (known after apply)
              + node_type_ingest                      = (known after apply)
              + node_type_master                      = (known after apply)
              + node_type_ml                          = (known after apply)
              + size                                  = "0g"
              + size_resource                         = "memory"
              + zone_count                            = 3
            }
          + ref_id         = "main-elasticsearch"
          + region         = (known after apply)
          + resource_id    = (known after apply)
          + snapshot       = (known after apply)
          + trust_account  = (known after apply)
          + trust_external = (known after apply)
          + warm           = {
              + autoscaling                           = {
                  + autoscale            = (known after apply)
                  + max_size             = (known after apply)
                  + max_size_resource    = (known after apply)
                  + min_size             = (known after apply)
                  + min_size_resource    = (known after apply)
                  + policy_override_json = (known after apply)
                }
              + instance_configuration_id             = (known after apply)
              + instance_configuration_version        = (known after apply)
              + latest_instance_configuration_id      = (known after apply)
              + latest_instance_configuration_version = (known after apply)
              + node_roles                            = (known after apply)
              + node_type_data                        = (known after apply)
              + node_type_ingest                      = (known after apply)
              + node_type_master                      = (known after apply)
              + node_type_ml                          = (known after apply)
              + size                                  = (known after apply)
              + size_resource                         = "memory"
              + zone_count                            = 3
            }
        }
      + elasticsearch_password     = (sensitive value)
      + elasticsearch_username     = (known after apply)
      + id                         = (known after apply)
      + kibana                     = {
          + elasticsearch_cluster_ref_id          = "main-elasticsearch"
          + http_endpoint                         = (known after apply)
          + https_endpoint                        = (known after apply)
          + instance_configuration_id             = (known after apply)
          + instance_configuration_version        = (known after apply)
          + latest_instance_configuration_id      = (known after apply)
          + latest_instance_configuration_version = (known after apply)
          + ref_id                                = "main-kibana"
          + region                                = (known after apply)
          + resource_id                           = (known after apply)
          + size                                  = "1g"
          + size_resource                         = "memory"
          + zone_count                            = 3
        }
      + migrate_to_latest_hardware = true
      + name                       = "prod-az-es-legacy-monitoring"
      + region                     = "azure-eastus"
      + request_id                 = (known after apply)
    
      + traffic_filter             = []
      + version                    = "8.13.4"
    }

Hi @wshao12,

You can use a moved block to tell Terraform that your intention is to change the address of an existing module instance rather than to declare a different module instance:

moved {
  from = module.elastic_deployment_monitoring_legacy
  to   = module.elastic_deployment_monitoring_legacy[0]
}

You should place this block in the same module that contains your module "elastic_deployment_monitoring_legacy" block, because Terraform resolves the from and to addresses relative to the module where the moved block is declared.

This should then cause Terraform to report that the resource instance address has changed, rather than proposing to delete the old address and create the new address.

2 Likes

Hi @wshao12,

Firstly, and based upon your question, what I understand is:
You need to add a count based on an expression make deploying these specific resources optional. If the environment is set to dev or qa you don’t want this resource. The current deployable module does not have such a way of not deploying these resources but all the environments have already been deployed (and you don’t want to destroy and re-create).

What you need to do is ‘move’ the cloud resource’s state from the current terraform resource address module.elastic_deployment_monitoring_legacy to a new address, which includes an index module.elastic_deployment_monitoring_legacy[0]

Terraform provides the moved block which will allow you to tell terraform that you want to retain the current resource’s state but move it to the new terraform resource address.

There is also a detailed tutorial here which, while not exactly your requirement does provide a walk through of how the code would be refactored and the resource state moved.

In short, after updating your code as you detail, you would add a block similar to the below, prior to running a plan to verify it will move as expected. When you are confident that the changes are as expected then you would apply. The apply would move the resources address in state while retaining that that linked to the deployed resource

moved = {
    from = module.elastic_deployment_monitoring_legacy
    to = module.elastic_deployment_monitoring_legacy[0]
}

Feature toggles

Related to your module code and your pattern to toggle deployment:

count = contains(["dev", "qa"], var.environment) ? 0 : 1

My preference in this situation is not to hard-code the exception in the module against a variable such as var.environment. Instead consider having a ‘feature toggle’ variable which you can set in each environment’s tfvars/configuration which controls the deployment of the resource independently

In this manner you can choose for each environment/configuration if the resource should be deployed and update it via a ‘configuration change’ rather than a change to the module’s code:

variable "create_elastic_deployment_monitoring_legacy" {
  type     = bool
  default  = false
  nullable = false
}

module "elastic_deployment_monitoring_legacy" {
  count = var.create_elastic_deployment_monitoring_legacy ? 1 : 0
...
}

HTH!

Happy Terraforming

2 Likes

It seems @apparentlymart can type quicker than me :slight_smile: :smile: