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 3c34b96836..2a735703fb 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 009aec5cd0..bc7f1f73ed 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 19c9f26111..b9eb064552 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 f01292abb9..20b37933d0 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 85be320e69..8e503c3d13 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