diff --git a/digitalocean/cdn/resource_cdn.go b/digitalocean/cdn/resource_cdn.go index bc2bb860d..35713990a 100644 --- a/digitalocean/cdn/resource_cdn.go +++ b/digitalocean/cdn/resource_cdn.go @@ -3,12 +3,16 @@ package cdn import ( "context" "log" + "net/http" "strings" + "time" "github.com/digitalocean/godo" "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/certificate" "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/config" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/util" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -185,8 +189,7 @@ func resourceDigitalOceanCDNCreate(ctx context.Context, d *schema.ResourceData, func resourceDigitalOceanCDNRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*config.CombinedConfig).GodoClient() - cdn, resp, err := client.CDNs.Get(context.Background(), d.Id()) - + cdn, resp, err := getCDNWithRetryBackoff(ctx, client, d.Id()) if err != nil { if resp != nil && resp.StatusCode == 404 { log.Printf("[DEBUG] CDN (%s) was not found - removing from state", d.Id()) @@ -217,6 +220,39 @@ func resourceDigitalOceanCDNRead(ctx context.Context, d *schema.ResourceData, me return nil } +func getCDNWithRetryBackoff(ctx context.Context, client *godo.Client, id string) (*godo.CDN, *godo.Response, error) { + var ( + cdn *godo.CDN + resp *godo.Response + timeout = 30 * time.Second + err error + ) + err = resource.RetryContext(ctx, timeout, func() *resource.RetryError { + cdn, resp, err = client.CDNs.Get(ctx, id) + if err != nil { + if util.IsDigitalOceanError(err, http.StatusNotFound, "") { + log.Printf("[DEBUG] Received %s, retrying CDN", err.Error()) + return resource.RetryableError(err) + } + + if util.IsDigitalOceanError(err, http.StatusTooManyRequests, "") { + log.Printf("[DEBUG] Received %s, backing off", err.Error()) + time.Sleep(10 * time.Second) + return resource.RetryableError(err) + } + + return resource.NonRetryableError(err) + } + + return nil + }) + if err != nil { + return nil, resp, err + } + + return cdn, resp, nil +} + func resourceDigitalOceanCDNUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*config.CombinedConfig).GodoClient() @@ -263,15 +299,29 @@ func resourceDigitalOceanCDNUpdate(ctx context.Context, d *schema.ResourceData, func resourceDigitalOceanCDNDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*config.CombinedConfig).GodoClient() - resourceId := d.Id() + resourceID := d.Id() + + timeout := 30 * time.Second + err := resource.RetryContext(ctx, timeout, func() *resource.RetryError { + _, err := client.CDNs.Delete(context.Background(), resourceID) + if err != nil { + if util.IsDigitalOceanError(err, http.StatusTooManyRequests, "") { + log.Printf("[DEBUG] Received %s, backing off", err.Error()) + time.Sleep(10 * time.Second) + return resource.RetryableError(err) + } + + return resource.NonRetryableError(err) + } - _, err := client.CDNs.Delete(context.Background(), resourceId) + return nil + }) if err != nil { return diag.Errorf("Error deleting CDN: %s", err) } d.SetId("") - log.Printf("[INFO] CDN deleted, ID: %s", resourceId) + log.Printf("[INFO] CDN deleted, ID: %s", resourceID) return nil } diff --git a/digitalocean/cdn/resource_cdn_test.go b/digitalocean/cdn/resource_cdn_test.go index 33185bf32..0af5f47ce 100644 --- a/digitalocean/cdn/resource_cdn_test.go +++ b/digitalocean/cdn/resource_cdn_test.go @@ -180,7 +180,6 @@ func testAccCheckDigitalOceanCDNExists(resource string) resource.TestCheckFunc { } foundCDN, _, err := client.CDNs.Get(context.Background(), rs.Primary.ID) - if err != nil { return err } @@ -223,12 +222,11 @@ resource "digitalocean_cdn" "foobar" { func testAccCheckDigitalOceanCDNConfig_CustomDomain(domain string, spaceName string, certName string) string { return fmt.Sprintf(` resource "tls_private_key" "example" { - algorithm = "ECDSA" - ecdsa_curve = "P384" + algorithm = "RSA" } resource "tls_self_signed_cert" "example" { - key_algorithm = "ECDSA" + key_algorithm = "RSA" private_key_pem = tls_private_key.example.private_key_pem dns_names = ["foo.%s"] subject { diff --git a/digitalocean/cdn/sweep.go b/digitalocean/cdn/sweep.go new file mode 100644 index 000000000..179a80592 --- /dev/null +++ b/digitalocean/cdn/sweep.go @@ -0,0 +1,47 @@ +package cdn + +import ( + "context" + "log" + "strings" + + "github.com/digitalocean/godo" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/config" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/sweep" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func init() { + resource.AddTestSweepers("digitalocean_cdn", &resource.Sweeper{ + Name: "digitalocean_cdn", + F: sweepCDN, + }) + +} + +func sweepCDN(region string) error { + meta, err := sweep.SharedConfigForRegion(region) + if err != nil { + return err + } + + client := meta.(*config.CombinedConfig).GodoClient() + + opt := &godo.ListOptions{PerPage: 200} + cdns, _, err := client.CDNs.List(context.Background(), opt) + if err != nil { + return err + } + + for _, c := range cdns { + if strings.HasPrefix(c.Origin, sweep.TestNamePrefix) { + log.Printf("Destroying CDN %s", c.Origin) + + if _, err := client.CDNs.Delete(context.Background(), c.ID); err != nil { + return err + } + } + } + + return nil +} diff --git a/digitalocean/sweep/sweep_test.go b/digitalocean/sweep/sweep_test.go index 9f1b3acdb..75f647a19 100644 --- a/digitalocean/sweep/sweep_test.go +++ b/digitalocean/sweep/sweep_test.go @@ -4,6 +4,7 @@ import ( "testing" _ "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/app" + _ "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/cdn" _ "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/certificate" _ "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/database" _ "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/domain"