From c70be3c3289282bf131664120c1397cc7e4fcb8f Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 12 Dec 2018 16:08:28 -0500 Subject: [PATCH 1/2] failing tests when using resources with count Two different tests failing around resourced with count --- builtin/providers/test/data_source.go | 14 ++++++ builtin/providers/test/data_source_test.go | 50 ++++++++++++++++++++++ builtin/providers/test/resource_test.go | 28 ++++++++++++ 3 files changed, 92 insertions(+) diff --git a/builtin/providers/test/data_source.go b/builtin/providers/test/data_source.go index 3c34b9683..2a735703f 100644 --- a/builtin/providers/test/data_source.go +++ b/builtin/providers/test/data_source.go @@ -31,6 +31,17 @@ func testDataSource() *schema.Resource { Type: schema.TypeString, Computed: true, }, + + "input_map": { + Type: schema.TypeMap, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + "output_map": { + Type: schema.TypeMap, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + }, }, } } @@ -45,5 +56,8 @@ func testDataSourceRead(d *schema.ResourceData, meta interface{}) error { d.Set("output", "some output") } + if inputMap, hasInput := d.GetOk("input_map"); hasInput { + d.Set("output_map", inputMap) + } return nil } diff --git a/builtin/providers/test/data_source_test.go b/builtin/providers/test/data_source_test.go index 009aec5cd..bc7f1f73e 100644 --- a/builtin/providers/test/data_source_test.go +++ b/builtin/providers/test/data_source_test.go @@ -3,6 +3,7 @@ package test import ( "errors" "fmt" + "regexp" "strings" "testing" @@ -189,3 +190,52 @@ data "test_data_source" "y" { }, }) } + +// referencing test_data_source.one.output_map["a"] should produce an error when +// there's a count, but instead we end up with an unknown value after apply. +func TestDataSource_indexedCountOfOne(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: strings.TrimSpace(` +data "test_data_source" "one" { + count = 1 + input_map = { + "a" = "b" + } +} + +data "test_data_source" "two" { + input_map = { + "x" = data.test_data_source.one.output_map["a"] + } +} + `), + ExpectError: regexp.MustCompile("value does not have any attributes"), + }, + }, + }) +} + +// Verify that we can destroy when a data source references something with a +// count of 1. +func TestDataSource_countRefDestroyError(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: strings.TrimSpace(` +data "test_data_source" "one" { + count = 1 + input = "a" +} + +data "test_data_source" "two" { + input = data.test_data_source.one[0].output +} + `), + }, + }, + }) +} diff --git a/builtin/providers/test/resource_test.go b/builtin/providers/test/resource_test.go index 19c9f2611..b9eb06455 100644 --- a/builtin/providers/test/resource_test.go +++ b/builtin/providers/test/resource_test.go @@ -493,3 +493,31 @@ resource "test_resource" "foo" { }, }) } + +// Verify that we can destroy when a managed resource references something with +// a count of 1. +func TestResource_countRefDestroyError(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: strings.TrimSpace(` +resource "test_resource" "one" { + count = 1 + required = "ok" + required_map = { + key = "val" + } +} + +resource "test_resource" "two" { + required = test_resource.one[0].id + required_map = { + key = "val" + } +} + `), + }, + }, + }) +} From 21d06aac41ac84862f0efd92bdffa1a3324385a2 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Sun, 16 Dec 2018 21:59:44 -0500 Subject: [PATCH 2/2] don't expand EachMode from state during validation Validate should not require state or changes to be present. Break out early when using evaluationStateData during walkValidate before checking state or changes, to prevent errors when indexing resources that haven't been expanded. --- terraform/eval_context_builtin.go | 1 + terraform/evaluate.go | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/terraform/eval_context_builtin.go b/terraform/eval_context_builtin.go index f01292abb..20b37933d 100644 --- a/terraform/eval_context_builtin.go +++ b/terraform/eval_context_builtin.go @@ -289,6 +289,7 @@ func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, keyData Evaluator: ctx.Evaluator, ModulePath: ctx.PathValue, InstanceKeyData: keyData, + Operation: ctx.Evaluator.Operation, } return ctx.Evaluator.Scope(data, self) } diff --git a/terraform/evaluate.go b/terraform/evaluate.go index 85be320e6..8e503c3d1 100644 --- a/terraform/evaluate.go +++ b/terraform/evaluate.go @@ -91,6 +91,10 @@ type evaluationStateData struct { // since the user specifies in that case which variable name to locally // shadow.) InstanceKeyData InstanceKeyEvalData + + // Operation records the type of walk the evaluationStateData is being used + // for. + Operation walkOperation } // InstanceKeyEvalData is used during evaluation to specify which values, @@ -506,6 +510,12 @@ func (d *evaluationStateData) GetResourceInstance(addr addrs.ResourceInstance, r return cty.DynamicVal, diags } + // Break out early during validation, because resource may not be expanded + // yet and indexed references may show up as invalid. + if d.Operation == walkValidate { + return cty.DynamicVal, diags + } + schema := d.getResourceSchema(addr.ContainingResource(), rs.ProviderConfig) // If we are able to automatically convert to the "right" type of instance