blob: fc8b60009001ec6c1af32d16845c0741d1d0bb93 [file] [log] [blame]
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/structured"
"github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path"
"github.com/hashicorp/terraform/internal/command/jsonplan"
"github.com/hashicorp/terraform/internal/plans"
)
func precomputeDiffs(plan Plan, mode plans.Mode) diffs {
diffs := diffs{
outputs: make(map[string]computed.Diff),
}
for _, drift := range plan.ResourceDrift {
var relevantAttrs attribute_path.Matcher
if mode == plans.RefreshOnlyMode {
// For a refresh only plan, we show all the drift.
relevantAttrs = attribute_path.AlwaysMatcher()
} else {
matcher := attribute_path.Empty(true)
// Otherwise we only want to show the drift changes that are
// relevant.
for _, attr := range plan.RelevantAttributes {
if len(attr.Resource) == 0 || attr.Resource == drift.Address {
matcher = attribute_path.AppendSingle(matcher, attr.Attr)
}
}
if len(matcher.Paths) > 0 {
relevantAttrs = matcher
}
}
if relevantAttrs == nil {
// If we couldn't build a relevant attribute matcher, then we are
// not going to show anything for this drift.
continue
}
schema := plan.getSchema(drift)
change := structured.FromJsonChange(drift.Change, relevantAttrs)
diffs.drift = append(diffs.drift, diff{
change: drift,
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.ComputeDiffForBlock(structuredChange, schema.Block),
})
}
for key, output := range plan.OutputChanges {
change := structured.FromJsonChange(output, attribute_path.AlwaysMatcher())
diffs.outputs[key] = differ.ComputeDiffForOutput(change)
}
return diffs
}
type diffs struct {
drift []diff
changes []diff
outputs map[string]computed.Diff
}
func (d diffs) Empty() bool {
for _, change := range d.changes {
if change.diff.Action != plans.NoOp || change.Moved() {
return false
}
}
for _, output := range d.outputs {
if output.Action != plans.NoOp {
return false
}
}
return true
}
type diff struct {
change jsonplan.ResourceChange
diff computed.Diff
}
func (d diff) Moved() bool {
return len(d.change.PreviousAddress) > 0 && d.change.PreviousAddress != d.change.Address
}