From e3f64af8ac5aa060d63d944947a14d9eae3b92c8 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Mon, 24 Sep 2018 15:14:32 -0400 Subject: [PATCH] Temporarily move 2 validate tests to plan We can't catch invalid attributes in validate at the moment, because the lack of count information causes the references to return unknown. Make sure they fail in plan, and mark the validate tests to fix later. --- terraform/context_plan_test.go | 87 +++++++++++++++++++++++++++--- terraform/context_validate_test.go | 7 +++ 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index 007e15a0f7..4b2ed72f8b 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -146,7 +146,7 @@ func TestContext2Plan_createBefore_deposed(t *testing.T) { ty := schema.ImpliedType() type InstanceGen struct { - Addr string + Addr string DeposedKey states.DeposedKey } want := map[InstanceGen]bool{ @@ -154,7 +154,7 @@ func TestContext2Plan_createBefore_deposed(t *testing.T) { Addr: "aws_instance.foo", }: true, { - Addr: "aws_instance.foo", + Addr: "aws_instance.foo", DeposedKey: states.DeposedKey("00000001"), }: true, } @@ -174,7 +174,7 @@ func TestContext2Plan_createBefore_deposed(t *testing.T) { } { - ric, err := changes[InstanceGen{Addr:"aws_instance.foo"}].Decode(ty) + ric, err := changes[InstanceGen{Addr: "aws_instance.foo"}].Decode(ty) if err != nil { t.Fatal(err) } @@ -193,7 +193,7 @@ func TestContext2Plan_createBefore_deposed(t *testing.T) { } { - ric, err := changes[InstanceGen{Addr:"aws_instance.foo", DeposedKey: states.DeposedKey("00000001")}].Decode(ty) + ric, err := changes[InstanceGen{Addr: "aws_instance.foo", DeposedKey: states.DeposedKey("00000001")}].Decode(ty) if err != nil { t.Fatal(err) } @@ -2558,7 +2558,6 @@ func TestContext2Plan_countZero(t *testing.T) { // This schema contains a DynamicPseudoType, and therefore can't go through any shim functions p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) { resp.PlannedState = req.ProposedNewState - fmt.Printf("PlANNED: %#v\n", req.ProposedNewState) resp.PlannedPrivate = req.PriorPrivate return resp } @@ -4928,7 +4927,6 @@ func TestContext2Plan_createBeforeDestroy_depends_datasource(t *testing.T) { switch i := ric.Addr.String(); i { case "aws_instance.foo[0]": - fmt.Printf("AFTER %#v\n", ric.After) if res.Action != plans.Create { t.Fatalf("resource %s should be created, got %s", ric.Addr, ric.Action) } @@ -4937,7 +4935,6 @@ func TestContext2Plan_createBeforeDestroy_depends_datasource(t *testing.T) { "computed": cty.UnknownVal(cty.String), }), ric.After) case "aws_instance.foo[1]": - fmt.Printf("AFTER %#v\n", ric.After) if res.Action != plans.Create { t.Fatalf("resource %s should be created, got %s", ric.Addr, ric.Action) } @@ -5422,6 +5419,82 @@ func TestContext2Plan_selfRefMultiAll(t *testing.T) { } } +func TestContext2Plan_invalidOutput(t *testing.T) { + m := testModuleInline(t, map[string]string{ + "main.tf": ` +data "aws_data_source" "name" {} + +output "out" { + value = "${data.aws_data_source.name.missing}" +}`, + }) + + p := testProvider("aws") + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "aws": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + if !diags.HasErrors() { + // Should get this error: + // Unsupported attribute: This object does not have an attribute named "missing" + t.Fatal("succeeded; want errors") + } + + gotErrStr := diags.Err().Error() + wantErrStr := "Unsupported attribute" + if !strings.Contains(gotErrStr, wantErrStr) { + t.Fatalf("missing expected error\ngot: %s\n\nwant: error containing %q", gotErrStr, wantErrStr) + } +} + +func TestContext2Plan_invalidModuleOutput(t *testing.T) { + m := testModuleInline(t, map[string]string{ + "child/main.tf": ` +data "aws_data_source" "name" {} + +output "out" { + value = "${data.aws_data_source.name.missing}" +}`, + "main.tf": ` +module "child" { + source = "./child" +} + +resource "aws_instance" "foo" { + foo = "${module.child.out}" +}`, + }) + + p := testProvider("aws") + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "aws": testProviderFuncFixed(p), + }, + ), + }) + + _, diags := ctx.Plan() + if !diags.HasErrors() { + // Should get this error: + // Unsupported attribute: This object does not have an attribute named "missing" + t.Fatal("succeeded; want errors") + } + + gotErrStr := diags.Err().Error() + wantErrStr := "Unsupported attribute" + if !strings.Contains(gotErrStr, wantErrStr) { + t.Fatalf("missing expected error\ngot: %s\n\nwant: error containing %q", gotErrStr, wantErrStr) + } +} + func checkVals(t *testing.T, expected, got cty.Value) { t.Helper() if !cmp.Equal(expected, got, valueComparer, typeComparer, equateEmpty) { diff --git a/terraform/context_validate_test.go b/terraform/context_validate_test.go index a2b902b53c..bac7bfa5b1 100644 --- a/terraform/context_validate_test.go +++ b/terraform/context_validate_test.go @@ -1113,6 +1113,12 @@ func TestContext2Validate_PlanGraphBuilder(t *testing.T) { } } +// FIXME: these 2 tests should be caught in validation. +// Since the evaluator can't determine if the resource contains a count during +// validation, any refereces are currently returned as unknown. We need a +// static validation of a reference to determine if it's possible within a +// particular schema. +/* func TestContext2Validate_invalidOutput(t *testing.T) { m := testModuleInline(t, map[string]string{ "main.tf": ` @@ -1176,3 +1182,4 @@ resource "aws_instance" "foo" { t.Fatal("succeeded; want errors") } } +*/