mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
6039622111
Now that we don't have to handle data sources that may or may not have been updated during a refresh phase, and the plan phase can save the data source to the refreshed state, we can remove a lot of the logic involved in detecting whether the data source needs to be planned or not. When there is no separate refresh phase, we always must attempt to read the data source during planning, and the only conditions are based on having a known configuration, and not having any dependencies on which we're waiting. If the data source is read during plan, we can now save that directly to the refreshed state, and don't need to smuggle the value as a change to be saved during apply.
83 lines
2.4 KiB
Go
83 lines
2.4 KiB
Go
package terraform
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform/plans"
|
|
"github.com/hashicorp/terraform/states"
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
)
|
|
|
|
// evalReadDataApply is an EvalNode implementation that deals with the main part
|
|
// of the data resource lifecycle: either actually reading from the data source
|
|
// or generating a plan to do so.
|
|
type evalReadDataApply struct {
|
|
evalReadData
|
|
}
|
|
|
|
func (n *evalReadDataApply) Eval(ctx EvalContext) (interface{}, error) {
|
|
absAddr := n.Addr.Absolute(ctx.Path())
|
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
var planned *plans.ResourceInstanceChange
|
|
if n.Planned != nil {
|
|
planned = *n.Planned
|
|
}
|
|
|
|
if n.ProviderSchema == nil || *n.ProviderSchema == nil {
|
|
return nil, fmt.Errorf("provider schema not available for %s", n.Addr)
|
|
}
|
|
|
|
if planned != nil && planned.Action != plans.Read {
|
|
// If any other action gets in here then that's always a bug; this
|
|
// EvalNode only deals with reading.
|
|
return nil, fmt.Errorf(
|
|
"invalid action %s for %s: only Read is supported (this is a bug in Terraform; please report it!)",
|
|
planned.Action, absAddr,
|
|
)
|
|
}
|
|
|
|
if err := ctx.Hook(func(h Hook) (HookAction, error) {
|
|
return h.PreApply(absAddr, states.CurrentGen, planned.Action, planned.Before, planned.After)
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
config := *n.Config
|
|
providerSchema := *n.ProviderSchema
|
|
schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource())
|
|
if schema == nil {
|
|
// Should be caught during validation, so we don't bother with a pretty error here
|
|
return nil, fmt.Errorf("provider %q does not support data source %q", n.ProviderAddr.Provider.String(), n.Addr.Resource.Type)
|
|
}
|
|
|
|
forEach, _ := evaluateForEachExpression(config.ForEach, ctx)
|
|
keyData := EvalDataForInstanceKey(n.Addr.Key, forEach)
|
|
|
|
configVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil, keyData)
|
|
diags = diags.Append(configDiags)
|
|
if configDiags.HasErrors() {
|
|
return nil, diags.ErrWithWarnings()
|
|
}
|
|
|
|
newVal, readDiags := n.readDataSource(ctx, configVal)
|
|
diags = diags.Append(readDiags)
|
|
if diags.HasErrors() {
|
|
return nil, diags.ErrWithWarnings()
|
|
}
|
|
|
|
*n.State = &states.ResourceInstanceObject{
|
|
Value: newVal,
|
|
Status: states.ObjectReady,
|
|
}
|
|
|
|
if err := ctx.Hook(func(h Hook) (HookAction, error) {
|
|
return h.PostApply(absAddr, states.CurrentGen, newVal, diags.Err())
|
|
}); err != nil {
|
|
diags = diags.Append(err)
|
|
}
|
|
|
|
return nil, diags.ErrWithWarnings()
|
|
}
|