mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
evaluate vars and outputs during import
Outputs were not being evaluated during import, because it was not added to the walk filter. Remove any unnecessary walk filters from all the Execute nodes.
This commit is contained in:
parent
bad0adb996
commit
a32028aeed
@ -38,7 +38,7 @@ func TestContextEval(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
`module.child.result`,
|
`module.child.result`,
|
||||||
cty.UnknownVal(cty.Number),
|
cty.NumberIntVal(6),
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -153,13 +153,13 @@ func (n *nodeModuleVariable) Execute(ctx EvalContext, op walkOperation) error {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch op {
|
switch op {
|
||||||
case walkPlan, walkApply, walkDestroy:
|
case walkValidate:
|
||||||
vals, err = n.EvalModuleCallArgument(ctx, false)
|
vals, err = n.EvalModuleCallArgument(ctx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case walkValidate:
|
default:
|
||||||
vals, err = n.EvalModuleCallArgument(ctx, true)
|
vals, err = n.EvalModuleCallArgument(ctx, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -199,61 +199,55 @@ func (n *NodeApplyableOutput) References() []*addrs.Reference {
|
|||||||
|
|
||||||
// GraphNodeExecutable
|
// GraphNodeExecutable
|
||||||
func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) error {
|
func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) error {
|
||||||
switch op {
|
// This has to run before we have a state lock, since evaluation also
|
||||||
// Everything except walkImport
|
// reads the state
|
||||||
case walkEval, walkPlan, walkApply, walkValidate, walkDestroy, walkPlanDestroy:
|
val, diags := ctx.EvaluateExpr(n.Config.Expr, cty.DynamicPseudoType, nil)
|
||||||
// This has to run before we have a state lock, since evaluation also
|
// We'll handle errors below, after we have loaded the module.
|
||||||
// reads the state
|
|
||||||
val, diags := ctx.EvaluateExpr(n.Config.Expr, cty.DynamicPseudoType, nil)
|
|
||||||
// We'll handle errors below, after we have loaded the module.
|
|
||||||
|
|
||||||
// Outputs don't have a separate mode for validation, so validate
|
// Outputs don't have a separate mode for validation, so validate
|
||||||
// depends_on expressions here too
|
// depends_on expressions here too
|
||||||
diags = diags.Append(validateDependsOn(ctx, n.Config.DependsOn))
|
diags = diags.Append(validateDependsOn(ctx, n.Config.DependsOn))
|
||||||
|
|
||||||
// Ensure that non-sensitive outputs don't include sensitive values
|
// Ensure that non-sensitive outputs don't include sensitive values
|
||||||
_, marks := val.UnmarkDeep()
|
_, marks := val.UnmarkDeep()
|
||||||
_, hasSensitive := marks["sensitive"]
|
_, hasSensitive := marks["sensitive"]
|
||||||
if !n.Config.Sensitive && hasSensitive {
|
if !n.Config.Sensitive && hasSensitive {
|
||||||
diags = diags.Append(&hcl.Diagnostic{
|
diags = diags.Append(&hcl.Diagnostic{
|
||||||
Severity: hcl.DiagError,
|
Severity: hcl.DiagError,
|
||||||
Summary: "Output refers to sensitive values",
|
Summary: "Output refers to sensitive values",
|
||||||
Detail: "Expressions used in outputs can only refer to sensitive values if the sensitive attribute is true.",
|
Detail: "Expressions used in outputs can only refer to sensitive values if the sensitive attribute is true.",
|
||||||
Subject: n.Config.DeclRange.Ptr(),
|
Subject: n.Config.DeclRange.Ptr(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
state := ctx.State()
|
state := ctx.State()
|
||||||
if state == nil {
|
if state == nil {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
changes := ctx.Changes() // may be nil, if we're not working on a changeset
|
|
||||||
|
|
||||||
// handling the interpolation error
|
|
||||||
if diags.HasErrors() {
|
|
||||||
if flagWarnOutputErrors {
|
|
||||||
log.Printf("[ERROR] Output interpolation %q failed: %s", n.Addr, diags.Err())
|
|
||||||
// if we're continuing, make sure the output is included, and
|
|
||||||
// marked as unknown. If the evaluator was able to find a type
|
|
||||||
// for the value in spite of the error then we'll use it.
|
|
||||||
n.setValue(state, changes, cty.UnknownVal(val.Type()))
|
|
||||||
return EvalEarlyExitError{}
|
|
||||||
}
|
|
||||||
return diags.Err()
|
|
||||||
}
|
|
||||||
n.setValue(state, changes, val)
|
|
||||||
|
|
||||||
// If we were able to evaluate a new value, we can update that in the
|
|
||||||
// refreshed state as well.
|
|
||||||
if state = ctx.RefreshState(); state != nil && val.IsWhollyKnown() {
|
|
||||||
n.setValue(state, changes, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changes := ctx.Changes() // may be nil, if we're not working on a changeset
|
||||||
|
|
||||||
|
// handling the interpolation error
|
||||||
|
if diags.HasErrors() {
|
||||||
|
if flagWarnOutputErrors {
|
||||||
|
log.Printf("[ERROR] Output interpolation %q failed: %s", n.Addr, diags.Err())
|
||||||
|
// if we're continuing, make sure the output is included, and
|
||||||
|
// marked as unknown. If the evaluator was able to find a type
|
||||||
|
// for the value in spite of the error then we'll use it.
|
||||||
|
n.setValue(state, changes, cty.UnknownVal(val.Type()))
|
||||||
|
return EvalEarlyExitError{}
|
||||||
|
}
|
||||||
|
return diags.Err()
|
||||||
|
}
|
||||||
|
n.setValue(state, changes, val)
|
||||||
|
|
||||||
|
// If we were able to evaluate a new value, we can update that in the
|
||||||
|
// refreshed state as well.
|
||||||
|
if state = ctx.RefreshState(); state != nil && val.IsWhollyKnown() {
|
||||||
|
n.setValue(state, changes, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// dag.GraphNodeDotter impl.
|
// dag.GraphNodeDotter impl.
|
||||||
|
@ -136,133 +136,130 @@ func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation)
|
|||||||
var state *states.ResourceInstanceObject
|
var state *states.ResourceInstanceObject
|
||||||
var provisionerErr error
|
var provisionerErr error
|
||||||
|
|
||||||
switch op {
|
provider, providerSchema, err := GetProvider(ctx, n.ResolvedProvider)
|
||||||
case walkApply, walkDestroy:
|
if err != nil {
|
||||||
provider, providerSchema, err := GetProvider(ctx, n.ResolvedProvider)
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
changeApply, err = n.readDiff(ctx, providerSchema)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
evalReduceDiff := &EvalReduceDiff{
|
||||||
|
Addr: addr.Resource,
|
||||||
|
InChange: &changeApply,
|
||||||
|
Destroy: true,
|
||||||
|
OutChange: &changeApply,
|
||||||
|
}
|
||||||
|
_, err = evalReduceDiff.Eval(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EvalReduceDiff may have simplified our planned change
|
||||||
|
// into a NoOp if it does not require destroying.
|
||||||
|
if changeApply == nil || changeApply.Action == plans.NoOp {
|
||||||
|
return EvalEarlyExitError{}
|
||||||
|
}
|
||||||
|
|
||||||
|
state, err = n.ReadResourceInstanceState(ctx, addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit early if the state object is null after reading the state
|
||||||
|
if state == nil || state.Value.IsNull() {
|
||||||
|
return EvalEarlyExitError{}
|
||||||
|
}
|
||||||
|
|
||||||
|
evalApplyPre := &EvalApplyPre{
|
||||||
|
Addr: addr.Resource,
|
||||||
|
State: &state,
|
||||||
|
Change: &changeApply,
|
||||||
|
}
|
||||||
|
_, err = evalApplyPre.Eval(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run destroy provisioners if not tainted
|
||||||
|
if state != nil && state.Status != states.ObjectTainted {
|
||||||
|
evalApplyProvisioners := &EvalApplyProvisioners{
|
||||||
|
Addr: addr.Resource,
|
||||||
|
State: &state,
|
||||||
|
ResourceConfig: n.Config,
|
||||||
|
Error: &provisionerErr,
|
||||||
|
When: configs.ProvisionerWhenDestroy,
|
||||||
|
}
|
||||||
|
_, err := evalApplyProvisioners.Eval(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if provisionerErr != nil {
|
||||||
changeApply, err = n.readDiff(ctx, providerSchema)
|
// If we have a provisioning error, then we just call
|
||||||
if err != nil {
|
// the post-apply hook now.
|
||||||
return err
|
evalApplyPost := &EvalApplyPost{
|
||||||
}
|
Addr: addr.Resource,
|
||||||
|
State: &state,
|
||||||
evalReduceDiff := &EvalReduceDiff{
|
Error: &provisionerErr,
|
||||||
Addr: addr.Resource,
|
|
||||||
InChange: &changeApply,
|
|
||||||
Destroy: true,
|
|
||||||
OutChange: &changeApply,
|
|
||||||
}
|
|
||||||
_, err = evalReduceDiff.Eval(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// EvalReduceDiff may have simplified our planned change
|
|
||||||
// into a NoOp if it does not require destroying.
|
|
||||||
if changeApply == nil || changeApply.Action == plans.NoOp {
|
|
||||||
return EvalEarlyExitError{}
|
|
||||||
}
|
|
||||||
|
|
||||||
state, err = n.ReadResourceInstanceState(ctx, addr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit early if the state object is null after reading the state
|
|
||||||
if state == nil || state.Value.IsNull() {
|
|
||||||
return EvalEarlyExitError{}
|
|
||||||
}
|
|
||||||
|
|
||||||
evalApplyPre := &EvalApplyPre{
|
|
||||||
Addr: addr.Resource,
|
|
||||||
State: &state,
|
|
||||||
Change: &changeApply,
|
|
||||||
}
|
|
||||||
_, err = evalApplyPre.Eval(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run destroy provisioners if not tainted
|
|
||||||
if state != nil && state.Status != states.ObjectTainted {
|
|
||||||
evalApplyProvisioners := &EvalApplyProvisioners{
|
|
||||||
Addr: addr.Resource,
|
|
||||||
State: &state,
|
|
||||||
ResourceConfig: n.Config,
|
|
||||||
Error: &provisionerErr,
|
|
||||||
When: configs.ProvisionerWhenDestroy,
|
|
||||||
}
|
}
|
||||||
_, err := evalApplyProvisioners.Eval(ctx)
|
_, err = evalApplyPost.Eval(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if provisionerErr != nil {
|
|
||||||
// If we have a provisioning error, then we just call
|
|
||||||
// the post-apply hook now.
|
|
||||||
evalApplyPost := &EvalApplyPost{
|
|
||||||
Addr: addr.Resource,
|
|
||||||
State: &state,
|
|
||||||
Error: &provisionerErr,
|
|
||||||
}
|
|
||||||
_, err = evalApplyPost.Eval(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Managed resources need to be destroyed, while data sources
|
// Managed resources need to be destroyed, while data sources
|
||||||
// are only removed from state.
|
// are only removed from state.
|
||||||
if addr.Resource.Resource.Mode == addrs.ManagedResourceMode {
|
if addr.Resource.Resource.Mode == addrs.ManagedResourceMode {
|
||||||
evalApply := &EvalApply{
|
evalApply := &EvalApply{
|
||||||
Addr: addr.Resource,
|
Addr: addr.Resource,
|
||||||
Config: nil, // No configuration because we are destroying
|
Config: nil, // No configuration because we are destroying
|
||||||
State: &state,
|
State: &state,
|
||||||
Change: &changeApply,
|
Change: &changeApply,
|
||||||
Provider: &provider,
|
Provider: &provider,
|
||||||
ProviderAddr: n.ResolvedProvider,
|
ProviderAddr: n.ResolvedProvider,
|
||||||
ProviderMetas: n.ProviderMetas,
|
ProviderMetas: n.ProviderMetas,
|
||||||
ProviderSchema: &providerSchema,
|
ProviderSchema: &providerSchema,
|
||||||
Output: &state,
|
Output: &state,
|
||||||
Error: &provisionerErr,
|
Error: &provisionerErr,
|
||||||
}
|
|
||||||
_, err = evalApply.Eval(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
evalWriteState := &EvalWriteState{
|
|
||||||
Addr: addr.Resource,
|
|
||||||
ProviderAddr: n.ResolvedProvider,
|
|
||||||
ProviderSchema: &providerSchema,
|
|
||||||
State: &state,
|
|
||||||
}
|
|
||||||
_, err = evalWriteState.Eval(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("[TRACE] NodeDestroyResourceInstance: removing state object for %s", n.Addr)
|
|
||||||
state := ctx.State()
|
|
||||||
state.SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider)
|
|
||||||
}
|
}
|
||||||
|
_, err = evalApply.Eval(ctx)
|
||||||
evalApplyPost := &EvalApplyPost{
|
|
||||||
Addr: addr.Resource,
|
|
||||||
State: &state,
|
|
||||||
Error: &provisionerErr,
|
|
||||||
}
|
|
||||||
_, err = evalApplyPost.Eval(ctx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = UpdateStateHook(ctx)
|
evalWriteState := &EvalWriteState{
|
||||||
|
Addr: addr.Resource,
|
||||||
|
ProviderAddr: n.ResolvedProvider,
|
||||||
|
ProviderSchema: &providerSchema,
|
||||||
|
State: &state,
|
||||||
|
}
|
||||||
|
_, err = evalWriteState.Eval(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("[TRACE] NodeDestroyResourceInstance: removing state object for %s", n.Addr)
|
||||||
|
state := ctx.State()
|
||||||
|
state.SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
evalApplyPost := &EvalApplyPost{
|
||||||
|
Addr: addr.Resource,
|
||||||
|
State: &state,
|
||||||
|
Error: &provisionerErr,
|
||||||
|
}
|
||||||
|
_, err = evalApplyPost.Eval(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = UpdateStateHook(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -76,44 +76,41 @@ func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx EvalContext, op walk
|
|||||||
var change *plans.ResourceInstanceChange
|
var change *plans.ResourceInstanceChange
|
||||||
var state *states.ResourceInstanceObject
|
var state *states.ResourceInstanceObject
|
||||||
|
|
||||||
switch op {
|
readStateDeposed := &EvalReadStateDeposed{
|
||||||
case walkPlan, walkPlanDestroy:
|
Addr: addr.Resource,
|
||||||
|
Output: &state,
|
||||||
readStateDeposed := &EvalReadStateDeposed{
|
Key: n.DeposedKey,
|
||||||
Addr: addr.Resource,
|
Provider: &provider,
|
||||||
Output: &state,
|
ProviderSchema: &providerSchema,
|
||||||
Key: n.DeposedKey,
|
|
||||||
Provider: &provider,
|
|
||||||
ProviderSchema: &providerSchema,
|
|
||||||
}
|
|
||||||
_, err = readStateDeposed.Eval(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
diffDestroy := &EvalDiffDestroy{
|
|
||||||
Addr: addr.Resource,
|
|
||||||
ProviderAddr: n.ResolvedProvider,
|
|
||||||
DeposedKey: n.DeposedKey,
|
|
||||||
State: &state,
|
|
||||||
Output: &change,
|
|
||||||
}
|
|
||||||
_, err = diffDestroy.Eval(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
writeDiff := &EvalWriteDiff{
|
|
||||||
Addr: addr.Resource,
|
|
||||||
DeposedKey: n.DeposedKey,
|
|
||||||
ProviderSchema: &providerSchema,
|
|
||||||
Change: &change,
|
|
||||||
}
|
|
||||||
_, err = writeDiff.Eval(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_, err = readStateDeposed.Eval(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
diffDestroy := &EvalDiffDestroy{
|
||||||
|
Addr: addr.Resource,
|
||||||
|
ProviderAddr: n.ResolvedProvider,
|
||||||
|
DeposedKey: n.DeposedKey,
|
||||||
|
State: &state,
|
||||||
|
Output: &change,
|
||||||
|
}
|
||||||
|
_, err = diffDestroy.Eval(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
writeDiff := &EvalWriteDiff{
|
||||||
|
Addr: addr.Resource,
|
||||||
|
DeposedKey: n.DeposedKey,
|
||||||
|
ProviderSchema: &providerSchema,
|
||||||
|
Change: &change,
|
||||||
|
}
|
||||||
|
_, err = writeDiff.Eval(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ func (m ReferenceMap) References(v dag.Vertex) []dag.Vertex {
|
|||||||
case addrs.ModuleCallInstance:
|
case addrs.ModuleCallInstance:
|
||||||
subject = ri.Call
|
subject = ri.Call
|
||||||
default:
|
default:
|
||||||
log.Printf("[WARN] ReferenceTransformer: reference not found: %q", subject)
|
log.Printf("[INFO] ReferenceTransformer: reference not found: %q", subject)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
key = m.referenceMapKey(v, subject)
|
key = m.referenceMapKey(v, subject)
|
||||||
|
Loading…
Reference in New Issue
Block a user