terraform: logic for shadowing the original graph
This introduces failing tests. How many is unknown since shadow graph errors cause a panic.
This commit is contained in:
parent
7d36e991da
commit
13b9007474
|
@ -363,35 +363,79 @@ func (c *Context) Apply() (*State, error) {
|
|||
// Copy our own state
|
||||
c.state = c.state.DeepCopy()
|
||||
|
||||
// Build the graph. If it is a destroy operation, we use the
|
||||
// standard graph builder. If it is an apply operation, we use
|
||||
// our new graph builder.
|
||||
var graph *Graph
|
||||
var err error
|
||||
if c.destroy || !X_newApply {
|
||||
graph, err = c.Graph(&ContextGraphOpts{Validate: true})
|
||||
} else {
|
||||
graph, err = (&ApplyGraphBuilder{
|
||||
Module: c.module,
|
||||
Diff: c.diff,
|
||||
State: c.state,
|
||||
Providers: c.components.ResourceProviders(),
|
||||
Provisioners: c.components.ResourceProvisioners(),
|
||||
}).Build(RootModulePath)
|
||||
// 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})
|
||||
if err != nil && X_newApply {
|
||||
// If we had an error graphing but we're using the new graph,
|
||||
// just set it to nil and let it go. There are some features that
|
||||
// may work with the new graph that don't with the old.
|
||||
oldGraph = nil
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Do the walk
|
||||
var walker *ContextGraphWalker
|
||||
if c.destroy {
|
||||
walker, err = c.walk(graph, graph, walkDestroy)
|
||||
} else {
|
||||
//walker, err = c.walk(graph, nil, walkApply)
|
||||
walker, err = c.walk(graph, graph, walkApply)
|
||||
// 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 {
|
||||
// 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))
|
||||
|
||||
newGraph = nil
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Determine what is the real and what is the shadow. The logic here
|
||||
// is straightforward though the if statements are not:
|
||||
//
|
||||
// * Destroy mode - always use original, shadow with nothing because
|
||||
// we're only testing the new APPLY graph.
|
||||
// * Apply with new apply - use new graph, shadow is new graph. We can't
|
||||
// shadow with the old graph because the old graph does a lot more
|
||||
// that it shouldn't.
|
||||
// * Apply with old apply - use old graph, shadow with new graph.
|
||||
//
|
||||
real := oldGraph
|
||||
shadow := newGraph
|
||||
if c.destroy {
|
||||
log.Printf("[WARN] terraform: real graph is original, shadow is nil")
|
||||
shadow = nil
|
||||
} 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")
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the operation
|
||||
operation := walkApply
|
||||
if c.destroy {
|
||||
operation = walkDestroy
|
||||
}
|
||||
|
||||
// This shouldn't happen, so assert it. This is before any state changes
|
||||
// so it is safe to crash here.
|
||||
if real == nil {
|
||||
panic("nil real graph")
|
||||
}
|
||||
|
||||
// Walk the graph
|
||||
walker, err := c.walk(real, shadow, operation)
|
||||
if len(walker.ValidationErrors) > 0 {
|
||||
err = multierror.Append(err, walker.ValidationErrors...)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue