mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
prune unused values based on behavior
remove the hard-coded types from PruneUnusedValuesTransformer
This commit is contained in:
parent
c0bca9d5e9
commit
1a1ace5930
@ -22,8 +22,14 @@ var (
|
|||||||
_ GraphNodeReferenceable = (*NodePlannableLocal)(nil)
|
_ GraphNodeReferenceable = (*NodePlannableLocal)(nil)
|
||||||
_ GraphNodeReferencer = (*NodePlannableLocal)(nil)
|
_ GraphNodeReferencer = (*NodePlannableLocal)(nil)
|
||||||
_ GraphNodeDynamicExpandable = (*NodePlannableLocal)(nil)
|
_ GraphNodeDynamicExpandable = (*NodePlannableLocal)(nil)
|
||||||
|
_ graphNodeTemporaryValue = (*NodePlannableLocal)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// graphNodeTemporaryValue
|
||||||
|
func (n *NodePlannableLocal) temporaryValue() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NodePlannableLocal) Name() string {
|
func (n *NodePlannableLocal) Name() string {
|
||||||
path := n.Module.String()
|
path := n.Module.String()
|
||||||
addr := n.Addr.String()
|
addr := n.Addr.String()
|
||||||
@ -83,9 +89,15 @@ var (
|
|||||||
_ GraphNodeReferenceable = (*NodeLocal)(nil)
|
_ GraphNodeReferenceable = (*NodeLocal)(nil)
|
||||||
_ GraphNodeReferencer = (*NodeLocal)(nil)
|
_ GraphNodeReferencer = (*NodeLocal)(nil)
|
||||||
_ GraphNodeEvalable = (*NodeLocal)(nil)
|
_ GraphNodeEvalable = (*NodeLocal)(nil)
|
||||||
|
_ graphNodeTemporaryValue = (*NodeLocal)(nil)
|
||||||
_ dag.GraphNodeDotter = (*NodeLocal)(nil)
|
_ dag.GraphNodeDotter = (*NodeLocal)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// graphNodeTemporaryValue
|
||||||
|
func (n *NodeLocal) temporaryValue() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NodeLocal) Name() string {
|
func (n *NodeLocal) Name() string {
|
||||||
return n.Addr.String()
|
return n.Addr.String()
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,14 @@ var (
|
|||||||
_ GraphNodeReferenceOutside = (*NodePlannableModuleVariable)(nil)
|
_ GraphNodeReferenceOutside = (*NodePlannableModuleVariable)(nil)
|
||||||
_ GraphNodeReferenceable = (*NodePlannableModuleVariable)(nil)
|
_ GraphNodeReferenceable = (*NodePlannableModuleVariable)(nil)
|
||||||
_ GraphNodeReferencer = (*NodePlannableModuleVariable)(nil)
|
_ GraphNodeReferencer = (*NodePlannableModuleVariable)(nil)
|
||||||
|
_ graphNodeTemporaryValue = (*NodePlannableModuleVariable)(nil)
|
||||||
_ RemovableIfNotTargeted = (*NodePlannableModuleVariable)(nil)
|
_ RemovableIfNotTargeted = (*NodePlannableModuleVariable)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (n *NodePlannableModuleVariable) temporaryValue() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NodePlannableModuleVariable) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
func (n *NodePlannableModuleVariable) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||||
var g Graph
|
var g Graph
|
||||||
expander := ctx.InstanceExpander()
|
expander := ctx.InstanceExpander()
|
||||||
@ -120,9 +125,14 @@ var (
|
|||||||
_ GraphNodeReferenceable = (*NodeApplyableModuleVariable)(nil)
|
_ GraphNodeReferenceable = (*NodeApplyableModuleVariable)(nil)
|
||||||
_ GraphNodeReferencer = (*NodeApplyableModuleVariable)(nil)
|
_ GraphNodeReferencer = (*NodeApplyableModuleVariable)(nil)
|
||||||
_ GraphNodeEvalable = (*NodeApplyableModuleVariable)(nil)
|
_ GraphNodeEvalable = (*NodeApplyableModuleVariable)(nil)
|
||||||
|
_ graphNodeTemporaryValue = (*NodeApplyableModuleVariable)(nil)
|
||||||
_ dag.GraphNodeDotter = (*NodeApplyableModuleVariable)(nil)
|
_ dag.GraphNodeDotter = (*NodeApplyableModuleVariable)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (n *NodeApplyableModuleVariable) temporaryValue() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NodeApplyableModuleVariable) Name() string {
|
func (n *NodeApplyableModuleVariable) Name() string {
|
||||||
return n.Addr.String()
|
return n.Addr.String()
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,14 @@ var (
|
|||||||
_ GraphNodeReferenceable = (*NodePlannableOutput)(nil)
|
_ GraphNodeReferenceable = (*NodePlannableOutput)(nil)
|
||||||
_ GraphNodeReferencer = (*NodePlannableOutput)(nil)
|
_ GraphNodeReferencer = (*NodePlannableOutput)(nil)
|
||||||
_ GraphNodeDynamicExpandable = (*NodePlannableOutput)(nil)
|
_ GraphNodeDynamicExpandable = (*NodePlannableOutput)(nil)
|
||||||
|
_ graphNodeTemporaryValue = (*NodeApplyableOutput)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (n *NodePlannableOutput) temporaryValue() bool {
|
||||||
|
// this must always be evaluated if it is a root module output
|
||||||
|
return !n.Module.IsRoot()
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NodePlannableOutput) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
func (n *NodePlannableOutput) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||||
var g Graph
|
var g Graph
|
||||||
expander := ctx.InstanceExpander()
|
expander := ctx.InstanceExpander()
|
||||||
@ -115,9 +121,15 @@ var (
|
|||||||
_ GraphNodeReferencer = (*NodeApplyableOutput)(nil)
|
_ GraphNodeReferencer = (*NodeApplyableOutput)(nil)
|
||||||
_ GraphNodeReferenceOutside = (*NodeApplyableOutput)(nil)
|
_ GraphNodeReferenceOutside = (*NodeApplyableOutput)(nil)
|
||||||
_ GraphNodeEvalable = (*NodeApplyableOutput)(nil)
|
_ GraphNodeEvalable = (*NodeApplyableOutput)(nil)
|
||||||
|
_ graphNodeTemporaryValue = (*NodeApplyableOutput)(nil)
|
||||||
_ dag.GraphNodeDotter = (*NodeApplyableOutput)(nil)
|
_ dag.GraphNodeDotter = (*NodeApplyableOutput)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (n *NodeApplyableOutput) temporaryValue() bool {
|
||||||
|
// this must always be evaluated if it is a root module output
|
||||||
|
return !n.Addr.Module.IsRoot()
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NodeApplyableOutput) Name() string {
|
func (n *NodeApplyableOutput) Name() string {
|
||||||
return n.Addr.String()
|
return n.Addr.String()
|
||||||
}
|
}
|
||||||
|
10
terraform/node_value.go
Normal file
10
terraform/node_value.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package terraform
|
||||||
|
|
||||||
|
// graphNodeTemporaryValue is implemented by nodes that may represent temporary
|
||||||
|
// values, which are those not saved to the state file. This includes locals,
|
||||||
|
// variables, and non-root outputs.
|
||||||
|
// A boolean return value allows a node which may need to be saved to
|
||||||
|
// conditionally do so.
|
||||||
|
type graphNodeTemporaryValue interface {
|
||||||
|
temporaryValue() bool
|
||||||
|
}
|
@ -185,63 +185,40 @@ type PruneUnusedValuesTransformer struct {
|
|||||||
Destroy bool
|
Destroy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: outputs will now have module expansion root nodes dependent on them,
|
|
||||||
// so we need to filter those out too. Might be a good time to decouple this
|
|
||||||
// from concrete types, and implement some interfaces.
|
|
||||||
func (t *PruneUnusedValuesTransformer) Transform(g *Graph) error {
|
func (t *PruneUnusedValuesTransformer) Transform(g *Graph) error {
|
||||||
// Pruning a value can effect previously checked edges, so loop until there
|
// Pruning a value can effect previously checked edges, so loop until there
|
||||||
// are no more changes.
|
// are no more changes.
|
||||||
for removed := 0; ; removed = 0 {
|
for removed := 0; ; removed = 0 {
|
||||||
for _, v := range g.Vertices() {
|
for _, v := range g.Vertices() {
|
||||||
|
// we're only concerned with values that don't need to be saved in state
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case *NodeApplyableOutput:
|
case graphNodeTemporaryValue:
|
||||||
// If we're not certain this is a full destroy, we need to keep any
|
if !v.temporaryValue() {
|
||||||
// root module outputs
|
|
||||||
if v.Addr.Module.IsRoot() && !t.Destroy {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
case *NodePlannableOutput:
|
|
||||||
// Have similar guardrails for plannable outputs as applyable above
|
|
||||||
if v.Module.IsRoot() && !t.Destroy {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case *NodeLocal, *NodeApplyableModuleVariable, *NodePlannableModuleVariable:
|
|
||||||
// OK
|
|
||||||
default:
|
default:
|
||||||
// We're only concerned with variables, locals and outputs
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
dependants := g.UpEdges(v)
|
dependants := g.UpEdges(v)
|
||||||
|
|
||||||
switch dependants.Len() {
|
// any referencers in the dependents means we need to keep this
|
||||||
case 0:
|
// value for evaluation
|
||||||
// nothing at all depends on this
|
removable := true
|
||||||
|
for _, d := range dependants.List() {
|
||||||
|
if _, ok := d.(GraphNodeReferencer); ok {
|
||||||
|
removable = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if removable {
|
||||||
log.Printf("[TRACE] PruneUnusedValuesTransformer: removing unused value %s", dag.VertexName(v))
|
log.Printf("[TRACE] PruneUnusedValuesTransformer: removing unused value %s", dag.VertexName(v))
|
||||||
g.Remove(v)
|
g.Remove(v)
|
||||||
removed++
|
removed++
|
||||||
default:
|
|
||||||
// because an output's destroy node always depends on the output,
|
|
||||||
// we need to check for the case of a single destroy node.
|
|
||||||
removable := true
|
|
||||||
SEARCH:
|
|
||||||
for _, d := range dependants.List() {
|
|
||||||
switch d.(type) {
|
|
||||||
case *NodeDestroyableOutput, *nodeCloseModule:
|
|
||||||
//pass
|
|
||||||
default:
|
|
||||||
removable = false
|
|
||||||
break SEARCH
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if removable {
|
|
||||||
log.Printf("[TRACE] PruneUnusedValuesTransformer: removing unused value %s", dag.VertexName(v))
|
|
||||||
g.Remove(v)
|
|
||||||
removed++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if removed == 0 {
|
if removed == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user