Skip to content

Commit

Permalink
fix: check resource namespaces are managed (#143)
Browse files Browse the repository at this point in the history
  • Loading branch information
jopit committed Sep 25, 2020
1 parent 7171d62 commit 828dc75
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 0 deletions.
24 changes: 24 additions & 0 deletions pkg/cache/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,13 +661,37 @@ func (c *clusterCache) IsNamespaced(gk schema.GroupKind) (bool, error) {
return false, errors.NewNotFound(schema.GroupResource{Group: gk.Group}, "")
}

func (c *clusterCache) managesNamespace(namespace string) bool {
if len(c.namespaces) == 0 {
return true
}
if namespace == "" {
return false
}
for _, ns := range c.namespaces {
if ns == namespace {
return true
}
}
return false
}

// GetManagedLiveObjs helps finding matching live K8S resources for a given resources list.
// The function returns all resources from cache for those `isManaged` function returns true and resources
// specified in targetObjs list.
func (c *clusterCache) GetManagedLiveObjs(targetObjs []*unstructured.Unstructured, isManaged func(r *Resource) bool) (map[kube.ResourceKey]*unstructured.Unstructured, error) {
c.lock.RLock()
defer c.lock.RUnlock()

for _, o := range targetObjs {
if !c.managesNamespace(o.GetNamespace()) {
if o.GetNamespace() == "" {
return nil, fmt.Errorf("Cluster level %s %q can not be managed when in namespaced mode", o.GetKind(), o.GetName())
}
return nil, fmt.Errorf("Namespace %q for %s %q is not managed", o.GetNamespace(), o.GetKind(), o.GetName())
}
}

managedObjs := make(map[kube.ResourceKey]*unstructured.Unstructured)
// iterate all objects in live state cache to find ones associated with app
for key, o := range c.resources {
Expand Down
107 changes: 107 additions & 0 deletions pkg/cache/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,113 @@ metadata:
})
}

func TestGetManagedLiveObjsNamespacedModeClusterLevelResource(t *testing.T) {
cluster := newCluster(testPod, testRS, testDeploy)
cluster.Invalidate(SetPopulateResourceInfoHandler(func(un *unstructured.Unstructured, isRoot bool) (info interface{}, cacheManifest bool) {
return nil, true
}))
cluster.namespaces = []string{"default", "production"}

err := cluster.EnsureSynced()
assert.Nil(t, err)

targetDeploy := strToUnstructured(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: helm-guestbook
labels:
app: helm-guestbook`)

managedObjs, err := cluster.GetManagedLiveObjs([]*unstructured.Unstructured{targetDeploy}, func(r *Resource) bool {
return len(r.OwnerRefs) == 0
})
assert.Nil(t, managedObjs)
assert.Equal(t, "Cluster level Deployment \"helm-guestbook\" can not be managed when in namespaced mode", err.Error())
}

func TestGetManagedLiveObjsAllNamespaces(t *testing.T) {
cluster := newCluster(testPod, testRS, testDeploy)
cluster.Invalidate(SetPopulateResourceInfoHandler(func(un *unstructured.Unstructured, isRoot bool) (info interface{}, cacheManifest bool) {
return nil, true
}))
cluster.namespaces = nil

err := cluster.EnsureSynced()
assert.Nil(t, err)

targetDeploy := strToUnstructured(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: helm-guestbook
namespace: production
labels:
app: helm-guestbook`)

managedObjs, err := cluster.GetManagedLiveObjs([]*unstructured.Unstructured{targetDeploy}, func(r *Resource) bool {
return len(r.OwnerRefs) == 0
})
assert.Nil(t, err)
assert.Equal(t, managedObjs, map[kube.ResourceKey]*unstructured.Unstructured{
kube.NewResourceKey("apps", "Deployment", "default", "helm-guestbook"): testDeploy,
})
}

func TestGetManagedLiveObjsValidNamespace(t *testing.T) {
cluster := newCluster(testPod, testRS, testDeploy)
cluster.Invalidate(SetPopulateResourceInfoHandler(func(un *unstructured.Unstructured, isRoot bool) (info interface{}, cacheManifest bool) {
return nil, true
}))
cluster.namespaces = []string{"default", "production"}

err := cluster.EnsureSynced()
assert.Nil(t, err)

targetDeploy := strToUnstructured(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: helm-guestbook
namespace: production
labels:
app: helm-guestbook`)

managedObjs, err := cluster.GetManagedLiveObjs([]*unstructured.Unstructured{targetDeploy}, func(r *Resource) bool {
return len(r.OwnerRefs) == 0
})
assert.Nil(t, err)
assert.Equal(t, managedObjs, map[kube.ResourceKey]*unstructured.Unstructured{
kube.NewResourceKey("apps", "Deployment", "default", "helm-guestbook"): testDeploy,
})
}

func TestGetManagedLiveObjsInvalidNamespace(t *testing.T) {
cluster := newCluster(testPod, testRS, testDeploy)
cluster.Invalidate(SetPopulateResourceInfoHandler(func(un *unstructured.Unstructured, isRoot bool) (info interface{}, cacheManifest bool) {
return nil, true
}))
cluster.namespaces = []string{"default", "develop"}

err := cluster.EnsureSynced()
assert.Nil(t, err)

targetDeploy := strToUnstructured(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: helm-guestbook
namespace: production
labels:
app: helm-guestbook`)

managedObjs, err := cluster.GetManagedLiveObjs([]*unstructured.Unstructured{targetDeploy}, func(r *Resource) bool {
return len(r.OwnerRefs) == 0
})
assert.Nil(t, managedObjs)
assert.Equal(t, "Namespace \"production\" for Deployment \"helm-guestbook\" is not managed", err.Error())
}

func TestChildDeletedEvent(t *testing.T) {
cluster := newCluster(testPod, testRS, testDeploy)
err := cluster.EnsureSynced()
Expand Down

0 comments on commit 828dc75

Please sign in to comment.