mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-28 09:26:26 -06:00
append dependencies during refresh
Refresh should load any new dependencies found because of configuration or state changes, but retain any dependencies already in the state. Orphaned resources would not be in config, but we do not want to lose the destroy ordering for the later apply.
This commit is contained in:
parent
886af20f07
commit
5e16e8eece
@ -1992,6 +1992,17 @@ func TestRefresh_updateDependencies(t *testing.T) {
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"id":"bar","foo":"foo"}`),
|
||||
Dependencies: []addrs.AbsResource{
|
||||
// Existing dependencies should not be removed during refresh
|
||||
{
|
||||
Module: addrs.RootModuleInstance,
|
||||
Resource: addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "aws_instance",
|
||||
Name: "baz",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
addrs.ProviderConfig{
|
||||
Type: "aws",
|
||||
@ -2034,6 +2045,7 @@ aws_instance.bar:
|
||||
foo = foo
|
||||
|
||||
Dependencies:
|
||||
aws_instance.baz
|
||||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
|
@ -89,6 +89,7 @@ func (n *EvalRefresh) Eval(ctx EvalContext) (interface{}, error) {
|
||||
newState := state.DeepCopy()
|
||||
newState.Value = resp.NewState
|
||||
newState.Private = resp.Private
|
||||
newState.Dependencies = state.Dependencies
|
||||
|
||||
// Call post-refresh hook
|
||||
err = ctx.Hook(func(h Hook) (HookAction, error) {
|
||||
|
@ -3,6 +3,7 @@ package terraform
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/configs"
|
||||
@ -203,7 +204,7 @@ type EvalWriteState struct {
|
||||
|
||||
// Dependencies are the inter-resource dependencies to be stored in the
|
||||
// state.
|
||||
Dependencies []addrs.AbsResource
|
||||
Dependencies *[]addrs.AbsResource
|
||||
}
|
||||
|
||||
func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) {
|
||||
@ -228,7 +229,10 @@ func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) {
|
||||
}
|
||||
|
||||
// store the new deps in the state
|
||||
obj.Dependencies = n.Dependencies
|
||||
if n.Dependencies != nil {
|
||||
log.Printf("[TRACE] EvalWriteState: recording %d dependencies for %s", len(*n.Dependencies), absAddr)
|
||||
obj.Dependencies = *n.Dependencies
|
||||
}
|
||||
|
||||
if n.ProviderSchema == nil || *n.ProviderSchema == nil {
|
||||
// Should never happen, unless our state object is nil
|
||||
@ -480,3 +484,44 @@ func (n *EvalForgetResourceState) Eval(ctx EvalContext) (interface{}, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// EvalRefreshDependencies is an EvalNode implementation that appends any newly
|
||||
// found dependencies to those saved in the state. The existing dependencies
|
||||
// are retained, as they may be missing from the config, and will be required
|
||||
// for the updates and destroys during the next apply.
|
||||
type EvalRefreshDependencies struct {
|
||||
// Prior State
|
||||
State **states.ResourceInstanceObject
|
||||
// Dependencies to write to the new state
|
||||
Dependencies *[]addrs.AbsResource
|
||||
}
|
||||
|
||||
func (n *EvalRefreshDependencies) Eval(ctx EvalContext) (interface{}, error) {
|
||||
state := *n.State
|
||||
if state == nil {
|
||||
// no existing state to append
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
depMap := make(map[string]addrs.AbsResource)
|
||||
for _, d := range *n.Dependencies {
|
||||
depMap[d.String()] = d
|
||||
}
|
||||
|
||||
for _, d := range state.Dependencies {
|
||||
depMap[d.String()] = d
|
||||
}
|
||||
|
||||
deps := make([]addrs.AbsResource, 0, len(depMap))
|
||||
for _, d := range depMap {
|
||||
deps = append(deps, d)
|
||||
}
|
||||
|
||||
sort.Slice(deps, func(i, j int) bool {
|
||||
return deps[i].String() < deps[j].String()
|
||||
})
|
||||
|
||||
*n.Dependencies = deps
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ func (n *NodeApplyableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderSchema: &providerSchema,
|
||||
State: &state,
|
||||
Dependencies: n.Dependencies,
|
||||
Dependencies: &n.Dependencies,
|
||||
},
|
||||
&EvalApplyProvisioners{
|
||||
Addr: addr.Resource,
|
||||
@ -389,7 +389,7 @@ func (n *NodeApplyableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderSchema: &providerSchema,
|
||||
State: &state,
|
||||
Dependencies: n.Dependencies,
|
||||
Dependencies: &n.Dependencies,
|
||||
},
|
||||
&EvalIf{
|
||||
If: func(ctx EvalContext) (bool, error) {
|
||||
|
@ -214,6 +214,11 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalN
|
||||
Output: &state,
|
||||
},
|
||||
|
||||
&EvalRefreshDependencies{
|
||||
State: &state,
|
||||
Dependencies: &n.Dependencies,
|
||||
},
|
||||
|
||||
&EvalRefresh{
|
||||
Addr: addr.Resource,
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
@ -228,6 +233,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalN
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderSchema: &providerSchema,
|
||||
State: &state,
|
||||
Dependencies: &n.Dependencies,
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -287,6 +293,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResourceNoState(
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderSchema: &providerSchema,
|
||||
State: &state,
|
||||
Dependencies: &n.Dependencies,
|
||||
},
|
||||
|
||||
// We must also save the planned change, so that expressions in
|
||||
|
Loading…
Reference in New Issue
Block a user