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.6k stars 4.64k forks source link

azurerm_cdn_frontdoor_custom_domain import path incorrect #21950

Closed caxejc closed 1 year ago

caxejc commented 1 year ago

Is there an existing issue for this?

Community Note

Terraform Version

1.3.6

AzureRM Provider Version

3.37.0

Affected Resource(s)/Data Source(s)

azurerm_cdn_frontdoor_custom_domain

Terraform Configuration Files

resource "azurerm_resource_group" "example" {
  name     = "example-rg"
  location = "west europe"
}

resource "azurerm_storage_account" "example" {
  name                     = "example"
  resource_group_name      = azurerm_resource_group.example.name
  location                 = azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "GRS"
}

resource "azurerm_cdn_profile" "example" {
  name                = "example-profile"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  sku                 = "Standard_Verizon"
}

resource "azurerm_cdn_endpoint" "example" {
  name                = "example-endpoint"
  profile_name        = azurerm_cdn_profile.example.name
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  origin {
    name      = "example"
    host_name = azurerm_storage_account.example.primary_blob_host
  }
}

data "azurerm_dns_zone" "example" {
  name                = "example-domain.com"
  resource_group_name = "domain-rg"
}

resource "azurerm_dns_cname_record" "example" {
  name                = "example"
  zone_name           = data.azurerm_dns_zone.example.name
  resource_group_name = data.azurerm_dns_zone.example.resource_group_name
  ttl                 = 3600
  target_resource_id  = azurerm_cdn_endpoint.example.id
}

resource "azurerm_cdn_endpoint_custom_domain" "example" {
  name            = "example-domain"
  cdn_endpoint_id = azurerm_cdn_endpoint.example.id
  host_name       = "${azurerm_dns_cname_record.example.name}.${data.azurerm_dns_zone.example.name}"
}

Debug Output/Panic Output

terraform import azurerm_cdn_endpoint_custom_domain.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Cdn/profiles/profile1/endpoints/endpoint1/customDomains/domain1
╷
│ Error: Cannot import non-existent remote object
│
│ While attempting to import an existing object to "module.frontdoor.module.custom_domain_website.azurerm_cdn_frontdoor_custom_domain.this", the provider detected that no object exists with the given id. Only pre-existing objects can be imported; check that the id is correct and that it is associated     
│ with the provider's configured region or endpoint, or use "terraform apply" to create a new remote object for this resource.
╵

When trying to map to the resource id when looking at the resource in Azure portal: (/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Cdn/profiles/profile1/endpoints/endpoint1/domains/domain1)

terraform import azurerm_cdn_endpoint_custom_domain.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Cdn/profiles/profile1/endpoints/endpoint1/domains/domain1  
╷
│ Error: parsing Resource ID "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Cdn/profiles/profile1/endpoints/endpoint1/domains/domain1": ID was missing the `customDomains` element

Expected Behaviour

Successful importing of Azure cdn custom domain into the state file.

Actual Behaviour

TF unable to find the object/resource.

Steps to Reproduce

  1. create domain in new version of Azure CDN_Frontdoor.
  2. terraform import

Important Factoids

No response

References

When looking at the actual blade for cdn domains it's called "domains" not "customDomains".

When trying to navigate to anything labeled "customDomains" on the Azure portal, Azure can't find it.

caxejc commented 1 year ago

I substituted generic commands for my subscription specific commands for privacy reasons.

WodansSon commented 1 year ago

@caxejc, based on the attached configuration file it appears that you may be using the incorrect resources for a CDN Frontdoor resource, can you please try using the below? For more information on the CDN Frontdoor resource please see the documentation 🚀

resource "azurerm_cdn_frontdoor_profile" "example" {
  ...
}

resource "azurerm_cdn_frontdoor_endpoint" "example" {
  ...
}

resource "azurerm_cdn_frontdoor_custom_domain" "example" {
  ...
}

Instead of:

resource "azurerm_cdn_profile" "example" {
  ...
}

resource "azurerm_cdn_endpoint" "example" {
  ...
}

resource "azurerm_cdn_endpoint_custom_domain" "example" {
  ...
}
caxejc commented 1 year ago

Apologies, when trying to get the generic code I pulled from the wrong location.

Here's the actual code removing anything identifying:

module "cdn_frontdoor_profile" {
  source = "../cdn_frontdoor_profile"

  name = "name"
  resource_group = module.demo_network_rg.name
  sku_name = "Premium_AzureFrontDoor"
}

module "cdn_frontdoor_endpoint_website" {
  source = "../cdn_frontdoor_endpoint"

