Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made bigquery table schema diffsuppress func handle nested lists gracefully #4832

Merged
merged 6 commits into from
Jun 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 27 additions & 22 deletions mmv1/third_party/terraform/resources/resource_bigquery_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"log"
"sort"
"strconv"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -43,7 +44,7 @@ func bigQueryTablecheckNameExists(jsonList []interface{}) error {
// Compares two json's while optionally taking in a compareMapKeyVal function.
// This function will override any comparison of a given map[string]interface{}
// on a specific key value allowing for a separate equality in specific scenarios
func jsonCompareWithMapKeyOverride(a, b interface{}, compareMapKeyVal func(key string, val1, val2 map[string]interface{}) bool) (bool, error) {
func jsonCompareWithMapKeyOverride(key string, a, b interface{}, compareMapKeyVal func(key string, val1, val2 map[string]interface{}) bool) (bool, error) {
switch a.(type) {
case []interface{}:
arrayA := a.([]interface{})
Expand All @@ -53,16 +54,20 @@ func jsonCompareWithMapKeyOverride(a, b interface{}, compareMapKeyVal func(key s
} else if len(arrayA) != len(arrayB) {
return false, nil
}
if err := bigQueryTablecheckNameExists(arrayA); err != nil {
return false, err
}
bigQueryTableSortArrayByName(arrayA)
if err := bigQueryTablecheckNameExists(arrayB); err != nil {
return false, err

// Sort fields by name so reordering them doesn't cause a diff.
if key == "schema" || key == "fields" {
if err := bigQueryTablecheckNameExists(arrayA); err != nil {
return false, err
}
bigQueryTableSortArrayByName(arrayA)
if err := bigQueryTablecheckNameExists(arrayB); err != nil {
return false, err
}
bigQueryTableSortArrayByName(arrayB)
}
bigQueryTableSortArrayByName(arrayB)
for i := range arrayA {
eq, err := jsonCompareWithMapKeyOverride(arrayA[i], arrayB[i], compareMapKeyVal)
eq, err := jsonCompareWithMapKeyOverride(strconv.Itoa(i), arrayA[i], arrayB[i], compareMapKeyVal)
if err != nil {
return false, err
} else if !eq {
Expand All @@ -78,22 +83,22 @@ func jsonCompareWithMapKeyOverride(a, b interface{}, compareMapKeyVal func(key s
}

var unionOfKeys map[string]bool = make(map[string]bool)
for key := range objectA {
unionOfKeys[key] = true
for subKey := range objectA {
unionOfKeys[subKey] = true
}
for key := range objectB {
unionOfKeys[key] = true
for subKey := range objectB {
unionOfKeys[subKey] = true
}

for key := range unionOfKeys {
eq := compareMapKeyVal(key, objectA, objectB)
for subKey := range unionOfKeys {
eq := compareMapKeyVal(subKey, objectA, objectB)
if !eq {
valA, ok1 := objectA[key]
valB, ok2 := objectB[key]
valA, ok1 := objectA[subKey]
valB, ok2 := objectB[subKey]
if !ok1 || !ok2 {
return false, nil
}
eq, err := jsonCompareWithMapKeyOverride(valA, valB, compareMapKeyVal)
eq, err := jsonCompareWithMapKeyOverride(subKey, valA, valB, compareMapKeyVal)
if err != nil || !eq {
return false, err
}
Expand Down Expand Up @@ -140,20 +145,20 @@ func bigQueryTableMapKeyOverride(key string, objectA, objectB map[string]interfa
}

// Compare the JSON strings are equal
func bigQueryTableSchemaDiffSuppress(_, old, new string, _ *schema.ResourceData) bool {
func bigQueryTableSchemaDiffSuppress(name, old, new string, _ *schema.ResourceData) bool {
// The API can return an empty schema which gets encoded to "null" during read.
if old == "null" {
old = "[]"
}
var a, b interface{}
if err := json.Unmarshal([]byte(old), &a); err != nil {
log.Printf("[DEBUG] unable to unmarshal json - %v", err)
log.Printf("[DEBUG] unable to unmarshal old json - %v", err)
}
if err := json.Unmarshal([]byte(new), &b); err != nil {
log.Printf("[DEBUG] unable to unmarshal json - %v", err)
log.Printf("[DEBUG] unable to unmarshal new json - %v", err)
}

eq, err := jsonCompareWithMapKeyOverride(a, b, bigQueryTableMapKeyOverride)
eq, err := jsonCompareWithMapKeyOverride(name, a, b, bigQueryTableMapKeyOverride)
if err != nil {
log.Printf("[DEBUG] %v", err)
log.Printf("[DEBUG] Error comparing JSON: %v, %v", old, new)
Expand Down
Loading