terraform: unify destroy/apply graph builders
They're so similar we unify them, they only change in a select few places. This is very similar to the old graph but is still much simpler.
This commit is contained in:
parent
1523504645
commit
5a8ec482a2
|
@ -392,23 +392,14 @@ func (c *Context) Apply() (*State, error) {
|
|||
}
|
||||
|
||||
// Build the new graph. We do this no matter what so we can shadow it.
|
||||
var newGraph *Graph
|
||||
if c.destroy {
|
||||
newGraph, err = (&DestroyApplyGraphBuilder{
|
||||
Module: c.module,
|
||||
Diff: c.diff,
|
||||
State: c.state,
|
||||
Providers: c.components.ResourceProviders(),
|
||||
}).Build(RootModulePath)
|
||||
} else {
|
||||
newGraph, err = (&ApplyGraphBuilder{
|
||||
Module: c.module,
|
||||
Diff: c.diff,
|
||||
State: c.state,
|
||||
Providers: c.components.ResourceProviders(),
|
||||
Provisioners: c.components.ResourceProvisioners(),
|
||||
}).Build(RootModulePath)
|
||||
}
|
||||
newGraph, err := (&ApplyGraphBuilder{
|
||||
Module: c.module,
|
||||
Diff: c.diff,
|
||||
State: c.state,
|
||||
Providers: c.components.ResourceProviders(),
|
||||
Provisioners: c.components.ResourceProvisioners(),
|
||||
Destroy: c.destroy,
|
||||
}).Build(RootModulePath)
|
||||
if err != nil && !newGraphEnabled {
|
||||
// If we had an error graphing but we're not using this graph, just
|
||||
// set it to nil and record it as a shadow error.
|
||||
|
|
|
@ -26,6 +26,10 @@ type BasicGraphBuilder struct {
|
|||
func (b *BasicGraphBuilder) Build(path []string) (*Graph, error) {
|
||||
g := &Graph{Path: path}
|
||||
for _, step := range b.Steps {
|
||||
if step == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := step.Transform(g); err != nil {
|
||||
return g, err
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ type ApplyGraphBuilder struct {
|
|||
|
||||
// DisableReduce, if true, will not reduce the graph. Great for testing.
|
||||
DisableReduce bool
|
||||
|
||||
// Destroy, if true, represents a pure destroy operation
|
||||
Destroy bool
|
||||
}
|
||||
|
||||
// See GraphBuilder
|
||||
|
@ -77,7 +80,10 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
|||
|
||||
// Destruction ordering
|
||||
&DestroyEdgeTransformer{Module: b.Module, State: b.State},
|
||||
&CBDEdgeTransformer{Module: b.Module, State: b.State},
|
||||
GraphTransformIf(
|
||||
func() bool { return !b.Destroy },
|
||||
&CBDEdgeTransformer{Module: b.Module, State: b.State},
|
||||
),
|
||||
|
||||
// Create all the providers
|
||||
&MissingProviderTransformer{Providers: b.Providers, Factory: providerFactory},
|
||||
|
@ -87,8 +93,13 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
|||
&AttachProviderConfigTransformer{Module: b.Module},
|
||||
|
||||
// Provisioner-related transformations
|
||||
&MissingProvisionerTransformer{Provisioners: b.Provisioners},
|
||||
&ProvisionerTransformer{},
|
||||
GraphTransformIf(
|
||||
func() bool { return !b.Destroy },
|
||||
GraphTransformMulti(
|
||||
&MissingProvisionerTransformer{Provisioners: b.Provisioners},
|
||||
&ProvisionerTransformer{},
|
||||
),
|
||||
),
|
||||
|
||||
// Add root variables
|
||||
&RootVariableTransformer{Module: b.Module},
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
// DestroyApplyGraphBuilder implements GraphBuilder and is responsible for
|
||||
// applying a pure-destroy plan.
|
||||
//
|
||||
// This graph builder is very similar to the ApplyGraphBuilder but
|
||||
// is slightly simpler.
|
||||
type DestroyApplyGraphBuilder struct {
|
||||
// Module is the root module for the graph to build.
|
||||
Module *module.Tree
|
||||
|
||||
// Diff is the diff to apply.
|
||||
Diff *Diff
|
||||
|
||||
// State is the current state
|
||||
State *State
|
||||
|
||||
// Providers is the list of providers supported.
|
||||
Providers []string
|
||||
|
||||
// DisableReduce, if true, will not reduce the graph. Great for testing.
|
||||
DisableReduce bool
|
||||
}
|
||||
|
||||
// See GraphBuilder
|
||||
func (b *DestroyApplyGraphBuilder) Build(path []string) (*Graph, error) {
|
||||
return (&BasicGraphBuilder{
|
||||
Steps: b.Steps(),
|
||||
Validate: true,
|
||||
}).Build(path)
|
||||
}
|
||||
|
||||
// See GraphBuilder
|
||||
func (b *DestroyApplyGraphBuilder) Steps() []GraphTransformer {
|
||||
// Custom factory for creating providers.
|
||||
providerFactory := func(name string, path []string) GraphNodeProvider {
|
||||
return &NodeApplyableProvider{
|
||||
NameValue: name,
|
||||
PathValue: path,
|
||||
}
|
||||
}
|
||||
|
||||
concreteResource := func(a *NodeAbstractResource) dag.Vertex {
|
||||
return &NodeApplyableResource{
|
||||
NodeAbstractResource: a,
|
||||
}
|
||||
}
|
||||
|
||||
steps := []GraphTransformer{
|
||||
// Creates all the nodes represented in the diff.
|
||||
&DiffTransformer{
|
||||
Concrete: concreteResource,
|
||||
|
||||
Diff: b.Diff,
|
||||
Module: b.Module,
|
||||
State: b.State,
|
||||
},
|
||||
|
||||
// Create orphan output nodes
|
||||
&OrphanOutputTransformer{Module: b.Module, State: b.State},
|
||||
|
||||
// Attach the configuration to any resources
|
||||
&AttachResourceConfigTransformer{Module: b.Module},
|
||||
|
||||
// Attach the state
|
||||
&AttachStateTransformer{State: b.State},
|
||||
|
||||
// Destruction ordering. NOTE: For destroys, we don't need to
|
||||
// do any CBD stuff, so that is explicitly not here.
|
||||
&DestroyEdgeTransformer{Module: b.Module, State: b.State},
|
||||
|
||||
// Create all the providers
|
||||
&MissingProviderTransformer{Providers: b.Providers, Factory: providerFactory},
|
||||
&ProviderTransformer{},
|
||||
&DisableProviderTransformer{},
|
||||
&ParentProviderTransformer{},
|
||||
&AttachProviderConfigTransformer{Module: b.Module},
|
||||
|
||||
// Add root variables
|
||||
&RootVariableTransformer{Module: b.Module},
|
||||
|
||||
// Add module variables
|
||||
&ModuleVariableTransformer{Module: b.Module},
|
||||
|
||||
// Add the outputs
|
||||
&OutputTransformer{Module: b.Module},
|
||||
|
||||
// Connect references so ordering is correct
|
||||
&ReferenceTransformer{},
|
||||
|
||||
// Add the node to fix the state count boundaries
|
||||
&CountBoundaryTransformer{},
|
||||
|
||||
// Single root
|
||||
&RootTransformer{},
|
||||
}
|
||||
|
||||
if !b.DisableReduce {
|
||||
// Perform the transitive reduction to make our graph a bit
|
||||
// more sane if possible (it usually is possible).
|
||||
steps = append(steps, &TransitiveReductionTransformer{})
|
||||
}
|
||||
|
||||
return steps
|
||||
}
|
|
@ -19,3 +19,34 @@ type GraphTransformer interface {
|
|||
type GraphVertexTransformer interface {
|
||||
Transform(dag.Vertex) (dag.Vertex, error)
|
||||
}
|
||||
|
||||
// GraphTransformIf is a helper function that conditionally returns a
|
||||
// GraphTransformer given. This is useful for calling inline a sequence
|
||||
// of transforms without having to split it up into multiple append() calls.
|
||||
func GraphTransformIf(f func() bool, then GraphTransformer) GraphTransformer {
|
||||
if f() {
|
||||
return then
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type graphTransformerMulti struct {
|
||||
Transforms []GraphTransformer
|
||||
}
|
||||
|
||||
func (t *graphTransformerMulti) Transform(g *Graph) error {
|
||||
for _, t := range t.Transforms {
|
||||
if err := t.Transform(g); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GraphTransformMulti combines multiple graph transformers into a single
|
||||
// GraphTransformer that runs all the individual graph transformers.
|
||||
func GraphTransformMulti(ts ...GraphTransformer) GraphTransformer {
|
||||
return &graphTransformerMulti{Transforms: ts}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue