mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
use the PlanGraphBuilder for destroy
Rather than maintain a separate graph builder for destroy, use the normal plan graph with some extra options. Utilize the same pattern as the validate graph for now, where we take the normal plan graph builder and inject a new concrete function for the destroy nodes.
This commit is contained in:
parent
77d13808d5
commit
8fed14fc59
@ -574,7 +574,7 @@ func (c *Context) planGraph(config *configs.Config, prevRunState *states.State,
|
||||
}).Build(addrs.RootModuleInstance)
|
||||
return graph, walkPlan, diags
|
||||
case plans.DestroyMode:
|
||||
graph, diags := (&DestroyPlanGraphBuilder{
|
||||
graph, diags := DestroyPlanGraphBuilder(&PlanGraphBuilder{
|
||||
Config: config,
|
||||
State: prevRunState,
|
||||
RootVariableValues: opts.SetVariables,
|
||||
|
@ -1,115 +1,17 @@
|
||||
package terraform
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/configs"
|
||||
"github.com/hashicorp/terraform/internal/dag"
|
||||
"github.com/hashicorp/terraform/internal/states"
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
)
|
||||
|
||||
// DestroyPlanGraphBuilder implements GraphBuilder and is responsible for
|
||||
// planning a pure-destroy.
|
||||
//
|
||||
// Planning a pure destroy operation is simple because we can ignore most
|
||||
// ordering configuration and simply reverse the state. This graph mainly
|
||||
// exists for targeting, because we need to walk the destroy dependencies to
|
||||
// ensure we plan the required resources. Without the requirement for
|
||||
// targeting, the plan could theoretically be created directly from the state.
|
||||
type DestroyPlanGraphBuilder struct {
|
||||
// Config is the configuration tree to build the plan from.
|
||||
Config *configs.Config
|
||||
|
||||
// State is the current state
|
||||
State *states.State
|
||||
|
||||
// RootVariableValues are the raw input values for root input variables
|
||||
// given by the caller, which we'll resolve into final values as part
|
||||
// of the plan walk.
|
||||
RootVariableValues InputValues
|
||||
|
||||
// Plugins is a library of plug-in components (providers and
|
||||
// provisioners) available for use.
|
||||
Plugins *contextPlugins
|
||||
|
||||
// Targets are resources to target
|
||||
Targets []addrs.Targetable
|
||||
|
||||
// If set, skipRefresh will cause us stop skip refreshing any existing
|
||||
// resource instances as part of our planning. This will cause us to fail
|
||||
// to detect if an object has already been deleted outside of Terraform.
|
||||
skipRefresh bool
|
||||
}
|
||||
|
||||
// See GraphBuilder
|
||||
func (b *DestroyPlanGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) {
|
||||
return (&BasicGraphBuilder{
|
||||
Steps: b.Steps(),
|
||||
Name: "DestroyPlanGraphBuilder",
|
||||
}).Build(path)
|
||||
}
|
||||
|
||||
// See GraphBuilder
|
||||
func (b *DestroyPlanGraphBuilder) Steps() []GraphTransformer {
|
||||
concreteResourceInstance := func(a *NodeAbstractResourceInstance) dag.Vertex {
|
||||
func DestroyPlanGraphBuilder(p *PlanGraphBuilder) GraphBuilder {
|
||||
p.ConcreteResourceInstance = func(a *NodeAbstractResourceInstance) dag.Vertex {
|
||||
return &NodePlanDestroyableResourceInstance{
|
||||
NodeAbstractResourceInstance: a,
|
||||
skipRefresh: b.skipRefresh,
|
||||
}
|
||||
}
|
||||
concreteResourceInstanceDeposed := func(a *NodeAbstractResourceInstance, key states.DeposedKey) dag.Vertex {
|
||||
return &NodePlanDeposedResourceInstanceObject{
|
||||
NodeAbstractResourceInstance: a,
|
||||
DeposedKey: key,
|
||||
skipRefresh: b.skipRefresh,
|
||||
skipRefresh: p.skipRefresh,
|
||||
}
|
||||
}
|
||||
p.destroy = true
|
||||
|
||||
concreteProvider := func(a *NodeAbstractProvider) dag.Vertex {
|
||||
return &NodeApplyableProvider{
|
||||
NodeAbstractProvider: a,
|
||||
}
|
||||
}
|
||||
|
||||
steps := []GraphTransformer{
|
||||
// Creates nodes for the resource instances tracked in the state.
|
||||
&StateTransformer{
|
||||
ConcreteCurrent: concreteResourceInstance,
|
||||
ConcreteDeposed: concreteResourceInstanceDeposed,
|
||||
State: b.State,
|
||||
},
|
||||
|
||||
// Create the delete changes for root module outputs.
|
||||
&OutputTransformer{
|
||||
Config: b.Config,
|
||||
Destroy: true,
|
||||
},
|
||||
|
||||
// Attach the state
|
||||
&AttachStateTransformer{State: b.State},
|
||||
|
||||
// Attach the configuration to any resources
|
||||
&AttachResourceConfigTransformer{Config: b.Config},
|
||||
|
||||
transformProviders(concreteProvider, b.Config),
|
||||
|
||||
// Destruction ordering. We require this only so that
|
||||
// targeting below will prune the correct things.
|
||||
&DestroyEdgeTransformer{
|
||||
Config: b.Config,
|
||||
State: b.State,
|
||||
},
|
||||
|
||||
&TargetsTransformer{Targets: b.Targets},
|
||||
|
||||
// Close opened plugin connections
|
||||
&CloseProviderTransformer{},
|
||||
|
||||
// Close the root module
|
||||
&CloseRootModuleTransformer{},
|
||||
|
||||
&TransitiveReductionTransformer{},
|
||||
}
|
||||
|
||||
return steps
|
||||
return p
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package terraform
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/configs"
|
||||
"github.com/hashicorp/terraform/internal/dag"
|
||||
@ -57,13 +55,16 @@ type PlanGraphBuilder struct {
|
||||
// CustomConcrete can be set to customize the node types created
|
||||
// for various parts of the plan. This is useful in order to customize
|
||||
// the plan behavior.
|
||||
CustomConcrete bool
|
||||
ConcreteProvider ConcreteProviderNodeFunc
|
||||
ConcreteResource ConcreteResourceNodeFunc
|
||||
ConcreteResourceOrphan ConcreteResourceInstanceNodeFunc
|
||||
ConcreteModule ConcreteModuleNodeFunc
|
||||
CustomConcrete bool
|
||||
ConcreteProvider ConcreteProviderNodeFunc
|
||||
ConcreteResource ConcreteResourceNodeFunc
|
||||
ConcreteResourceInstance ConcreteResourceInstanceNodeFunc
|
||||
ConcreteResourceOrphan ConcreteResourceInstanceNodeFunc
|
||||
ConcreteResourceInstanceDeposed ConcreteResourceInstanceDeposedNodeFunc
|
||||
ConcreteModule ConcreteModuleNodeFunc
|
||||
|
||||
once sync.Once
|
||||
// destroy is set to true when create a full destroy plan.
|
||||
destroy bool
|
||||
}
|
||||
|
||||
// See GraphBuilder
|
||||
@ -76,36 +77,32 @@ func (b *PlanGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Dia
|
||||
|
||||
// See GraphBuilder
|
||||
func (b *PlanGraphBuilder) Steps() []GraphTransformer {
|
||||
b.once.Do(b.init)
|
||||
|
||||
concreteResourceInstanceDeposed := func(a *NodeAbstractResourceInstance, key states.DeposedKey) dag.Vertex {
|
||||
return &NodePlanDeposedResourceInstanceObject{
|
||||
NodeAbstractResourceInstance: a,
|
||||
DeposedKey: key,
|
||||
|
||||
skipRefresh: b.skipRefresh,
|
||||
skipPlanChanges: b.skipPlanChanges,
|
||||
}
|
||||
}
|
||||
b.init()
|
||||
|
||||
steps := []GraphTransformer{
|
||||
// Creates all the resources represented in the config
|
||||
&ConfigTransformer{
|
||||
Concrete: b.ConcreteResource,
|
||||
Config: b.Config,
|
||||
Concrete: b.ConcreteResource,
|
||||
Config: b.Config,
|
||||
destroyPlan: b.destroy,
|
||||
},
|
||||
|
||||
// Add dynamic values
|
||||
&RootVariableTransformer{Config: b.Config, RawValues: b.RootVariableValues},
|
||||
&ModuleVariableTransformer{Config: b.Config},
|
||||
&LocalTransformer{Config: b.Config},
|
||||
&OutputTransformer{Config: b.Config, RefreshOnly: b.skipPlanChanges},
|
||||
&OutputTransformer{
|
||||
Config: b.Config,
|
||||
RefreshOnly: b.skipPlanChanges,
|
||||
destroyPlan: b.destroy,
|
||||
},
|
||||
|
||||
// Add orphan resources
|
||||
&OrphanResourceInstanceTransformer{
|
||||
Concrete: b.ConcreteResourceOrphan,
|
||||
State: b.State,
|
||||
Config: b.Config,
|
||||
Concrete: b.ConcreteResourceOrphan,
|
||||
State: b.State,
|
||||
Config: b.Config,
|
||||
destroyPlan: b.destroy,
|
||||
},
|
||||
|
||||
// We also need nodes for any deposed instance objects present in the
|
||||
@ -113,7 +110,8 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
|
||||
// skips creating nodes for _current_ objects, since ConfigTransformer
|
||||
// created nodes that will do that during DynamicExpand.)
|
||||
&StateTransformer{
|
||||
ConcreteDeposed: concreteResourceInstanceDeposed,
|
||||
ConcreteCurrent: b.ConcreteResourceInstance,
|
||||
ConcreteDeposed: b.ConcreteResourceInstanceDeposed,
|
||||
State: b.State,
|
||||
},
|
||||
|
||||
@ -141,15 +139,18 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
|
||||
// objects that can belong to modules.
|
||||
&ModuleExpansionTransformer{Concrete: b.ConcreteModule, Config: b.Config},
|
||||
|
||||
// Connect so that the references are ready for targeting. We'll
|
||||
// have to connect again later for providers and so on.
|
||||
&ReferenceTransformer{},
|
||||
|
||||
&AttachDependenciesTransformer{},
|
||||
|
||||
// Make sure data sources are aware of any depends_on from the
|
||||
// configuration
|
||||
&attachDataResourceDependsOnTransformer{},
|
||||
|
||||
// DestroyEdgeTransformer is only required during a plan so that the
|
||||
// TargetsTransformer can determine which nodes to keep in the graph.
|
||||
&DestroyEdgeTransformer{},
|
||||
|
||||
// Target
|
||||
&TargetsTransformer{Targets: b.Targets},
|
||||
|
||||
@ -199,4 +200,15 @@ func (b *PlanGraphBuilder) init() {
|
||||
skipPlanChanges: b.skipPlanChanges,
|
||||
}
|
||||
}
|
||||
|
||||
b.ConcreteResourceInstanceDeposed = func(a *NodeAbstractResourceInstance, key states.DeposedKey) dag.Vertex {
|
||||
return &NodePlanDeposedResourceInstanceObject{
|
||||
NodeAbstractResourceInstance: a,
|
||||
DeposedKey: key,
|
||||
|
||||
skipRefresh: b.skipRefresh,
|
||||
skipPlanChanges: b.skipPlanChanges,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user