terraform: context verifies real and shadow state/diff match

This commit is contained in:
Mitchell Hashimoto 2016-10-04 20:52:14 -07:00
parent 62162427f4
commit 184b4a8b09
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
3 changed files with 38 additions and 1 deletions

View File

@ -613,13 +613,13 @@ func (c *Context) walk(
realCtx := c realCtx := c
// If we have a shadow graph, walk that as well // If we have a shadow graph, walk that as well
var shadowCtx *Context
var shadowCh chan error var shadowCh chan error
var shadowCloser io.Closer var shadowCloser io.Closer
if shadow != nil { if shadow != nil {
// Build the shadow context. In the process, override the real context // Build the shadow context. In the process, override the real context
// with the one that is wrapped so that the shadow context can verify // with the one that is wrapped so that the shadow context can verify
// the results of the real. // the results of the real.
var shadowCtx *Context
realCtx, shadowCtx, shadowCloser = newShadowContext(c) realCtx, shadowCtx, shadowCloser = newShadowContext(c)
// Build the graph walker for the shadow. // Build the graph walker for the shadow.
@ -657,6 +657,11 @@ func (c *Context) walk(
c.shadowErr = multierror.Append(c.shadowErr, err) c.shadowErr = multierror.Append(c.shadowErr, err)
} }
// Verify the contexts (compare)
if err := shadowContextVerify(realCtx, shadowCtx); err != nil {
c.shadowErr = multierror.Append(c.shadowErr, err)
}
if c.shadowErr == nil { if c.shadowErr == nil {
log.Printf("[INFO] Shadow graph success!") log.Printf("[INFO] Shadow graph success!")
} else { } else {

View File

@ -1,8 +1,11 @@
package terraform package terraform
import ( import (
"fmt"
"io" "io"
"reflect"
"github.com/hashicorp/go-multierror"
"github.com/mitchellh/copystructure" "github.com/mitchellh/copystructure"
) )
@ -63,6 +66,32 @@ func newShadowContext(c *Context) (*Context, *Context, io.Closer) {
} }
} }
// shadowContextVerify takes the real and shadow context and verifies they
// have equal diffs and states.
func shadowContextVerify(real, shadow *Context) error {
var result error
// Compare the states
if !real.state.Equal(shadow.state) {
result = multierror.Append(result, fmt.Errorf(
"Real and shadow states do not match! "+
"Real state:\n\n%s\n\n"+
"Shadow state:\n\n%s\n\n",
real.state, shadow.state))
}
// Compare the diffs
if !reflect.DeepEqual(real.diff, shadow.diff) {
result = multierror.Append(result, fmt.Errorf(
"Real and shadow diffs do not match! "+
"Real diff:\n\n%s\n\n"+
"Shadow diff:\n\n%s\n\n",
real.diff, shadow.diff))
}
return result
}
// shadowContextCloser is the io.Closer returned by newShadowContext that // shadowContextCloser is the io.Closer returned by newShadowContext that
// closes all the shadows and returns the results. // closes all the shadows and returns the results.
type shadowContextCloser struct { type shadowContextCloser struct {

View File

@ -167,6 +167,9 @@ type shadowResourceProviderShadow struct {
} }
type shadowResourceProviderShared struct { type shadowResourceProviderShared struct {
// NOTE: Anytime a value is added here, be sure to add it to
// the Close() method so that it is closed.
CloseErr shadow.Value CloseErr shadow.Value
Input shadow.Value Input shadow.Value
Validate shadow.Value Validate shadow.Value