Skip to content

Commit 7d12617

Browse files
Handle email casing in google_bigquery_dataset access (#15792) (#11139)
[upstream:d5a72e8bc4be1d9d998b62c49280c4cdc6e34423] Signed-off-by: Modular Magician <magic-modules@google.com>
1 parent 989522d commit 7d12617

File tree

3 files changed

+97
-10
lines changed

3 files changed

+97
-10
lines changed

.changelog/15792.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:bug
2+
bigquery: fixed the permadiff when email field values contain non-lower-case characters in `access` in `google_bigquery_dataset`
3+
```

google-beta/services/bigquery/resource_bigquery_dataset.go

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ func validateDefaultTableExpirationMs(v interface{}, k string) (ws []string, err
8787
}
8888

8989
// bigqueryDatasetAccessHash is a custom hash function for the access block.
90-
// It normalizes the 'role' field before hashing, treating legacy roles
91-
// and their modern IAM equivalents as the same.
90+
// It normalizes
91+
// 1) the 'role' field before hashing, treating legacy roles
92+
// and their modern IAM equivalents as the same,
93+
// 2) the 'user_by_email' and 'group_by_email' fields to be case-insensitive.
9294
func resourceBigqueryDatasetAccessHash(v interface{}) int {
9395
m, ok := v.(map[string]interface{})
9496
if !ok {
@@ -100,6 +102,14 @@ func resourceBigqueryDatasetAccessHash(v interface{}) int {
100102
copy[k] = val
101103
}
102104

105+
// Normalize user_by_email and group_by_email to be case-insensitive
106+
if email, ok := copy["user_by_email"].(string); ok && email != "" {
107+
copy["user_by_email"] = strings.ToLower(email)
108+
}
109+
if email, ok := copy["group_by_email"].(string); ok && email != "" {
110+
copy["group_by_email"] = strings.ToLower(email)
111+
}
112+
103113
// Normalize the role if it exists and matches a legacy role.
104114
if role, ok := copy["role"].(string); ok {
105115
if newRole, ok := bigqueryDatasetAccessPrimitiveToRoleMap[role]; ok {
@@ -1142,7 +1152,11 @@ func flattenBigQueryDatasetAccessDomain(v interface{}, d *schema.ResourceData, c
11421152
}
11431153

11441154
func flattenBigQueryDatasetAccessGroupByEmail(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1145-
return v
1155+
if v == nil {
1156+
return nil
1157+
}
1158+
1159+
return strings.ToLower(v.(string))
11461160
}
11471161

11481162
func flattenBigQueryDatasetAccessRole(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
@@ -1158,7 +1172,11 @@ func flattenBigQueryDatasetAccessIamMember(v interface{}, d *schema.ResourceData
11581172
}
11591173

11601174
func flattenBigQueryDatasetAccessUserByEmail(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1161-
return v
1175+
if v == nil {
1176+
return nil
1177+
}
1178+
1179+
return strings.ToLower(v.(string))
11621180
}
11631181

11641182
func flattenBigQueryDatasetAccessView(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
@@ -1614,7 +1632,11 @@ func expandBigQueryDatasetAccessDomain(v interface{}, d tpgresource.TerraformRes
16141632
}
16151633

16161634
func expandBigQueryDatasetAccessGroupByEmail(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1617-
return v, nil
1635+
if v == nil {
1636+
return nil, nil
1637+
}
1638+
1639+
return strings.ToLower(v.(string)), nil
16181640
}
16191641

16201642
func expandBigQueryDatasetAccessRole(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
@@ -1630,7 +1652,11 @@ func expandBigQueryDatasetAccessIamMember(v interface{}, d tpgresource.Terraform
16301652
}
16311653

16321654
func expandBigQueryDatasetAccessUserByEmail(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1633-
return v, nil
1655+
if v == nil {
1656+
return nil, nil
1657+
}
1658+
1659+
return strings.ToLower(v.(string)), nil
16341660
}
16351661

16361662
func expandBigQueryDatasetAccessView(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {

google-beta/services/bigquery/resource_bigquery_dataset_test.go

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@ package bigquery_test
2020

2121
import (
2222
"fmt"
23-
"regexp"
24-
"strings"
25-
"testing"
26-
2723
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
2824
"github.com/hashicorp/terraform-plugin-testing/terraform"
2925
"github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest"
3026
"github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar"
3127
"google.golang.org/api/bigquery/v2"
28+
"regexp"
29+
"strings"
30+
"testing"
3231
)
3332

3433
func TestAccBigQueryDataset_basic(t *testing.T) {
@@ -335,6 +334,52 @@ func TestAccBigQueryDataset_access(t *testing.T) {
335334
})
336335
}
337336

337+
func TestAccBigQueryDataset_accessMixedCase_userByEmail(t *testing.T) {
338+
t.Parallel()
339+
340+
datasetID := fmt.Sprintf("tf_test_access_%s", acctest.RandString(t, 10))
341+
342+
acctest.VcrTest(t, resource.TestCase{
343+
PreCheck: func() { acctest.AccTestPreCheck(t) },
344+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
345+
CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t),
346+
Steps: []resource.TestStep{
347+
{
348+
Config: testAccBigQueryDataset_accessMixedCase(datasetID, "user_by_email", "alicE@google.COM"),
349+
},
350+
{
351+
ResourceName: "google_bigquery_dataset.access_test",
352+
ImportState: true,
353+
ImportStateVerify: true,
354+
ImportStateVerifyIgnore: []string{"labels", "terraform_labels"},
355+
},
356+
},
357+
})
358+
}
359+
360+
func TestAccBigQueryDataset_accessMixedCase_groupByEmail(t *testing.T) {
361+
t.Parallel()
362+
363+
datasetID := fmt.Sprintf("tf_test_access_%s", acctest.RandString(t, 10))
364+
365+
acctest.VcrTest(t, resource.TestCase{
366+
PreCheck: func() { acctest.AccTestPreCheck(t) },
367+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
368+
CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t),
369+
Steps: []resource.TestStep{
370+
{
371+
Config: testAccBigQueryDataset_accessMixedCase(datasetID, "group_by_email", "MAGIC-MODULES@gOOgle.com"),
372+
},
373+
{
374+
ResourceName: "google_bigquery_dataset.access_test",
375+
ImportState: true,
376+
ImportStateVerify: true,
377+
ImportStateVerifyIgnore: []string{"labels", "terraform_labels"},
378+
},
379+
},
380+
})
381+
}
382+
338383
func TestAccBigQueryDataset_regionalLocation(t *testing.T) {
339384
t.Parallel()
340385

@@ -855,6 +900,19 @@ resource "google_bigquery_dataset" "access_test" {
855900
`, otherDatasetID, otherTableID, datasetID)
856901
}
857902

903+
func testAccBigQueryDataset_accessMixedCase(datasetID, accessType, email string) string {
904+
return fmt.Sprintf(`
905+
resource "google_bigquery_dataset" "access_test" {
906+
dataset_id = "%s"
907+
908+
access {
909+
role = "OWNER"
910+
%s = "%s"
911+
}
912+
}
913+
`, datasetID, accessType, email)
914+
}
915+
858916
func testAccBigQueryDataset_cmek(pid, datasetID, kmsKey string) string {
859917
return fmt.Sprintf(`
860918
data "google_project" "project" {

0 commit comments

Comments
 (0)