hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.52k stars 4.6k forks source link

Terraform is unable to update tags on private endpoint that is attached to redis cache with enabled geo replication. #20909

Open DzmitrySurovets opened 1 year ago

DzmitrySurovets commented 1 year ago

Is there an existing issue for this?

Community Note

Terraform Version

1.4.0

AzureRM Provider Version

3.47.0

Affected Resource(s)/Data Source(s)

azurerm_private_endpoint

Terraform Configuration Files

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "first_redis_cache_rg" {
  name     = "first_redis_cache_rg"
  location = "westeurope"
}

resource "azurerm_resource_group" "second_redis_cache_rg" {
  name     = "second_redis_cache_rg"
  location = "northeurope"
}

# NOTE: the Name used for Redis needs to be globally unique
resource "azurerm_redis_cache" "first" {
  name                = "first-redis-cache"
  location            = azurerm_resource_group.first_redis_cache_rg.location
  resource_group_name = azurerm_resource_group.first_redis_cache_rg.name
  capacity            = 1
  family              = "P"
  sku_name            = "Premium"
  enable_non_ssl_port = false
  shard_count         = 3

  redis_configuration {
    maxmemory_reserved = 2
    maxmemory_delta    = 2
    maxmemory_policy   = "allkeys-lru"
  }
}

resource "azurerm_redis_cache" "second" {
  name                = "second-redis-cache"
  location            = azurerm_resource_group.second_redis_cache_rg.location
  resource_group_name = azurerm_resource_group.second_redis_cache_rg.name
  capacity            = 1
  family              = "P"
  sku_name            = "Premium"
  enable_non_ssl_port = false
  shard_count         = 3

  redis_configuration {
    maxmemory_reserved = 2
    maxmemory_delta    = 2
    maxmemory_policy   = "allkeys-lru"
  }
}

resource "azurerm_redis_linked_server" "this" {

  target_redis_cache_name     = azurerm_redis_cache.first.name
  resource_group_name         = azurerm_resource_group.first_redis_cache_rg.name
  linked_redis_cache_id       = azurerm_redis_cache.second.id
  linked_redis_cache_location = azurerm_resource_group.second_redis_cache_rg.location
  server_role                 = "Secondary"
  depends_on = [azurerm_private_endpoint.this]
}

resource "azurerm_private_endpoint" "this" {
  name                = "first-redis-cache-private-endpoint"
  location            = azurerm_resource_group.first_redis_cache_rg.location
  resource_group_name = azurerm_resource_group.first_redis_cache_rg.name
  subnet_id           = var.private_endpoint_subnet_id

  private_service_connection {
    name                           = "first-redis-cache-private-endpoint"
    private_connection_resource_id = azurerm_redis_cache.first.id
    subresource_names              = ["redisCache"]
    is_manual_connection           = false
  }

  private_dns_zone_group {
    name                 = "privatelink.documents.azure.com"
    private_dns_zone_ids = tolist([var.private_dns_zone_id])
  }

  tags = var.tags
}

variable private_endpoint_subnet_id {
  type        = string
  default    = "/subscriptions/***/resourceGroups/***/providers/Microsoft.Network/virtualNetworks/***/subnets/***"
  description = "The ID of the Subnet from which Private IP Addresses will be allocated for this Private Endpoint."
}

variable private_dns_zone_id {
  type        = string
  default    = "/subscriptions/***/resourceGroups/***/providers/Microsoft.Network/privateDnsZones/privatelink.redis.cache.windows.net"
  description = "Id of privatelink.documents.azure.com private dns zone"
}

variable tags {
  type        = map
  default     = {
    tag1 = "value1"
    tag2 = "value3"
  }
  description = "description"
}

Debug Output/Panic Output

