From 949f6b02da60f59973492b1b9e17a1e1b65b2ef3 Mon Sep 17 00:00:00 2001 From: The Magician Date: Mon, 23 Jan 2023 10:40:31 -0800 Subject: [PATCH] containerattached: Add deletion policy. (#7134) (#13551) Signed-off-by: Modular Magician Signed-off-by: Modular Magician --- .changelog/7134.txt | 3 + google/resource_container_attached_cluster.go | 25 ++++ ...ntainer_attached_cluster_generated_test.go | 54 ++++++++ ...container_attached_cluster_sweeper_test.go | 124 ------------------ .../container_attached_cluster.html.markdown | 35 +++++ 5 files changed, 117 insertions(+), 124 deletions(-) create mode 100644 .changelog/7134.txt delete mode 100644 google/resource_container_attached_cluster_sweeper_test.go diff --git a/.changelog/7134.txt b/.changelog/7134.txt new file mode 100644 index 00000000000..c7df1470ab5 --- /dev/null +++ b/.changelog/7134.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +containerattached: Add a deletion policy enum field. +``` diff --git a/google/resource_container_attached_cluster.go b/google/resource_container_attached_cluster.go index cbf5c9c0fa2..6190cb4f03b 100644 --- a/google/resource_container_attached_cluster.go +++ b/google/resource_container_attached_cluster.go @@ -308,6 +308,12 @@ the Workload Identity Pool.`, }, }, }, + "deletion_policy": { + Type: schema.TypeString, + Optional: true, + Default: "DELETE", + Description: `Policy to determine what flags to send on delete.`, + }, "project": { Type: schema.TypeString, Optional: true, @@ -478,6 +484,12 @@ func resourceContainerAttachedClusterRead(d *schema.ResourceData, meta interface return handleNotFoundError(err, d, fmt.Sprintf("ContainerAttachedCluster %q", d.Id())) } + // Explicitly set virtual fields to default values if unset + if _, ok := d.GetOkExists("deletion_policy"); !ok { + if err := d.Set("deletion_policy", "DELETE"); err != nil { + return fmt.Errorf("Error setting deletion_policy: %s", err) + } + } if err := d.Set("project", project); err != nil { return fmt.Errorf("Error reading Cluster: %s", err) } @@ -722,6 +734,14 @@ func resourceContainerAttachedClusterDelete(d *schema.ResourceData, meta interfa } var obj map[string]interface{} + if v, ok := d.GetOk("deletion_policy"); ok { + if v == "DELETE_IGNORE_ERRORS" { + url, err = addQueryParams(url, map[string]string{"ignore_errors": "true"}) + if err != nil { + return err + } + } + } log.Printf("[DEBUG] Deleting Cluster %q", d.Id()) // err == nil indicates that the billing_project value was found @@ -763,6 +783,11 @@ func resourceContainerAttachedClusterImport(d *schema.ResourceData, meta interfa } d.SetId(id) + // Explicitly set virtual fields to default values on import + if err := d.Set("deletion_policy", "DELETE"); err != nil { + return nil, fmt.Errorf("Error setting deletion_policy: %s", err) + } + return []*schema.ResourceData{d}, nil } diff --git a/google/resource_container_attached_cluster_generated_test.go b/google/resource_container_attached_cluster_generated_test.go index 9d7ea66a2ea..332ad9023ac 100644 --- a/google/resource_container_attached_cluster_generated_test.go +++ b/google/resource_container_attached_cluster_generated_test.go @@ -144,6 +144,60 @@ resource "google_container_attached_cluster" "primary" { `, context) } +func TestAccContainerAttachedCluster_containerAttachedClusterIgnoreErrorsExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckContainerAttachedClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerAttachedCluster_containerAttachedClusterIgnoreErrorsExample(context), + }, + { + ResourceName: "google_container_attached_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "deletion_policy"}, + }, + }, + }) +} + +func testAccContainerAttachedCluster_containerAttachedClusterIgnoreErrorsExample(context map[string]interface{}) string { + return Nprintf(` +data "google_project" "project" { +} + +data "google_container_attached_versions" "versions" { + location = "us-west1" + project = data.google_project.project.project_id +} + +resource "google_container_attached_cluster" "primary" { + name = "basic%{random_suffix}" + location = "us-west1" + project = data.google_project.project.project_id + description = "Test cluster" + distribution = "aks" + oidc_config { + issuer_url = "https://oidc.issuer.url" + } + platform_version = data.google_container_attached_versions.versions.valid_versions[0] + fleet { + project = "projects/${data.google_project.project.number}" + } + + deletion_policy = "DELETE_IGNORE_ERRORS" +} +`, context) +} + func testAccCheckContainerAttachedClusterDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/google/resource_container_attached_cluster_sweeper_test.go b/google/resource_container_attached_cluster_sweeper_test.go deleted file mode 100644 index d50f4c72d30..00000000000 --- a/google/resource_container_attached_cluster_sweeper_test.go +++ /dev/null @@ -1,124 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// *** AUTO GENERATED CODE *** Type: MMv1 *** -// -// ---------------------------------------------------------------------------- -// -// This file is automatically generated by Magic Modules and manual -// changes will be clobbered when the file is regenerated. -// -// Please read more about how to change this file in -// .github/CONTRIBUTING.md. -// -// ---------------------------------------------------------------------------- - -package google - -import ( - "context" - "log" - "strings" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func init() { - resource.AddTestSweepers("ContainerAttachedCluster", &resource.Sweeper{ - Name: "ContainerAttachedCluster", - F: testSweepContainerAttachedCluster, - }) -} - -// At the time of writing, the CI only passes us-central1 as the region -func testSweepContainerAttachedCluster(region string) error { - resourceName := "ContainerAttachedCluster" - log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) - - config, err := sharedConfigForRegion(region) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) - return err - } - - err = config.LoadAndValidate(context.Background()) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) - return err - } - - t := &testing.T{} - billingId := getTestBillingAccountFromEnv(t) - - // Setup variables to replace in list template - d := &ResourceDataMock{ - FieldsInSchema: map[string]interface{}{ - "project": config.Project, - "region": region, - "location": region, - "zone": "-", - "billing_account": billingId, - }, - } - - listTemplate := strings.Split("https://{{location}}-gkemulticloud.googleapis.com/v1/projects/{{project}}/locations/{{location}}/attachedClusters", "?")[0] - listUrl, err := replaceVars(d, config, listTemplate) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) - return nil - } - - res, err := sendRequest(config, "GET", config.Project, listUrl, config.userAgent, nil) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) - return nil - } - - resourceList, ok := res["clusters"] - if !ok { - log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") - return nil - } - - rl := resourceList.([]interface{}) - - log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) - // Keep count of items that aren't sweepable for logging. - nonPrefixCount := 0 - for _, ri := range rl { - obj := ri.(map[string]interface{}) - if obj["name"] == nil { - log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) - return nil - } - - name := GetResourceNameFromSelfLink(obj["name"].(string)) - // Skip resources that shouldn't be sweeped - if !isSweepableTestResource(name) { - nonPrefixCount++ - continue - } - - deleteTemplate := "https://{{location}}-gkemulticloud.googleapis.com/v1/projects/{{project}}/locations/{{location}}/attachedClusters/{{name}}" - deleteUrl, err := replaceVars(d, config, deleteTemplate) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) - return nil - } - deleteUrl = deleteUrl + name - - // Don't wait on operations as we may have a lot to delete - _, err = sendRequest(config, "DELETE", config.Project, deleteUrl, config.userAgent, nil) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) - } else { - log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) - } - } - - if nonPrefixCount > 0 { - log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) - } - - return nil -} diff --git a/website/docs/r/container_attached_cluster.html.markdown b/website/docs/r/container_attached_cluster.html.markdown index fa963f7b607..4c35408a8e9 100644 --- a/website/docs/r/container_attached_cluster.html.markdown +++ b/website/docs/r/container_attached_cluster.html.markdown @@ -111,6 +111,40 @@ resource "google_container_attached_cluster" "primary" { } } ``` + +## Example Usage - Container Attached Cluster Ignore Errors + + +```hcl +data "google_project" "project" { +} + +data "google_container_attached_versions" "versions" { + location = "us-west1" + project = data.google_project.project.project_id +} + +resource "google_container_attached_cluster" "primary" { + name = "basic" + location = "us-west1" + project = data.google_project.project.project_id + description = "Test cluster" + distribution = "aks" + oidc_config { + issuer_url = "https://oidc.issuer.url" + } + platform_version = data.google_container_attached_versions.versions.valid_versions[0] + fleet { + project = "projects/${data.google_project.project.number}" + } + + deletion_policy = "DELETE_IGNORE_ERRORS" +} +``` ## Argument Reference @@ -209,6 +243,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. +* `deletion_policy` - (Optional) Policy to determine what flags to send on delete. The `logging_config` block supports: