mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Refactor of differ to make code reuse easier (#33054)
* refactor of differ to make code reuse easier * fix imports
This commit is contained in:
parent
324c82b077
commit
357012a2f3
@ -9,7 +9,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/collections"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
)
|
||||
|
||||
|
@ -3,7 +3,8 @@ package jsonformat
|
||||
import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonplan"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
)
|
||||
@ -42,22 +43,25 @@ func precomputeDiffs(plan Plan, mode plans.Mode) diffs {
|
||||
}
|
||||
|
||||
schema := plan.getSchema(drift)
|
||||
change := structured.FromJsonChange(drift.Change, relevantAttrs)
|
||||
diffs.drift = append(diffs.drift, diff{
|
||||
change: drift,
|
||||
diff: differ.FromJsonChange(drift.Change, relevantAttrs).ComputeDiffForBlock(schema.Block),
|
||||
diff: differ.ComputeDiffForBlock(change, schema.Block),
|
||||
})
|
||||
}
|
||||
|
||||
for _, change := range plan.ResourceChanges {
|
||||
schema := plan.getSchema(change)
|
||||
structuredChange := structured.FromJsonChange(change.Change, attribute_path.AlwaysMatcher())
|
||||
diffs.changes = append(diffs.changes, diff{
|
||||
change: change,
|
||||
diff: differ.FromJsonChange(change.Change, attribute_path.AlwaysMatcher()).ComputeDiffForBlock(schema.Block),
|
||||
diff: differ.ComputeDiffForBlock(structuredChange, schema.Block),
|
||||
})
|
||||
}
|
||||
|
||||
for key, output := range plan.OutputChanges {
|
||||
diffs.outputs[key] = differ.FromJsonChange(output, attribute_path.AlwaysMatcher()).ComputeDiffForOutput()
|
||||
change := structured.FromJsonChange(output, attribute_path.AlwaysMatcher())
|
||||
diffs.outputs[key] = differ.ComputeDiffForOutput(change)
|
||||
}
|
||||
|
||||
return diffs
|
||||
|
@ -1,6 +1,7 @@
|
||||
package differ
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
ctyjson "github.com/zclconf/go-cty/cty/json"
|
||||
|
||||
@ -9,42 +10,42 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
)
|
||||
|
||||
func (change Change) ComputeDiffForAttribute(attribute *jsonprovider.Attribute) computed.Diff {
|
||||
func ComputeDiffForAttribute(change structured.Change, attribute *jsonprovider.Attribute) computed.Diff {
|
||||
if attribute.AttributeNestedType != nil {
|
||||
return change.computeDiffForNestedAttribute(attribute.AttributeNestedType)
|
||||
return computeDiffForNestedAttribute(change, attribute.AttributeNestedType)
|
||||
}
|
||||
return change.ComputeDiffForType(unmarshalAttribute(attribute))
|
||||
return ComputeDiffForType(change, unmarshalAttribute(attribute))
|
||||
}
|
||||
|
||||
func (change Change) computeDiffForNestedAttribute(nested *jsonprovider.NestedType) computed.Diff {
|
||||
if sensitive, ok := change.checkForSensitiveNestedAttribute(nested); ok {
|
||||
func computeDiffForNestedAttribute(change structured.Change, nested *jsonprovider.NestedType) computed.Diff {
|
||||
if sensitive, ok := checkForSensitiveNestedAttribute(change, nested); ok {
|
||||
return sensitive
|
||||
}
|
||||
|
||||
if computed, ok := change.checkForUnknownNestedAttribute(nested); ok {
|
||||
if computed, ok := checkForUnknownNestedAttribute(change, nested); ok {
|
||||
return computed
|
||||
}
|
||||
|
||||
switch NestingMode(nested.NestingMode) {
|
||||
case nestingModeSingle, nestingModeGroup:
|
||||
return change.computeAttributeDiffAsNestedObject(nested.Attributes)
|
||||
return computeAttributeDiffAsNestedObject(change, nested.Attributes)
|
||||
case nestingModeMap:
|
||||
return change.computeAttributeDiffAsNestedMap(nested.Attributes)
|
||||
return computeAttributeDiffAsNestedMap(change, nested.Attributes)
|
||||
case nestingModeList:
|
||||
return change.computeAttributeDiffAsNestedList(nested.Attributes)
|
||||
return computeAttributeDiffAsNestedList(change, nested.Attributes)
|
||||
case nestingModeSet:
|
||||
return change.computeAttributeDiffAsNestedSet(nested.Attributes)
|
||||
return computeAttributeDiffAsNestedSet(change, nested.Attributes)
|
||||
default:
|
||||
panic("unrecognized nesting mode: " + nested.NestingMode)
|
||||
}
|
||||
}
|
||||
|
||||
func (change Change) ComputeDiffForType(ctype cty.Type) computed.Diff {
|
||||
if sensitive, ok := change.checkForSensitiveType(ctype); ok {
|
||||
func ComputeDiffForType(change structured.Change, ctype cty.Type) computed.Diff {
|
||||
if sensitive, ok := checkForSensitiveType(change, ctype); ok {
|
||||
return sensitive
|
||||
}
|
||||
|
||||
if computed, ok := change.checkForUnknownType(ctype); ok {
|
||||
if computed, ok := checkForUnknownType(change, ctype); ok {
|
||||
return computed
|
||||
}
|
||||
|
||||
@ -56,19 +57,19 @@ func (change Change) ComputeDiffForType(ctype cty.Type) computed.Diff {
|
||||
// function computeChangeForDynamicValues(), but external callers will
|
||||
// only be in this situation when processing outputs so this function
|
||||
// is named for their benefit.
|
||||
return change.ComputeDiffForOutput()
|
||||
return ComputeDiffForOutput(change)
|
||||
case ctype.IsPrimitiveType():
|
||||
return change.computeAttributeDiffAsPrimitive(ctype)
|
||||
return computeAttributeDiffAsPrimitive(change, ctype)
|
||||
case ctype.IsObjectType():
|
||||
return change.computeAttributeDiffAsObject(ctype.AttributeTypes())
|
||||
return computeAttributeDiffAsObject(change, ctype.AttributeTypes())
|
||||
case ctype.IsMapType():
|
||||
return change.computeAttributeDiffAsMap(ctype.ElementType())
|
||||
return computeAttributeDiffAsMap(change, ctype.ElementType())
|
||||
case ctype.IsListType():
|
||||
return change.computeAttributeDiffAsList(ctype.ElementType())
|
||||
return computeAttributeDiffAsList(change, ctype.ElementType())
|
||||
case ctype.IsTupleType():
|
||||
return change.computeAttributeDiffAsTuple(ctype.TupleElementTypes())
|
||||
return computeAttributeDiffAsTuple(change, ctype.TupleElementTypes())
|
||||
case ctype.IsSetType():
|
||||
return change.computeAttributeDiffAsSet(ctype.ElementType())
|
||||
return computeAttributeDiffAsSet(change, ctype.ElementType())
|
||||
default:
|
||||
panic("unrecognized type: " + ctype.FriendlyName())
|
||||
}
|
||||
|
@ -4,26 +4,27 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/collections"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
)
|
||||
|
||||
func (change Change) ComputeDiffForBlock(block *jsonprovider.Block) computed.Diff {
|
||||
if sensitive, ok := change.checkForSensitiveBlock(block); ok {
|
||||
func ComputeDiffForBlock(change structured.Change, block *jsonprovider.Block) computed.Diff {
|
||||
if sensitive, ok := checkForSensitiveBlock(change, block); ok {
|
||||
return sensitive
|
||||
}
|
||||
|
||||
if unknown, ok := change.checkForUnknownBlock(block); ok {
|
||||
if unknown, ok := checkForUnknownBlock(change, block); ok {
|
||||
return unknown
|
||||
}
|
||||
|
||||
current := change.getDefaultActionForIteration()
|
||||
current := change.GetDefaultActionForIteration()
|
||||
|
||||
blockValue := change.asMap()
|
||||
blockValue := change.AsMap()
|
||||
|
||||
attributes := make(map[string]computed.Diff)
|
||||
for key, attr := range block.Attributes {
|
||||
childValue := blockValue.getChild(key)
|
||||
childValue := blockValue.GetChild(key)
|
||||
|
||||
if !childValue.RelevantAttributes.MatchesPartial() {
|
||||
// Mark non-relevant attributes as unchanged.
|
||||
@ -43,7 +44,7 @@ func (change Change) ComputeDiffForBlock(block *jsonprovider.Block) computed.Dif
|
||||
childValue.BeforeExplicit = false
|
||||
childValue.AfterExplicit = false
|
||||
|
||||
childChange := childValue.ComputeDiffForAttribute(attr)
|
||||
childChange := ComputeDiffForAttribute(childValue, attr)
|
||||
if childChange.Action == plans.NoOp && childValue.Before == nil && childValue.After == nil {
|
||||
// Don't record nil values at all in blocks.
|
||||
continue
|
||||
@ -64,20 +65,20 @@ func (change Change) ComputeDiffForBlock(block *jsonprovider.Block) computed.Dif
|
||||
}
|
||||
|
||||
for key, blockType := range block.BlockTypes {
|
||||
childValue := blockValue.getChild(key)
|
||||
childValue := blockValue.GetChild(key)
|
||||
|
||||
if !childValue.RelevantAttributes.MatchesPartial() {
|
||||
// Mark non-relevant attributes as unchanged.
|
||||
childValue = childValue.AsNoOp()
|
||||
}
|
||||
|
||||
beforeSensitive := childValue.isBeforeSensitive()
|
||||
afterSensitive := childValue.isAfterSensitive()
|
||||
beforeSensitive := childValue.IsBeforeSensitive()
|
||||
afterSensitive := childValue.IsAfterSensitive()
|
||||
forcesReplacement := childValue.ReplacePaths.Matches()
|
||||
|
||||
switch NestingMode(blockType.NestingMode) {
|
||||
case nestingModeSet:
|
||||
diffs, action := childValue.computeBlockDiffsAsSet(blockType.Block)
|
||||
diffs, action := computeBlockDiffsAsSet(childValue, blockType.Block)
|
||||
if action == plans.NoOp && childValue.Before == nil && childValue.After == nil {
|
||||
// Don't record nil values in blocks.
|
||||
continue
|
||||
@ -85,7 +86,7 @@ func (change Change) ComputeDiffForBlock(block *jsonprovider.Block) computed.Dif
|
||||
blocks.AddAllSetBlock(key, diffs, forcesReplacement, beforeSensitive, afterSensitive)
|
||||
current = collections.CompareActions(current, action)
|
||||
case nestingModeList:
|
||||
diffs, action := childValue.computeBlockDiffsAsList(blockType.Block)
|
||||
diffs, action := computeBlockDiffsAsList(childValue, blockType.Block)
|
||||
if action == plans.NoOp && childValue.Before == nil && childValue.After == nil {
|
||||
// Don't record nil values in blocks.
|
||||
continue
|
||||
@ -93,7 +94,7 @@ func (change Change) ComputeDiffForBlock(block *jsonprovider.Block) computed.Dif
|
||||
blocks.AddAllListBlock(key, diffs, forcesReplacement, beforeSensitive, afterSensitive)
|
||||
current = collections.CompareActions(current, action)
|
||||
case nestingModeMap:
|
||||
diffs, action := childValue.computeBlockDiffsAsMap(blockType.Block)
|
||||
diffs, action := computeBlockDiffsAsMap(childValue, blockType.Block)
|
||||
if action == plans.NoOp && childValue.Before == nil && childValue.After == nil {
|
||||
// Don't record nil values in blocks.
|
||||
continue
|
||||
@ -101,7 +102,7 @@ func (change Change) ComputeDiffForBlock(block *jsonprovider.Block) computed.Dif
|
||||
blocks.AddAllMapBlocks(key, diffs, forcesReplacement, beforeSensitive, afterSensitive)
|
||||
current = collections.CompareActions(current, action)
|
||||
case nestingModeSingle, nestingModeGroup:
|
||||
diff := childValue.ComputeDiffForBlock(blockType.Block)
|
||||
diff := ComputeDiffForBlock(childValue, blockType.Block)
|
||||
if diff.Action == plans.NoOp && childValue.Before == nil && childValue.After == nil {
|
||||
// Don't record nil values in blocks.
|
||||
continue
|
||||
|
12
internal/command/jsonformat/differ/differ.go
Normal file
12
internal/command/jsonformat/differ/differ.go
Normal file
@ -0,0 +1,12 @@
|
||||
package differ
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
)
|
||||
|
||||
// asDiff is a helper function to abstract away some simple and common
|
||||
// functionality when converting a renderer into a concrete diff.
|
||||
func asDiff(change structured.Change, renderer computed.DiffRenderer) computed.Diff {
|
||||
return computed.NewDiff(renderer, change.CalculateAction(), change.ReplacePaths.Matches())
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -6,16 +6,17 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/collections"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
)
|
||||
|
||||
func (change Change) computeAttributeDiffAsList(elementType cty.Type) computed.Diff {
|
||||
sliceValue := change.asSlice()
|
||||
func computeAttributeDiffAsList(change structured.Change, elementType cty.Type) computed.Diff {
|
||||
sliceValue := change.AsSlice()
|
||||
|
||||
processIndices := func(beforeIx, afterIx int) computed.Diff {
|
||||
value := sliceValue.getChild(beforeIx, afterIx)
|
||||
value := sliceValue.GetChild(beforeIx, afterIx)
|
||||
|
||||
// It's actually really difficult to render the diffs when some indices
|
||||
// within a slice are relevant and others aren't. To make this simpler
|
||||
@ -37,7 +38,7 @@ func (change Change) computeAttributeDiffAsList(elementType cty.Type) computed.D
|
||||
// after.
|
||||
value.RelevantAttributes = attribute_path.AlwaysMatcher()
|
||||
|
||||
return value.ComputeDiffForType(elementType)
|
||||
return ComputeDiffForType(value, elementType)
|
||||
}
|
||||
|
||||
isObjType := func(_ interface{}) bool {
|
||||
@ -48,11 +49,11 @@ func (change Change) computeAttributeDiffAsList(elementType cty.Type) computed.D
|
||||
return computed.NewDiff(renderers.List(elements), current, change.ReplacePaths.Matches())
|
||||
}
|
||||
|
||||
func (change Change) computeAttributeDiffAsNestedList(attributes map[string]*jsonprovider.Attribute) computed.Diff {
|
||||
func computeAttributeDiffAsNestedList(change structured.Change, attributes map[string]*jsonprovider.Attribute) computed.Diff {
|
||||
var elements []computed.Diff
|
||||
current := change.getDefaultActionForIteration()
|
||||
change.processNestedList(func(value Change) {
|
||||
element := value.computeDiffForNestedAttribute(&jsonprovider.NestedType{
|
||||
current := change.GetDefaultActionForIteration()
|
||||
processNestedList(change, func(value structured.Change) {
|
||||
element := computeDiffForNestedAttribute(value, &jsonprovider.NestedType{
|
||||
Attributes: attributes,
|
||||
NestingMode: "single",
|
||||
})
|
||||
@ -62,21 +63,21 @@ func (change Change) computeAttributeDiffAsNestedList(attributes map[string]*jso
|
||||
return computed.NewDiff(renderers.NestedList(elements), current, change.ReplacePaths.Matches())
|
||||
}
|
||||
|
||||
func (change Change) computeBlockDiffsAsList(block *jsonprovider.Block) ([]computed.Diff, plans.Action) {
|
||||
func computeBlockDiffsAsList(change structured.Change, block *jsonprovider.Block) ([]computed.Diff, plans.Action) {
|
||||
var elements []computed.Diff
|
||||
current := change.getDefaultActionForIteration()
|
||||
change.processNestedList(func(value Change) {
|
||||
element := value.ComputeDiffForBlock(block)
|
||||
current := change.GetDefaultActionForIteration()
|
||||
processNestedList(change, func(value structured.Change) {
|
||||
element := ComputeDiffForBlock(value, block)
|
||||
elements = append(elements, element)
|
||||
current = collections.CompareActions(current, element.Action)
|
||||
})
|
||||
return elements, current
|
||||
}
|
||||
|
||||
func (change Change) processNestedList(process func(value Change)) {
|
||||
sliceValue := change.asSlice()
|
||||
func processNestedList(change structured.Change, process func(value structured.Change)) {
|
||||
sliceValue := change.AsSlice()
|
||||
for ix := 0; ix < len(sliceValue.Before) || ix < len(sliceValue.After); ix++ {
|
||||
value := sliceValue.getChild(ix, ix)
|
||||
value := sliceValue.GetChild(ix, ix)
|
||||
if !value.RelevantAttributes.MatchesPartial() {
|
||||
// Mark non-relevant attributes as unchanged.
|
||||
value = value.AsNoOp()
|
||||
|
@ -6,12 +6,13 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/collections"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
)
|
||||
|
||||
func (change Change) computeAttributeDiffAsMap(elementType cty.Type) computed.Diff {
|
||||
mapValue := change.asMap()
|
||||
func computeAttributeDiffAsMap(change structured.Change, elementType cty.Type) computed.Diff {
|
||||
mapValue := change.AsMap()
|
||||
|
||||
// The jsonplan package will have stripped out unknowns from our after value
|
||||
// so we're going to add them back in here.
|
||||
@ -45,25 +46,25 @@ func (change Change) computeAttributeDiffAsMap(elementType cty.Type) computed.Di
|
||||
}
|
||||
|
||||
elements, current := collections.TransformMap(mapValue.Before, after, func(key string) computed.Diff {
|
||||
value := mapValue.getChild(key)
|
||||
value := mapValue.GetChild(key)
|
||||
if !value.RelevantAttributes.MatchesPartial() {
|
||||
// Mark non-relevant attributes as unchanged.
|
||||
value = value.AsNoOp()
|
||||
}
|
||||
return value.ComputeDiffForType(elementType)
|
||||
return ComputeDiffForType(value, elementType)
|
||||
})
|
||||
return computed.NewDiff(renderers.Map(elements), current, change.ReplacePaths.Matches())
|
||||
}
|
||||
|
||||
func (change Change) computeAttributeDiffAsNestedMap(attributes map[string]*jsonprovider.Attribute) computed.Diff {
|
||||
mapValue := change.asMap()
|
||||
func computeAttributeDiffAsNestedMap(change structured.Change, attributes map[string]*jsonprovider.Attribute) computed.Diff {
|
||||
mapValue := change.AsMap()
|
||||
elements, current := collections.TransformMap(mapValue.Before, mapValue.After, func(key string) computed.Diff {
|
||||
value := mapValue.getChild(key)
|
||||
value := mapValue.GetChild(key)
|
||||
if !value.RelevantAttributes.MatchesPartial() {
|
||||
// Mark non-relevant attributes as unchanged.
|
||||
value = value.AsNoOp()
|
||||
}
|
||||
return value.computeDiffForNestedAttribute(&jsonprovider.NestedType{
|
||||
return computeDiffForNestedAttribute(value, &jsonprovider.NestedType{
|
||||
Attributes: attributes,
|
||||
NestingMode: "single",
|
||||
})
|
||||
@ -71,14 +72,14 @@ func (change Change) computeAttributeDiffAsNestedMap(attributes map[string]*json
|
||||
return computed.NewDiff(renderers.NestedMap(elements), current, change.ReplacePaths.Matches())
|
||||
}
|
||||
|
||||
func (change Change) computeBlockDiffsAsMap(block *jsonprovider.Block) (map[string]computed.Diff, plans.Action) {
|
||||
mapValue := change.asMap()
|
||||
func computeBlockDiffsAsMap(change structured.Change, block *jsonprovider.Block) (map[string]computed.Diff, plans.Action) {
|
||||
mapValue := change.AsMap()
|
||||
return collections.TransformMap(mapValue.Before, mapValue.After, func(key string) computed.Diff {
|
||||
value := mapValue.getChild(key)
|
||||
value := mapValue.GetChild(key)
|
||||
if !value.RelevantAttributes.MatchesPartial() {
|
||||
// Mark non-relevant attributes as unchanged.
|
||||
value = value.AsNoOp()
|
||||
}
|
||||
return value.ComputeDiffForBlock(block)
|
||||
return ComputeDiffForBlock(value, block)
|
||||
})
|
||||
}
|
||||
|
@ -6,20 +6,21 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/collections"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
)
|
||||
|
||||
func (change Change) computeAttributeDiffAsObject(attributes map[string]cty.Type) computed.Diff {
|
||||
attributeDiffs, action := processObject(change, attributes, func(value Change, ctype cty.Type) computed.Diff {
|
||||
return value.ComputeDiffForType(ctype)
|
||||
func computeAttributeDiffAsObject(change structured.Change, attributes map[string]cty.Type) computed.Diff {
|
||||
attributeDiffs, action := processObject(change, attributes, func(value structured.Change, ctype cty.Type) computed.Diff {
|
||||
return ComputeDiffForType(value, ctype)
|
||||
})
|
||||
return computed.NewDiff(renderers.Object(attributeDiffs), action, change.ReplacePaths.Matches())
|
||||
}
|
||||
|
||||
func (change Change) computeAttributeDiffAsNestedObject(attributes map[string]*jsonprovider.Attribute) computed.Diff {
|
||||
attributeDiffs, action := processObject(change, attributes, func(value Change, attribute *jsonprovider.Attribute) computed.Diff {
|
||||
return value.ComputeDiffForAttribute(attribute)
|
||||
func computeAttributeDiffAsNestedObject(change structured.Change, attributes map[string]*jsonprovider.Attribute) computed.Diff {
|
||||
attributeDiffs, action := processObject(change, attributes, func(value structured.Change, attribute *jsonprovider.Attribute) computed.Diff {
|
||||
return ComputeDiffForAttribute(value, attribute)
|
||||
})
|
||||
return computed.NewDiff(renderers.NestedObject(attributeDiffs), action, change.ReplacePaths.Matches())
|
||||
}
|
||||
@ -35,13 +36,13 @@ func (change Change) computeAttributeDiffAsNestedObject(attributes map[string]*j
|
||||
// Also, as it generic we cannot make this function a method on Change as you
|
||||
// can't create generic methods on structs. Instead, we make this a generic
|
||||
// function that receives the value as an argument.
|
||||
func processObject[T any](v Change, attributes map[string]T, computeDiff func(Change, T) computed.Diff) (map[string]computed.Diff, plans.Action) {
|
||||
func processObject[T any](v structured.Change, attributes map[string]T, computeDiff func(structured.Change, T) computed.Diff) (map[string]computed.Diff, plans.Action) {
|
||||
attributeDiffs := make(map[string]computed.Diff)
|
||||
mapValue := v.asMap()
|
||||
mapValue := v.AsMap()
|
||||
|
||||
currentAction := v.getDefaultActionForIteration()
|
||||
currentAction := v.GetDefaultActionForIteration()
|
||||
for key, attribute := range attributes {
|
||||
attributeValue := mapValue.getChild(key)
|
||||
attributeValue := mapValue.GetChild(key)
|
||||
|
||||
if !attributeValue.RelevantAttributes.MatchesPartial() {
|
||||
// Mark non-relevant attributes as unchanged.
|
||||
|
@ -5,14 +5,15 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
)
|
||||
|
||||
func (change Change) ComputeDiffForOutput() computed.Diff {
|
||||
if sensitive, ok := change.checkForSensitiveType(cty.DynamicPseudoType); ok {
|
||||
func ComputeDiffForOutput(change structured.Change) computed.Diff {
|
||||
if sensitive, ok := checkForSensitiveType(change, cty.DynamicPseudoType); ok {
|
||||
return sensitive
|
||||
}
|
||||
|
||||
if unknown, ok := change.checkForUnknownType(cty.DynamicPseudoType); ok {
|
||||
if unknown, ok := checkForUnknownType(change, cty.DynamicPseudoType); ok {
|
||||
return unknown
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,10 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
)
|
||||
|
||||
func (change Change) computeAttributeDiffAsPrimitive(ctype cty.Type) computed.Diff {
|
||||
return change.asDiff(renderers.Primitive(change.Before, change.After, ctype))
|
||||
func computeAttributeDiffAsPrimitive(change structured.Change, ctype cty.Type) computed.Diff {
|
||||
return asDiff(change, renderers.Primitive(change.Before, change.After, ctype))
|
||||
}
|
||||
|
@ -5,33 +5,34 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
)
|
||||
|
||||
type CreateSensitiveRenderer func(computed.Diff, bool, bool) computed.DiffRenderer
|
||||
|
||||
func (change Change) checkForSensitiveType(ctype cty.Type) (computed.Diff, bool) {
|
||||
return change.checkForSensitive(renderers.Sensitive, func(value Change) computed.Diff {
|
||||
return value.ComputeDiffForType(ctype)
|
||||
func checkForSensitiveType(change structured.Change, ctype cty.Type) (computed.Diff, bool) {
|
||||
return checkForSensitive(change, renderers.Sensitive, func(value structured.Change) computed.Diff {
|
||||
return ComputeDiffForType(value, ctype)
|
||||
})
|
||||
}
|
||||
|
||||
func (change Change) checkForSensitiveNestedAttribute(attribute *jsonprovider.NestedType) (computed.Diff, bool) {
|
||||
return change.checkForSensitive(renderers.Sensitive, func(value Change) computed.Diff {
|
||||
return value.computeDiffForNestedAttribute(attribute)
|
||||
func checkForSensitiveNestedAttribute(change structured.Change, attribute *jsonprovider.NestedType) (computed.Diff, bool) {
|
||||
return checkForSensitive(change, renderers.Sensitive, func(value structured.Change) computed.Diff {
|
||||
return computeDiffForNestedAttribute(value, attribute)
|
||||
})
|
||||
}
|
||||
|
||||
func (change Change) checkForSensitiveBlock(block *jsonprovider.Block) (computed.Diff, bool) {
|
||||
return change.checkForSensitive(renderers.SensitiveBlock, func(value Change) computed.Diff {
|
||||
return value.ComputeDiffForBlock(block)
|
||||
func checkForSensitiveBlock(change structured.Change, block *jsonprovider.Block) (computed.Diff, bool) {
|
||||
return checkForSensitive(change, renderers.SensitiveBlock, func(value structured.Change) computed.Diff {
|
||||
return ComputeDiffForBlock(value, block)
|
||||
})
|
||||
}
|
||||
|
||||
func (change Change) checkForSensitive(create CreateSensitiveRenderer, computedDiff func(value Change) computed.Diff) (computed.Diff, bool) {
|
||||
beforeSensitive := change.isBeforeSensitive()
|
||||
afterSensitive := change.isAfterSensitive()
|
||||
func checkForSensitive(change structured.Change, create CreateSensitiveRenderer, computedDiff func(value structured.Change) computed.Diff) (computed.Diff, bool) {
|
||||
beforeSensitive := change.IsBeforeSensitive()
|
||||
afterSensitive := change.IsAfterSensitive()
|
||||
|
||||
if !beforeSensitive && !afterSensitive {
|
||||
return computed.Diff{}, false
|
||||
@ -44,7 +45,7 @@ func (change Change) checkForSensitive(create CreateSensitiveRenderer, computedD
|
||||
// The change can choose what to do with this information, in most cases
|
||||
// it will just be ignored in favour of printing `(sensitive value)`.
|
||||
|
||||
value := Change{
|
||||
value := structured.Change{
|
||||
BeforeExplicit: change.BeforeExplicit,
|
||||
AfterExplicit: change.AfterExplicit,
|
||||
Before: change.Before,
|
||||
@ -75,17 +76,3 @@ func (change Change) checkForSensitive(create CreateSensitiveRenderer, computedD
|
||||
|
||||
return computed.NewDiff(create(inner, beforeSensitive, afterSensitive), action, change.ReplacePaths.Matches()), true
|
||||
}
|
||||
|
||||
func (change Change) isBeforeSensitive() bool {
|
||||
if sensitive, ok := change.BeforeSensitive.(bool); ok {
|
||||
return sensitive
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (change Change) isAfterSensitive() bool {
|
||||
if sensitive, ok := change.AfterSensitive.(bool); ok {
|
||||
return sensitive
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -8,27 +8,28 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/collections"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
)
|
||||
|
||||
func (change Change) computeAttributeDiffAsSet(elementType cty.Type) computed.Diff {
|
||||
func computeAttributeDiffAsSet(change structured.Change, elementType cty.Type) computed.Diff {
|
||||
var elements []computed.Diff
|
||||
current := change.getDefaultActionForIteration()
|
||||
change.processSet(func(value Change) {
|
||||
element := value.ComputeDiffForType(elementType)
|
||||
current := change.GetDefaultActionForIteration()
|
||||
processSet(change, func(value structured.Change) {
|
||||
element := ComputeDiffForType(value, elementType)
|
||||
elements = append(elements, element)
|
||||
current = collections.CompareActions(current, element.Action)
|
||||
})
|
||||
return computed.NewDiff(renderers.Set(elements), current, change.ReplacePaths.Matches())
|
||||
}
|
||||
|
||||
func (change Change) computeAttributeDiffAsNestedSet(attributes map[string]*jsonprovider.Attribute) computed.Diff {
|
||||
func computeAttributeDiffAsNestedSet(change structured.Change, attributes map[string]*jsonprovider.Attribute) computed.Diff {
|
||||
var elements []computed.Diff
|
||||
current := change.getDefaultActionForIteration()
|
||||
change.processSet(func(value Change) {
|
||||
element := value.computeDiffForNestedAttribute(&jsonprovider.NestedType{
|
||||
current := change.GetDefaultActionForIteration()
|
||||
processSet(change, func(value structured.Change) {
|
||||
element := computeDiffForNestedAttribute(value, &jsonprovider.NestedType{
|
||||
Attributes: attributes,
|
||||
NestingMode: "single",
|
||||
})
|
||||
@ -38,19 +39,19 @@ func (change Change) computeAttributeDiffAsNestedSet(attributes map[string]*json
|
||||
return computed.NewDiff(renderers.NestedSet(elements), current, change.ReplacePaths.Matches())
|
||||
}
|
||||
|
||||
func (change Change) computeBlockDiffsAsSet(block *jsonprovider.Block) ([]computed.Diff, plans.Action) {
|
||||
func computeBlockDiffsAsSet(change structured.Change, block *jsonprovider.Block) ([]computed.Diff, plans.Action) {
|
||||
var elements []computed.Diff
|
||||
current := change.getDefaultActionForIteration()
|
||||
change.processSet(func(value Change) {
|
||||
element := value.ComputeDiffForBlock(block)
|
||||
current := change.GetDefaultActionForIteration()
|
||||
processSet(change, func(value structured.Change) {
|
||||
element := ComputeDiffForBlock(value, block)
|
||||
elements = append(elements, element)
|
||||
current = collections.CompareActions(current, element.Action)
|
||||
})
|
||||
return elements, current
|
||||
}
|
||||
|
||||
func (change Change) processSet(process func(value Change)) {
|
||||
sliceValue := change.asSlice()
|
||||
func processSet(change structured.Change, process func(value structured.Change)) {
|
||||
sliceValue := change.AsSlice()
|
||||
|
||||
foundInBefore := make(map[int]int)
|
||||
foundInAfter := make(map[int]int)
|
||||
@ -67,8 +68,8 @@ func (change Change) processSet(process func(value Change)) {
|
||||
continue
|
||||
}
|
||||
|
||||
child := sliceValue.getChild(ix, jx)
|
||||
if reflect.DeepEqual(child.Before, child.After) && child.isBeforeSensitive() == child.isAfterSensitive() && !child.isUnknown() {
|
||||
child := sliceValue.GetChild(ix, jx)
|
||||
if reflect.DeepEqual(child.Before, child.After) && child.IsBeforeSensitive() == child.IsAfterSensitive() && !child.IsUnknown() {
|
||||
matched = true
|
||||
foundInBefore[ix] = jx
|
||||
foundInAfter[jx] = ix
|
||||
@ -80,7 +81,7 @@ func (change Change) processSet(process func(value Change)) {
|
||||
}
|
||||
}
|
||||
|
||||
clearRelevantStatus := func(change Change) Change {
|
||||
clearRelevantStatus := func(change structured.Change) structured.Change {
|
||||
// It's actually really difficult to render the diffs when some indices
|
||||
// within a slice are relevant and others aren't. To make this simpler
|
||||
// we just treat all children of a relevant list or set as also
|
||||
@ -112,11 +113,11 @@ func (change Change) processSet(process func(value Change)) {
|
||||
|
||||
for ix := 0; ix < len(sliceValue.Before); ix++ {
|
||||
if jx := foundInBefore[ix]; jx >= 0 {
|
||||
child := clearRelevantStatus(sliceValue.getChild(ix, jx))
|
||||
child := clearRelevantStatus(sliceValue.GetChild(ix, jx))
|
||||
process(child)
|
||||
continue
|
||||
}
|
||||
child := clearRelevantStatus(sliceValue.getChild(ix, len(sliceValue.After)))
|
||||
child := clearRelevantStatus(sliceValue.GetChild(ix, len(sliceValue.After)))
|
||||
process(child)
|
||||
}
|
||||
|
||||
@ -125,7 +126,7 @@ func (change Change) processSet(process func(value Change)) {
|
||||
// Then this value was handled in the previous for loop.
|
||||
continue
|
||||
}
|
||||
child := clearRelevantStatus(sliceValue.getChild(len(sliceValue.Before), jx))
|
||||
child := clearRelevantStatus(sliceValue.GetChild(len(sliceValue.Before), jx))
|
||||
process(child)
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,20 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/collections"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
)
|
||||
|
||||
func (change Change) computeAttributeDiffAsTuple(elementTypes []cty.Type) computed.Diff {
|
||||
func computeAttributeDiffAsTuple(change structured.Change, elementTypes []cty.Type) computed.Diff {
|
||||
var elements []computed.Diff
|
||||
current := change.getDefaultActionForIteration()
|
||||
sliceValue := change.asSlice()
|
||||
current := change.GetDefaultActionForIteration()
|
||||
sliceValue := change.AsSlice()
|
||||
for ix, elementType := range elementTypes {
|
||||
childValue := sliceValue.getChild(ix, ix)
|
||||
childValue := sliceValue.GetChild(ix, ix)
|
||||
if !childValue.RelevantAttributes.MatchesPartial() {
|
||||
// Mark non-relevant attributes as unchanged.
|
||||
childValue = childValue.AsNoOp()
|
||||
}
|
||||
element := childValue.ComputeDiffForType(elementType)
|
||||
element := ComputeDiffForType(childValue, elementType)
|
||||
elements = append(elements, element)
|
||||
current = collections.CompareActions(current, element.Action)
|
||||
}
|
||||
|
@ -4,18 +4,17 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
)
|
||||
|
||||
func (change Change) checkForUnknownType(ctype cty.Type) (computed.Diff, bool) {
|
||||
return change.checkForUnknown(false, func(value Change) computed.Diff {
|
||||
return value.ComputeDiffForType(ctype)
|
||||
func checkForUnknownType(change structured.Change, ctype cty.Type) (computed.Diff, bool) {
|
||||
return checkForUnknown(change, false, func(value structured.Change) computed.Diff {
|
||||
return ComputeDiffForType(value, ctype)
|
||||
})
|
||||
}
|
||||
func (change Change) checkForUnknownNestedAttribute(attribute *jsonprovider.NestedType) (computed.Diff, bool) {
|
||||
func checkForUnknownNestedAttribute(change structured.Change, attribute *jsonprovider.NestedType) (computed.Diff, bool) {
|
||||
|
||||
// We want our child attributes to show up as computed instead of deleted.
|
||||
// Let's populate that here.
|
||||
@ -24,12 +23,12 @@ func (change Change) checkForUnknownNestedAttribute(attribute *jsonprovider.Nest
|
||||
childUnknown[key] = true
|
||||
}
|
||||
|
||||
return change.checkForUnknown(childUnknown, func(value Change) computed.Diff {
|
||||
return value.computeDiffForNestedAttribute(attribute)
|
||||
return checkForUnknown(change, childUnknown, func(value structured.Change) computed.Diff {
|
||||
return computeDiffForNestedAttribute(value, attribute)
|
||||
})
|
||||
}
|
||||
|
||||
func (change Change) checkForUnknownBlock(block *jsonprovider.Block) (computed.Diff, bool) {
|
||||
func checkForUnknownBlock(change structured.Change, block *jsonprovider.Block) (computed.Diff, bool) {
|
||||
|
||||
// We want our child attributes to show up as computed instead of deleted.
|
||||
// Let's populate that here.
|
||||
@ -38,13 +37,13 @@ func (change Change) checkForUnknownBlock(block *jsonprovider.Block) (computed.D
|
||||
childUnknown[key] = true
|
||||
}
|
||||
|
||||
return change.checkForUnknown(childUnknown, func(value Change) computed.Diff {
|
||||
return value.ComputeDiffForBlock(block)
|
||||
return checkForUnknown(change, childUnknown, func(value structured.Change) computed.Diff {
|
||||
return ComputeDiffForBlock(value, block)
|
||||
})
|
||||
}
|
||||
|
||||
func (change Change) checkForUnknown(childUnknown interface{}, computeDiff func(value Change) computed.Diff) (computed.Diff, bool) {
|
||||
unknown := change.isUnknown()
|
||||
func checkForUnknown(change structured.Change, childUnknown interface{}, computeDiff func(value structured.Change) computed.Diff) (computed.Diff, bool) {
|
||||
unknown := change.IsUnknown()
|
||||
|
||||
if !unknown {
|
||||
return computed.Diff{}, false
|
||||
@ -56,26 +55,19 @@ func (change Change) checkForUnknown(childUnknown interface{}, computeDiff func(
|
||||
change.AfterExplicit = true
|
||||
|
||||
if change.Before == nil {
|
||||
return change.asDiff(renderers.Unknown(computed.Diff{})), true
|
||||
return asDiff(change, renderers.Unknown(computed.Diff{})), true
|
||||
}
|
||||
|
||||
// If we get here, then we have a before value. We're going to model a
|
||||
// delete operation and our renderer later can render the overall change
|
||||
// accurately.
|
||||
|
||||
beforeValue := Change{
|
||||
beforeValue := structured.Change{
|
||||
Before: change.Before,
|
||||
BeforeSensitive: change.BeforeSensitive,
|
||||
Unknown: childUnknown,
|
||||
ReplacePaths: change.ReplacePaths,
|
||||
RelevantAttributes: change.RelevantAttributes,
|
||||
}
|
||||
return change.asDiff(renderers.Unknown(computeDiff(beforeValue))), true
|
||||
}
|
||||
|
||||
func (change Change) isUnknown() bool {
|
||||
if unknown, ok := change.Unknown.(bool); ok {
|
||||
return unknown
|
||||
}
|
||||
return false
|
||||
return asDiff(change, renderers.Unknown(computeDiff(beforeValue))), true
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/collections"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
)
|
||||
|
||||
@ -150,7 +150,6 @@ func (opts JsonOpts) processObject(before, after map[string]interface{}, relevan
|
||||
// Mark non-relevant attributes as unchanged.
|
||||
afterChild = beforeChild
|
||||
afterExplicit = beforeExplicit
|
||||
|
||||
}
|
||||
|
||||
return opts.Transform(beforeChild, afterChild, beforeExplicit, afterExplicit, childRelevantAttributes)
|
||||
|
@ -11,7 +11,8 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonplan"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
@ -6654,12 +6655,11 @@ func runTestCases(t *testing.T, testCases map[string]testCase) {
|
||||
}
|
||||
|
||||
jsonschemas := jsonprovider.MarshalForRenderer(tfschemas)
|
||||
change := structured.FromJsonChange(jsonchanges[0].Change, attribute_path.AlwaysMatcher())
|
||||
renderer := Renderer{Colorize: color}
|
||||
diff := diff{
|
||||
change: jsonchanges[0],
|
||||
diff: differ.
|
||||
FromJsonChange(jsonchanges[0].Change, attribute_path.AlwaysMatcher()).
|
||||
ComputeDiffForBlock(jsonschemas[jsonchanges[0].ProviderName].ResourceSchemas[jsonchanges[0].Type].Block),
|
||||
diff: differ.ComputeDiffForBlock(change, jsonschemas[jsonchanges[0].ProviderName].ResourceSchemas[jsonchanges[0].Type].Block),
|
||||
}
|
||||
output, _ := renderHumanDiff(renderer, diff, proposedChange)
|
||||
if diff := cmp.Diff(output, tc.ExpectedOutput); diff != "" {
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/command/format"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonplan"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonstate"
|
||||
@ -112,7 +113,7 @@ func (r Renderer) RenderLog(log *JSONLog) error {
|
||||
if len(log.Outputs) > 0 {
|
||||
r.Streams.Println(r.Colorize.Color("[bold][green]Outputs:[reset]"))
|
||||
for name, output := range log.Outputs {
|
||||
change := differ.FromJsonViewsOutput(output)
|
||||
change := structured.FromJsonViewsOutput(output)
|
||||
ctype, err := ctyjson.UnmarshalType(output.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -121,7 +122,7 @@ func (r Renderer) RenderLog(log *JSONLog) error {
|
||||
opts := computed.NewRenderHumanOpts(r.Colorize)
|
||||
opts.ShowUnchangedChildren = true
|
||||
|
||||
outputDiff := change.ComputeDiffForType(ctype)
|
||||
outputDiff := differ.ComputeDiffForType(change, ctype)
|
||||
outputStr := outputDiff.RenderHuman(0, opts)
|
||||
|
||||
msg := fmt.Sprintf("%s = %s", name, outputStr)
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonstate"
|
||||
)
|
||||
@ -63,9 +64,11 @@ func (state State) renderHumanStateModule(renderer Renderer, module jsonstate.Mo
|
||||
schema := state.GetSchema(resource)
|
||||
switch resource.Mode {
|
||||
case jsonstate.ManagedResourceMode:
|
||||
renderer.Streams.Printf("resource %q %q %s", resource.Type, resource.Name, differ.FromJsonResource(resource).ComputeDiffForBlock(schema.Block).RenderHuman(0, opts))
|
||||
change := structured.FromJsonResource(resource)
|
||||
renderer.Streams.Printf("resource %q %q %s", resource.Type, resource.Name, differ.ComputeDiffForBlock(change, schema.Block).RenderHuman(0, opts))
|
||||
case jsonstate.DataResourceMode:
|
||||
renderer.Streams.Printf("data %q %q %s", resource.Type, resource.Name, differ.FromJsonResource(resource).ComputeDiffForBlock(schema.Block).RenderHuman(0, opts))
|
||||
change := structured.FromJsonResource(resource)
|
||||
renderer.Streams.Printf("data %q %q %s", resource.Type, resource.Name, differ.ComputeDiffForBlock(change, schema.Block).RenderHuman(0, opts))
|
||||
default:
|
||||
panic("found unrecognized resource mode: " + resource.Mode)
|
||||
}
|
||||
@ -91,13 +94,14 @@ func (state State) renderHumanStateOutputs(renderer Renderer, opts computed.Rend
|
||||
|
||||
for _, key := range keys {
|
||||
output := state.RootModuleOutputs[key]
|
||||
change := structured.FromJsonOutput(output)
|
||||
ctype, err := ctyjson.UnmarshalType(output.Type)
|
||||
if err != nil {
|
||||
// We can actually do this without the type, so even if we fail
|
||||
// to work out the type let's just render this anyway.
|
||||
renderer.Streams.Printf("%s = %s\n", key, differ.FromJsonOutput(state.RootModuleOutputs[key]).ComputeDiffForOutput().RenderHuman(0, opts))
|
||||
renderer.Streams.Printf("%s = %s\n", key, differ.ComputeDiffForOutput(change).RenderHuman(0, opts))
|
||||
} else {
|
||||
renderer.Streams.Printf("%s = %s\n", key, differ.FromJsonOutput(state.RootModuleOutputs[key]).ComputeDiffForType(ctype).RenderHuman(0, opts))
|
||||
renderer.Streams.Printf("%s = %s\n", key, differ.ComputeDiffForType(change, ctype).RenderHuman(0, opts))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
package differ
|
||||
package structured
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonplan"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonstate"
|
||||
viewsjson "github.com/hashicorp/terraform/internal/command/views/json"
|
||||
@ -163,11 +162,13 @@ func FromJsonViewsOutput(output viewsjson.Output) Change {
|
||||
}
|
||||
}
|
||||
|
||||
func (change Change) asDiff(renderer computed.DiffRenderer) computed.Diff {
|
||||
return computed.NewDiff(renderer, change.calculateChange(), change.ReplacePaths.Matches())
|
||||
}
|
||||
// AsDiff
|
||||
|
||||
func (change Change) calculateChange() plans.Action {
|
||||
// CalculateAction does a very simple analysis to make the best guess at the
|
||||
// action this change describes. For complex types such as objects, maps, lists,
|
||||
// or sets it is likely more efficient to work out the action directly instead
|
||||
// of relying on this function.
|
||||
func (change Change) CalculateAction() plans.Action {
|
||||
if (change.Before == nil && !change.BeforeExplicit) && (change.After != nil || change.AfterExplicit) {
|
||||
return plans.Create
|
||||
}
|
||||
@ -175,14 +176,14 @@ func (change Change) calculateChange() plans.Action {
|
||||
return plans.Delete
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(change.Before, change.After) && change.AfterExplicit == change.BeforeExplicit && change.isAfterSensitive() == change.isBeforeSensitive() {
|
||||
if reflect.DeepEqual(change.Before, change.After) && change.AfterExplicit == change.BeforeExplicit && change.IsAfterSensitive() == change.IsBeforeSensitive() {
|
||||
return plans.NoOp
|
||||
}
|
||||
|
||||
return plans.Update
|
||||
}
|
||||
|
||||
// getDefaultActionForIteration is used to guess what the change could be for
|
||||
// GetDefaultActionForIteration is used to guess what the change could be for
|
||||
// complex attributes (collections and objects) and blocks.
|
||||
//
|
||||
// You can't really tell the difference between a NoOp and an Update just by
|
||||
@ -192,7 +193,7 @@ func (change Change) calculateChange() plans.Action {
|
||||
// values were null, and returns a NoOp for all other cases. It should be used
|
||||
// in conjunction with compareActions to calculate the actual action based on
|
||||
// the actions of the children.
|
||||
func (change Change) getDefaultActionForIteration() plans.Action {
|
||||
func (change Change) GetDefaultActionForIteration() plans.Action {
|
||||
if change.Before == nil && change.After == nil {
|
||||
return plans.NoOp
|
||||
}
|
6
internal/command/jsonformat/structured/doc.go
Normal file
6
internal/command/jsonformat/structured/doc.go
Normal file
@ -0,0 +1,6 @@
|
||||
// Package structured contains the structured representation of the JSON changes
|
||||
// returned by the jsonplan package.
|
||||
//
|
||||
// Placing these in a dedicated package allows for greater reuse across the
|
||||
// various type of renderers.
|
||||
package structured
|
@ -1,7 +1,7 @@
|
||||
package differ
|
||||
package structured
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
|
||||
)
|
||||
|
||||
// ChangeMap is a Change that represents a Map or an Object type, and has
|
||||
@ -32,7 +32,10 @@ type ChangeMap struct {
|
||||
RelevantAttributes attribute_path.Matcher
|
||||
}
|
||||
|
||||
func (change Change) asMap() ChangeMap {
|
||||
// AsMap converts the Change into an object or map representation by converting
|
||||
// the internal Before, After, Unknown, BeforeSensitive, and AfterSensitive
|
||||
// data structures into generic maps.
|
||||
func (change Change) AsMap() ChangeMap {
|
||||
return ChangeMap{
|
||||
Before: genericToMap(change.Before),
|
||||
After: genericToMap(change.After),
|
||||
@ -44,7 +47,9 @@ func (change Change) asMap() ChangeMap {
|
||||
}
|
||||
}
|
||||
|
||||
func (m ChangeMap) getChild(key string) Change {
|
||||
// GetChild safely packages up a Change object for the given child, handling
|
||||
// all the cases where the data might be null or a static boolean.
|
||||
func (m ChangeMap) GetChild(key string) Change {
|
||||
before, beforeExplicit := getFromGenericMap(m.Before, key)
|
||||
after, afterExplicit := getFromGenericMap(m.After, key)
|
||||
unknown, _ := getFromGenericMap(m.Unknown, key)
|
||||
@ -64,6 +69,29 @@ func (m ChangeMap) getChild(key string) Change {
|
||||
}
|
||||
}
|
||||
|
||||
// Keys returns all the possible keys for this map. The keys for the map are
|
||||
// potentially hidden and spread across multiple internal data structures and
|
||||
// so this function conveniently packages them up.
|
||||
func (m ChangeMap) Keys() []string {
|
||||
var keys []string
|
||||
for before := range m.Before {
|
||||
keys = append(keys, before)
|
||||
}
|
||||
for after := range m.After {
|
||||
keys = append(keys, after)
|
||||
}
|
||||
for unknown := range m.Unknown {
|
||||
keys = append(keys, unknown)
|
||||
}
|
||||
for sensitive := range m.AfterSensitive {
|
||||
keys = append(keys, sensitive)
|
||||
}
|
||||
for sensitive := range m.BeforeSensitive {
|
||||
keys = append(keys, sensitive)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func getFromGenericMap(generic map[string]interface{}, key string) (interface{}, bool) {
|
||||
if generic == nil {
|
||||
return nil, false
|
15
internal/command/jsonformat/structured/sensitive.go
Normal file
15
internal/command/jsonformat/structured/sensitive.go
Normal file
@ -0,0 +1,15 @@
|
||||
package structured
|
||||
|
||||
func (change Change) IsBeforeSensitive() bool {
|
||||
if sensitive, ok := change.BeforeSensitive.(bool); ok {
|
||||
return sensitive
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (change Change) IsAfterSensitive() bool {
|
||||
if sensitive, ok := change.AfterSensitive.(bool); ok {
|
||||
return sensitive
|
||||
}
|
||||
return false
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package differ
|
||||
package structured
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/differ/attribute_path"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
|
||||
)
|
||||
|
||||
// ChangeSlice is a Change that represents a Tuple, Set, or List type, and has
|
||||
@ -31,7 +31,10 @@ type ChangeSlice struct {
|
||||
RelevantAttributes attribute_path.Matcher
|
||||
}
|
||||
|
||||
func (change Change) asSlice() ChangeSlice {
|
||||
// AsSlice converts the Change into a slice representation by converting the
|
||||
// internal Before, After, Unknown, BeforeSensitive, and AfterSensitive data
|
||||
// structures into generic slices.
|
||||
func (change Change) AsSlice() ChangeSlice {
|
||||
return ChangeSlice{
|
||||
Before: genericToSlice(change.Before),
|
||||
After: genericToSlice(change.After),
|
||||
@ -43,7 +46,9 @@ func (change Change) asSlice() ChangeSlice {
|
||||
}
|
||||
}
|
||||
|
||||
func (s ChangeSlice) getChild(beforeIx, afterIx int) Change {
|
||||
// GetChild safely packages up a Change object for the given child, handling
|
||||
// all the cases where the data might be null or a static boolean.
|
||||
func (s ChangeSlice) GetChild(beforeIx, afterIx int) Change {
|
||||
before, beforeExplicit := getFromGenericSlice(s.Before, beforeIx)
|
||||
after, afterExplicit := getFromGenericSlice(s.After, afterIx)
|
||||
unknown, _ := getFromGenericSlice(s.Unknown, afterIx)
|
8
internal/command/jsonformat/structured/unknown.go
Normal file
8
internal/command/jsonformat/structured/unknown.go
Normal file
@ -0,0 +1,8 @@
|
||||
package structured
|
||||
|
||||
func (change Change) IsUnknown() bool {
|
||||
if unknown, ok := change.Unknown.(bool); ok {
|
||||
return unknown
|
||||
}
|
||||
return false
|
||||
}
|
Loading…
Reference in New Issue
Block a user