mirror of
https://github.com/kyverno/policy-reporter.git
synced 2024-12-14 11:57:32 +00:00
feat(api): Support LabelSelector in,exist and notexist operation (#607)
Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de>
This commit is contained in:
parent
0119e1dfa9
commit
ea2d67622b
2 changed files with 63 additions and 6 deletions
|
@ -2,10 +2,14 @@ package namespaces
|
|||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
gocache "github.com/patrickmn/go-cache"
|
||||
"go.uber.org/zap"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
|
||||
"github.com/kyverno/policy-reporter/pkg/helper"
|
||||
|
@ -22,13 +26,38 @@ type k8sClient struct {
|
|||
}
|
||||
|
||||
func (c *k8sClient) List(ctx context.Context, selector map[string]string) ([]string, error) {
|
||||
labelSelector := metav1.FormatLabelSelector(&metav1.LabelSelector{MatchLabels: selector})
|
||||
if cached, ok := c.cache.Get(labelSelector); ok {
|
||||
s := labels.NewSelector()
|
||||
for l, v := range selector {
|
||||
var err error
|
||||
var req *labels.Requirement
|
||||
|
||||
if strings.Contains(v, ",") {
|
||||
req, err = labels.NewRequirement(l, selection.In, helper.Map(strings.Split(v, ","), func(val string) string {
|
||||
return strings.TrimSpace(val)
|
||||
}))
|
||||
} else if v == "*" {
|
||||
req, err = labels.NewRequirement(l, selection.Exists, nil)
|
||||
} else if v == "!*" {
|
||||
req, err = labels.NewRequirement(l, selection.DoesNotExist, nil)
|
||||
} else {
|
||||
req, err = labels.NewRequirement(l, selection.Equals, []string{v})
|
||||
}
|
||||
if err != nil {
|
||||
zap.L().Error("failed to create selector requirement", zap.Error(err), zap.String("label", l), zap.String("value", v))
|
||||
continue
|
||||
}
|
||||
|
||||
s = s.Add(*req)
|
||||
}
|
||||
|
||||
zap.L().Debug("created label selector for namespace resolution", zap.String("selector", s.String()))
|
||||
|
||||
if cached, ok := c.cache.Get(s.String()); ok {
|
||||
return cached.([]string), nil
|
||||
}
|
||||
|
||||
list, err := kubernetes.Retry(func() ([]string, error) {
|
||||
namespaces, err := c.client.List(ctx, metav1.ListOptions{LabelSelector: labelSelector})
|
||||
namespaces, err := c.client.List(ctx, metav1.ListOptions{LabelSelector: s.String()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -41,7 +70,7 @@ func (c *k8sClient) List(ctx context.Context, selector map[string]string) ([]str
|
|||
return nil, err
|
||||
}
|
||||
|
||||
c.cache.Set(labelSelector, list, 0)
|
||||
c.cache.Set(s.String(), list, 0)
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@ func newFakeClient() v1.NamespaceInterface {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "default",
|
||||
Labels: map[string]string{
|
||||
"team": "team-a",
|
||||
"name": "default",
|
||||
"team": "team-a",
|
||||
"name": "default",
|
||||
"exist": "yes",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -47,6 +48,33 @@ func (s *nsErrorClient) List(ctx context.Context, opts metav1.ListOptions) (*cor
|
|||
}
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
t.Run("read from api with list", func(t *testing.T) {
|
||||
client := namespaces.NewClient(newFakeClient(), gocache.New(gocache.DefaultExpiration, gocache.DefaultExpiration))
|
||||
|
||||
list, err := client.List(context.Background(), map[string]string{"name": "default,user"})
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 2, len(list))
|
||||
})
|
||||
t.Run("read from api with exist check", func(t *testing.T) {
|
||||
client := namespaces.NewClient(newFakeClient(), gocache.New(gocache.DefaultExpiration, gocache.DefaultExpiration))
|
||||
|
||||
list, err := client.List(context.Background(), map[string]string{"exist": "*"})
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, len(list))
|
||||
assert.Equal(t, list[0], "default")
|
||||
})
|
||||
t.Run("read from api with not exist check", func(t *testing.T) {
|
||||
client := namespaces.NewClient(newFakeClient(), gocache.New(gocache.DefaultExpiration, gocache.DefaultExpiration))
|
||||
|
||||
list, err := client.List(context.Background(), map[string]string{"exist": "!*"})
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, len(list))
|
||||
assert.Equal(t, list[0], "user")
|
||||
})
|
||||
|
||||
t.Run("read from api", func(t *testing.T) {
|
||||
client := namespaces.NewClient(newFakeClient(), gocache.New(gocache.DefaultExpiration, gocache.DefaultExpiration))
|
||||
|
||||
|
|
Loading…
Reference in a new issue