mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-11 00:22:32 -06:00
2448204201
Earlier commits arranged for each of our tofu.Context exported methods that perform graph-based operations to take a context.Context from their callers, and for the main callers in package command and package backend to connect those contexts to the top-level context from "package main" that can potentially have an OpenTelemetry span attached to it. This propagates those contexts a little deeper into the guts of the language runtime, getting it as far as the shared logic that drives a graph walk. The next step from here would be to change the interfaces GraphNodeExecutable and GraphNodeDynamicExpandable so that their methods both take a context.Context, but that would involve a big sprawling update to every implementation of each of those interfaces and so we'll save that for a later commit to keep this one relatively clean. This commit also reaches the first point of ambiguity where our older conventions call for "ctx" to be the variable name for a tofu.EvalContext rather than a context.Context. Since "ctx context.Context" is a core idiom in the Go community, we'll switch to using evalCtx as the variable name for tofu.EvalContext both here and in our future commits that will modify the two main graph walk interfaces that make extensive use of the tofu.EvalContext interface. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
91 lines
2.9 KiB
Go
91 lines
2.9 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package tofu
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
"github.com/opentofu/opentofu/internal/addrs"
|
|
"github.com/opentofu/opentofu/internal/configs"
|
|
"github.com/opentofu/opentofu/internal/states"
|
|
"github.com/opentofu/opentofu/internal/tfdiags"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
// Validate performs semantic validation of a configuration, and returns
|
|
// any warnings or errors.
|
|
//
|
|
// Syntax and structural checks are performed by the configuration loader,
|
|
// and so are not repeated here.
|
|
//
|
|
// Validate considers only the configuration and so it won't catch any
|
|
// errors caused by current values in the state, or other external information
|
|
// such as root module input variables. However, the Plan function includes
|
|
// all of the same checks as Validate, in addition to the other work it does
|
|
// to consider the previous run state and the planning options.
|
|
func (c *Context) Validate(ctx context.Context, config *configs.Config) tfdiags.Diagnostics {
|
|
defer c.acquireRun("validate")()
|
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
moreDiags := c.checkConfigDependencies(config)
|
|
diags = diags.Append(moreDiags)
|
|
// If required dependencies are not available then we'll bail early since
|
|
// otherwise we're likely to just see a bunch of other errors related to
|
|
// incompatibilities, which could be overwhelming for the user.
|
|
if diags.HasErrors() {
|
|
return diags
|
|
}
|
|
|
|
log.Printf("[DEBUG] Building and walking validate graph")
|
|
|
|
// Validate is to check if the given module is valid regardless of
|
|
// input values, current state, etc. Therefore we populate all of the
|
|
// input values with unknown values of the expected type, allowing us
|
|
// to perform a type check without assuming any particular values.
|
|
varValues := make(InputValues)
|
|
for name, variable := range config.Module.Variables {
|
|
ty := variable.Type
|
|
if ty == cty.NilType {
|
|
// Can't predict the type at all, so we'll just mark it as
|
|
// cty.DynamicVal (unknown value of cty.DynamicPseudoType).
|
|
ty = cty.DynamicPseudoType
|
|
}
|
|
varValues[name] = &InputValue{
|
|
Value: cty.UnknownVal(ty),
|
|
SourceType: ValueFromUnknown,
|
|
}
|
|
}
|
|
|
|
providerFunctionTracker := make(ProviderFunctionMapping)
|
|
|
|
graph, moreDiags := (&PlanGraphBuilder{
|
|
Config: config,
|
|
Plugins: c.plugins,
|
|
State: states.NewState(),
|
|
RootVariableValues: varValues,
|
|
Operation: walkValidate,
|
|
ProviderFunctionTracker: providerFunctionTracker,
|
|
}).Build(addrs.RootModuleInstance)
|
|
diags = diags.Append(moreDiags)
|
|
if moreDiags.HasErrors() {
|
|
return diags
|
|
}
|
|
|
|
walker, walkDiags := c.walk(ctx, graph, walkValidate, &graphWalkOpts{
|
|
Config: config,
|
|
ProviderFunctionTracker: providerFunctionTracker,
|
|
})
|
|
diags = diags.Append(walker.NonFatalDiagnostics)
|
|
diags = diags.Append(walkDiags)
|
|
if walkDiags.HasErrors() {
|
|
return diags
|
|
}
|
|
|
|
return diags
|
|
}
|