Skip to content

Commit

Permalink
updates post create rather than using customize diff
Browse files Browse the repository at this point in the history
  • Loading branch information
megan07 committed Aug 14, 2020
1 parent 35b05b7 commit 40b312d
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 92 deletions.
37 changes: 12 additions & 25 deletions products/bigquery/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,32 +103,19 @@ overrides: !ruby/object:Overrides::ResourceOverrides
# before comparison.
custom_expand: "templates/terraform/custom_expand/bigquery_access_role.go.erb"
iamMember: !ruby/object:Overrides::Terraform::PropertyOverride
# iamMember sometimes gets returned as userByEmail, groupByEmail, domain, or specialGroup
# and needs to be "computed" in order for the customizeDiff to Clear it from the diff
default_from_api: true
userByEmail: !ruby/object:Overrides::Terraform::PropertyOverride
# these need to be "computed" in order for the customizeDiff to be SetNew
# with iamMember. we parse the value passed into iamMember and reconfigure
# one of these fields based in the prefix of the value passed in
default_from_api: true
groupByEmail: !ruby/object:Overrides::Terraform::PropertyOverride
# these need to be "computed" in order for the customizeDiff to be SetNew
# with iamMember. we parse the value passed into iamMember and reconfigure
# one of these fields based in the prefix of the value passed in
default_from_api: true
domain: !ruby/object:Overrides::Terraform::PropertyOverride
# these need to be "computed" in order for the customizeDiff to be SetNew
# with iamMember. we parse the value passed into iamMember and reconfigure
# one of these fields based in the prefix of the value passed in
default_from_api: true
specialGroup: !ruby/object:Overrides::Terraform::PropertyOverride
# these need to be "computed" in order for the customizeDiff to be SetNew
# with iamMember. we parse the value passed into iamMember and reconfigure
# one of these fields based in the prefix of the value passed in
default_from_api: true
diff_suppress_func: resourceBigQueryDatasetAccessIamMemberDiffSuppress
userByEmail: !ruby/object:Overrides::Terraform::PropertyOverride
diff_suppress_func: resourceBigQueryDatasetAccessIamMemberDiffSuppress
groupByEmail: !ruby/object:Overrides::Terraform::PropertyOverride
diff_suppress_func: resourceBigQueryDatasetAccessIamMemberDiffSuppress
specialGroup: !ruby/object:Overrides::Terraform::PropertyOverride
diff_suppress_func: resourceBigQueryDatasetAccessIamMemberDiffSuppress
domain: !ruby/object:Overrides::Terraform::PropertyOverride
diff_suppress_func: resourceBigQueryDatasetAccessIamMemberDiffSuppress
custom_code: !ruby/object:Provider::Terraform::CustomCode
constants: templates/terraform/constants/bigquery_dataset_access.go
resource_definition: templates/terraform/resource_definition/bigquery_dataset_access.go.erb
constants: templates/terraform/constants/bigquery_dataset_access.go.erb
post_create: templates/terraform/post_create/bigquery_dataset_access.go.erb
extra_schema_entry: templates/terraform/extra_schema_entry/bigquery_dataset_access.go.erb
Job: !ruby/object:Overrides::Terraform::ResourceOverride
import_format: ["projects/{{project}}/jobs/{{job_id}}"]
skip_delete: true
Expand Down
66 changes: 0 additions & 66 deletions templates/terraform/constants/bigquery_dataset_access.go

This file was deleted.

126 changes: 126 additions & 0 deletions templates/terraform/constants/bigquery_dataset_access.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
var bigqueryAccessRoleToPrimitiveMap = map[string]string {
"roles/bigquery.dataOwner": "OWNER",
"roles/bigquery.dataEditor": "WRITER",
"roles/bigquery.dataViewer": "READER",
}

var bigqueryAccessIamMemberToTypeMap = map[string]string{
"serviceAccount": "user_by_email",
"user": "user_by_email",
"group": "group_by_email",
"domain": "domain",
"specialGroup": "special_group",
"allUsers": "iam_member",
"projectOwners": "special_group",
"projectReaders": "special_group",
"projectWriters": "special_group",
"allAuthenticatedUsers": "special_group",
}

func resourceBigQueryDatasetAccessRoleDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
if primitiveRole, ok := bigqueryAccessRoleToPrimitiveMap[new]; ok {
return primitiveRole == old
}
return false
}

func resourceBigQueryDatasetAccessIamMemberDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
if primitiveRole, ok := bigqueryAccessRoleToPrimitiveMap[new]; ok {
return primitiveRole == old
}

if d.Get("api_updated_member") == true {
expectedIamMember := d.Get("iam_member").(string)
parts := strings.SplitAfter(expectedIamMember, ":")

strippedIamMember := parts[0]
if len(parts) > 1 {
strippedIamMember = parts[1]
}

if memberInState := d.Get("user_by_email").(string); memberInState != "" {
return memberInState == strippedIamMember
}

if memberInState := d.Get("group_by_email").(string); memberInState != "" {
return memberInState == strippedIamMember
}

if memberInState := d.Get("domain").(string); memberInState != "" {
return memberInState == strippedIamMember
}

if memberInState := d.Get("special_group").(string); memberInState != "" {
return memberInState == strippedIamMember
}
}

return false
}

