mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-25 01:00:16 -05:00
lang/eval: Stub of ConfigInstance.prepareToPlan
This is my current idea for how to resolve the chicken/egg problem of the planning phase needing to know who uses ephemeral resource instances and provider instances but us needing to evaluate the configuration to know those relationships. This borrows the evaluation behavior previously used for ConfigInstance.Validate to produce a conservative evaluation of the configuration without depending on any configured providers or ephemeral resource instances, which we (in future commits) will use to discover the relationships between those objects so that the real walk during the planning phase can know when to start and stop them. This relies on the idea that an evaluation with values stubbed out as unknown should produce _at least_ the relationships that would occur with fewer unknown values, though it might also report additional dependencies that would vanish once values become more known. This gives the plan phase something to start with and then we'll learn a tighter set of dependencies during the planning phase which will form the basis of the apply-time execution graph. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
@@ -8,11 +8,7 @@ package eval
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/lang/eval/internal/configgraph"
|
||||
"github.com/opentofu/opentofu/internal/lang/grapheval"
|
||||
"github.com/opentofu/opentofu/internal/plans/objchange"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
@@ -26,56 +22,13 @@ import (
|
||||
// [ConfigInstance.DrivePlanning] because equivalent checks occur within those
|
||||
// operations.
|
||||
func (c *ConfigInstance) Validate(ctx context.Context) tfdiags.Diagnostics {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
// All of our work will be associated with a workgraph worker that serves
|
||||
// as the initial worker node in the work graph.
|
||||
ctx = grapheval.ContextWithNewWorker(ctx)
|
||||
|
||||
internalGlue := &validationGlue{
|
||||
providers: c.evalContext.Providers,
|
||||
}
|
||||
rootModuleInstance, moreDiags := c.newRootModuleInstance(ctx, internalGlue)
|
||||
diags = diags.Append(moreDiags)
|
||||
if moreDiags.HasErrors() {
|
||||
// If we can't even load the root module then we'll bail out early.
|
||||
return diags
|
||||
}
|
||||
|
||||
// For validation purposes we don't need to do anything other than the
|
||||
// full-tree check that would normally run alongside the driving of
|
||||
// some other operation.
|
||||
moreDiags = checkAll(ctx, rootModuleInstance)
|
||||
diags = diags.Append(moreDiags)
|
||||
_, diags := c.precheckedModuleInstance(ctx)
|
||||
// For validation purposes we don't need to do anything more with
|
||||
// the module instance we checked... the check result _is_ the validation
|
||||
// result.
|
||||
return diags
|
||||
}
|
||||
|
||||
// validationGlue is the [evaluationGlue] implementation used by
|
||||
// [ConfigInstance.Validate].
|
||||
type validationGlue struct {
|
||||
// validationGlue uses provider schema information to prepare placeholder
|
||||
// "final state" values for resource instances because validation does
|
||||
// not use information from the state.
|
||||
providers Providers
|
||||
}
|
||||
|
||||
// ResourceInstanceValue implements evaluationGlue.
|
||||
func (v *validationGlue) ResourceInstanceValue(ctx context.Context, ri *configgraph.ResourceInstance, configVal cty.Value) (cty.Value, tfdiags.Diagnostics) {
|
||||
schema, diags := v.providers.ResourceTypeSchema(ctx,
|
||||
ri.Provider,
|
||||
ri.Addr.Resource.Resource.Mode,
|
||||
ri.Addr.Resource.Resource.Type,
|
||||
)
|
||||
if diags.HasErrors() {
|
||||
// If we can't get schema then we'll return a fully-unknown value
|
||||
// as a placeholder because we don't even know what type we need.
|
||||
return cty.DynamicVal, diags
|
||||
}
|
||||
|
||||
// We now have enough information to produce a placeholder "planned new
|
||||
// state" by placing unknown values in any location that the provider
|
||||
// would be allowed to choose a value.
|
||||
return objchange.ProposedNew(
|
||||
schema.Block, cty.NullVal(schema.Block.ImpliedType()), configVal,
|
||||
), diags
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user