dsurovets@*** terraform_bug_report $ terraform apply
azurerm_resource_group.first_redis_cache_rg: Refreshing state... [id=/subscriptions/***/resourceGroups/first_redis_cache_rg]
azurerm_resource_group.second_redis_cache_rg: Refreshing state... [id=/subscriptions/***/resourceGroups/second_redis_cache_rg]
azurerm_redis_cache.second: Refreshing state... [id=/subscriptions/***/resourceGroups/second_redis_cache_rg/providers/Microsoft.Cache/redis/second-redis-cache]
azurerm_redis_cache.first: Refreshing state... [id=/subscriptions/***/resourceGroups/first_redis_cache_rg/providers/Microsoft.Cache/redis/first-redis-cache]
azurerm_private_endpoint.this: Refreshing state... [id=/subscriptions/***/resourceGroups/first_redis_cache_rg/providers/Microsoft.Network/privateEndpoints/first-redis-cache-private-endpoint]
azurerm_redis_linked_server.this: Refreshing state... [id=/subscriptions/***/resourceGroups/first_redis_cache_rg/providers/Microsoft.Cache/redis/first-redis-cache/linkedServers/second-redis-cache]

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:

  # azurerm_private_endpoint.this will be updated in-place
  ~ resource "azurerm_private_endpoint" "this" {
        id                       = "/subscriptions/***/resourceGroups/first_redis_cache_rg/providers/Microsoft.Network/privateEndpoints/first-redis-cache-private-endpoint"
        name                     = "first-redis-cache-private-endpoint"
      ~ tags                     = {
            "tag1" = "value1"
          ~ "tag2" = "value2" -> "value3"
        }
        # (6 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # azurerm_redis_cache.first will be updated in-place
  ~ resource "azurerm_redis_cache" "first" {
        id                            = "/subscriptions/***/resourceGroups/first_redis_cache_rg/providers/Microsoft.Cache/redis/first-redis-cache"
        name                          = "first-redis-cache"
      ~ public_network_access_enabled = false -> true
        tags                          = {}
        # (20 unchanged attributes hidden)

      ~ redis_configuration {
          ~ maxmemory_delta                 = 642 -> 2
          ~ maxmemory_reserved              = 642 -> 2
            # (8 unchanged attributes hidden)
        }
    }

  # azurerm_redis_cache.second will be updated in-place
  ~ resource "azurerm_redis_cache" "second" {
        id                            = "/subscriptions/***/resourceGroups/second_redis_cache_rg/providers/Microsoft.Cache/redis/second-redis-cache"
        name                          = "second-redis-cache"
        tags                          = {}
        # (21 unchanged attributes hidden)

      ~ redis_configuration {
          ~ maxmemory_delta                 = 642 -> 2
          ~ maxmemory_reserved              = 642 -> 2
            # (8 unchanged attributes hidden)
        }
    }

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

azurerm_redis_cache.first: Modifying... [id=/subscriptions/***/resourceGroups/first_redis_cache_rg/providers/Microsoft.Cache/redis/first-redis-cache]
azurerm_redis_cache.second: Modifying... [id=/subscriptions/***/resourceGroups/second_redis_cache_rg/providers/Microsoft.Cache/redis/second-redis-cache]
azurerm_redis_cache.second: Modifications complete after 4s [id=/subscriptions/***/resourceGroups/second_redis_cache_rg/providers/Microsoft.Cache/redis/second-redis-cache]
azurerm_redis_cache.first: Still modifying... [id=/subscriptions/***-...icrosoft.Cache/redis/first-redis-cache, 10s elapsed]
azurerm_redis_cache.first: Modifications complete after 19s [id=/subscriptions/***/resourceGroups/first_redis_cache_rg/providers/Microsoft.Cache/redis/first-redis-cache]
azurerm_private_endpoint.this: Modifying... [id=/subscriptions/***/resourceGroups/first_redis_cache_rg/providers/Microsoft.Network/privateEndpoints/first-redis-cache-private-endpoint]
╷
│ Error: updating Private Endpoint "first-redis-cache-private-endpoint" (Resource Group "first_redis_cache_rg"): network.PrivateEndpointsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="BadRequest" Message="Call to Microsoft.Cache/redis failed. Error message: This cache is geo replicated and cannot be the target of a private endpoint.\r\nRequestID=83e2bf92-e864-4ef3-b753-67efab282272" Details=[]
│
│   with azurerm_private_endpoint.this,
│   on main.tf line 61, in resource "azurerm_private_endpoint" "this":
│   61: resource "azurerm_private_endpoint" "this" {
│
╵

Expected Behaviour

Tags on private endpoint should be updated.

Actual Behaviour

│ Error: updating Private Endpoint "first-redis-cache-private-endpoint" (Resource Group "first_redis_cache_rg"): network.PrivateEndpointsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="BadRequest" Message="Call to Microsoft.Cache/redis failed. Error message: This cache is geo replicated and cannot be the target of a private endpoint.\r\nRequestID=83e2bf92-e864-4ef3-b753-67efab282272" Details=[] │ │ with azurerm_private_endpoint.this, │ on main.tf line 61, in resource "azurerm_private_endpoint" "this": │ 61: resource "azurerm_private_endpoint" "this" { │ ╵

Steps to Reproduce

  1. Create "privatelink.documents.azure.com" private dns zone.

  2. Specify following variables: private_dns_zone_id private_endpoint_subnet_id

  3. Run "terraform apply"

  4. Change values in tags variable

  5. Run "terraform apply"

Important Factoids

No response

References

No response

xuzhang3 commented 1 year ago

@DzmitrySurovets A linked sever was created between the two Redis instance, you need remove the linked server before update the tags.

DzmitrySurovets commented 1 year ago

@xuzhang3 Yes, that's right, but I am finding the solution how to update private endpoint tags without removing the linked server. I can update tags on private endpoint with azure cli or with ARM template, but I can't update with terraform.

jeffreyrubi commented 5 months ago

I experienced the same issue of failing to update the value of a tags in a private-endpoint through terraform.