  name = "name"
  cdn_frontdoor_profile_id = module.cdn_frontdoor_profile.id
}

module "custom_domain_website" {
  source = "../cdn_frontdoor_custom_domain"

  name = "name"
  cdn_frontdoor_profile_id = module.cdn_frontdoor_profile.id
  host_name = "host_name"
}

It Terraform Inits and Plans just fine (identifying stuff removed again):

  # module.frontdoor.module.custom_domain_website.azurerm_cdn_frontdoor_custom_domain.this will be created
  + resource "azurerm_cdn_frontdoor_custom_domain" "this" {
      + cdn_frontdoor_profile_id = "cdn_frontdoor_profile_id"
      + dns_zone_id              = "dns_zone_id"
      + expiration_date          = (known after apply)
      + host_name                = "host_name.com"
      + id                       = (known after apply)
      + name                     = "name"
      + validation_token         = (known after apply)

      + tls {
          + cdn_frontdoor_secret_id = (known after apply)
          + certificate_type        = "ManagedCertificate"
          + minimum_tls_version     = "TLS12"
        }
    }

So, the config works just fine. The issue is with the Import.

terraform import module.frontdoor.module.custom_domain_website.azurerm_cdn_frontdoor_custom_domain.this /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1/providers/Microsoft.Cdn/profiles/profile1/customDomains/customDomain1
╷
│ Error: Cannot import non-existent remote object
│
│ While attempting to import an existing object to "module.frontdoor.module.custom_domain_website.azurerm_cdn_frontdoor_custom_domain.this", the provider detected that no object exists with the given id. Only pre-existing objects can be imported; check that    
│ the id is correct and that it is associated with the provider's configured region or endpoint, or use "terraform apply" to create a new remote object for this resource.

So when I look in the actual Azure Blade for the new CDN Frontdoor domains it's not "customDomains" it's "domains"

image

When trying to import using "domains" instead of "customDomains" this happens:

terraform import module.frontdoor.module.custom_domain_website.azurerm_cdn_frontdoor_custom_domain.this /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1/providers/Microsoft.Cdn/profiles/profile1/domains/customDomain1
╷
│ Error: parsing Resource ID "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1/providers/Microsoft.Cdn/profiles/profile1/domains/customDomain1": ID was missing the `customDomains` element
WodansSon commented 1 year ago

@caxejc, thank you for your reply. I will have to reach out to the service team to see if they have changed there resource ID schema. This also maybe an issue with the Azure Portal and Terraform using different version of the API, where in the newer version the service team has changed the customDomains element to just domains.

caxejc commented 1 year ago

Perfect thank you.


