diff --git a/mmv1/products/bigqueryreservation/ReservationAssignment.yaml b/mmv1/products/bigqueryreservation/ReservationAssignment.yaml index 2c0494b0526f..764ec22596e0 100644 --- a/mmv1/products/bigqueryreservation/ReservationAssignment.yaml +++ b/mmv1/products/bigqueryreservation/ReservationAssignment.yaml @@ -41,6 +41,9 @@ nested_query: modify_by_patch: false custom_code: pre_create: 'templates/terraform/pre_create/bigquery_reservation_assignment.go.tmpl' + post_read: 'templates/terraform/post_read/bigquery_reservation_assignment.go.tmpl' + constants: 'templates/terraform/constants/bigquery_reservation_assignment.go.tmpl' + test_check_destroy: 'templates/terraform/custom_check_destroy/bigquery_reservation_assignment.go.tmpl' legacy_long_form_project: true examples: - name: 'bigquery_reservation_assignment_basic' @@ -71,6 +74,7 @@ parameters: immutable: true resource: 'reservation' imports: 'name' + diff_suppress_func: 'bigqueryReservationAssignmentReservationDiffSuppressFunc' properties: - name: 'name' type: String diff --git a/mmv1/templates/terraform/constants/bigquery_reservation_assignment.go.tmpl b/mmv1/templates/terraform/constants/bigquery_reservation_assignment.go.tmpl new file mode 100644 index 000000000000..f79944e11a30 --- /dev/null +++ b/mmv1/templates/terraform/constants/bigquery_reservation_assignment.go.tmpl @@ -0,0 +1,10 @@ +func bigqueryReservationAssignmentReservationDiffSuppressFunc(k, old, new string, d *schema.ResourceData) bool { + oldParts := strings.Split(old, "/") + newParts := strings.Split(new, "/") + + if len(oldParts) == 1 || len(newParts) == 1 { + return tpgresource.GetResourceNameFromSelfLink(old) == tpgresource.GetResourceNameFromSelfLink(new) + } + + return tpgresource.CompareSelfLinkOrResourceName(k, old, new, d) +} diff --git a/mmv1/templates/terraform/custom_check_destroy/bigquery_reservation_assignment.go.tmpl b/mmv1/templates/terraform/custom_check_destroy/bigquery_reservation_assignment.go.tmpl new file mode 100644 index 000000000000..53060bbba7da --- /dev/null +++ b/mmv1/templates/terraform/custom_check_destroy/bigquery_reservation_assignment.go.tmpl @@ -0,0 +1,62 @@ +config := acctest.GoogleProviderConfig(t) +url, err := tpgresource.ReplaceVarsForTest(config, rs, transport_tpg.BaseUrl(bigqueryreservation.Product, config)+"projects/{{"{{"}}project{{"}}"}}/locations/{{"{{"}}location{{"}}"}}/reservations/{{"{{"}}reservation{{"}}"}}/assignments") +if err != nil { + return err +} + +billingProject := "" + +if config.BillingProject != "" { + billingProject = config.BillingProject +} + +res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, +}) +if err != nil { + if transport_tpg.IsGoogleApiErrorWithCode(err, 404) { + continue + } + return err +} + +v, ok := res["assignments"] +if !ok || v == nil { + continue +} + +var items []interface{} +switch list := v.(type) { +case []interface{}: + items = list +case map[string]interface{}: + items = []interface{}{list} +default: + return fmt.Errorf("expected list or map for assignments in CheckDestroy") +} + +expectedName := tpgresource.GetResourceNameFromSelfLink(rs.Primary.ID) +found := false +for _, itemRaw := range items { + if itemRaw == nil { + continue + } + item := itemRaw.(map[string]interface{}) + nameRaw, ok := item["name"].(string) + if !ok { + continue + } + itemName := tpgresource.GetResourceNameFromSelfLink(nameRaw) + if itemName == expectedName { + found = true + break + } +} + +if found { + return fmt.Errorf("BigqueryReservationReservationAssignment %q still exists at %s", expectedName, url) +} diff --git a/mmv1/templates/terraform/post_read/bigquery_reservation_assignment.go.tmpl b/mmv1/templates/terraform/post_read/bigquery_reservation_assignment.go.tmpl new file mode 100644 index 000000000000..2a1d3b881d46 --- /dev/null +++ b/mmv1/templates/terraform/post_read/bigquery_reservation_assignment.go.tmpl @@ -0,0 +1,20 @@ +if reservationVal, ok := d.GetOk("reservation"); ok { + reservation := reservationVal.(string) + if !strings.Contains(reservation, "/") && reservation != "" { + if project, err := tpgresource.GetProject(d, config); err == nil { + project = strings.TrimPrefix(project, "projects/") + location := d.Get("location").(string) + if location == "" { + idParts := strings.Split(d.Id(), "/") + if len(idParts) >= 4 && idParts[2] == "locations" { + location = idParts[3] + } + } + if location != "" { + if err := d.Set("reservation", fmt.Sprintf("projects/%s/locations/%s/reservations/%s", project, location, reservation)); err != nil { + return fmt.Errorf("Error setting normalized reservation: %s", err) + } + } + } + } +} diff --git a/mmv1/third_party/terraform/services/bigqueryreservation/resource_bigquery_reservation_assignment_test.go b/mmv1/third_party/terraform/services/bigqueryreservation/resource_bigquery_reservation_assignment_test.go index 860ea46f7fd8..e7e73981ea33 100644 --- a/mmv1/third_party/terraform/services/bigqueryreservation/resource_bigquery_reservation_assignment_test.go +++ b/mmv1/third_party/terraform/services/bigqueryreservation/resource_bigquery_reservation_assignment_test.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" _ "github.com/hashicorp/terraform-provider-google/google/services/bigqueryreservation" ) @@ -44,3 +45,57 @@ resource "google_bigquery_reservation_assignment" "test" { } `, context) } + +func TestAccBigqueryReservationReservationAssignment_customSymmetricReservationDiffSuppress(t *testing.T) { + t.Parallel() + + randomSuffix := acctest.RandString(t, 10) + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "reservation_name": "tf-test-example-res-" + randomSuffix, + "random_suffix": randomSuffix, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigqueryReservationReservationAssignmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigqueryReservationReservationAssignment_customSymmetricReservationDiffSuppress(context), + }, + { + ResourceName: "google_bigquery_reservation_assignment.assignment", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location"}, // Verify reservation is NOT ignored and passes verification! + }, + { + ResourceName: "google_bigquery_reservation_assignment.assignment", + RefreshState: true, + ExpectNonEmptyPlan: false, // Verify plan is clean post-import! + ImportStateKind: resource.ImportBlockWithResourceIdentity, + }, + }, + }) +} + +func testAccBigqueryReservationReservationAssignment_customSymmetricReservationDiffSuppress(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_bigquery_reservation" "basic" { + name = "%{reservation_name}" + project = "%{project}" + location = "us-central1" + slot_capacity = 0 + ignore_idle_slots = false +} + +resource "google_bigquery_reservation_assignment" "assignment" { + assignee = "projects/%{project}" + job_type = "PIPELINE" + reservation = google_bigquery_reservation.basic.id + location = "us-central1" +} +`, context) +} diff --git a/mmv1/third_party/terraform/tpgresource/resource_test_utils.go b/mmv1/third_party/terraform/tpgresource/resource_test_utils.go index a15deba3c94d..2b50c0f3f0f0 100644 --- a/mmv1/third_party/terraform/tpgresource/resource_test_utils.go +++ b/mmv1/third_party/terraform/tpgresource/resource_test_utils.go @@ -180,6 +180,14 @@ func ReplaceVarsForTest(config *transport_tpg.Config, rs *terraform.ResourceStat } if v, ok := rs.Primary.Attributes[m]; ok { + if strings.Count(v, "/") >= 3 && + !strings.Contains(m, "parent") && + m != "project" && + m != "location" && + m != "region" && + m != "zone" { + return GetResourceNameFromSelfLink(v) + } return v }