From 86477c8fc788da798530c056caf69eceb1e841ae Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 25 Sep 2019 09:26:50 -0400 Subject: [PATCH] ensure data sources are always written to state This commit was generated from hashicorp/terraform#22895. --- terraform/context_refresh_test.go | 58 +++++++++++++++++++ terraform/node_data_refresh.go | 22 ++----- .../testdata/plan-data-depends-on/main.tf | 14 +++++ 3 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 terraform/testdata/plan-data-depends-on/main.tf diff --git a/terraform/context_refresh_test.go b/terraform/context_refresh_test.go index 91628820d6d..d33c0a15b73 100644 --- a/terraform/context_refresh_test.go +++ b/terraform/context_refresh_test.go @@ -1906,3 +1906,61 @@ data "aws_data_source" "foo" { t.Fatal("ValidateDataSourceConfig not called during plan") } } + +func TestContext2Refresh_dataResourceDependsOn(t *testing.T) { + m := testModule(t, "plan-data-depends-on") + p := testProvider("test") + p.GetSchemaReturn = &ProviderSchema{ + ResourceTypes: map[string]*configschema.Block{ + "test_resource": { + Attributes: map[string]*configschema.Attribute{ + "id": {Type: cty.String, Computed: true}, + "foo": {Type: cty.String, Optional: true}, + }, + }, + }, + DataSources: map[string]*configschema.Block{ + "test_data": { + Attributes: map[string]*configschema.Attribute{ + "compute": {Type: cty.String, Computed: true}, + }, + }, + }, + } + p.DiffFn = testDiffFn + + s := MustShimLegacyState(&State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "test_resource.a": &ResourceState{ + Type: "test_resource", + Provider: "provider.test", + Primary: &InstanceState{ + ID: "a", + Attributes: map[string]string{ + "id": "a", + }, + }, + }, + }, + }, + }, + }) + + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ), + State: s, + }) + + _, diags := ctx.Refresh() + if diags.HasErrors() { + t.Fatalf("unexpected errors: %s", diags.Err()) + } +} diff --git a/terraform/node_data_refresh.go b/terraform/node_data_refresh.go index 72b12a1498b..60bcdb74c63 100644 --- a/terraform/node_data_refresh.go +++ b/terraform/node_data_refresh.go @@ -162,22 +162,6 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode { ProviderSchema: &providerSchema, }, - &EvalIf{ - If: func(ctx EvalContext) (bool, error) { - // If the config explicitly has a depends_on for this - // data source, assume the intention is to prevent - // refreshing ahead of that dependency, and therefore - // we need to deal with this resource during the apply - // phase.. - if len(n.Config.DependsOn) > 0 { - return true, EvalEarlyExitError{} - } - - return true, nil - }, - Then: EvalNoop{}, - }, - // EvalReadData will _attempt_ to read the data source, but may // generate an incomplete planned object if the configuration // includes values that won't be known until apply. @@ -191,6 +175,12 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode { OutputChange: &change, OutputConfigValue: &configVal, OutputState: &state, + // If the config explicitly has a depends_on for this data + // source, assume the intention is to prevent refreshing ahead + // of that dependency, and therefore we need to deal with this + // resource during the apply phase. We do that by forcing this + // read to result in a plan. + ForcePlanRead: len(n.Config.DependsOn) > 0, }, &EvalIf{ diff --git a/terraform/testdata/plan-data-depends-on/main.tf b/terraform/testdata/plan-data-depends-on/main.tf new file mode 100644 index 00000000000..c7332ad291e --- /dev/null +++ b/terraform/testdata/plan-data-depends-on/main.tf @@ -0,0 +1,14 @@ +resource "test_resource" "a" { +} + +data "test_data" "d" { + count = 1 + depends_on = [ + test_resource.a + ] +} + +resource "test_resource" "b" { + count = 1 + foo = data.test_data.d[count.index].compute +}