Don't use plans.Update for data sources

The new data source planning logic no longer needs a separate action,
and the apply status can be determined from whether the After value is
complete or not.
This commit is contained in:
James Bardin 2020-05-13 13:49:05 -04:00
parent 8850d787f4
commit 291110fe78
3 changed files with 15 additions and 10 deletions

View File

@ -5053,16 +5053,16 @@ func TestContext2Plan_createBeforeDestroy_depends_datasource(t *testing.T) {
"computed": cty.StringVal("data_id"), "computed": cty.StringVal("data_id"),
}), ric.After) }), ric.After)
case "data.aws_vpc.bar[0]": case "data.aws_vpc.bar[0]":
if res.Action != plans.Update { if res.Action != plans.Read {
t.Fatalf("resource %s should be update, got %s", ric.Addr, ric.Action) t.Fatalf("resource %s should be read, got %s", ric.Addr, ric.Action)
} }
checkVals(t, objectVal(t, schema, map[string]cty.Value{ checkVals(t, objectVal(t, schema, map[string]cty.Value{
"id": cty.StringVal("data_id"), "id": cty.StringVal("data_id"),
"foo": cty.StringVal("0"), "foo": cty.StringVal("0"),
}), ric.After) }), ric.After)
case "data.aws_vpc.bar[1]": case "data.aws_vpc.bar[1]":
if res.Action != plans.Update { if res.Action != plans.Read {
t.Fatalf("resource %s should be update, got %s", ric.Addr, ric.Action) t.Fatalf("resource %s should be read, got %s", ric.Addr, ric.Action)
} }
checkVals(t, objectVal(t, schema, map[string]cty.Value{ checkVals(t, objectVal(t, schema, map[string]cty.Value{
"id": cty.StringVal("data_id"), "id": cty.StringVal("data_id"),

View File

@ -29,11 +29,11 @@ func (n *evalReadDataApply) Eval(ctx EvalContext) (interface{}, error) {
return nil, fmt.Errorf("provider schema not available for %s", n.Addr) return nil, fmt.Errorf("provider schema not available for %s", n.Addr)
} }
if planned != nil && !(planned.Action == plans.Read || planned.Action == plans.Update) { if planned != nil && planned.Action != plans.Read {
// If any other action gets in here then that's always a bug; this // If any other action gets in here then that's always a bug; this
// EvalNode only deals with reading. // EvalNode only deals with reading.
return nil, fmt.Errorf( return nil, fmt.Errorf(
"invalid action %s for %s: only Read or Update is supported (this is a bug in Terraform; please report it!)", "invalid action %s for %s: only Read is supported (this is a bug in Terraform; please report it!)",
planned.Action, absAddr, planned.Action, absAddr,
) )
} }
@ -44,9 +44,9 @@ func (n *evalReadDataApply) Eval(ctx EvalContext) (interface{}, error) {
return nil, err return nil, err
} }
// we have a change and it is complete, which means we read the data // We have a change and it is complete, which means we read the data
// source during plan and only need to store it in state. // source during plan and only need to store it in state.
if planned.Action == plans.Update { if planned.After.IsWhollyKnown() {
if err := ctx.Hook(func(h Hook) (HookAction, error) { if err := ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostApply(absAddr, states.CurrentGen, planned.After, nil) return h.PostApply(absAddr, states.CurrentGen, planned.After, nil)
}); err != nil { }); err != nil {

View File

@ -81,6 +81,8 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) {
return nil, diags.ErrWithWarnings() return nil, diags.ErrWithWarnings()
} }
// Apply detects that the data source will need to be read by the After
// value containing unknowns from PlanDataResourceObject.
*n.OutputChange = &plans.ResourceInstanceChange{ *n.OutputChange = &plans.ResourceInstanceChange{
Addr: absAddr, Addr: absAddr,
ProviderAddr: n.ProviderAddr, ProviderAddr: n.ProviderAddr,
@ -124,12 +126,15 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) {
return nil, diags.ErrWithWarnings() return nil, diags.ErrWithWarnings()
} }
// Produce a change regardless of the outcome. // The returned value from ReadDataSource must be non-nil and known,
// which we store in the change. Apply will use the fact that the After
// value is wholly kown to save the state directly, rather than reading the
// data source again.
*n.OutputChange = &plans.ResourceInstanceChange{ *n.OutputChange = &plans.ResourceInstanceChange{
Addr: absAddr, Addr: absAddr,
ProviderAddr: n.ProviderAddr, ProviderAddr: n.ProviderAddr,
Change: plans.Change{ Change: plans.Change{
Action: plans.Update, Action: plans.Read,
Before: priorVal, Before: priorVal,
After: newVal, After: newVal,
}, },