Skip to content

create_before_destroy = false not working as expected when renaming TF resources #606

Open
@jakauppila

Description

@jakauppila

Describe the bug

Terraform offers a lifecycle block to customize how a resource is managed.

In attempting to leverage the create_before_destroy = false config since AVI has constraints on resource names, I've found that more often than not the provider is still running into a name conflict. I think it's simply due to timing, but it should be able to handle this appropriately.

Reproduction steps

  1. Use the following TF config:
terraform {
  required_providers {
    avi = {
      source  = "vmware/avi"
      version = "30.2.1"
    }
  }
}

provider "avi" {
}

resource "avi_pool" "pool" {
  name = "foo"

  lifecycle {
    create_before_destroy = false
  }
}
  1. Terraform apply
  2. Modify the TF to name the pool from pool to pool-80
  3. Terraform apply
  4. Error!
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create
  - destroy

Terraform will perform the following actions:

  # avi_pool.pool will be destroyed
  # (because avi_pool.pool is not in configuration)
  - resource "avi_pool" "pool" {
      - analytics_profile_ref                 = "https://AVICONTROLLER/api/analyticsprofile/analyticsprofile-73519e8a-3134-482e-8a30-6a0b826b45dc" -> null
      - append_port                           = "NON_DEFAULT_80_443" -> null
      - capacity_estimation                   = "false" -> null
      - capacity_estimation_ttfb_thresh       = "0" -> null
      - cloud_ref                             = "https://AVICONTROLLER/api/cloud/cloud-13da7a90-8288-4f4a-80d0-5974e52c174b" -> null
      - connection_ramp_duration              = "10" -> null
      - default_server_port                   = "80" -> null
      - delete_server_on_dns_refresh          = "true" -> null
      - enable_http2                          = "false" -> null
      - enabled                               = "true" -> null
      - fewest_tasks_feedback_delay           = "10" -> null
      - graceful_disable_timeout              = "1" -> null
      - graceful_hm_down_disable_timeout      = "-1" -> null
      - host_check_enabled                    = "false" -> null
      - id                                    = "https://AVICONTROLLER/api/pool/pool-2c571284-b144-43e8-b0ea-7ab36246ca0d" -> null
      - ignore_server_port                    = "false" -> null
      - ignore_servers                        = false -> null
      - inline_health_monitor                 = "true" -> null
      - lb_algo_rr_per_se                     = "false" -> null
      - lb_algorithm                          = "LB_ALGORITHM_LEAST_CONNECTIONS" -> null
      - lb_algorithm_core_nonaffinity         = "2" -> null
      - lb_algorithm_hash                     = "LB_ALGORITHM_CONSISTENT_HASH_SOURCE_IP_ADDRESS" -> null
      - lookup_server_by_name                 = "false" -> null
      - max_concurrent_connections_per_server = "0" -> null
      - name                                  = "foo" -> null
      - pool_type                             = "POOL_TYPE_GENERIC_APP" -> null
      - request_queue_depth                   = "128" -> null
      - request_queue_enabled                 = "false" -> null
      - rewrite_host_header_to_server_name    = "false" -> null
      - rewrite_host_header_to_sni            = "false" -> null
      - routing_pool                          = "false" -> null
      - server_disable_type                   = "DISALLOW_NEW_CONNECTION" -> null
      - server_timeout                        = "0" -> null
      - sni_enabled                           = "true" -> null
      - tenant_ref                            = "https://AVICONTROLLER/api/tenant/admin" -> null
      - use_service_port                      = "false" -> null
      - use_service_ssl_mode                  = "false" -> null
      - uuid                                  = "pool-2c571284-b144-43e8-b0ea-7ab36246ca0d" -> null
      - vrf_ref                               = "https://AVICONTROLLER/api/vrfcontext/vrfcontext-b58b3dee-5947-495a-8ad4-ae5b9bf2fe50" -> null

      - http2_properties {
          - max_http2_control_frames_per_connection = "0" -> null
          - max_http2_header_field_size             = "4096" -> null
        }
    }

  # avi_pool.pool-80 will be created
  + resource "avi_pool" "pool-80" {
      + analytics_profile_ref                 = (known after apply)
      + append_port                           = "NON_DEFAULT_80_443"
      + application_persistence_profile_ref   = (known after apply)
      + autoscale_launch_config_ref           = (known after apply)
      + autoscale_policy_ref                  = (known after apply)
      + capacity_estimation                   = "false"
      + capacity_estimation_ttfb_thresh       = "0"
      + cloud_config_cksum                    = (known after apply)
      + cloud_ref                             = (known after apply)
      + connection_ramp_duration              = "10"
      + created_by                            = (known after apply)
      + default_server_port                   = "80"
      + delete_server_on_dns_refresh          = "true"
      + description                           = (known after apply)
      + east_west                             = (known after apply)
      + enable_http2                          = "false"
      + enabled                               = "true"
      + fewest_tasks_feedback_delay           = "10"
      + graceful_disable_timeout              = "1"
      + graceful_hm_down_disable_timeout      = "-1"
      + gslb_sp_enabled                       = (known after apply)
      + host_check_enabled                    = "false"
      + id                                    = (known after apply)
      + ignore_server_port                    = "false"
      + ignore_servers                        = false
      + inline_health_monitor                 = "true"
      + ipaddrgroup_ref                       = (known after apply)
      + lb_algo_rr_per_se                     = "false"
      + lb_algorithm                          = "LB_ALGORITHM_LEAST_CONNECTIONS"
      + lb_algorithm_consistent_hash_hdr      = (known after apply)
      + lb_algorithm_core_nonaffinity         = "2"
      + lb_algorithm_hash                     = "LB_ALGORITHM_CONSISTENT_HASH_SOURCE_IP_ADDRESS"
      + lookup_server_by_name                 = "false"
      + max_concurrent_connections_per_server = "0"
      + min_health_monitors_up                = (known after apply)
      + min_servers_up                        = (known after apply)
      + name                                  = "foo"
      + pki_profile_ref                       = (known after apply)
      + pool_type                             = "POOL_TYPE_GENERIC_APP"
      + request_queue_depth                   = "128"
      + request_queue_enabled                 = "false"
      + resolve_pool_by_dns                   = (known after apply)
      + rewrite_host_header_to_server_name    = "false"
      + rewrite_host_header_to_sni            = "false"
      + routing_pool                          = "false"
      + server_disable_type                   = "DISALLOW_NEW_CONNECTION"
      + server_name                           = (known after apply)
      + server_timeout                        = "0"
      + service_metadata                      = (known after apply)
      + sni_enabled                           = "true"
      + ssl_key_and_certificate_ref           = (known after apply)
      + ssl_profile_ref                       = (known after apply)
      + tenant_ref                            = (known after apply)
      + tier1_lr                              = (known after apply)
      + use_service_port                      = "false"
      + use_service_ssl_mode                  = "false"
      + uuid                                  = (known after apply)
      + vrf_ref                               = (known after apply)
    }

