diff --git a/azurerm/internal/services/apimanagement/api_management_resource.go b/azurerm/internal/services/apimanagement/api_management_resource.go index 97643d4c93a9..e3305e7e53f1 100644 --- a/azurerm/internal/services/apimanagement/api_management_resource.go +++ b/azurerm/internal/services/apimanagement/api_management_resource.go @@ -10,10 +10,10 @@ import ( "github.com/Azure/azure-sdk-for-go/services/apimanagement/mgmt/2019-12-01/apimanagement" "github.com/hashicorp/go-azure-helpers/response" + "github.com/hashicorp/terraform-plugin-sdk/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" @@ -46,10 +46,10 @@ func resourceArmApiManagementService() *schema.Resource { }, Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(60 * time.Minute), + Create: schema.DefaultTimeout(3 * time.Hour), Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(60 * time.Minute), - Delete: schema.DefaultTimeout(60 * time.Minute), + Update: schema.DefaultTimeout(3 * time.Hour), + Delete: schema.DefaultTimeout(3 * time.Hour), }, Schema: map[string]*schema.Schema{ @@ -125,7 +125,6 @@ func resourceArmApiManagementService() *schema.Resource { Type: schema.TypeString, Optional: true, Default: string(apimanagement.VirtualNetworkTypeNone), - ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ string(apimanagement.VirtualNetworkTypeNone), string(apimanagement.VirtualNetworkTypeExternal), @@ -142,7 +141,6 @@ func resourceArmApiManagementService() *schema.Resource { "subnet_id": { Type: schema.TypeString, Required: true, - ForceNew: true, ValidateFunc: azure.ValidateResourceID, }, }, @@ -301,7 +299,6 @@ func resourceArmApiManagementService() *schema.Resource { "hostname_configuration": { Type: schema.TypeList, Optional: true, - Computed: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -469,6 +466,21 @@ func resourceArmApiManagementService() *schema.Resource { "tags": tags.Schema(), }, + + // we can only change `virtual_network_type` from None to Internal Or External, Else the subnet can not be destroyed cause “InUseSubnetCannotBeDeleted” for 3 hours + // we can not change the subnet from subnet1 to subnet2 either, Else the subnet1 can not be destroyed cause “InUseSubnetCannotBeDeleted” for 3 hours + // Issue: https://github.com/Azure/azure-rest-api-specs/issues/10395 + CustomizeDiff: customdiff.All( + customdiff.ForceNewIfChange("virtual_network_type", func(old, new, meta interface{}) bool { + return !(old.(string) == string(apimanagement.VirtualNetworkTypeNone) && + (new.(string) == string(apimanagement.VirtualNetworkTypeInternal) || + new.(string) == string(apimanagement.VirtualNetworkTypeExternal))) + }), + + customdiff.ForceNewIfChange("virtual_network_configuration", func(old, new, meta interface{}) bool { + return !(len(old.([]interface{})) == 0 && len(new.([]interface{})) > 0) + }), + ), } } @@ -618,6 +630,7 @@ func resourceArmApiManagementServiceCreateUpdate(d *schema.ResourceData, meta in func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).ApiManagement.ServiceClient + environment := meta.(*clients.Client).Account.Environment ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -694,7 +707,8 @@ func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("setting `protocols`: %+v", err) } - hostnameConfigs := flattenApiManagementHostnameConfigurations(props.HostnameConfigurations, d) + apimHostNameSuffix := environment.APIManagementHostNameSuffix + hostnameConfigs := flattenApiManagementHostnameConfigurations(props.HostnameConfigurations, d, name, apimHostNameSuffix) if err := d.Set("hostname_configuration", hostnameConfigs); err != nil { return fmt.Errorf("setting `hostname_configuration`: %+v", err) } @@ -864,7 +878,7 @@ func expandApiManagementCommonHostnameConfiguration(input map[string]interface{} return output } -func flattenApiManagementHostnameConfigurations(input *[]apimanagement.HostnameConfiguration, d *schema.ResourceData) []interface{} { +func flattenApiManagementHostnameConfigurations(input *[]apimanagement.HostnameConfiguration, d *schema.ResourceData, name, apimHostNameSuffix string) []interface{} { results := make([]interface{}, 0) if input == nil { return results @@ -883,6 +897,11 @@ func flattenApiManagementHostnameConfigurations(input *[]apimanagement.HostnameC output["host_name"] = *config.HostName } + // There'll always be a default custom domain with hostName "apim_name.azure-api.net" and Type "Proxy", which should be ignored + if *config.HostName == strings.ToLower(name)+"."+apimHostNameSuffix && config.Type == apimanagement.HostnameTypeProxy { + continue + } + if config.NegotiateClientCertificate != nil { output["negotiate_client_certificate"] = *config.NegotiateClientCertificate } @@ -929,6 +948,10 @@ func flattenApiManagementHostnameConfigurations(input *[]apimanagement.HostnameC } } + if len(managementResults) == 0 && len(portalResults) == 0 && len(developerPortalResults) == 0 && len(proxyResults) == 0 && len(scmResults) == 0 { + return []interface{}{} + } + return []interface{}{ map[string]interface{}{ "management": managementResults, diff --git a/azurerm/internal/services/apimanagement/tests/api_management_resource_test.go b/azurerm/internal/services/apimanagement/tests/api_management_resource_test.go index 976e06b4097a..a40a8a81a618 100644 --- a/azurerm/internal/services/apimanagement/tests/api_management_resource_test.go +++ b/azurerm/internal/services/apimanagement/tests/api_management_resource_test.go @@ -183,6 +183,32 @@ func TestAccAzureRMApiManagement_virtualNetworkInternal(t *testing.T) { }) } +func TestAccAzureRMApiManagement_virtualNetworkInternalUpdate(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_api_management", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMApiManagementDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagement_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMApiManagement_virtualNetworkInternal(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func TestAccAzureRMApiManagement_virtualNetworkInternalAdditionalLocation(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_api_management", "test") @@ -205,6 +231,10 @@ func TestAccAzureRMApiManagement_virtualNetworkInternalAdditionalLocation(t *tes }) } +// Api Management doesn't support hostname keyvault using UserAssigned Identity +// There will be a inevitable dependency cycle here when using SystemAssigned Identity +// 1. create SystemAssigned Identity, grant the identity certificate access +// 2. Update the hostname configuration of the keyvault certificate func TestAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsVersionedKeyVaultId(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_api_management", "test") @@ -214,14 +244,14 @@ func TestAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurati CheckDestroy: testCheckAzureRMApiManagementDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMApiManagement_identitySystemAssigned(data), + Config: testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsKeyVaultId(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMApiManagementExists(data.ResourceName), ), }, data.ImportStep(), { - Config: testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsVersionedKeyVaultId(data), + Config: testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsVersionedKeyVaultIdUpdateCD(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMApiManagementExists(data.ResourceName), ), @@ -240,14 +270,14 @@ func TestAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurati CheckDestroy: testCheckAzureRMApiManagementDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMApiManagement_identitySystemAssigned(data), + Config: testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsKeyVaultId(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMApiManagementExists(data.ResourceName), ), }, data.ImportStep(), { - Config: testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsVersionlessKeyVaultId(data), + Config: testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsVersionlessKeyVaultIdUpdateCD(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMApiManagementExists(data.ResourceName), ), @@ -269,7 +299,6 @@ func testCheckAzureRMApiManagementDestroy(s *terraform.State) error { name := rs.Primary.Attributes["name"] resourceGroup := rs.Primary.Attributes["resource_group_name"] resp, err := conn.Get(ctx, resourceGroup, name) - if err != nil { if utils.ResponseWasNotFound(resp.Response) { return nil @@ -853,11 +882,10 @@ resource "azurerm_api_management" "test" { certificate_password = "terraform" } - #developer_portal { - # host_name = "developer-portal.terraform.io" - # certificate = filebase64("testdata/api_management_developer_portal_test.pfx") - # certificate_password = "terraform" - #} + developer_portal { + host_name = "developer-portal.terraform.io" + certificate = filebase64("testdata/api_management_developer_portal_test.pfx") + } } sku_name = "Premium_1" @@ -872,31 +900,63 @@ resource "azurerm_api_management" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Secondary, data.RandomInteger, data.Locations.Ternary, data.RandomInteger) } -func testAccAzureRMApiManagement_virtualNetworkInternal(data acceptance.TestData) string { +func testAccAzureRMApiManagement_virtualNetworkTemplate(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { features {} } resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" + name = "acctestRG-%[1]d" + location = "%[2]s" } resource "azurerm_virtual_network" "test" { - name = "acctestVNET-%d" + name = "acctestVNET-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name address_space = ["10.0.0.0/16"] } resource "azurerm_subnet" "test" { - name = "acctestSNET-%d" + name = "acctestSNET-%[1]d" resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.test.name - address_prefix = "10.0.1.0/24" + address_prefixes = ["10.0.1.0/24"] } +resource "azurerm_network_security_group" "test" { + name = "acctest-NSG-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet_network_security_group_association" "test" { + subnet_id = azurerm_subnet.test.id + network_security_group_id = azurerm_network_security_group.test.id +} + +resource "azurerm_network_security_rule" "port_3443" { + name = "Port_3443" + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "3443" + source_address_prefix = "ApiManagement" + destination_address_prefix = "VirtualNetwork" + resource_group_name = azurerm_resource_group.test.name + network_security_group_name = azurerm_network_security_group.test.name +} +`, data.RandomInteger, data.Locations.Primary) +} + +func testAccAzureRMApiManagement_virtualNetworkInternal(data acceptance.TestData) string { + template := testAccAzureRMApiManagement_virtualNetworkTemplate(data) + return fmt.Sprintf(` +%s + resource "azurerm_api_management" "test" { name = "acctestAM-%d" location = azurerm_resource_group.test.location @@ -911,57 +971,63 @@ resource "azurerm_api_management" "test" { subnet_id = azurerm_subnet.test.id } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } func testAccAzureRMApiManagement_virtualNetworkInternalAdditionalLocation(data acceptance.TestData) string { + template := testAccAzureRMApiManagement_virtualNetworkTemplate(data) return fmt.Sprintf(` -provider "azurerm" { - features {} -} - -resource "azurerm_resource_group" "test1" { - name = "acctestRG1-%d" - location = "%s" -} +%[1]s resource "azurerm_resource_group" "test2" { - name = "acctestRG2-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test1" { - name = "acctestVNET1-%d" - location = azurerm_resource_group.test1.location - resource_group_name = azurerm_resource_group.test1.name - address_space = ["10.0.0.0/16"] -} - -resource "azurerm_subnet" "test1" { - name = "acctestSNET1-%d" - resource_group_name = azurerm_resource_group.test1.name - virtual_network_name = azurerm_virtual_network.test1.name - address_prefix = "10.0.1.0/24" + name = "acctestRG2-%[2]d" + location = "%[3]s" } +// subnet2 from the second location resource "azurerm_virtual_network" "test2" { - name = "acctestVNET2-%d" + name = "acctestVNET2-%[2]d" location = azurerm_resource_group.test2.location resource_group_name = azurerm_resource_group.test2.name address_space = ["10.1.0.0/16"] } resource "azurerm_subnet" "test2" { - name = "acctestSNET2-%d" + name = "acctestSNET2-%[2]d" resource_group_name = azurerm_resource_group.test2.name virtual_network_name = azurerm_virtual_network.test2.name address_prefix = "10.1.1.0/24" } +resource "azurerm_network_security_group" "test2" { + name = "acctest-NSG2-%[2]d" + location = azurerm_resource_group.test2.location + resource_group_name = azurerm_resource_group.test2.name +} + +resource "azurerm_subnet_network_security_group_association" "test2" { + subnet_id = azurerm_subnet.test2.id + network_security_group_id = azurerm_network_security_group.test2.id +} + +resource "azurerm_network_security_rule" "port_3443_2" { + name = "Port_3443" + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "3443" + source_address_prefix = "ApiManagement" + destination_address_prefix = "VirtualNetwork" + resource_group_name = azurerm_resource_group.test2.name + network_security_group_name = azurerm_network_security_group.test2.name +} + resource "azurerm_api_management" "test" { - name = "acctestAM-%d" - location = azurerm_resource_group.test1.location - resource_group_name = azurerm_resource_group.test1.name + name = "acctestAM-%[2]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name publisher_name = "pub1" publisher_email = "pub1@email.com" @@ -976,10 +1042,10 @@ resource "azurerm_api_management" "test" { virtual_network_type = "Internal" virtual_network_configuration { - subnet_id = azurerm_subnet.test1.id + subnet_id = azurerm_subnet.test.id } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Secondary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger, data.Locations.Secondary) } func testAccAzureRMApiManagement_identityUserAssigned(data acceptance.TestData) string { @@ -1101,7 +1167,7 @@ resource "azurerm_api_management" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsVersionlessKeyVaultId(data acceptance.TestData) string { +func testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsTemplate(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -1142,7 +1208,6 @@ resource "azurerm_key_vault_access_policy" "test" { "List", "Purge", ] - depends_on = [azurerm_key_vault.test] } resource "azurerm_key_vault_access_policy" "test2" { key_vault_id = azurerm_key_vault.test.id @@ -1152,7 +1217,6 @@ resource "azurerm_key_vault_access_policy" "test2" { "Get", "List", ] - depends_on = [azurerm_key_vault.test] } resource "azurerm_key_vault_certificate" "test" { depends_on = [azurerm_key_vault_access_policy.test] @@ -1191,8 +1255,34 @@ resource "azurerm_key_vault_certificate" "test" { } } } +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString) +} +func testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsKeyVaultId(data acceptance.TestData) string { + template := testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsTemplate(data) + return fmt.Sprintf(` +%s + +resource "azurerm_api_management" "test" { + name = "acctestAM-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + publisher_name = "pub1" + publisher_email = "pub1@email.com" + sku_name = "Developer_1" + identity { + type = "SystemAssigned" + } +} +`, template, data.RandomInteger) +} + +func testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsVersionlessKeyVaultIdUpdateCD(data acceptance.TestData) string { + template := testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsTemplate(data) + return fmt.Sprintf(` +%s + resource "azurerm_api_management" "test" { - name = "acctestAM-%[3]d" + name = "acctestAM-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name publisher_name = "pub1" @@ -1210,101 +1300,16 @@ resource "azurerm_api_management" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString) +`, template, data.RandomInteger) } -func testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsVersionedKeyVaultId(data acceptance.TestData) string { +func testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsVersionedKeyVaultIdUpdateCD(data acceptance.TestData) string { + template := testAccAzureRMApiManagement_identitySystemAssignedUpdateHostnameConfigurationsTemplate(data) return fmt.Sprintf(` -provider "azurerm" { - features {} -} -resource "azurerm_resource_group" "test" { - name = "acctestRG-%[1]d" - location = "%[2]s" -} -data "azurerm_client_config" "current" {} -resource "azurerm_key_vault" "test" { - name = "acctestKV-%[4]s" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - tenant_id = data.azurerm_client_config.current.tenant_id - sku_name = "standard" -} -resource "azurerm_key_vault_access_policy" "test" { - key_vault_id = azurerm_key_vault.test.id - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - certificate_permissions = [ - "Create", - "Delete", - "Deleteissuers", - "Get", - "Getissuers", - "Import", - "List", - "Listissuers", - "Managecontacts", - "Manageissuers", - "Setissuers", - "Update", - ] - secret_permissions = [ - "Delete", - "Get", - "List", - "Purge", - ] - depends_on = [azurerm_key_vault.test] -} -resource "azurerm_key_vault_access_policy" "test2" { - key_vault_id = azurerm_key_vault.test.id - tenant_id = azurerm_api_management.test.identity[0].tenant_id - object_id = azurerm_api_management.test.identity[0].principal_id - secret_permissions = [ - "Get", - "List", - ] - depends_on = [azurerm_key_vault.test] -} -resource "azurerm_key_vault_certificate" "test" { - depends_on = [azurerm_key_vault_access_policy.test, azurerm_key_vault.test] - name = "acctestKVCert-%[3]d" - key_vault_id = azurerm_key_vault.test.id - certificate_policy { - issuer_parameters { - name = "Self" - } - key_properties { - exportable = true - key_size = 2048 - key_type = "RSA" - reuse_key = true - } - secret_properties { - content_type = "application/x-pkcs12" - } - x509_certificate_properties { - # Server Authentication = 1.3.6.1.5.5.7.3.1 - # Client Authentication = 1.3.6.1.5.5.7.3.2 - extended_key_usage = ["1.3.6.1.5.5.7.3.1"] - key_usage = [ - "cRLSign", - "dataEncipherment", - "digitalSignature", - "keyAgreement", - "keyCertSign", - "keyEncipherment", - ] - subject_alternative_names { - dns_names = ["api.terraform.io"] - } - subject = "CN=api.terraform.io" - validity_in_months = 1 - } - } -} +%s + resource "azurerm_api_management" "test" { - name = "acctestAM-%[3]d" + name = "acctestAM-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name publisher_name = "pub1" @@ -1322,5 +1327,5 @@ resource "azurerm_api_management" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString) +`, template, data.RandomInteger) } diff --git a/azurerm/internal/services/apimanagement/tests/testdata/api_management_developer_portal_test.pfx b/azurerm/internal/services/apimanagement/tests/testdata/api_management_developer_portal_test.pfx index cede6279330b..c86d2089c0fd 100644 Binary files a/azurerm/internal/services/apimanagement/tests/testdata/api_management_developer_portal_test.pfx and b/azurerm/internal/services/apimanagement/tests/testdata/api_management_developer_portal_test.pfx differ diff --git a/website/docs/r/api_management.html.markdown b/website/docs/r/api_management.html.markdown index 12e0a7b3b35c..8cb2f5318790 100644 --- a/website/docs/r/api_management.html.markdown +++ b/website/docs/r/api_management.html.markdown @@ -83,7 +83,8 @@ The following arguments are supported: * `sign_up` - (Optional) A `sign_up` block as defined below. -* `virtual_network_type` - (Optional) The type of virtual network you want to use, valid values include: `None`, `External`, `Internal`. +* `virtual_network_type` - (Optional) The type of virtual network you want to use, valid values include: `None`, `External`, `Internal`. +> **NOTE:** Please ensure that in the subnet, inbound port 3443 is open when `virtual_network_type` is `Internal` or `External`. And please ensure other necessary ports are open according to [api management network configuration](https://docs.microsoft.com/en-us/azure/api-management/api-management-using-with-vnet#-common-network-configuration-issues). * `virtual_network_configuration` - (Optional) A `virtual_network_configuration` block as defined below. Required when `virtual_network_type` is `External` or `Internal`. @@ -325,10 +326,10 @@ An `identity` block exports the following: The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: -* `create` - (Defaults to 60 minutes) Used when creating the API Management Service. -* `update` - (Defaults to 60 minutes) Used when updating the API Management Service. +* `create` - (Defaults to 3 hours) Used when creating the API Management Service. +* `update` - (Defaults to 3 hours) Used when updating the API Management Service. * `read` - (Defaults to 5 minutes) Used when retrieving the API Management Service. -* `delete` - (Defaults to 60 minutes) Used when deleting the API Management Service. +* `delete` - (Defaults to 3 hours) Used when deleting the API Management Service. ## Import