From 1aed6f8abb1ab1a934b49bfaff58e10f86fc0af6 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 30 Oct 2016 14:27:08 -0700 Subject: [PATCH] terraform: validate graph on resource expansation to catch cycles Fixes #5342 The dynamically expanded subgraph wasn't being validated so cycles weren't being caught here and Terraform would just hang. This fixes that. Note that it may make sense to validate higher level when the graph is expanded but there are certain cases we actually expect the graph to potentially be invalid, so this seems safer for now. --- terraform/context_plan_test.go | 21 +++++++++++++++++++ terraform/graph_config_node_resource.go | 2 +- .../plan-provisioner-cycle/main.tf | 7 +++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 terraform/test-fixtures/plan-provisioner-cycle/main.tf diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index 2cadb5ab8..d2c3dbb3b 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -841,6 +841,27 @@ func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) { } } +func TestContext2Plan_provisionerCycle(t *testing.T) { + m := testModule(t, "plan-provisioner-cycle") + p := testProvider("aws") + p.DiffFn = testDiffFn + pr := testProvisioner() + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + Provisioners: map[string]ResourceProvisionerFactory{ + "local-exec": testProvisionerFuncFixed(pr), + }, + }) + + _, err := ctx.Plan() + if err == nil { + t.Fatalf("should error") + } +} + func TestContext2Plan_computed(t *testing.T) { m := testModule(t, "plan-computed") p := testProvider("aws") diff --git a/terraform/graph_config_node_resource.go b/terraform/graph_config_node_resource.go index 1c45289a9..0e35d4b38 100644 --- a/terraform/graph_config_node_resource.go +++ b/terraform/graph_config_node_resource.go @@ -188,7 +188,7 @@ func (n *GraphNodeConfigResource) DynamicExpand(ctx EvalContext) (*Graph, error) steps = append(steps, &RootTransformer{}) // Build the graph - b := &BasicGraphBuilder{Steps: steps} + b := &BasicGraphBuilder{Steps: steps, Validate: true} return b.Build(ctx.Path()) } diff --git a/terraform/test-fixtures/plan-provisioner-cycle/main.tf b/terraform/test-fixtures/plan-provisioner-cycle/main.tf new file mode 100644 index 000000000..ed65c0918 --- /dev/null +++ b/terraform/test-fixtures/plan-provisioner-cycle/main.tf @@ -0,0 +1,7 @@ +resource "aws_instance" "foo" { + count = 3 + + provisioner "local-exec" { + command = "echo ${aws_instance.foo.0.id} ${aws_instance.foo.1.id} ${aws_instance.foo.2.id}" + } +}