Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CBD GraphNodeCreators cannot depend on GraphNodeDestroyers #23399

Merged
merged 3 commits into from
Nov 18, 2019

Conversation

jbardin
Copy link
Member

@jbardin jbardin commented Nov 15, 2019

GraphNodeCreators are connected directly to their dependency's destroy nodes, so that any updates in the creator happen after the dependency is destroyed. This ordering isn't required for our configuration evaluation, however it is implied in the dependency contract with providers, and many times resources cannot be updated correctly until the create-destroy lifecycle of their dependencies is complete.

This however fails when the GraphNodeCreator itself is CreateBeforeDestroy, because the inversion of the create order introduces a cycle. For example, the natural graph edges for replacing A and B when A depends on B is (eliding B's create node and edges since they don't participate in the cycle):

A_create  -> A_destroy
A_create  -> B_destroy
B_destroy -> A_destroy

When A becomes CreateBeforeDestroy, the first edge is reversed, introducing a cycle between the 3 nodes.

We can solve this for now by pruning out any edges going into a CreateBeforeDestroy node, coming from a GraphNodeCreator. This works because any dependency of a CreateBeforeDestroy node also becomes CreateBeforeDestroy itself.

While it may be more precise to not connect CreateBeforeDestroy nodes to destroy nodes in the first place, we don't have the information readily available at that time in the graph. The use case for a resource update that can't happen once the dependency replacement has been created would be hard to find, but we should strive for the most precise ordering whenever possible, and can work that information into the graph transformation at a later time.

This also updates EvalRefreshDependencies to not append to existing dependencies in the state. While appending any newly found dependencies is tempting in order to have the largest set available, changes to the config could conflict with the prior dependencies causing cycles.

Fixes #23374

@jbardin jbardin requested a review from a team November 15, 2019 21:42
@ghost ghost added the sdkv1 [PRs only] Marks changes that may potentially need to be ported to the plugi nSDK label Nov 15, 2019
Since a create node cannot both depend on its destroy node AND be
CreateBeforeDestroy, the same goes for its dependencies. While we do
connect resources with dependency destroy nodes so that updates are
ordered correctly, this ordering does not make sense in the
CreateBeforeDestroy case.

If resource node is CreateBeforeDestroy, we need to remove any direct
dependencies from it to destroy nodes to prevent cycles. Since we don't
know for certain if a crate node is going to be CreateBeforeDestroy at
the time the edge is added in the graph, we add it unconditionally and
prune it out later on. The pruning happens during the CBD transformer
when the CBD destroy node reverses it's own destroy edge.  The reason
this works for detecting the original edge, is that dependencies of CBD
resources are forced to be CBD themselves. This does have a false
positive where the case of the original node is NOT CBD, but this can be
taken care of later when we gather enough information in the graph to
prevent the connection in the first place.
@jbardin
Copy link
Member Author

jbardin commented Nov 17, 2019

Fixed the go.mod change that was inadvertently rebased in, and tried to further clarify the commit messages.

for _, d := range state.Dependencies {
depMap[d.String()] = d
// We have dependencies in state, so we need to trust those for refresh. We
// won't can't out new dependencies until apply time.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, can you clarify this comment?

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.
@jbardin jbardin changed the title GraphNodeCreators cannot depend on GraphNodeDestroyerCBD CBD GraphNodeCreators cannot depend on GraphNodeDestroyers Nov 18, 2019
@jbardin jbardin merged commit 5a113db into master Nov 18, 2019
@jbardin jbardin deleted the jbardin/cbd-cycle branch November 18, 2019 21:54
jchitel added a commit to jchitel/jakechitel.com that referenced this pull request Nov 19, 2019
…interpolation-only" expressions.

Additionally, there is a bug in this version of terraform that is causing a circular dependency
when creating an updated launch configuration. PR here: hashicorp/terraform#23399

We won't be able to deploy until this is fixed.
@ghost
Copy link

ghost commented Mar 28, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Mar 28, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
sdkv1 [PRs only] Marks changes that may potentially need to be ported to the plugi nSDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cycle Error on 0.12.14 using blue green deployment
3 participants