Skip to content

Commit

Permalink
Add force_destroy to google_dns_managed_zone (#3917) (#7289)
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
modular-magician authored Sep 16, 2020
1 parent 8cbe425 commit d4523fe
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 125 deletions.
3 changes: 3 additions & 0 deletions .changelog/3917.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
dns: added `force_destroy` option to `google_dns_managed_zone` to delete records created outside of Terraform
```
83 changes: 83 additions & 0 deletions google/resource_dns_managed_zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/helper/hashcode"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"google.golang.org/api/dns/v1"
)

func resourceDNSManagedZone() *schema.Resource {
Expand Down Expand Up @@ -256,6 +257,11 @@ defined by the server`,
Type: schema.TypeString,
},
},
"force_destroy": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"project": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -422,6 +428,10 @@ func resourceDNSManagedZoneRead(d *schema.ResourceData, meta interface{}) error
return handleNotFoundError(err, d, fmt.Sprintf("DNSManagedZone %q", d.Id()))
}

// Explicitly set virtual fields to default values if unset
if _, ok := d.GetOk("force_destroy"); !ok {
d.Set("force_destroy", false)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading ManagedZone: %s", err)
}
Expand Down Expand Up @@ -549,6 +559,76 @@ func resourceDNSManagedZoneDelete(d *schema.ResourceData, meta interface{}) erro
}

var obj map[string]interface{}
if d.Get("force_destroy").(bool) {
zone := d.Get("name").(string)
token := ""
for paginate := true; paginate; {
var resp *dns.ResourceRecordSetsListResponse
if token == "" {
resp, err = config.clientDns.ResourceRecordSets.List(project, zone).Do()
if err != nil {
return fmt.Errorf("Error reading ResourceRecordSets: %s", err)
}
} else {
resp, err = config.clientDns.ResourceRecordSets.List(project, zone).PageToken(token).Do()
if err != nil {
return fmt.Errorf("Error reading ResourceRecordSets: %s", err)
}
}

for _, rr := range resp.Rrsets {
// Build the change
chg := &dns.Change{
Deletions: []*dns.ResourceRecordSet{
{
Name: rr.Name,
Type: rr.Type,
Ttl: rr.Ttl,
Rrdatas: rr.Rrdatas,
},
},
}

if rr.Type == "NS" {
mz, err := config.clientDns.ManagedZones.Get(project, zone).Do()
if err != nil {
return fmt.Errorf("Error retrieving managed zone %q from %q: %s", zone, project, err)
}
domain := mz.DnsName

if domain == rr.Name {
log.Println("[DEBUG] NS records can't be deleted due to API restrictions, so they're being left in place. See https://www.terraform.io/docs/providers/google/r/dns_record_set.html for more information.")
continue
}
}

if rr.Type == "SOA" {
log.Println("[DEBUG] SOA records can't be deleted due to API restrictions, so they're being left in place.")
continue
}

log.Printf("[DEBUG] DNS Record delete request via MZ: %#v", chg)
chg, err = config.clientDns.Changes.Create(project, zone, chg).Do()
if err != nil {
return fmt.Errorf("Unable to delete ResourceRecordSets: %s", err)
}

w := &DnsChangeWaiter{
Service: config.clientDns,
Change: chg,
Project: project,
ManagedZone: zone,
}
_, err = w.Conf().WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for Google DNS change: %s", err)
}
}

token = resp.NextPageToken
paginate = token != ""
}
}
log.Printf("[DEBUG] Deleting ManagedZone %q", d.Id())

// err == nil indicates that the billing_project value was found
Expand Down Expand Up @@ -582,6 +662,9 @@ func resourceDNSManagedZoneImport(d *schema.ResourceData, meta interface{}) ([]*
}
d.SetId(id)

// Explicitly set virtual fields to default values on import
d.Set("force_destroy", false)

return []*schema.ResourceData{d}, nil
}

Expand Down
124 changes: 0 additions & 124 deletions google/resource_dns_managed_zone_sweeper_test.go

This file was deleted.

85 changes: 85 additions & 0 deletions google/resource_dns_managed_zone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"google.golang.org/api/dns/v1"
)

func TestAccDNSManagedZone_update(t *testing.T) {
Expand Down Expand Up @@ -149,6 +151,89 @@ func TestAccDNSManagedZone_privateForwardingUpdate(t *testing.T) {
})
}

func TestAccDNSManagedZone_forceDestroy(t *testing.T) {
//t.Parallel()

zoneSuffix := randString(t, 10)
project := getTestProjectFromEnv()

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckDNSManagedZoneDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccDNSManagedZone_forceDestroy(zoneSuffix),
Check: resource.ComposeTestCheckFunc(
testAccCheckManagedZoneCreateRRs(t, zoneSuffix, project),
),
},
},
})
}

func testAccCheckManagedZoneCreateRRs(t *testing.T, zoneSuffix string, project string) resource.TestCheckFunc {
return func(s *terraform.State) error {
config := googleProviderConfig(t)
zone := fmt.Sprintf("mzone-test-%s", zoneSuffix)
// Build the change
chg := &dns.Change{
Additions: []*dns.ResourceRecordSet{
{
Name: fmt.Sprintf("cname.%s.hashicorptest.com.", zoneSuffix),
Type: "CNAME",
Ttl: 300,
Rrdatas: []string{"foo.example.com."},
},
{
Name: fmt.Sprintf("a.%s.hashicorptest.com.", zoneSuffix),
Type: "A",
Ttl: 300,
Rrdatas: []string{"1.1.1.1"},
},
{
Name: fmt.Sprintf("nested.%s.hashicorptest.com.", zoneSuffix),
Type: "NS",
Ttl: 300,
Rrdatas: []string{"ns.hashicorp.services.", "ns2.hashicorp.services."},
},
},
}

chg, err := config.clientDns.Changes.Create(project, zone, chg).Do()
if err != nil {
return fmt.Errorf("Error creating DNS RecordSet: %s", err)
}

w := &DnsChangeWaiter{
Service: config.clientDns,
Change: chg,
Project: project,
ManagedZone: zone,
}
_, err = w.Conf().WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for Google DNS change: %s", err)
}

return nil
}
}

func testAccDNSManagedZone_forceDestroy(suffix string) string {
return fmt.Sprintf(`
resource "google_dns_managed_zone" "foobar" {
name = "mzone-test-%s"
dns_name = "%s.hashicorptest.com."
labels = {
foo = "bar"
}
force_destroy = true
visibility = "public"
}
`, suffix, suffix)
}

func testAccDnsManagedZone_basic(suffix, description string) string {
return fmt.Sprintf(`
resource "google_dns_managed_zone" "foobar" {
Expand Down
2 changes: 1 addition & 1 deletion website/docs/r/dns_managed_zone.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ The following arguments are supported:
* `project` - (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.


* `force_destroy` - (Optional) Set this true to delete all records in the zone.
The `dnssec_config` block supports:

* `kind` -
Expand Down

0 comments on commit d4523fe

Please sign in to comment.