terraform: run the shadow graph for Apply operations (everything fails)
This commit is contained in:
parent
02e93f5920
commit
742af8752b
|
@ -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,16 +661,23 @@ 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 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 && c.shadowErr != nil {
|
||||
if contextFailOnShadowError {
|
||||
realErr = multierror.Append(realErr, multierror.Prefix(
|
||||
c.shadowErr, "shadow graph:"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return walker, realErr
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue