From 33bef7c42e1931bdfa579ba54bd24b9fd3b17346 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 15 Nov 2019 16:00:13 -0500 Subject: [PATCH] don't append refreshed state dependencies EvalRefreshDependencies is used to update resource dependencies when they don't exist, allow broken or old states to be updated. While appending any newly found dependencies is tempting to have the largest set available, changes to the config could conflict with the prior dependencies causing cycles. --- terraform/context_refresh_test.go | 26 ++++++++++++++------------ terraform/eval_state.go | 9 +++++++-- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/terraform/context_refresh_test.go b/terraform/context_refresh_test.go index d8479ae6c..0c4fa0302 100644 --- a/terraform/context_refresh_test.go +++ b/terraform/context_refresh_test.go @@ -1978,6 +1978,17 @@ func TestRefresh_updateDependencies(t *testing.T) { &states.ResourceInstanceObjectSrc{ Status: states.ObjectReady, AttrsJSON: []byte(`{"id":"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", @@ -1992,17 +2003,6 @@ 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", @@ -2045,11 +2045,13 @@ aws_instance.bar: foo = foo Dependencies: - aws_instance.baz aws_instance.foo aws_instance.foo: ID = foo provider = provider.aws + + Dependencies: + aws_instance.baz `) checkStateString(t, result, expect) diff --git a/terraform/eval_state.go b/terraform/eval_state.go index b0fcee007..0be877544 100644 --- a/terraform/eval_state.go +++ b/terraform/eval_state.go @@ -508,8 +508,13 @@ func (n *EvalRefreshDependencies) Eval(ctx EvalContext) (interface{}, error) { depMap[d.String()] = d } - for _, d := range state.Dependencies { - depMap[d.String()] = d + // We have already 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 } deps := make([]addrs.AbsResource, 0, len(depMap))