Skip to content

Commit e3a4e91

Browse files
committed
data source depends_on
A data source referencing another data source through depends_on should not be forced to defer until apply. Data sources have no side effects, so nothing should need to be applied. If the dependency has a planned change due to a managed resource, the original data source will also encounter that further down the list of dependencies. This prevents a data source being read during plan for any reason from causing other data sources to be deferred until apply. It does not change the behavior noticeably in 0.14, but because 0.13 still had separate refresh and plan phases which could read the data source, the deferral could cause many things downstream to become unexpectedly unknown until apply.
1 parent ef64df9 commit e3a4e91

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

terraform/context_plan_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6414,3 +6414,61 @@ resource "test_instance" "a" {
64146414
t.Fatal("Resource should not have been refreshed")
64156415
}
64166416
}
6417+
6418+
func TestContext2Plan_dataInModuleDependsOn(t *testing.T) {
6419+
p := testProvider("test")
6420+
p.ApplyFn = testApplyFn
6421+
p.DiffFn = testDiffFn
6422+
6423+
readDataSourceB := false
6424+
p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) (resp providers.ReadDataSourceResponse) {
6425+
cfg := req.Config.AsValueMap()
6426+
foo := cfg["foo"].AsString()
6427+
6428+
cfg["id"] = cty.StringVal("ID")
6429+
cfg["foo"] = cty.StringVal("new")
6430+
6431+
if foo == "b" {
6432+
readDataSourceB = true
6433+
}
6434+
6435+
resp.State = cty.ObjectVal(cfg)
6436+
return resp
6437+
}
6438+
6439+
m := testModuleInline(t, map[string]string{
6440+
"main.tf": `
6441+
module "a" {
6442+
source = "./mod_a"
6443+
}
6444+
6445+
module "b" {
6446+
source = "./mod_b"
6447+
depends_on = [module.a]
6448+
}`,
6449+
"mod_a/main.tf": `
6450+
data "test_data_source" "a" {
6451+
foo = "a"
6452+
}`,
6453+
"mod_b/main.tf": `
6454+
data "test_data_source" "b" {
6455+
foo = "b"
6456+
}`,
6457+
})
6458+
6459+
ctx := testContext2(t, &ContextOpts{
6460+
Config: m,
6461+
Providers: map[addrs.Provider]providers.Factory{
6462+
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
6463+
},
6464+
})
6465+
6466+
_, diags := ctx.Plan()
6467+
assertNoErrors(t, diags)
6468+
6469+
// The change to data source a should not prevent data source b from being
6470+
// read.
6471+
if !readDataSourceB {
6472+
t.Fatal("data source b was not read during plan")
6473+
}
6474+
}

terraform/eval_read_data_plan.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/zclconf/go-cty/cty"
99

10+
"github.com/hashicorp/terraform/addrs"
1011
"github.com/hashicorp/terraform/plans"
1112
"github.com/hashicorp/terraform/plans/objchange"
1213
"github.com/hashicorp/terraform/states"
@@ -154,6 +155,14 @@ func (n *evalReadDataPlan) forcePlanRead(ctx EvalContext) bool {
154155
// configuration.
155156
changes := ctx.Changes()
156157
for _, d := range n.dependsOn {
158+
if d.Resource.Mode == addrs.DataResourceMode {
159+
// Data sources have no side effects, so don't create a need to
160+
// delay this read. If the they do have a change planned, it must
161+
// be because of a dependency on a managed resource, in which case
162+
// we'll also encounter it in this list of dependencies.
163+
continue
164+
}
165+
157166
for _, change := range changes.GetChangesForConfigResource(d) {
158167
if change != nil && change.Action != plans.NoOp {
159168
return true

0 commit comments

Comments
 (0)