Plan: 1 to add, 0 to change, 1 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

avi_pool.pool: Destroying... [id=https://AVICONTROLLER/api/pool/pool-2c571284-b144-43e8-b0ea-7ab36246ca0d]
avi_pool.pool-80: Creating...
avi_pool.pool: Destruction complete after 1s
╷
│ Error: Encountered an error on POST request to URL https://AVICONTROLLER/api/pool: HTTP code: 409; error from Controller: map[error:Pool with this Name, Tenant ref and Cloud ref already exists.]
│
│   with avi_pool.pool-80,
│   on main.tf line 1, in resource "avi_pool" "pool-80":
│    1: resource "avi_pool" "pool-80" {
│
╵

Expected behavior

The provider should properly handle the timing of destroying the old resource and creating the new resource.

I can occasionally get this to work.

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create
  - destroy

Terraform will perform the following actions:

  # avi_pool.pool will be destroyed
  # (because avi_pool.pool is not in configuration)
  - resource "avi_pool" "pool" {
      - analytics_profile_ref                 = "https://AVICONTROLLER/api/analyticsprofile/analyticsprofile-73519e8a-3134-482e-8a30-6a0b826b45dc" -> null
      - append_port                           = "NON_DEFAULT_80_443" -> null
      - capacity_estimation                   = "false" -> null
      - capacity_estimation_ttfb_thresh       = "0" -> null
      - cloud_ref                             = "https://AVICONTROLLER/api/cloud/cloud-13da7a90-8288-4f4a-80d0-5974e52c174b" -> null
      - connection_ramp_duration              = "10" -> null
      - default_server_port                   = "80" -> null
      - delete_server_on_dns_refresh          = "true" -> null
      - enable_http2                          = "false" -> null
      - enabled                               = "true" -> null
      - fewest_tasks_feedback_delay           = "10" -> null
      - graceful_disable_timeout              = "1" -> null
      - graceful_hm_down_disable_timeout      = "-1" -> null
      - host_check_enabled                    = "false" -> null
      - id                                    = "https://AVICONTROLLER/api/pool/pool-ee216ef8-6969-44cb-bf87-7bc33918fe6a" -> null
      - ignore_server_port                    = "false" -> null
      - ignore_servers                        = false -> null
      - inline_health_monitor                 = "true" -> null
      - lb_algo_rr_per_se                     = "false" -> null
      - lb_algorithm                          = "LB_ALGORITHM_LEAST_CONNECTIONS" -> null
      - lb_algorithm_core_nonaffinity         = "2" -> null
      - lb_algorithm_hash                     = "LB_ALGORITHM_CONSISTENT_HASH_SOURCE_IP_ADDRESS" -> null
      - lookup_server_by_name                 = "false" -> null
      - max_concurrent_connections_per_server = "0" -> null
      - name                                  = "foo" -> null
      - pool_type                             = "POOL_TYPE_GENERIC_APP" -> null
      - request_queue_depth                   = "128" -> null
      - request_queue_enabled                 = "false" -> null
      - rewrite_host_header_to_server_name    = "false" -> null
      - rewrite_host_header_to_sni            = "false" -> null
      - routing_pool                          = "false" -> null
      - server_disable_type                   = "DISALLOW_NEW_CONNECTION" -> null
      - server_timeout                        = "0" -> null
      - sni_enabled                           = "true" -> null
      - tenant_ref                            = "https://AVICONTROLLER/api/tenant/admin" -> null
      - use_service_port                      = "false" -> null
      - use_service_ssl_mode                  = "false" -> null
      - uuid                                  = "pool-ee216ef8-6969-44cb-bf87-7bc33918fe6a" -> null
      - vrf_ref                               = "https://AVICONTROLLER/api/vrfcontext/vrfcontext-b58b3dee-5947-495a-8ad4-ae5b9bf2fe50" -> null

      - http2_properties {
          - max_http2_control_frames_per_connection = "0" -> null
          - max_http2_header_field_size             = "4096" -> null
        }
    }

  # avi_pool.pool-80 will be created
  + resource "avi_pool" "pool-80" {
      + analytics_profile_ref                 = (known after apply)
      + append_port                           = "NON_DEFAULT_80_443"
      + application_persistence_profile_ref   = (known after apply)
      + autoscale_launch_config_ref           = (known after apply)
      + autoscale_policy_ref                  = (known after apply)
      + capacity_estimation                   = "false"
      + capacity_estimation_ttfb_thresh       = "0"
      + cloud_config_cksum                    = (known after apply)
      + cloud_ref                             = (known after apply)
      + connection_ramp_duration              = "10"
      + created_by                            = (known after apply)
      + default_server_port                   = "80"
      + delete_server_on_dns_refresh          = "true"
      + description                           = (known after apply)
      + east_west                             = (known after apply)
      + enable_http2                          = "false"
      + enabled                               = "true"
      + fewest_tasks_feedback_delay           = "10"
      + graceful_disable_timeout              = "1"
      + graceful_hm_down_disable_timeout      = "-1"
      + gslb_sp_enabled                       = (known after apply)
      + host_check_enabled                    = "false"
      + id                                    = (known after apply)
      + ignore_server_port                    = "false"
      + ignore_servers                        = false
      + inline_health_monitor                 = "true"
      + ipaddrgroup_ref                       = (known after apply)
      + lb_algo_rr_per_se                     = "false"
      + lb_algorithm                          = "LB_ALGORITHM_LEAST_CONNECTIONS"
      + lb_algorithm_consistent_hash_hdr      = (known after apply)
      + lb_algorithm_core_nonaffinity         = "2"
      + lb_algorithm_hash                     = "LB_ALGORITHM_CONSISTENT_HASH_SOURCE_IP_ADDRESS"
      + lookup_server_by_name                 = "false"
      + max_concurrent_connections_per_server = "0"
      + min_health_monitors_up                = (known after apply)
      + min_servers_up                        = (known after apply)
      + name                                  = "foo"
      + pki_profile_ref                       = (known after apply)
      + pool_type                             = "POOL_TYPE_GENERIC_APP"
      + request_queue_depth                   = "128"
      + request_queue_enabled                 = "false"
      + resolve_pool_by_dns                   = (known after apply)
      + rewrite_host_header_to_server_name    = "false"
      + rewrite_host_header_to_sni            = "false"
      + routing_pool                          = "false"
      + server_disable_type                   = "DISALLOW_NEW_CONNECTION"
      + server_name                           = (known after apply)
      + server_timeout                        = "0"
      + service_metadata                      = (known after apply)
      + sni_enabled                           = "true"
      + ssl_key_and_certificate_ref           = (known after apply)
      + ssl_profile_ref                       = (known after apply)
      + tenant_ref                            = (known after apply)
      + tier1_lr                              = (known after apply)
      + use_service_port                      = "false"
      + use_service_ssl_mode                  = "false"
      + uuid                                  = (known after apply)
      + vrf_ref                               = (known after apply)
    }

Plan: 1 to add, 0 to change, 1 to destroy.
avi_pool.pool: Destroying... [id=https://AVICONTROLLER/api/pool/pool-ee216ef8-6969-44cb-bf87-7bc33918fe6a]
avi_pool.pool-80: Creating...
avi_pool.pool: Destruction complete after 1s
avi_pool.pool-80: Creation complete after 2s [id=https://AVICONTROLLER/api/pool/pool-0a17b276-0d00-4300-b95e-4ce384a700ed]

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions