Skip to content

Commit

Permalink
Fixed consistency checkers ability to handle sets
Browse files Browse the repository at this point in the history
  • Loading branch information
dginty4 committed Sep 13, 2024
1 parent 15ceeda commit f9f6d06
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 34 deletions.
29 changes: 8 additions & 21 deletions genesyscloud/consistency_checker/consistency_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type ConsistencyCheck struct {
maxStateChecks int
resourceType string
computedBlocks []string
computedAttributes []string
}

type consistencyError struct {
Expand Down Expand Up @@ -87,10 +88,8 @@ func NewConsistencyCheck(ctx context.Context, d *schema.ResourceData, meta inter
resourceType: resourceType,
}

// Find any computed nested blocks
var computedBlocks []string
populateComputedBlocks(cc.resource, &computedBlocks, "")
cc.computedBlocks = computedBlocks
// Find computed properties
populateComputedProperties(cc.resource, &cc.computedAttributes, &cc.computedBlocks, "")

mccMutex.Lock()
defer mccMutex.Unlock()
Expand Down Expand Up @@ -126,7 +125,7 @@ func (cc *ConsistencyCheck) CheckState(currentState *schema.ResourceData) *retry
currentStateMap := resourceDataToMap(currentState)
currentStateValues := currentState.State().Attributes

// Sort attributes. This ensure we check top level attributes and number of blocks before nested blocks
// Sort attributes. This ensures we check top level attributes and number of blocks before nested blocks
var attributesSorted []string
for attribute := range diff.Attributes {
attributesSorted = append(attributesSorted, attribute)
Expand All @@ -145,25 +144,13 @@ func (cc *ConsistencyCheck) CheckState(currentState *schema.ResourceData) *retry
})

for _, attribute := range attributesSorted {
// If the original state doesn't contain the attribute, skip it
if _, ok := cc.originalStateValues[attribute]; !ok {
// If the original state doesn't contain the attribute or the attribute is computed, skip it
if _, ok := cc.originalStateValues[attribute]; !ok || cc.isComputed(attribute) {
continue
}

// Check we have the same number of nested blocks
if strings.HasSuffix(attribute, "#") {
// Don't check the length of computed blocks
if isComputedBlock(cc.computedBlocks, strings.TrimSuffix(attribute, ".#")) {
continue
}

if cc.originalStateValues[attribute] != currentStateValues[attribute] {
return cc.handleError(attribute, cc.originalStateValues[attribute], currentStateValues[attribute])
}
}

// Handle top level attributes
if !strings.Contains(attribute, ".") {
// Handle top level attributes and the same number of nested blocks
if !strings.Contains(attribute, ".") || strings.HasSuffix(attribute, "#") {
if cc.originalStateValues[attribute] != currentStateValues[attribute] {
return cc.handleError(attribute, cc.originalStateValues[attribute], currentStateValues[attribute])
}
Expand Down
35 changes: 22 additions & 13 deletions genesyscloud/consistency_checker/consistency_checker_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,28 +83,31 @@ func isEmptyState(d *schema.ResourceData) *bool {
return &isEmpty
}

// populateComputedBlocks will find any sets or lists in a resource marked as computed
func populateComputedBlocks(resource *schema.Resource, blocks *[]string, parent string) {
// populateComputedProperties will find any properties in a resource marked as computed
func populateComputedProperties(resource *schema.Resource, attributes, blocks *[]string, parent string) {
for attr, attrSchema := range resource.Schema {
if attrSchema.Type == schema.TypeSet || attrSchema.Type == schema.TypeList {
var fullName string
if parent == "" {
fullName = attr
} else {
fullName = parent + "." + attr
}
var fullName string
if parent == "" {
fullName = attr
} else {
fullName = parent + "." + attr
}

if attrSchema.Type == schema.TypeSet || attrSchema.Type == schema.TypeList {
if attrSchema.Computed == true {
*blocks = append(*blocks, fullName)
}

switch elem := attrSchema.Elem.(type) {
case *schema.Resource:
populateComputedBlocks(elem, blocks, fullName)
populateComputedProperties(elem, attributes, blocks, fullName)
default:
continue
}

} else {
if attrSchema.Computed == true {
*attributes = append(*attributes, fullName)
}
}
}
}
Expand Down Expand Up @@ -173,7 +176,7 @@ func compareSlices(slice1, slice2 []interface{}) bool {
return reflect.DeepEqual(sortedSlice1, sortedSlice2)
}

func isComputedBlock(computedBlocks []string, attribute string) bool {
func (cc *ConsistencyCheck) isComputed(attribute string) bool {
// Convert attribute from <attr1>.x.<attr2> to <attr1>.<attr2> before comparing
attrParts := strings.Split(attribute, ".")
var cleanAttrName string
Expand All @@ -184,11 +187,17 @@ func isComputedBlock(computedBlocks []string, attribute string) bool {
}
cleanAttrName = strings.TrimPrefix(cleanAttrName, ".")

for _, computedBlock := range computedBlocks {
for _, computedBlock := range cc.computedBlocks {
if computedBlock == cleanAttrName {
return true
}
}

for _, computedAttribute := range cc.computedAttributes {
if computedAttribute == cleanAttrName {
return true
}
}

return false
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ func createOAuthClient(ctx context.Context, d *schema.ResourceData, meta interfa

createCredential(ctx, d, client, oauthClientProxy)

if client.RoleDivisions != nil {
_ = d.Set("roles", flattenOAuthRoles(*client.RoleDivisions))
} else {
_ = d.Set("roles", nil)
}

d.SetId(*client.Id)
log.Printf("Created oauth client %s %s", name, *client.Id)
return readOAuthClient(ctx, d, meta)
Expand Down

0 comments on commit f9f6d06

Please sign in to comment.