we no longer need EvalRefreshDependencies
This evaluation was required when refresh ran in a separate walk and managed resources were only partly handled by configuration. Now that we have the correct dependency information available when refreshing configured resources, we can update their state accordingly. Since orphaned resources are not refreshed, they can retain their stored dependencies for correct ordering. This also prevents users from introducing cycles with nodes they can't "see", since only orphaned nodes will retain their stored dependencies, and the remaining nodes will be updated according to the configuration.
This commit is contained in:
parent
bd5aeb3d45
commit
def1f9b084
|
@ -1582,7 +1582,7 @@ func TestRefresh_updateDependencies(t *testing.T) {
|
|||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
Dependencies: []addrs.ConfigResource{
|
||||
// Existing dependencies should not be removed during refresh
|
||||
// Existing dependencies should be removed when overridden by the config
|
||||
{
|
||||
Module: addrs.RootModule,
|
||||
Resource: addrs.Resource{
|
||||
|
@ -1598,6 +1598,32 @@ func TestRefresh_updateDependencies(t *testing.T) {
|
|||
Module: addrs.RootModule,
|
||||
},
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "aws_instance",
|
||||
Name: "baz",
|
||||
}.Instance(addrs.NoKey),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"id":"baz"}`),
|
||||
Dependencies: []addrs.ConfigResource{
|
||||
// Existing dependencies should not be removed from orphaned instances
|
||||
{
|
||||
Module: addrs.RootModule,
|
||||
Resource: addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "aws_instance",
|
||||
Name: "bam",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
|
@ -1621,7 +1647,8 @@ resource "aws_instance" "bar" {
|
|||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
}`,
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
||||
p := testProvider("aws")
|
||||
|
@ -1649,12 +1676,15 @@ aws_instance.bar:
|
|||
|
||||
Dependencies:
|
||||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
aws_instance.baz:
|
||||
ID = baz
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
|
||||
Dependencies:
|
||||
aws_instance.baz
|
||||
aws_instance.bam
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
`)
|
||||
|
||||
checkStateString(t, result, expect)
|
||||
|
|
|
@ -3,7 +3,6 @@ package terraform
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/configs"
|
||||
|
@ -530,49 +529,3 @@ func (n *EvalWriteResourceState) 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.ConfigResource
|
||||
}
|
||||
|
||||
func (n *EvalRefreshDependencies) Eval(ctx EvalContext) (interface{}, error) {
|
||||
state := *n.State
|
||||
if state == nil {
|
||||
// no existing state to append
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// We already have dependencies in state, so we need to trust those for
|
||||
// refresh. We can't write out new dependencies until apply time in case
|
||||
// the configuration has been changed in a manner the conflicts with the
|
||||
// stored dependencies.
|
||||
if len(state.Dependencies) > 0 {
|
||||
*n.Dependencies = state.Dependencies
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
depMap := make(map[string]addrs.ConfigResource)
|
||||
for _, d := range *n.Dependencies {
|
||||
depMap[d.String()] = d
|
||||
}
|
||||
|
||||
deps := make([]addrs.ConfigResource, 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
|
||||
}
|
||||
|
|
|
@ -141,10 +141,6 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe
|
|||
ProviderSchema: &providerSchema,
|
||||
Output: &instanceRefreshState,
|
||||
},
|
||||
&EvalRefreshDependencies{
|
||||
State: &instanceRefreshState,
|
||||
Dependencies: &n.Dependencies,
|
||||
},
|
||||
&EvalRefresh{
|
||||
Addr: addr.Resource,
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
|
|
Loading…
Reference in New Issue