From: Wodans Son @.> Sent: Wednesday, June 7, 2023 4:31:55 PM To: hashicorp/terraform-provider-azurerm @.> Cc: Jonathan Close @.>; Mention @.> Subject: Re: [hashicorp/terraform-provider-azurerm] azurerm_cdn_frontdoor_custom_domain import path incorrect (Issue #21950)

You don't often get email from @.*** Learn why this is importanthttps://aka.ms/LearnAboutSenderIdentification This message originated outside of CorpAxe. Use caution with links and attachments.

@caxejchttps://github.com/caxejc, thank you for your reply. I will have to reach out to the service team to see if they have changed there resource ID schema. This also maybe an issue with the Azure Portal and Terraform using different version of the API, where in the newer version the service team has changed the customDomains element to just domains.

— Reply to this email directly, view it on GitHubhttps://github.com/hashicorp/terraform-provider-azurerm/issues/21950#issuecomment-1581539310, or unsubscribehttps://github.com/notifications/unsubscribe-auth/BAD4P777MH36AXTMMXBYRVDXKDXMXANCNFSM6AAAAAAYQQEVWU. You are receiving this because you were mentioned.Message ID: @.***>

WodansSon commented 1 year ago

@caxejc, I have spoken with the service team and they have stated that they did not change the elements in the Resource ID (e.g., .../profiles/profile1/customDomains/customDomain1 is correct). I also cannot repro the issue locally:

terraform import azurerm_cdn_frontdoor_custom_domain.contoso /subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Cdn/profiles/repro-profile/customDomains/contoso-custom-domain
azurerm_cdn_frontdoor_custom_domain.contoso: Importing from ID "/subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Cdn/profiles/repro-profile/customDomains/contoso-custom-domain"...
azurerm_cdn_frontdoor_custom_domain.contoso: Import prepared!
  Prepared azurerm_cdn_frontdoor_custom_domain for import
azurerm_cdn_frontdoor_custom_domain.contoso: Refreshing state... [id=/subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Cdn/profiles/repro-profile/customDomains/contoso-custom-domain]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

How did you create the custom domain that you want to import into the state file which is showing the /domains/ element instead of the /customDomains/ element?

caxejc commented 1 year ago

I manually created the domain in the DNS zone associated our domain. Then manually added the domain in the Front Door and CDN profile - domain blade.

When manually adding, it allowed me to select the DNS zone and custom domain that I had manually created.

caxejc commented 1 year ago

So I used powershell to see if I was doing something wrong with the ID. Using the Get-AzFrontDoorCdnCustomDomain cmdlet I received this for the ID:

image

I plugged that into the import command and received this error again:

Error: parsing Resource ID "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1/providers/Microsoft.Cdn/profiles/profile1/customdomains/customDomain1": ID was missing the `customDomains` element

I then capitalized the "D" in customDomains and tried again, then got this again:

│ Error: Cannot import non-existent remote object
│
│ While attempting to import an existing object to "module.frontdoor.module.custom_domain_website.azurerm_cdn_frontdoor_custom_domain.this", the provider detected that no object exists with the given id. Only pre-existing objects can be imported; check that the id is  
│ correct and that it is associated with the provider's configured region or endpoint, or use "terraform apply" to create a new remote object for this resource.

It exists, using powershell I can see that the ID matches what's expected for the import other than the capitalized "D" in "customDomains". The cdn frontdoor profile was created via Terraform in the same config file. So it's not an access or location issue.

WodansSon commented 1 year ago

@rcskosir this is a well known issue with the portal, and other tool sets. I think the easiest way to fix this is if I write an import stub for the Custom Domain resource so it treats the resource ID as case insensitive.

WodansSon commented 1 year ago

@rcskosir, with my referenced PR you may now import custom domains no matter the casing of the resource ID.

terraform import azurerm_cdn_frontdoor_custom_domain.contoso /subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Cdn/profiles/repro-profile/customdomains/contoso-wodans-son-com

azurerm_cdn_frontdoor_custom_domain.contoso: Importing from ID "/subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Cdn/profiles/repro-profile/customdomains/contoso-wodans-son-com"...
azurerm_cdn_frontdoor_custom_domain.contoso: Import prepared!
  Prepared azurerm_cdn_frontdoor_custom_domain for import
azurerm_cdn_frontdoor_custom_domain.contoso: Refreshing state... [id=/subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Cdn/profiles/repro-profile/customDomains/contoso-wodans-son-com]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

Notice that casing of the resource ID on import (e.g. /customdomains/) and when Terraform writes it to the state file (e.g. /customDomains/).

tombuildsstuff commented 1 year ago

hey @caxejc

As you've mentioned, the Resource ID casing that Terraform's expecting and that being returned by the Azure API differ here, notably the casing on the customdomains segment needs to be updated to customDomains.

Whilst newer versions of the Resource ID Parsers output more information as to the value for each segment that we're expecting (see here for an example) - unfortunately the older Resource ID parsers used by this Resource don't, which is why you're seeing this error message at this time.

The Resource IDs used by Terraform do not necessarily map 1:1 with the Resource IDs defined within the Azure API - indeed, there's many cases where these don't, as such the documentation for each Resource defines the Resource ID used at Import time in the import section of the documentation, which in this case can be found here.

Since each Provider instance is related to a Subscription, my guess here would be that the Subscription being used in Terraform (that is, defined in the Provider block or sourced from the Azure CLI) differs from the one defined in the Resource ID string - as such it'd be worth confirming both the Subscription ID and the Resource ID being used to ensure these match - would you be able to confirm those values match?

Thanks!

WodansSon commented 1 year ago

@caxejc @tombuildsstuff

I backed out all of my changes to make the import case-insensitive and tested this scenario locally with the following configuration file:

provider "azurerm" {
  features {}
}

locals {
  loc = "westeurope"
}

resource "azurerm_resource_group" "test" {
  name     = "repro-afdx-21950"
  location = local.loc
} 

resource "azurerm_dns_zone" "test" {
  name                = "{hostName}.com"
  resource_group_name = azurerm_resource_group.test.name
}

resource "azurerm_cdn_frontdoor_profile" "test" {
  name                = "repro-profile"
  resource_group_name = azurerm_resource_group.test.name
  sku_name            = "Premium_AzureFrontDoor"

  response_timeout_seconds = 120
}

resource "azurerm_cdn_frontdoor_endpoint" "contoso" {
  name                     = "repro-endpoint-contosos"
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.test.id
  enabled                  = true
}

resource "azurerm_dns_cname_record" "test" {
  name                = "contoso"
  zone_name           = azurerm_dns_zone.test.name
  resource_group_name = azurerm_resource_group.test.name
  ttl                 = 3600
  record              = azurerm_cdn_frontdoor_endpoint.contoso.host_name
}

Once the above configuration was applied I then used the Azure Portal to create my DNS auth txt record and my Front Door Custom Domain. I then validated the casing of the resource ID coming from Azure for the Custom Domain I created in the portal.

Azure Payload from GET call:

{"id":"/subscriptions/{subscription}/resourcegroups/repro-afdx-21950/providers/Microsoft.Cdn/profiles/repro-profile/customdomains/contoso-{hostName}-com","type":"Microsoft.Cdn/profiles/customdomains","name":"contoso-{hostName}-com","properties":{"hostName":"contoso.{hostName}.com","tlsSettings":{"certificateType":"ManagedCertificate","minimumTlsVersion":"TLS12","secret":{"id":"/subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Cdn/Profiles/repro-profile/secrets/28679753-ef1c-4598-a73c-d9cbfa7e0cf8-contoso-{hostName}-com"}},"validationProperties":{"validationToken":"lt8mrsf0znj7rvh3q6lm8nx54480kvp1","expirationDate":"2023-07-03T22:38:04.2850497+00:00"},"azureDnsZone":{"id":"/subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Network/dnszones/{hostName}.com"},"domainValidationState":"Approved","preValidatedCustomDomainResourceId":null,"provisioningState":"Succeeded","deploymentStatus":"Succeeded"}}

NOTE: The /customdomains/ segment casing here coming from Azure.

Once the above manual steps were completed and I validated the Custom Domain's resource ID casing in Azure I updated my configuration file to include the stub for the Custom Domain for import:

provider "azurerm" {
  features {}
}

locals {
  loc = "westeurope"
}

resource "azurerm_resource_group" "test" {
  name     = "repro-afdx-21950"
  location = local.loc
} 

resource "azurerm_dns_zone" "test" {
  name                = "{hostName}.com"
  resource_group_name = azurerm_resource_group.test.name
}

resource "azurerm_cdn_frontdoor_profile" "test" {
  name                = "repro-profile"
  resource_group_name = azurerm_resource_group.test.name
  sku_name            = "Premium_AzureFrontDoor"

  response_timeout_seconds = 120
}

resource "azurerm_cdn_frontdoor_endpoint" "contoso" {
  name                     = "repro-endpoint-contosos"
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.test.id
  enabled                  = true
}

resource "azurerm_cdn_frontdoor_custom_domain" "contoso" {
}

resource "azurerm_dns_cname_record" "test" {
  name                = "contoso"
  zone_name           = azurerm_dns_zone.test.name
  resource_group_name = azurerm_resource_group.test.name
  ttl                 = 3600
  record              = azurerm_cdn_frontdoor_endpoint.contoso.host_name
}

I then ran the following import command:

Terraform Command:

terraform import azurerm_cdn_frontdoor_custom_domain.contoso /subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Cdn/profiles/repro-profile/customDomains/contoso-wodans-son-com

NOTE: The /customDomains/ segment casing here. The casing does not match what is in Azure since Azure is case-insensitive, but it is in the casing that Terraform expects it to be in.

The Result of the Terraform Import Command:

azurerm_cdn_frontdoor_custom_domain.contoso: Import prepared!
  Prepared azurerm_cdn_frontdoor_custom_domain for import
azurerm_cdn_frontdoor_custom_domain.contoso: Refreshing state... [id=/subscriptions/{subscription}/resourceGroups/repro-afdx-21950/providers/Microsoft.Cdn/profiles/repro-profile/customDomains/contoso-{hostName}-com]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

So, from this test, it appears that the issue is not that the import path is incorrect in the Custom Domain resource, as @tombuildsstuff has stated above, but that something else seems to be afoot here.

caxejc commented 1 year ago

Thank you for all your help. I figured out the issue and it was my fault.

My az account set was on the wrong subscription. It had been a month or so since the last time I imported and when I went to check what subscription I was hooked to I mistakenly used the powershell cmdlet "get-azcontext", which showed the subscription that I expected.

What I should have done, and did to fix the issue, was use az account show. That showed me as being connected to the wrong sub. I then az account set to the correct sub and it worked first time.

Appreciate the work and patience guys, sorry for the run around.

You can mark this as closed, thank you.

github-actions[bot] commented 5 months ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.