terraform: destroy graph builder, -Xnew-destroy flag
This commit is contained in:
parent
bff4e31070
commit
db807f4b0f
|
@ -21,6 +21,10 @@ var (
|
|||
// X_newApply will enable the new apply graph. This will be removed
|
||||
// and be on by default in 0.8.0.
|
||||
X_newApply = false
|
||||
|
||||
// X_newDestroy will enable the new destroy graph. This will be removed
|
||||
// and be on by default in 0.8.0.
|
||||
X_newDestroy = false
|
||||
)
|
||||
|
||||
// InputMode defines what sort of input will be asked for when Input
|
||||
|
@ -371,6 +375,8 @@ func (c *Context) Apply() (*State, error) {
|
|||
// Copy our own state
|
||||
c.state = c.state.DeepCopy()
|
||||
|
||||
newGraphEnabled := (c.destroy && X_newDestroy) || (!c.destroy && X_newApply)
|
||||
|
||||
// Build the original graph. This is before the new graph builders
|
||||
// coming in 0.8. We do this for shadow graphing.
|
||||
oldGraph, err := c.Graph(&ContextGraphOpts{Validate: true})
|
||||
|
@ -386,18 +392,28 @@ func (c *Context) Apply() (*State, error) {
|
|||
}
|
||||
|
||||
// Build the new graph. We do this no matter what so we can shadow it.
|
||||
newGraph, err := (&ApplyGraphBuilder{
|
||||
Module: c.module,
|
||||
Diff: c.diff,
|
||||
State: c.state,
|
||||
Providers: c.components.ResourceProviders(),
|
||||
Provisioners: c.components.ResourceProvisioners(),
|
||||
}).Build(RootModulePath)
|
||||
if err != nil && !X_newApply {
|
||||
var newGraph *Graph
|
||||
if c.destroy {
|
||||
newGraph, err = (&DestroyApplyGraphBuilder{
|
||||
Module: c.module,
|
||||
Diff: c.diff,
|
||||
State: c.state,
|
||||
Providers: c.providersList(),
|
||||
}).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)
|
||||
}
|
||||
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.
|
||||
c.shadowErr = multierror.Append(c.shadowErr, fmt.Errorf(
|
||||
"Error building new apply graph: %s", err))
|
||||
"Error building new graph: %s", err))
|
||||
|
||||
newGraph = nil
|
||||
err = nil
|
||||
|
@ -418,16 +434,11 @@ func (c *Context) Apply() (*State, error) {
|
|||
//
|
||||
real := oldGraph
|
||||
shadow := newGraph
|
||||
if c.destroy {
|
||||
log.Printf("[WARN] terraform: real graph is original, shadow is nil")
|
||||
shadow = nil
|
||||
if newGraphEnabled {
|
||||
log.Printf("[WARN] terraform: real graph is experiment, shadow is experiment")
|
||||
real = shadow
|
||||
} else {
|
||||
if X_newApply {
|
||||
log.Printf("[WARN] terraform: real graph is Xnew-apply, shadow is Xnew-apply")
|
||||
real = shadow
|
||||
} else {
|
||||
log.Printf("[WARN] terraform: real graph is original, shadow is Xnew-apply")
|
||||
}
|
||||
log.Printf("[WARN] terraform: real graph is original, shadow is experiment")
|
||||
}
|
||||
|
||||
// For now, always shadow with the real graph for verification. We don't
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
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{},
|
||||
&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
|
||||
}
|
|
@ -24,6 +24,7 @@ const fixtureDir = "./test-fixtures"
|
|||
func TestMain(m *testing.M) {
|
||||
// Experimental features
|
||||
xNewApply := flag.Bool("Xnew-apply", false, "Experiment: new apply graph")
|
||||
xNewDestroy := flag.Bool("Xnew-destroy", false, "Experiment: new destroy graph")
|
||||
|
||||
// Normal features
|
||||
shadow := flag.Bool("shadow", true, "Enable shadow graph")
|
||||
|
@ -32,6 +33,7 @@ func TestMain(m *testing.M) {
|
|||
|
||||
// Setup experimental features
|
||||
X_newApply = *xNewApply
|
||||
X_newDestroy = *xNewDestroy
|
||||
|
||||
if testing.Verbose() {
|
||||
// if we're verbose, use the logging requested by TF_LOG
|
||||
|
|
Loading…
Reference in New Issue