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.
|
// Build the new graph. We do this no matter what so we can shadow it.
|
||||||
var newGraph *Graph
|
newGraph, err := (&ApplyGraphBuilder{
|
||||||
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,
|
Module: c.module,
|
||||||
Diff: c.diff,
|
Diff: c.diff,
|
||||||
State: c.state,
|
State: c.state,
|
||||||
Providers: c.components.ResourceProviders(),
|
Providers: c.components.ResourceProviders(),
|
||||||
Provisioners: c.components.ResourceProvisioners(),
|
Provisioners: c.components.ResourceProvisioners(),
|
||||||
|
Destroy: c.destroy,
|
||||||
}).Build(RootModulePath)
|
}).Build(RootModulePath)
|
||||||
}
|
|
||||||
if err != nil && !newGraphEnabled {
|
if err != nil && !newGraphEnabled {
|
||||||
// If we had an error graphing but we're not using this graph, just
|
// 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.
|
// 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) {
|
func (b *BasicGraphBuilder) Build(path []string) (*Graph, error) {
|
||||||
g := &Graph{Path: path}
|
g := &Graph{Path: path}
|
||||||
for _, step := range b.Steps {
|
for _, step := range b.Steps {
|
||||||
|
if step == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if err := step.Transform(g); err != nil {
|
if err := step.Transform(g); err != nil {
|
||||||
return g, err
|
return g, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@ type ApplyGraphBuilder struct {
|
||||||
|
|
||||||
// DisableReduce, if true, will not reduce the graph. Great for testing.
|
// DisableReduce, if true, will not reduce the graph. Great for testing.
|
||||||
DisableReduce bool
|
DisableReduce bool
|
||||||
|
|
||||||
|
// Destroy, if true, represents a pure destroy operation
|
||||||
|
Destroy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// See GraphBuilder
|
// See GraphBuilder
|
||||||
|
@ -77,7 +80,10 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
||||||
|
|
||||||
// Destruction ordering
|
// Destruction ordering
|
||||||
&DestroyEdgeTransformer{Module: b.Module, State: b.State},
|
&DestroyEdgeTransformer{Module: b.Module, State: b.State},
|
||||||
|
GraphTransformIf(
|
||||||
|
func() bool { return !b.Destroy },
|
||||||
&CBDEdgeTransformer{Module: b.Module, State: b.State},
|
&CBDEdgeTransformer{Module: b.Module, State: b.State},
|
||||||
|
),
|
||||||
|
|
||||||
// Create all the providers
|
// Create all the providers
|
||||||
&MissingProviderTransformer{Providers: b.Providers, Factory: providerFactory},
|
&MissingProviderTransformer{Providers: b.Providers, Factory: providerFactory},
|
||||||
|
@ -87,8 +93,13 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
||||||
&AttachProviderConfigTransformer{Module: b.Module},
|
&AttachProviderConfigTransformer{Module: b.Module},
|
||||||
|
|
||||||
// Provisioner-related transformations
|
// Provisioner-related transformations
|
||||||
|
GraphTransformIf(
|
||||||
|
func() bool { return !b.Destroy },
|
||||||
|
GraphTransformMulti(
|
||||||
&MissingProvisionerTransformer{Provisioners: b.Provisioners},
|
&MissingProvisionerTransformer{Provisioners: b.Provisioners},
|
||||||
&ProvisionerTransformer{},
|
&ProvisionerTransformer{},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
// Add root variables
|
// Add root variables
|
||||||
&RootVariableTransformer{Module: b.Module},
|
&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 {
|
type GraphVertexTransformer interface {
|
||||||
Transform(dag.Vertex) (dag.Vertex, error)
|
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