Issue #1013 - handle k8s resources circular dependency (#1016)

This commit is contained in:
Alexander Matyushentsev 2019-01-15 03:24:28 -08:00 committed by Jesse Suen
parent 4e2700b5d4
commit 2200a27a5f
3 changed files with 40 additions and 5 deletions

View file

@ -169,7 +169,7 @@ func (c *clusterInfo) getChildren(obj *unstructured.Unstructured) []appv1.Resour
nsNodes := c.nsIndex[obj.GetNamespace()]
for _, child := range nsNodes {
if objInfo.isParentOf(child) {
children = append(children, child.childResourceNodes(nsNodes))
children = append(children, child.childResourceNodes(nsNodes, map[kube.ResourceKey]bool{objInfo.resourceKey(): true}))
}
}
}

View file

@ -258,3 +258,19 @@ func TestUpdateAppResource(t *testing.T) {
assert.Equal(t, []string{"helm-guestbook"}, updatesReceived)
}
func TestCircularReference(t *testing.T) {
dep := testDeploy.DeepCopy()
dep.SetOwnerReferences([]metav1.OwnerReference{{
Name: testPod.GetName(),
Kind: testPod.GetKind(),
APIVersion: testPod.GetAPIVersion(),
}})
cluster := newCluster(testPod, testRS, dep)
err := cluster.ensureSynced()
assert.Nil(t, err)
children := cluster.getChildren(dep)
assert.Len(t, children, 1)
}

View file

@ -1,8 +1,11 @@
package cache
import (
log "github.com/sirupsen/logrus"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util/kube"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -57,11 +60,27 @@ func (n *node) getApp(ns map[kube.ResourceKey]*node) string {
return ""
}
func (n *node) childResourceNodes(ns map[kube.ResourceKey]*node) appv1.ResourceNode {
func newResourceKeySet(set map[kube.ResourceKey]bool, keys ...kube.ResourceKey) map[kube.ResourceKey]bool {
newSet := make(map[kube.ResourceKey]bool)
for k, v := range set {
newSet[k] = v
}
for i := range keys {
newSet[keys[i]] = true
}
return newSet
}
func (n *node) childResourceNodes(ns map[kube.ResourceKey]*node, parents map[kube.ResourceKey]bool) appv1.ResourceNode {
children := make([]appv1.ResourceNode, 0)
for key := range ns {
if n.isParentOf(ns[key]) {
children = append(children, ns[key].childResourceNodes(ns))
for childKey := range ns {
if n.isParentOf(ns[childKey]) {
if parents[childKey] {
key := n.resourceKey()
log.Warnf("Circular dependency detected. %s is child and parent of %s", childKey.String(), key.String())
} else {
children = append(children, ns[childKey].childResourceNodes(ns, newResourceKeySet(parents, n.resourceKey())))
}
}
}
gv, err := schema.ParseGroupVersion(n.ref.APIVersion)