terraform: run the shadow graph for Apply operations (everything fails)

This commit is contained in:
Mitchell Hashimoto 2016-10-03 09:45:18 -07:00
parent 02e93f5920
commit 742af8752b
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
3 changed files with 36 additions and 9 deletions

View File

@ -375,7 +375,7 @@ func (c *Context) Apply() (*State, error) {
if c.destroy {
walker, err = c.walk(graph, nil, walkDestroy)
} else {
walker, err = c.walk(graph, nil, walkApply)
walker, err = c.walk(graph, graph, walkApply)
}
if len(walker.ValidationErrors) > 0 {
@ -641,6 +641,7 @@ func (c *Context) walk(
// on the real walk so it is fine to start first.
shadowCh = make(chan error)
go func() {
log.Printf("[INFO] Starting shadow graph walk: %s", operation.String())
shadowCh <- shadow.Walk(shadowWalker)
}()
}
@ -660,14 +661,21 @@ func (c *Context) walk(
}
// Wait for the walk to end
log.Printf("[DEBUG] Waiting for shadow graph to complete...")
if err := <-shadowCh; err != nil {
c.shadowErr = multierror.Append(c.shadowErr, err)
}
// If we're supposed to fail on shadow errors, then report it
if contextFailOnShadowError && c.shadowErr != nil {
realErr = multierror.Append(realErr, multierror.Prefix(
c.shadowErr, "shadow graph:"))
if c.shadowErr == nil {
log.Printf("[INFO] Shadow graph success!")
} else {
log.Printf("[ERROR] Shadow graph error: %s", c.shadowErr)
// If we're supposed to fail on shadow errors, then report it
if contextFailOnShadowError {
realErr = multierror.Append(realErr, multierror.Prefix(
c.shadowErr, "shadow graph:"))
}
}
}

View File

@ -14,7 +14,7 @@ import (
"github.com/hashicorp/terraform/config/module"
)
func TestContext2Apply(t *testing.T) {
func TestContext2Apply_basic(t *testing.T) {
m := testModule(t, "apply-good")
p := testProvider("aws")
p.ApplyFn = testApplyFn

View File

@ -19,13 +19,13 @@ import (
// copied, no real providers or resources are used, etc.
func newShadowContext(c *Context) (*Context, *Context, io.Closer) {
// Copy the targets
targetRaw, err := copystructure.Config{Lock: true}.Copy(c.targets)
targetRaw, err := copystructure.Copy(c.targets)
if err != nil {
panic(err)
}
// Copy the variables
varRaw, err := copystructure.Config{Lock: true}.Copy(c.variables)
varRaw, err := copystructure.Copy(c.variables)
if err != nil {
panic(err)
}
@ -45,6 +45,12 @@ func newShadowContext(c *Context) (*Context, *Context, io.Closer) {
targets: targetRaw.([]string),
uiInput: nil, // TODO
variables: varRaw.(map[string]interface{}),
// Hardcoded to 4 since parallelism in the shadow doesn't matter
// a ton since we're doing far less compared to the real side
// and our operations are MUCH faster.
parallelSem: NewSemaphore(4),
providerInputConfig: make(map[string]map[string]interface{}),
}
// Create the real context. This is effectively just a copy of
@ -53,5 +59,18 @@ func newShadowContext(c *Context) (*Context, *Context, io.Closer) {
real := *c
real.providers = providerFactory.RealMap()
return &real, shadow, nil
return &real, shadow, &shadowContextCloser{
Providers: providerFactory,
}
}
// shadowContextCloser is the io.Closer returned by newShadowContext that
// closes all the shadows and returns the results.
type shadowContextCloser struct {
Providers interface{}
}
// Close closes the shadow context.
func (c *shadowContextCloser) Close() error {
return nil
}