From ff0de07e1f71d630ca2fa50e56e96c19e688756b Mon Sep 17 00:00:00 2001 From: dginty4 Date: Fri, 13 Sep 2024 12:06:57 +0100 Subject: [PATCH] Fixed consistency checkers ability to handle sets --- .../consistency_checker.go | 29 +++++---------- .../consistency_checker_utils.go | 35 ++++++++++++------- .../resource_genesyscloud_oauth_client.go | 6 ++++ 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/genesyscloud/consistency_checker/consistency_checker.go b/genesyscloud/consistency_checker/consistency_checker.go index 773838395..9fe137cc0 100644 --- a/genesyscloud/consistency_checker/consistency_checker.go +++ b/genesyscloud/consistency_checker/consistency_checker.go @@ -39,6 +39,7 @@ type ConsistencyCheck struct { maxStateChecks int resourceType string computedBlocks []string + computedAttributes []string } type consistencyError struct { @@ -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() @@ -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) @@ -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]) } diff --git a/genesyscloud/consistency_checker/consistency_checker_utils.go b/genesyscloud/consistency_checker/consistency_checker_utils.go index d4968d8be..1dc2d6538 100644 --- a/genesyscloud/consistency_checker/consistency_checker_utils.go +++ b/genesyscloud/consistency_checker/consistency_checker_utils.go @@ -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) + } } } } @@ -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 .x. to . before comparing attrParts := strings.Split(attribute, ".") var cleanAttrName string @@ -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 } diff --git a/genesyscloud/oauth_client/resource_genesyscloud_oauth_client.go b/genesyscloud/oauth_client/resource_genesyscloud_oauth_client.go index 3693ad9a0..dfe5233b7 100644 --- a/genesyscloud/oauth_client/resource_genesyscloud_oauth_client.go +++ b/genesyscloud/oauth_client/resource_genesyscloud_oauth_client.go @@ -106,6 +106,12 @@ func createOAuthClient(ctx context.Context, d *schema.ResourceData, meta interfa _ = d.Set("integration_credential_name", *credential.Name) } + 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)