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
|
// Copy our own state
|
||||||
c.state = c.state.DeepCopy()
|
c.state = c.state.DeepCopy()
|
||||||
|
|
||||||
// Build the graph. If it is a destroy operation, we use the
|
// Build the original graph. This is before the new graph builders
|
||||||
// standard graph builder. If it is an apply operation, we use
|
// coming in 0.8. We do this for shadow graphing.
|
||||||
// our new graph builder.
|
oldGraph, err := c.Graph(&ContextGraphOpts{Validate: true})
|
||||||
var graph *Graph
|
if err != nil && X_newApply {
|
||||||
var err error
|
// If we had an error graphing but we're using the new graph,
|
||||||
if c.destroy || !X_newApply {
|
// just set it to nil and let it go. There are some features that
|
||||||
graph, err = c.Graph(&ContextGraphOpts{Validate: true})
|
// may work with the new graph that don't with the old.
|
||||||
} else {
|
oldGraph = nil
|
||||||
graph, err = (&ApplyGraphBuilder{
|
err = nil
|
||||||
Module: c.module,
|
|
||||||
Diff: c.diff,
|
|
||||||
State: c.state,
|
|
||||||
Providers: c.components.ResourceProviders(),
|
|
||||||
Provisioners: c.components.ResourceProvisioners(),
|
|
||||||
}).Build(RootModulePath)
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the walk
|
// Build the new graph. We do this no matter what so we can shadow it.
|
||||||
var walker *ContextGraphWalker
|
newGraph, err := (&ApplyGraphBuilder{
|
||||||
if c.destroy {
|
Module: c.module,
|
||||||
walker, err = c.walk(graph, graph, walkDestroy)
|
Diff: c.diff,
|
||||||
} else {
|
State: c.state,
|
||||||
//walker, err = c.walk(graph, nil, walkApply)
|
Providers: c.components.ResourceProviders(),
|
||||||
walker, err = c.walk(graph, graph, walkApply)
|
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 {
|
if len(walker.ValidationErrors) > 0 {
|
||||||
err = multierror.Append(err, walker.ValidationErrors...)
|
err = multierror.Append(err, walker.ValidationErrors...)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue