github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/jsonformat/differ/object.go (about) 1 package differ 2 3 import ( 4 "github.com/zclconf/go-cty/cty" 5 6 "github.com/hashicorp/terraform/internal/command/jsonformat/collections" 7 "github.com/hashicorp/terraform/internal/command/jsonformat/computed" 8 "github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers" 9 "github.com/hashicorp/terraform/internal/command/jsonprovider" 10 "github.com/hashicorp/terraform/internal/plans" 11 ) 12 13 func (change Change) computeAttributeDiffAsObject(attributes map[string]cty.Type) computed.Diff { 14 attributeDiffs, action := processObject(change, attributes, func(value Change, ctype cty.Type) computed.Diff { 15 return value.ComputeDiffForType(ctype) 16 }) 17 return computed.NewDiff(renderers.Object(attributeDiffs), action, change.ReplacePaths.Matches()) 18 } 19 20 func (change Change) computeAttributeDiffAsNestedObject(attributes map[string]*jsonprovider.Attribute) computed.Diff { 21 attributeDiffs, action := processObject(change, attributes, func(value Change, attribute *jsonprovider.Attribute) computed.Diff { 22 return value.ComputeDiffForAttribute(attribute) 23 }) 24 return computed.NewDiff(renderers.NestedObject(attributeDiffs), action, change.ReplacePaths.Matches()) 25 } 26 27 // processObject steps through the children of value as if it is an object and 28 // calls out to the provided computeDiff function once it has collated the 29 // diffs for each child attribute. 30 // 31 // We have to make this generic as attributes and nested objects process either 32 // cty.Type or jsonprovider.Attribute children respectively. And we want to 33 // reuse as much code as possible. 34 // 35 // Also, as it generic we cannot make this function a method on Change as you 36 // can't create generic methods on structs. Instead, we make this a generic 37 // function that receives the value as an argument. 38 func processObject[T any](v Change, attributes map[string]T, computeDiff func(Change, T) computed.Diff) (map[string]computed.Diff, plans.Action) { 39 attributeDiffs := make(map[string]computed.Diff) 40 mapValue := v.asMap() 41 42 currentAction := v.getDefaultActionForIteration() 43 for key, attribute := range attributes { 44 attributeValue := mapValue.getChild(key) 45 46 if !attributeValue.RelevantAttributes.MatchesPartial() { 47 // Mark non-relevant attributes as unchanged. 48 attributeValue = attributeValue.AsNoOp() 49 } 50 51 // We always assume changes to object are implicit. 52 attributeValue.BeforeExplicit = false 53 attributeValue.AfterExplicit = false 54 55 attributeDiff := computeDiff(attributeValue, attribute) 56 if attributeDiff.Action == plans.NoOp && attributeValue.Before == nil && attributeValue.After == nil { 57 // We skip attributes of objects that are null both before and 58 // after. We don't even count these as unchanged attributes. 59 continue 60 } 61 attributeDiffs[key] = attributeDiff 62 currentAction = collections.CompareActions(currentAction, attributeDiff.Action) 63 } 64 65 return attributeDiffs, currentAction 66 }