From b1222e2730d731300ec8557e69b4b4df0d87d908 Mon Sep 17 00:00:00 2001 From: Ujjwal Kumar Date: Thu, 19 Oct 2023 23:41:10 +0530 Subject: [PATCH] added force_delete for dns bindings --- ...ource_ibm_is_vpc_dns_resolution_binding.go | 40 +++ ..._ibm_is_vpc_dns_resolution_binding_test.go | 266 ++++++++++++++++++ ...s_vpc_dns_resolution_binding.html.markdown | 1 + 3 files changed, 307 insertions(+) diff --git a/ibm/service/vpc/resource_ibm_is_vpc_dns_resolution_binding.go b/ibm/service/vpc/resource_ibm_is_vpc_dns_resolution_binding.go index 3ec4a1ff60..fc60af98e6 100644 --- a/ibm/service/vpc/resource_ibm_is_vpc_dns_resolution_binding.go +++ b/ibm/service/vpc/resource_ibm_is_vpc_dns_resolution_binding.go @@ -121,6 +121,12 @@ func ResourceIBMIsVPCDnsResolutionBinding() *schema.Resource { Computed: true, Description: "The URL for this DNS resolution binding.", }, + "force_delete": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "The URL for this DNS resolution binding.", + }, "lifecycle_state": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -395,10 +401,44 @@ func resourceIBMIsVPCDnsResolutionBindingDelete(context context.Context, d *sche if err != nil { return diag.FromErr(err) } + vpcId, id, err := ParseVPCDNSTerraformID(d.Id()) if err != nil { return diag.FromErr(err) } + + if d.Get("force_delete").(bool) { + updateVpcOptions := &vpcv1.UpdateVPCOptions{ + ID: &vpcId, + } + vpcPatchModel := &vpcv1.VPCPatch{} + vpcPatch, err := vpcPatchModel.AsPatch() + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error calling asPatch for VPCPatch during dns binding delete: %s", err)) + } + dnsMap := make(map[string]interface{}) + resolverMap := make(map[string]interface{}) + resolverMap["vpc"] = nil + resolverMap["type"] = "system" + dnsMap["resolver"] = resolverMap + vpcPatch["dns"] = dnsMap + updateVpcOptions.VPCPatch = vpcPatch + + _, response, err := sess.UpdateVPC(updateVpcOptions) + if err != nil { + responsestring := strings.ToLower(response.String()) + if strings.Contains(strings.ToLower(err.Error()), strings.ToLower("The supplied header is not supported for this request")) && strings.Contains(responsestring, "bad_header") && strings.Contains(responsestring, strings.ToLower("If-Match")) { + log.Printf("[DEBUG] retrying update vpc without If-Match during dns binding delete") + updateVpcOptions.IfMatch = nil + _, nestedresponse, nestederr := sess.UpdateVPC(updateVpcOptions) + if nestederr != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error Updating VPC on retry during dns binding delete : %s\n%s", nestederr, nestedresponse)) + } + } else { + return diag.FromErr(fmt.Errorf("[ERROR] Error Updating VPC during dns binding delete : %s\n%s", err, response)) + } + } + } deleteVPCDnsResolutionBindingOptions := &vpcv1.DeleteVPCDnsResolutionBindingOptions{} deleteVPCDnsResolutionBindingOptions.SetVPCID(vpcId) diff --git a/ibm/service/vpc/resource_ibm_is_vpc_dns_resolution_binding_test.go b/ibm/service/vpc/resource_ibm_is_vpc_dns_resolution_binding_test.go index c4dad92fb4..9b954b8d22 100644 --- a/ibm/service/vpc/resource_ibm_is_vpc_dns_resolution_binding_test.go +++ b/ibm/service/vpc/resource_ibm_is_vpc_dns_resolution_binding_test.go @@ -39,7 +39,273 @@ func TestAccIBMIsVPCDnsResolutionBindingResourceBasic(t *testing.T) { }, }) } +func TestAccIBMIsVPCDnsResolutionBindingResourceForceDelete(t *testing.T) { + name1 := fmt.Sprintf("terraformvpcuat-%d", acctest.RandIntRange(10, 100)) + name2 := fmt.Sprintf("terraformvpcuat-%d", acctest.RandIntRange(10, 100)) + subnet1 := fmt.Sprintf("terraformsubnet-%d", acctest.RandIntRange(10, 100)) + subnet2 := fmt.Sprintf("terraformsubnet-%d", acctest.RandIntRange(10, 100)) + subnet3 := fmt.Sprintf("terraformsubnet-%d", acctest.RandIntRange(10, 100)) + subnet4 := fmt.Sprintf("terraformsubnet-%d", acctest.RandIntRange(10, 100)) + resourecinstance := fmt.Sprintf("terraformresource-%d", acctest.RandIntRange(10, 100)) + resolver1 := fmt.Sprintf("terraformresolver-%d", acctest.RandIntRange(10, 100)) + resolver2 := fmt.Sprintf("terraformresolver-%d", acctest.RandIntRange(10, 100)) + binding := fmt.Sprintf("terraformbinding-%d", acctest.RandIntRange(10, 100)) + enableHubTrue := true + enableHubFalse := false + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsVPCDnsResolutionBindingForceDeleteResourceConfig(name1, name2, subnet1, subnet2, subnet3, subnet4, resourecinstance, resolver1, resolver2, binding, enableHubTrue, enableHubFalse), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "id"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "vpc_id"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "href"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "name"), + resource.TestCheckResourceAttr("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "name", binding), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "vpc.#"), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_true", "name", name1), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_false_delegated", "name", name2), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_true", "dns.0.enable_hub", fmt.Sprintf("%t", enableHubTrue)), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_true", "dns.0.resolver.0.type", "system"), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_false_delegated", "dns.0.enable_hub", fmt.Sprintf("%t", enableHubFalse)), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_false_delegated", "dns.0.resolver.0.type", "system"), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMIsVPCDnsResolutionBindingForceDeleteUpdateResourceConfig(name1, name2, subnet1, subnet2, subnet3, subnet4, resourecinstance, resolver1, resolver2, binding, enableHubTrue, enableHubFalse), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "id"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "vpc_id"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "href"), + resource.TestCheckResourceAttr("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "name", binding), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "name"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_vpc_dns_resolution_binding.is_vpc_dns_resolution_binding", "vpc.#"), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_true", "name", name1), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_false_delegated", "name", name2), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_true", "dns.0.resolution_binding_count", "1"), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_true", "dns.0.enable_hub", fmt.Sprintf("%t", enableHubTrue)), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_true", "dns.0.resolver.0.type", "system"), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_false_delegated", "dns.0.enable_hub", fmt.Sprintf("%t", enableHubFalse)), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_false_delegated", "dns.0.resolver.0.type", "delegated"), + resource.TestCheckResourceAttr( + "ibm_is_vpc.hub_false_delegated", "dns.0.resolution_binding_count", "1"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsVPCDnsResolutionBindingForceDeleteResourceConfig(vpcname, vpcname2, subnetname1, subnetname2, subnetname3, subnetname4, resourceinstance, resolver1, resolver2, bindingname string, enableHub, enablehubfalse bool) string { + return fmt.Sprintf(` + data "ibm_resource_group" "rg" { + is_default = true + } + + resource ibm_is_vpc hub_true { + name = "%s" + dns { + enable_hub = %t + } + } + + resource ibm_is_vpc hub_false_delegated { + name = "%s" + dns { + enable_hub = %t + } + } + + resource "ibm_is_subnet" "hub_true_sub1" { + name = "%s" + vpc = ibm_is_vpc.hub_true.id + zone = "%s" + total_ipv4_address_count = 16 + } + resource "ibm_is_subnet" "hub_true_sub2" { + name = "%s" + vpc = ibm_is_vpc.hub_true.id + zone = "%s" + total_ipv4_address_count = 16 + } + resource "ibm_is_subnet" "hub_false_delegated_sub1" { + name = "%s" + vpc = ibm_is_vpc.hub_false_delegated.id + zone = "%s" + total_ipv4_address_count = 16 + } + resource "ibm_is_subnet" "hub_false_delegated_sub2" { + name = "%s" + vpc = ibm_is_vpc.hub_false_delegated.id + zone = "%s" + total_ipv4_address_count = 16 + } + resource "ibm_resource_instance" "dns-cr-instance" { + name = "%s" + resource_group_id = data.ibm_resource_group.rg.id + location = "global" + service = "dns-svcs" + plan = "standard-dns" + } + resource "ibm_dns_custom_resolver" "test_hub_true" { + name = "%s" + instance_id = ibm_resource_instance.dns-cr-instance.guid + description = "new test CR - TF" + high_availability = true + enabled = true + locations { + subnet_crn = ibm_is_subnet.hub_true_sub1.crn + enabled = true + } + locations { + subnet_crn = ibm_is_subnet.hub_true_sub2.crn + enabled = true + } + } + resource "ibm_dns_custom_resolver" "test_hub_false_delegated" { + name = "%s" + instance_id = ibm_resource_instance.dns-cr-instance.guid + description = "new test CR - TF" + high_availability = true + enabled = true + locations { + subnet_crn = ibm_is_subnet.hub_false_delegated_sub1.crn + enabled = true + } + locations { + subnet_crn = ibm_is_subnet.hub_false_delegated_sub2.crn + enabled = true + } + } + + resource ibm_is_vpc_dns_resolution_binding is_vpc_dns_resolution_binding { + name = "%s" + vpc_id= ibm_is_vpc.hub_false_delegated.id + vpc { + id = ibm_is_vpc.hub_true.id + } + force_delete = true + } + `, vpcname, enableHub, vpcname2, enablehubfalse, subnetname1, acc.ISZoneName, subnetname2, acc.ISZoneName, subnetname3, acc.ISZoneName, subnetname4, acc.ISZoneName, resourceinstance, resolver1, resolver2, bindingname) +} +func testAccCheckIBMIsVPCDnsResolutionBindingForceDeleteUpdateResourceConfig(vpcname, vpcname2, subnetname1, subnetname2, subnetname3, subnetname4, resourceinstance, resolver1, resolver2, bindingname string, enableHub, enablehubfalse bool) string { + return fmt.Sprintf(` + data "ibm_resource_group" "rg" { + is_default = true + } + + resource ibm_is_vpc hub_true { + name = "%s" + dns { + enable_hub = %t + } + } + + resource ibm_is_vpc hub_false_delegated { + name = "%s" + dns { + enable_hub = %t + resolver { + type = "delegated" + vpc_id = ibm_is_vpc.hub_true.id + } + } + } + + resource "ibm_is_subnet" "hub_true_sub1" { + name = "%s" + vpc = ibm_is_vpc.hub_true.id + zone = "%s" + total_ipv4_address_count = 16 + } + resource "ibm_is_subnet" "hub_true_sub2" { + name = "%s" + vpc = ibm_is_vpc.hub_true.id + zone = "%s" + total_ipv4_address_count = 16 + } + resource "ibm_is_subnet" "hub_false_delegated_sub1" { + name = "%s" + vpc = ibm_is_vpc.hub_false_delegated.id + zone = "%s" + total_ipv4_address_count = 16 + } + resource "ibm_is_subnet" "hub_false_delegated_sub2" { + name = "%s" + vpc = ibm_is_vpc.hub_false_delegated.id + zone = "%s" + total_ipv4_address_count = 16 + } + resource "ibm_resource_instance" "dns-cr-instance" { + name = "%s" + resource_group_id = data.ibm_resource_group.rg.id + location = "global" + service = "dns-svcs" + plan = "standard-dns" + } + resource "ibm_dns_custom_resolver" "test_hub_true" { + name = "%s" + instance_id = ibm_resource_instance.dns-cr-instance.guid + description = "new test CR - TF" + high_availability = true + enabled = true + locations { + subnet_crn = ibm_is_subnet.hub_true_sub1.crn + enabled = true + } + locations { + subnet_crn = ibm_is_subnet.hub_true_sub2.crn + enabled = true + } + } + resource "ibm_dns_custom_resolver" "test_hub_false_delegated" { + name = "%s" + instance_id = ibm_resource_instance.dns-cr-instance.guid + description = "new test CR - TF" + high_availability = true + enabled = true + locations { + subnet_crn = ibm_is_subnet.hub_false_delegated_sub1.crn + enabled = true + } + locations { + subnet_crn = ibm_is_subnet.hub_false_delegated_sub2.crn + enabled = true + } + } + + resource ibm_is_vpc_dns_resolution_binding is_vpc_dns_resolution_binding { + name = "%s" + vpc_id= ibm_is_vpc.hub_false_delegated.id + vpc { + id = ibm_is_vpc.hub_true.id + } + force_delete = true + } + + `, vpcname, enableHub, vpcname2, enablehubfalse, subnetname1, acc.ISZoneName, subnetname2, acc.ISZoneName, subnetname3, acc.ISZoneName, subnetname4, acc.ISZoneName, resourceinstance, resolver1, resolver2, bindingname) +} func testAccCheckIBMIsVPCDnsResolutionBindingResourceConfigBasic(vpcname1, vpcname2, bindingname string, enablehub1, enablehub2 bool) string { return fmt.Sprintf(` resource ibm_is_vpc testacc_vpc1 { diff --git a/website/docs/r/is_vpc_dns_resolution_binding.html.markdown b/website/docs/r/is_vpc_dns_resolution_binding.html.markdown index 9510b1f654..20f6398632 100644 --- a/website/docs/r/is_vpc_dns_resolution_binding.html.markdown +++ b/website/docs/r/is_vpc_dns_resolution_binding.html.markdown @@ -43,6 +43,7 @@ resource "ibm_is_vpc_dns_resolution_binding" "is_vpc_dns_resolution_binding_href Review the argument reference that you can specify for your data source. - `name` - (Optional, String) The DNS resolution binding name. +- `force_delete` - (Optional, Bool) If you want to forcefully delete the dns binding when dns.resolver.type is set to delegated on the vpc. This will produce changes on the vpc. - `vpc_id` - (Required, Forces new resource, String) The VPC identifier of the source vpc. - `vpc` - (Required, Forces new resource, String) The VPC identifier/href/crn of the target. Nested scheme for **vpc**: