diff --git a/.changelog/3471.txt b/.changelog/3471.txt new file mode 100644 index 00000000000..a0c3e4d13ba --- /dev/null +++ b/.changelog/3471.txt @@ -0,0 +1,3 @@ +```release-note:bug +bigquery: Fixed error where `google_bigquery_dataset_access` resources could not be found post-creation if role was set to a predefined IAM role with an equivalent primative role (e.g. `roles/bigquery.dataOwner` and `OWNER`) +``` diff --git a/google/resource_big_query_dataset.go b/google/resource_big_query_dataset.go index c26067094a9..36537f21a70 100644 --- a/google/resource_big_query_dataset.go +++ b/google/resource_big_query_dataset.go @@ -243,7 +243,7 @@ domain specified will be granted the specified access`, member of the access object. Primitive, Predefined and custom roles are supported. Predefined roles that have equivalent primitive roles are swapped by the API to their Primitive -counterparts, and will show a diff post-create. See +counterparts. See [official docs](https://cloud.google.com/bigquery/docs/access-control).`, }, "special_group": { diff --git a/google/resource_big_query_dataset_access.go b/google/resource_big_query_dataset_access.go index 6f4add4a50f..c572574099f 100644 --- a/google/resource_big_query_dataset_access.go +++ b/google/resource_big_query_dataset_access.go @@ -24,6 +24,19 @@ import ( "google.golang.org/api/googleapi" ) +var bigqueryAccessRoleToPrimitiveMap = map[string]string{ + "roles/bigquery.dataOwner": "OWNER", + "roles/bigquery.dataEditor": "WRITER", + "roles/bigquery.dataViewer": "VIEWER", +} + +func resourceBigQueryDatasetAccessRoleDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + if primitiveRole, ok := bigqueryAccessRoleToPrimitiveMap[new]; ok { + return primitiveRole == old + } + return false +} + func resourceBigQueryDatasetAccess() *schema.Resource { return &schema.Resource{ Create: resourceBigQueryDatasetAccessCreate, @@ -68,9 +81,10 @@ group, domain, or special group. For example: 'allUsers'`, ExactlyOneOf: []string{"user_by_email", "group_by_email", "domain", "special_group", "iam_member", "view"}, }, "role": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: resourceBigQueryDatasetAccessRoleDiffSuppress, Description: `Describes the rights granted to the user specified by the other member of the access object. Primitive, Predefined and custom roles are supported. Predefined roles that have equivalent @@ -396,6 +410,13 @@ func expandNestedBigQueryDatasetAccessDatasetId(v interface{}, d TerraformResour } func expandNestedBigQueryDatasetAccessRole(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + if v == nil { + return nil, nil + } + + if primitiveRole, ok := bigqueryAccessRoleToPrimitiveMap[v.(string)]; ok { + return primitiveRole, nil + } return v, nil } diff --git a/google/resource_bigquery_dataset_access_test.go b/google/resource_bigquery_dataset_access_test.go index 0cbd8657ce6..3cb1b0f3acd 100644 --- a/google/resource_bigquery_dataset_access_test.go +++ b/google/resource_bigquery_dataset_access_test.go @@ -106,6 +106,37 @@ func TestAccBigQueryDatasetAccess_multiple(t *testing.T) { }) } +func TestAccBigQueryDatasetAccess_predefinedRole(t *testing.T) { + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", randString(t, 10)) + + expected1 := map[string]interface{}{ + "role": "WRITER", + "domain": "google.com", + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDatasetAccess_predefinedRole(datasetID), + Check: resource.ComposeTestCheckFunc( + testAccCheckBigQueryDatasetAccessPresent(t, "google_bigquery_dataset.dataset", expected1), + ), + }, + { + // Destroy step instead of CheckDestroy so we can check the access is removed without deleting the dataset + Config: testAccBigQueryDatasetAccess_destroy(datasetID, "dataset"), + Check: resource.ComposeTestCheckFunc( + testAccCheckBigQueryDatasetAccessAbsent(t, "google_bigquery_dataset.dataset", expected1), + ), + }, + }, + }) +} + func testAccCheckBigQueryDatasetAccessPresent(t *testing.T, n string, expected map[string]interface{}) resource.TestCheckFunc { return testAccCheckBigQueryDatasetAccess(t, n, expected, true) } @@ -224,3 +255,17 @@ resource "google_bigquery_dataset" "dataset" { } `, datasetID) } + +func testAccBigQueryDatasetAccess_predefinedRole(datasetID string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset_access" "access" { + dataset_id = google_bigquery_dataset.dataset.dataset_id + role = "roles/bigquery.dataEditor" + domain = "google.com" +} + +resource "google_bigquery_dataset" "dataset" { + dataset_id = "%s" +} +`, datasetID) +} diff --git a/website/docs/r/bigquery_dataset.html.markdown b/website/docs/r/bigquery_dataset.html.markdown index fbe6598fa9c..d27b3900ee8 100644 --- a/website/docs/r/bigquery_dataset.html.markdown +++ b/website/docs/r/bigquery_dataset.html.markdown @@ -206,7 +206,7 @@ The `access` block supports: member of the access object. Primitive, Predefined and custom roles are supported. Predefined roles that have equivalent primitive roles are swapped by the API to their Primitive - counterparts, and will show a diff post-create. See + counterparts. See [official docs](https://cloud.google.com/bigquery/docs/access-control). * `special_group` -