github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/jsonformat/differ/list.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/jsonformat/differ/attribute_path" 10 "github.com/hashicorp/terraform/internal/command/jsonprovider" 11 "github.com/hashicorp/terraform/internal/plans" 12 ) 13 14 func (change Change) computeAttributeDiffAsList(elementType cty.Type) computed.Diff { 15 sliceValue := change.asSlice() 16 17 processIndices := func(beforeIx, afterIx int) computed.Diff { 18 value := sliceValue.getChild(beforeIx, afterIx) 19 20 // It's actually really difficult to render the diffs when some indices 21 // within a slice are relevant and others aren't. To make this simpler 22 // we just treat all children of a relevant list or set as also 23 // relevant. 24 // 25 // Interestingly the terraform plan builder also agrees with this, and 26 // never sets relevant attributes beneath lists or sets. We're just 27 // going to enforce this logic here as well. If the collection is 28 // relevant (decided elsewhere), then every element in the collection is 29 // also relevant. To be clear, in practice even if we didn't do the 30 // following explicitly the effect would be the same. It's just nicer 31 // for us to be clear about the behaviour we expect. 32 // 33 // What makes this difficult is the fact that the beforeIx and afterIx 34 // can be different, and it's quite difficult to work out which one is 35 // the relevant one. For nested lists, block lists, and tuples it's much 36 // easier because we always process the same indices in the before and 37 // after. 38 value.RelevantAttributes = attribute_path.AlwaysMatcher() 39 40 return value.ComputeDiffForType(elementType) 41 } 42 43 isObjType := func(_ interface{}) bool { 44 return elementType.IsObjectType() 45 } 46 47 elements, current := collections.TransformSlice(sliceValue.Before, sliceValue.After, processIndices, isObjType) 48 return computed.NewDiff(renderers.List(elements), current, change.ReplacePaths.Matches()) 49 } 50 51 func (change Change) computeAttributeDiffAsNestedList(attributes map[string]*jsonprovider.Attribute) computed.Diff { 52 var elements []computed.Diff 53 current := change.getDefaultActionForIteration() 54 change.processNestedList(func(value Change) { 55 element := value.computeDiffForNestedAttribute(&jsonprovider.NestedType{ 56 Attributes: attributes, 57 NestingMode: "single", 58 }) 59 elements = append(elements, element) 60 current = collections.CompareActions(current, element.Action) 61 }) 62 return computed.NewDiff(renderers.NestedList(elements), current, change.ReplacePaths.Matches()) 63 } 64 65 func (change Change) computeBlockDiffsAsList(block *jsonprovider.Block) ([]computed.Diff, plans.Action) { 66 var elements []computed.Diff 67 current := change.getDefaultActionForIteration() 68 change.processNestedList(func(value Change) { 69 element := value.ComputeDiffForBlock(block) 70 elements = append(elements, element) 71 current = collections.CompareActions(current, element.Action) 72 }) 73 return elements, current 74 } 75 76 func (change Change) processNestedList(process func(value Change)) { 77 sliceValue := change.asSlice() 78 for ix := 0; ix < len(sliceValue.Before) || ix < len(sliceValue.After); ix++ { 79 value := sliceValue.getChild(ix, ix) 80 if !value.RelevantAttributes.MatchesPartial() { 81 // Mark non-relevant attributes as unchanged. 82 value = value.AsNoOp() 83 } 84 process(value) 85 } 86 }