Skip to content

Commit d5a72e8

Browse files
authored
Handle email casing in google_bigquery_dataset access (#15792)
1 parent b117259 commit d5a72e8

File tree

3 files changed

+78
-6
lines changed

3 files changed

+78
-6
lines changed

mmv1/products/bigquery/Dataset.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ properties:
142142
- name: 'groupByEmail'
143143
type: String
144144
description: An email address of a Google Group to grant access to.
145+
custom_expand: 'templates/terraform/custom_expand/string_to_lower_case.go.tmpl'
146+
custom_flatten: 'templates/terraform/custom_flatten/string_to_lower_case.go.tmpl'
145147
- name: 'role'
146148
type: String
147149
description: |
@@ -168,6 +170,8 @@ properties:
168170
description: |
169171
An email address of a user to grant access to. For example:
170172
173+
custom_expand: 'templates/terraform/custom_expand/string_to_lower_case.go.tmpl'
174+
custom_flatten: 'templates/terraform/custom_flatten/string_to_lower_case.go.tmpl'
171175
- name: 'view'
172176
type: NestedObject
173177
description: |

mmv1/templates/terraform/constants/bigquery_dataset.go.tmpl

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

3333
{{- if ne $.Compiler "terraformgoogleconversion-codegen" }}
3434
// bigqueryDatasetAccessHash is a custom hash function for the access block.
35-
// It normalizes the 'role' field before hashing, treating legacy roles
36-
// and their modern IAM equivalents as the same.
35+
// It normalizes
36+
// 1) the 'role' field before hashing, treating legacy roles
37+
// and their modern IAM equivalents as the same,
38+
// 2) the 'user_by_email' and 'group_by_email' fields to be case-insensitive.
3739
func resourceBigqueryDatasetAccessHash(v interface{}) int {
3840
m, ok := v.(map[string]interface{})
3941
if !ok {
@@ -45,6 +47,14 @@ func resourceBigqueryDatasetAccessHash(v interface{}) int {
4547
copy[k] = val
4648
}
4749

50+
// Normalize user_by_email and group_by_email to be case-insensitive
51+
if email, ok := copy["user_by_email"].(string); ok && email != "" {
52+
copy["user_by_email"] = strings.ToLower(email)
53+
}
54+
if email, ok := copy["group_by_email"].(string); ok && email != "" {
55+
copy["group_by_email"] = strings.ToLower(email)
56+
}
57+
4858
// Normalize the role if it exists and matches a legacy role.
4959
if role, ok := copy["role"].(string); ok {
5060
if newRole, ok := bigqueryDatasetAccessPrimitiveToRoleMap[role]; ok {

mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go

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

55
import (
66
"fmt"
7-
"regexp"
8-
"strings"
9-
"testing"
10-
117
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
128
"github.com/hashicorp/terraform-plugin-testing/terraform"
139
"github.com/hashicorp/terraform-provider-google/google/acctest"
1410
"github.com/hashicorp/terraform-provider-google/google/envvar"
1511
"google.golang.org/api/bigquery/v2"
12+
"regexp"
13+
"strings"
14+
"testing"
1615
)
1716

1817
func TestAccBigQueryDataset_basic(t *testing.T) {
@@ -319,6 +318,52 @@ func TestAccBigQueryDataset_access(t *testing.T) {
319318
})
320319
}
321320

321+
func TestAccBigQueryDataset_accessMixedCase_userByEmail(t *testing.T) {
322+
t.Parallel()
323+
324+
datasetID := fmt.Sprintf("tf_test_access_%s", acctest.RandString(t, 10))
325+
326+
acctest.VcrTest(t, resource.TestCase{
327+
PreCheck: func() { acctest.AccTestPreCheck(t) },
328+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
329+
CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t),
330+
Steps: []resource.TestStep{
331+
{
332+
Config: testAccBigQueryDataset_accessMixedCase(datasetID, "user_by_email", "[email protected]"),
333+
},
334+
{
335+
ResourceName: "google_bigquery_dataset.access_test",
336+
ImportState: true,
337+
ImportStateVerify: true,
338+
ImportStateVerifyIgnore: []string{"labels", "terraform_labels"},
339+
},
340+
},
341+
})
342+
}
343+
344+
func TestAccBigQueryDataset_accessMixedCase_groupByEmail(t *testing.T) {
345+
t.Parallel()
346+
347+
datasetID := fmt.Sprintf("tf_test_access_%s", acctest.RandString(t, 10))
348+
349+
acctest.VcrTest(t, resource.TestCase{
350+
PreCheck: func() { acctest.AccTestPreCheck(t) },
351+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
352+
CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t),
353+
Steps: []resource.TestStep{
354+
{
355+
Config: testAccBigQueryDataset_accessMixedCase(datasetID, "group_by_email", "[email protected]"),
356+
},
357+
{
358+
ResourceName: "google_bigquery_dataset.access_test",
359+
ImportState: true,
360+
ImportStateVerify: true,
361+
ImportStateVerifyIgnore: []string{"labels", "terraform_labels"},
362+
},
363+
},
364+
})
365+
}
366+
322367
func TestAccBigQueryDataset_regionalLocation(t *testing.T) {
323368
t.Parallel()
324369

@@ -839,6 +884,19 @@ resource "google_bigquery_dataset" "access_test" {
839884
`, otherDatasetID, otherTableID, datasetID)
840885
}
841886

887+
func testAccBigQueryDataset_accessMixedCase(datasetID, accessType, email string) string {
888+
return fmt.Sprintf(`
889+
resource "google_bigquery_dataset" "access_test" {
890+
dataset_id = "%s"
891+
892+
access {
893+
role = "OWNER"
894+
%s = "%s"
895+
}
896+
}
897+
`, datasetID, accessType, email)
898+
}
899+
842900
func testAccBigQueryDataset_cmek(pid, datasetID, kmsKey string) string {
843901
return fmt.Sprintf(`
844902
data "google_project" "project" {

0 commit comments

Comments
 (0)