terraform: shadow errors with UUID() must be ignored

People with `uuid()` usage in their configurations would receive shadow
errors every time on plan because the UUID would change.

This is hacky fix but I also believe correct: if a shadow error contains
uuid() then we ignore the shadow error completely. This feels wrong but
I'll explain why it is likely right:

The "right" feeling solution is to create deterministic random output
across graph runs. This would require using math/rand and seeding it
with the same value each run. However, this alone probably won't work
due to Terraform's parallelism and potential to call uuid() in different
orders. In addition to this, you can't seed crypto/rand and its unlikely
that we'll NEVER use crypto/rand in the future even if we switched
uuid() to use math/rand.

Therefore, the solution is simple: if there is no shadow error, no
problem. If there is a shadow error and it contains uuid(), then ignore
it.
This commit is contained in:
Mitchell Hashimoto 2016-11-14 10:17:42 -08:00
parent 9205d25d38
commit aa5d16be79
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
3 changed files with 36 additions and 1 deletions

View File

@ -2010,6 +2010,25 @@ func TestContext2Plan_orphan(t *testing.T) {
}
}
// This tests that configurations with UUIDs don't produce errors.
// For shadows, this would produce errors since a UUID changes every time.
func TestContext2Plan_shadowUuid(t *testing.T) {
m := testModule(t, "plan-shadow-uuid")
p := testProvider("aws")
p.DiffFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Module: m,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
})
_, err := ctx.Plan()
if err != nil {
t.Fatalf("err: %s", err)
}
}
func TestContext2Plan_state(t *testing.T) {
m := testModule(t, "plan-good")
p := testProvider("aws")

View File

@ -2,6 +2,7 @@ package terraform
import (
"fmt"
"strings"
"github.com/hashicorp/go-multierror"
"github.com/mitchellh/copystructure"
@ -138,5 +139,17 @@ func (c *shadowContextCloser) CloseShadow() error {
}
func (c *shadowContextCloser) ShadowError() error {
return c.Components.ShadowError()
err := c.Components.ShadowError()
if err == nil {
return nil
}
// This is a sad edge case: if the configuration contains uuid() at
// any point, we cannot reason aboyt the shadow execution. Tested
// with Context2Plan_shadowUuid.
if strings.Contains(err.Error(), "uuid()") {
err = nil
}
return err
}

View File

@ -0,0 +1,3 @@
resource "aws_instance" "test" {
value = "${uuid()}"
}