// this function will go through a response's access list and see if the iam_member has been reassigned to a different member_type
// if it has, it will return the member type, and the member
func resourceBigQueryDatasetAccessReassignIamMemberInNestedObjectList(d *schema.ResourceData, meta interface{}, items []interface{}) (member_type string, member interface{}, err error) {
expectedRole, err := expandNestedBigQueryDatasetAccessRole(d.Get("role"), d, meta.(*Config))
if err != nil {
return "", nil, err
}
expectedFlattenedRole := flattenNestedBigQueryDatasetAccessRole(expectedRole, d, meta.(*Config))

expectedIamMember, err := expandNestedBigQueryDatasetAccessIamMember(d.Get("iam_member"), d, meta.(*Config))
if err != nil {
return "", nil, err
}
expectedFlattenedIamMember := flattenNestedBigQueryDatasetAccessIamMember(expectedIamMember, d, meta.(*Config))

parts := strings.SplitAfter(expectedFlattenedIamMember.(string), ":")

expectedStrippedIamMember := parts[0]
if len(parts) > 1 {
expectedStrippedIamMember = parts[1]
}

// Search list for this resource.
for _, itemRaw := range items {
if itemRaw == nil {
continue
}
item := itemRaw.(map[string]interface{})

itemRole := flattenNestedBigQueryDatasetAccessRole(item["role"], d, meta.(*Config))
// isEmptyValue check so that if one is nil and the other is "", that's considered a match
if !(isEmptyValue(reflect.ValueOf(itemRole)) && isEmptyValue(reflect.ValueOf(expectedFlattenedRole))) && !reflect.DeepEqual(itemRole, expectedFlattenedRole) {
log.Printf("[DEBUG] Skipping item with role= %#v, looking for %#v)", itemRole, expectedFlattenedRole)
continue
}

itemUserByEmail := flattenNestedBigQueryDatasetAccessUserByEmail(item["userByEmail"], d, meta.(*Config))
if reflect.DeepEqual(itemUserByEmail, expectedStrippedIamMember) {
log.Printf("[DEBUG] Iam Member changed to userByEmail= %#v)", itemUserByEmail)
return "user_by_email", itemUserByEmail, nil
}
itemGroupByEmail := flattenNestedBigQueryDatasetAccessGroupByEmail(item["groupByEmail"], d, meta.(*Config))
if reflect.DeepEqual(itemGroupByEmail, expectedStrippedIamMember) {
log.Printf("[DEBUG] Iam Member changed to groupByEmail= %#v)", itemGroupByEmail)
return "group_by_email", itemGroupByEmail, nil
}
itemDomain := flattenNestedBigQueryDatasetAccessDomain(item["domain"], d, meta.(*Config))
if reflect.DeepEqual(itemDomain, expectedStrippedIamMember) {
log.Printf("[DEBUG] Iam Member changed to domain= %#v)", itemDomain)
return "domain", itemDomain, nil
}
itemSpecialGroup := flattenNestedBigQueryDatasetAccessSpecialGroup(item["specialGroup"], d, meta.(*Config))
if reflect.DeepEqual(itemSpecialGroup, expectedStrippedIamMember) {
log.Printf("[DEBUG] Iam Member changed to specialGroup= %#v)", itemSpecialGroup)
return "special_group", itemSpecialGroup, nil
}
itemIamMember := flattenNestedBigQueryDatasetAccessIamMember(item["iamMember"], d, meta.(*Config))
if reflect.DeepEqual(itemIamMember, expectedFlattenedIamMember) {
log.Printf("[DEBUG] Iam Member stayed as iamMember= %#v)", itemIamMember)
return "", nil, nil
}
continue
}
log.Printf("[DEBUG] Did not find item for resource %q)", d.Id())
return "", nil, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-%>
CustomizeDiff: customDiffBigQueryDatasetAccess,
"api_updated_member": {
Type: schema.TypeBool,
Computed: true,
Description: "If true, represents that that the iam_member in the config was translated to a different member type by the API, and is stored in state as a different member type",
},
34 changes: 34 additions & 0 deletions templates/terraform/post_create/bigquery_dataset_access.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<%# The license inside this block applies to this file.
# Copyright 2020 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-%>

// by default, we are not updating the member
d.Set("api_updated_member", false)

// iam_member is a generalized attribute, if the API can map it to a different member type on the backend, it will return
// the correct member_type in the response. If it cannot be mapped to a different member type, it will stay in iam_member.
if d.Get("iam_member") != nil {
member_type, member, err := resourceBigQueryDatasetAccessReassignIamMemberInNestedObjectList(d, meta, res["access"].([]interface{}))
if err != nil {
fmt.Println(err)
}

// if the member type changed, we set that member_type in state (it's already in the response) and we clear iam_member
// and we set "api_updated_member" to true to acknowledge that we are making this change
if member_type != "" {
d.Set(member_type, member.(string))
d.Set("iam_member", "")
d.Set("api_updated_member", true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ func TestAccBigQueryDatasetAccess_allUsers(t *testing.T) {
{
Config: testAccBigQueryDatasetAccess_allUsers(datasetID),
},
{
Config: testAccBigQueryDatasetAccess_allAuthenticatedUsers(datasetID),
},
},
})
}
Expand Down

0 comments on commit 40b312d

Please sign in to comment.