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  }