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 {
|
if c.destroy {
|
||||||
walker, err = c.walk(graph, nil, walkDestroy)
|
walker, err = c.walk(graph, nil, walkDestroy)
|
||||||
} else {
|
} else {
|
||||||
walker, err = c.walk(graph, nil, walkApply)
|
walker, err = c.walk(graph, graph, walkApply)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(walker.ValidationErrors) > 0 {
|
if len(walker.ValidationErrors) > 0 {
|
||||||
|
@ -641,6 +641,7 @@ func (c *Context) walk(
|
||||||
// on the real walk so it is fine to start first.
|
// on the real walk so it is fine to start first.
|
||||||
shadowCh = make(chan error)
|
shadowCh = make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
|
log.Printf("[INFO] Starting shadow graph walk: %s", operation.String())
|
||||||
shadowCh <- shadow.Walk(shadowWalker)
|
shadowCh <- shadow.Walk(shadowWalker)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -660,14 +661,21 @@ func (c *Context) walk(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the walk to end
|
// Wait for the walk to end
|
||||||
|
log.Printf("[DEBUG] Waiting for shadow graph to complete...")
|
||||||
if err := <-shadowCh; err != nil {
|
if err := <-shadowCh; err != nil {
|
||||||
c.shadowErr = multierror.Append(c.shadowErr, err)
|
c.shadowErr = multierror.Append(c.shadowErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're supposed to fail on shadow errors, then report it
|
if c.shadowErr == nil {
|
||||||
if contextFailOnShadowError && c.shadowErr != nil {
|
log.Printf("[INFO] Shadow graph success!")
|
||||||
realErr = multierror.Append(realErr, multierror.Prefix(
|
} else {
|
||||||
c.shadowErr, "shadow graph:"))
|
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:"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestContext2Apply(t *testing.T) {
|
func TestContext2Apply_basic(t *testing.T) {
|
||||||
m := testModule(t, "apply-good")
|
m := testModule(t, "apply-good")
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
p.ApplyFn = testApplyFn
|
p.ApplyFn = testApplyFn
|
||||||
|
|
|
@ -19,13 +19,13 @@ import (
|
||||||
// copied, no real providers or resources are used, etc.
|
// copied, no real providers or resources are used, etc.
|
||||||
func newShadowContext(c *Context) (*Context, *Context, io.Closer) {
|
func newShadowContext(c *Context) (*Context, *Context, io.Closer) {
|
||||||
// Copy the targets
|
// Copy the targets
|
||||||
targetRaw, err := copystructure.Config{Lock: true}.Copy(c.targets)
|
targetRaw, err := copystructure.Copy(c.targets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the variables
|
// Copy the variables
|
||||||
varRaw, err := copystructure.Config{Lock: true}.Copy(c.variables)
|
varRaw, err := copystructure.Copy(c.variables)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,12 @@ func newShadowContext(c *Context) (*Context, *Context, io.Closer) {
|
||||||
targets: targetRaw.([]string),
|
targets: targetRaw.([]string),
|
||||||
uiInput: nil, // TODO
|
uiInput: nil, // TODO
|
||||||
variables: varRaw.(map[string]interface{}),
|
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
|
// 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 := *c
|
||||||
real.providers = providerFactory.RealMap()
|
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