mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 10:28:36 +00:00
refactor: move util funcs in sub packages (#5754)
* refactor: move util func in sub packages Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * Update pkg/utils/kube/crd.go Signed-off-by: shuting <shutting06@gmail.com> Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> Signed-off-by: shuting <shutting06@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
This commit is contained in:
parent
3c997d88a8
commit
94abfaf13e
23 changed files with 490 additions and 491 deletions
|
@ -18,7 +18,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/leaderelection"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/tls"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"go.uber.org/multierr"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
coordinationv1 "k8s.io/api/coordination/v1"
|
||||
|
@ -53,7 +53,7 @@ func main() {
|
|||
kyvernoClient := internal.CreateKyvernoClient(logger)
|
||||
client := internal.CreateDClient(logger, ctx, dynamicClient, kubeClient, 15*time.Minute)
|
||||
// Exit for unsupported version of kubernetes cluster
|
||||
if !utils.HigherThanKubernetesVersion(kubeClient.Discovery(), logging.GlobalLogger(), 1, 16, 0) {
|
||||
if !kubeutils.HigherThanKubernetesVersion(kubeClient.Discovery(), logging.GlobalLogger(), 1, 16, 0) {
|
||||
os.Exit(1)
|
||||
}
|
||||
requests := []request{
|
||||
|
|
|
@ -45,7 +45,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"github.com/kyverno/kyverno/pkg/tls"
|
||||
"github.com/kyverno/kyverno/pkg/toggle"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
runtimeutils "github.com/kyverno/kyverno/pkg/utils/runtime"
|
||||
"github.com/kyverno/kyverno/pkg/webhooks"
|
||||
webhooksexception "github.com/kyverno/kyverno/pkg/webhooks/exception"
|
||||
|
@ -99,7 +99,7 @@ func showWarnings(logger logr.Logger) {
|
|||
}
|
||||
|
||||
func sanityChecks(dynamicClient dclient.Interface) error {
|
||||
if !utils.CRDsInstalled(dynamicClient.Discovery()) {
|
||||
if !kubeutils.CRDsInstalled(dynamicClient.Discovery()) {
|
||||
return fmt.Errorf("CRDs not installed")
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
kyvernoutils "github.com/kyverno/kyverno/pkg/utils"
|
||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||
engineutils "github.com/kyverno/kyverno/pkg/utils/engine"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"golang.org/x/exp/slices"
|
||||
|
@ -595,7 +595,7 @@ func newGenResource(genAPIVersion, genKind, genNamespace, genName string) kyvern
|
|||
}
|
||||
|
||||
func manageData(log logr.Logger, apiVersion, kind, namespace, name string, data interface{}, synchronize bool, ur kyvernov1beta1.UpdateRequest, client dclient.Interface) (map[string]interface{}, ResourceMode, error) {
|
||||
resource, err := kyvernoutils.ToMap(data)
|
||||
resource, err := datautils.ToMap(data)
|
||||
if err != nil {
|
||||
return nil, Skip, err
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/in-toto/in-toto-golang/in_toto"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"github.com/kyverno/kyverno/pkg/tracing"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||
wildcard "github.com/kyverno/kyverno/pkg/utils/wildcard"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sigstore/cosign/cmd/cosign/cli/fulcio"
|
||||
|
@ -404,7 +404,7 @@ func decodePayload(payloadBase64 string) (map[string]interface{}, error) {
|
|||
// - in_toto.PredicateLinkV1
|
||||
// - in_toto.PredicateSPDX
|
||||
// any other custom predicate
|
||||
return utils.ToMap(statement)
|
||||
return datautils.ToMap(statement)
|
||||
}
|
||||
|
||||
return decodeCosignCustomProvenanceV01(statement)
|
||||
|
@ -432,7 +432,7 @@ func decodeCosignCustomProvenanceV01(statement in_toto.Statement) (map[string]in
|
|||
statement.Predicate = predicate
|
||||
}
|
||||
|
||||
return utils.ToMap(statement)
|
||||
return datautils.ToMap(statement)
|
||||
}
|
||||
|
||||
func stringToJSONMap(i interface{}) (map[string]interface{}, error) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
|
@ -71,13 +71,13 @@ func (t *Traversal) traverseJSON(element interface{}, path string) (interface{},
|
|||
// traverse further
|
||||
switch typed := element.(type) {
|
||||
case map[string]interface{}:
|
||||
return t.traverseObject(utils.CopyMap(typed), path)
|
||||
return t.traverseObject(datautils.CopyMap(typed), path)
|
||||
|
||||
case []interface{}:
|
||||
return t.traverseList(slices.Clone(typed), path)
|
||||
|
||||
case []map[string]interface{}:
|
||||
return t.traverseList(utils.CopySliceOfMaps(typed), path)
|
||||
return t.traverseList(datautils.CopySliceOfMaps(typed), path)
|
||||
|
||||
case Key:
|
||||
return typed.Key, nil
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/mutate/patch"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
@ -91,7 +91,7 @@ func ForEach(name string, foreach kyvernov1.ForEachMutation, ctx context.Interfa
|
|||
}
|
||||
|
||||
func substituteAllInForEach(fe kyvernov1.ForEachMutation, ctx context.Interface, logger logr.Logger) (*kyvernov1.ForEachMutation, error) {
|
||||
jsonObj, err := utils.ToMap(fe)
|
||||
jsonObj, err := datautils.ToMap(fe)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/engine/wildcards"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"github.com/kyverno/kyverno/pkg/utils/wildcard"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -210,14 +210,14 @@ func doesResourceMatchConditionBlock(subresourceGVKToAPIResource map[string]*met
|
|||
|
||||
keys := append(admissionInfo.AdmissionUserInfo.Groups, admissionInfo.AdmissionUserInfo.Username)
|
||||
var userInfoErrors []error
|
||||
if len(userInfo.Roles) > 0 && !utils.SliceContains(keys, dynamicConfig...) {
|
||||
if !utils.SliceContains(userInfo.Roles, admissionInfo.Roles...) {
|
||||
if len(userInfo.Roles) > 0 && !datautils.SliceContains(keys, dynamicConfig...) {
|
||||
if !datautils.SliceContains(userInfo.Roles, admissionInfo.Roles...) {
|
||||
userInfoErrors = append(userInfoErrors, fmt.Errorf("user info does not match roles for the given conditionBlock"))
|
||||
}
|
||||
}
|
||||
|
||||
if len(userInfo.ClusterRoles) > 0 && !utils.SliceContains(keys, dynamicConfig...) {
|
||||
if !utils.SliceContains(userInfo.ClusterRoles, admissionInfo.ClusterRoles...) {
|
||||
if len(userInfo.ClusterRoles) > 0 && !datautils.SliceContains(keys, dynamicConfig...) {
|
||||
if !datautils.SliceContains(userInfo.ClusterRoles, admissionInfo.ClusterRoles...) {
|
||||
userInfoErrors = append(userInfoErrors, fmt.Errorf("user info does not match clustersRoles for the given conditionBlock"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/pss"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"github.com/kyverno/kyverno/pkg/tracing"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/kyverno/kyverno/pkg/utils/api"
|
||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||
matched "github.com/kyverno/kyverno/pkg/utils/match"
|
||||
"github.com/pkg/errors"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
@ -216,7 +216,7 @@ func newValidator(log logr.Logger, rclient registryclient.Client, ctx *PolicyCon
|
|||
|
||||
func newForEachValidator(foreach kyvernov1.ForEachValidation, rclient registryclient.Client, nesting int, rule *kyvernov1.Rule, ctx *PolicyContext, log logr.Logger) (*validator, error) {
|
||||
ruleCopy := rule.DeepCopy()
|
||||
anyAllConditions, err := utils.ToMap(foreach.AnyAllConditions)
|
||||
anyAllConditions, err := datautils.ToMap(foreach.AnyAllConditions)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to convert ruleCopy.Validation.ForEachValidation.AnyAllConditions")
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/go-logr/logr"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"github.com/kyverno/kyverno/pkg/utils/wildcard"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -94,7 +93,7 @@ func excludeResources(included map[string]unstructured.Unstructured, exclude kyv
|
|||
if len(exclude.Namespaces) == 0 {
|
||||
return NotEvaluate
|
||||
}
|
||||
if utils.ContainsNamepace(exclude.Namespaces, namespace) {
|
||||
if wildcard.CheckPatterns(exclude.Namespaces, namespace) {
|
||||
return Skip
|
||||
}
|
||||
return Process
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/openapi"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"github.com/kyverno/kyverno/pkg/utils/wildcard"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/exp/slices"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
|
@ -1268,20 +1269,20 @@ func validateKinds(kinds []string, mock, backgroundScanningEnabled, isValidation
|
|||
}
|
||||
|
||||
func validateWildcardsWithNamespaces(enforce, audit, enforceW, auditW []string) error {
|
||||
pat, ns, notOk := utils.CheckWildcardNamespaces(auditW, enforce)
|
||||
pat, ns, notOk := wildcard.MatchPatterns(auditW, enforce...)
|
||||
if notOk {
|
||||
return fmt.Errorf("wildcard pattern '%s' matches with namespace '%s'", pat, ns)
|
||||
}
|
||||
pat, ns, notOk = utils.CheckWildcardNamespaces(enforceW, audit)
|
||||
pat, ns, notOk = wildcard.MatchPatterns(enforceW, audit...)
|
||||
if notOk {
|
||||
return fmt.Errorf("wildcard pattern '%s' matches with namespace '%s'", pat, ns)
|
||||
}
|
||||
|
||||
pat1, pat2, notOk := utils.CheckWildcardNamespaces(auditW, enforceW)
|
||||
pat1, pat2, notOk := wildcard.MatchPatterns(auditW, enforceW...)
|
||||
if notOk {
|
||||
return fmt.Errorf("wildcard pattern '%s' conflicts with the pattern '%s'", pat1, pat2)
|
||||
}
|
||||
pat1, pat2, notOk = utils.CheckWildcardNamespaces(enforceW, auditW)
|
||||
pat1, pat2, notOk = wildcard.MatchPatterns(enforceW, auditW...)
|
||||
if notOk {
|
||||
return fmt.Errorf("wildcard pattern '%s' conflicts with the pattern '%s'", pat1, pat2)
|
||||
}
|
||||
|
@ -1298,7 +1299,7 @@ func validateNamespaces(s *kyvernov1.Spec, path *field.Path) error {
|
|||
}
|
||||
|
||||
for i, vfa := range s.ValidationFailureActionOverrides {
|
||||
patternList, nsList := utils.SeperateWildcards(vfa.Namespaces)
|
||||
patternList, nsList := wildcard.SeperateWildcards(vfa.Namespaces)
|
||||
|
||||
if vfa.Action.Audit() {
|
||||
if action["enforce"].HasAny(nsList...) {
|
||||
|
|
|
@ -2,7 +2,7 @@ package policycache
|
|||
|
||||
import (
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
kyvernoutils "github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/kyverno/kyverno/pkg/utils/wildcard"
|
||||
)
|
||||
|
||||
// Cache get method use for to get policy names and mostly use to test cache testcases
|
||||
|
@ -81,7 +81,7 @@ func checkValidationFailureActionOverrides(enforce bool, ns string, policy kyver
|
|||
return false
|
||||
}
|
||||
for _, action := range validationFailureActionOverrides {
|
||||
if action.Action.Enforce() != enforce && kyvernoutils.ContainsNamepace(action.Namespaces, ns) {
|
||||
if action.Action.Enforce() != enforce && wildcard.CheckPatterns(action.Namespaces, ns) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
pssutils "github.com/kyverno/kyverno/pkg/pss/utils"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/kyverno/kyverno/pkg/utils/wildcard"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/pod-security-admission/api"
|
||||
|
@ -126,18 +126,18 @@ func GetPodWithMatchingContainers(exclude kyvernov1.PodSecurityStandard, pod *co
|
|||
},
|
||||
}
|
||||
for _, container := range pod.Spec.Containers {
|
||||
if utils.ContainsWildcardPatterns(matchingImages, container.Image) {
|
||||
if wildcard.CheckPatterns(matchingImages, container.Image) {
|
||||
matching.Spec.Containers = append(matching.Spec.Containers, container)
|
||||
}
|
||||
}
|
||||
for _, container := range pod.Spec.InitContainers {
|
||||
if utils.ContainsWildcardPatterns(matchingImages, container.Image) {
|
||||
if wildcard.CheckPatterns(matchingImages, container.Image) {
|
||||
matching.Spec.InitContainers = append(matching.Spec.InitContainers, container)
|
||||
}
|
||||
}
|
||||
|
||||
for _, container := range pod.Spec.EphemeralContainers {
|
||||
if utils.ContainsWildcardPatterns(matchingImages, container.Image) {
|
||||
if wildcard.CheckPatterns(matchingImages, container.Image) {
|
||||
matching.Spec.EphemeralContainers = append(matching.Spec.EphemeralContainers, container)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
|
@ -24,7 +24,7 @@ const (
|
|||
// GetRoleRef gets the list of roles and cluster roles for the incoming api-request
|
||||
func GetRoleRef(rbLister rbacv1listers.RoleBindingLister, crbLister rbacv1listers.ClusterRoleBindingLister, request *admissionv1.AdmissionRequest, dynamicConfig config.Configuration) ([]string, []string, error) {
|
||||
keys := append(request.UserInfo.Groups, request.UserInfo.Username)
|
||||
if utils.SliceContains(keys, dynamicConfig.GetExcludeGroupRole()...) {
|
||||
if datautils.SliceContains(keys, dynamicConfig.GetExcludeGroupRole()...) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
// rolebindings
|
||||
|
|
46
pkg/utils/data/data.go
Normal file
46
pkg/utils/data/data.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
package data
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// CopyMap creates a full copy of the target map
|
||||
func CopyMap(m map[string]interface{}) map[string]interface{} {
|
||||
mapCopy := make(map[string]interface{})
|
||||
for k, v := range m {
|
||||
mapCopy[k] = v
|
||||
}
|
||||
return mapCopy
|
||||
}
|
||||
|
||||
// CopySliceOfMaps creates a full copy of the target slice
|
||||
func CopySliceOfMaps(s []map[string]interface{}) []interface{} {
|
||||
sliceCopy := make([]interface{}, len(s))
|
||||
for i, v := range s {
|
||||
sliceCopy[i] = CopyMap(v)
|
||||
}
|
||||
return sliceCopy
|
||||
}
|
||||
|
||||
func ToMap(data interface{}) (map[string]interface{}, error) {
|
||||
if m, ok := data.(map[string]interface{}); ok {
|
||||
return m, nil
|
||||
}
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapData := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &mapData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mapData, nil
|
||||
}
|
||||
|
||||
// SliceContains checks whether values are contained in slice
|
||||
func SliceContains(slice []string, values ...string) bool {
|
||||
return sets.New(slice...).HasAny(values...)
|
||||
}
|
95
pkg/utils/data/data_test.go
Normal file
95
pkg/utils/data/data_test.go
Normal file
|
@ -0,0 +1,95 @@
|
|||
package data
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func TestOriginalMapMustNotBeChanged(t *testing.T) {
|
||||
// no variables
|
||||
originalMap := map[string]interface{}{
|
||||
"rsc": 3711,
|
||||
"r": 2138,
|
||||
"gri": 1908,
|
||||
"adg": 912,
|
||||
}
|
||||
mapCopy := CopyMap(originalMap)
|
||||
mapCopy["r"] = 1
|
||||
assert.Equal(t, originalMap["r"], 2138)
|
||||
}
|
||||
|
||||
func TestSliceContains(t *testing.T) {
|
||||
type args struct {
|
||||
slice []string
|
||||
values []string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{{
|
||||
name: "empty slice",
|
||||
args: args{
|
||||
slice: []string{},
|
||||
values: []string{"ccc", "ddd"},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
name: "nil slice",
|
||||
args: args{
|
||||
slice: nil,
|
||||
values: []string{"ccc", "ddd"},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
name: "empty values",
|
||||
args: args{
|
||||
slice: []string{"aaa", "bbb"},
|
||||
values: []string{},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
name: "nil values",
|
||||
args: args{
|
||||
slice: []string{"aaa", "bbb"},
|
||||
values: nil,
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
name: "none match",
|
||||
args: args{
|
||||
slice: []string{"aaa", "bbb"},
|
||||
values: []string{"ccc", "ddd"},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
name: "one match",
|
||||
args: args{
|
||||
slice: []string{"aaa", "bbb"},
|
||||
values: []string{"aaa"},
|
||||
},
|
||||
want: true,
|
||||
}, {
|
||||
name: "one match, one doesn't match",
|
||||
args: args{
|
||||
slice: []string{"aaa", "bbb"},
|
||||
values: []string{"aaa", "ddd"},
|
||||
},
|
||||
want: true,
|
||||
}, {
|
||||
name: "all match",
|
||||
args: args{
|
||||
slice: []string{"aaa", "bbb"},
|
||||
values: []string{"aaa", "bbb"},
|
||||
},
|
||||
want: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := SliceContains(tt.args.slice, tt.args.values...); got != tt.want {
|
||||
t.Errorf("SliceContains() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
35
pkg/utils/kube/crd.go
Normal file
35
pkg/utils/kube/crd.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package kube
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
type disco interface {
|
||||
GetGVRFromKind(string) (schema.GroupVersionResource, error)
|
||||
}
|
||||
|
||||
// CRDsInstalled checks if the Kyverno CRDs are installed or not
|
||||
func CRDsInstalled(discovery disco) bool {
|
||||
kyvernoCRDs := []string{"ClusterPolicy", "Policy", "ClusterPolicyReport", "PolicyReport", "AdmissionReport", "BackgroundScanReport", "ClusterAdmissionReport", "ClusterBackgroundScanReport"}
|
||||
for _, crd := range kyvernoCRDs {
|
||||
if !isCRDInstalled(discovery, crd) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isCRDInstalled(discovery disco, kind string) bool {
|
||||
gvr, err := discovery.GetGVRFromKind(kind)
|
||||
if gvr.Empty() {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("not found")
|
||||
}
|
||||
logging.Error(err, "failed to retrieve CRD", "kind", kind)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
53
pkg/utils/kube/version.go
Normal file
53
pkg/utils/kube/version.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package kube
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"k8s.io/client-go/discovery"
|
||||
)
|
||||
|
||||
var regexVersion = regexp.MustCompile(`v(\d+).(\d+).(\d+)\.*`)
|
||||
|
||||
// HigherThanKubernetesVersion compare Kubernetes client version to user given version
|
||||
func HigherThanKubernetesVersion(client discovery.ServerVersionInterface, log logr.Logger, major, minor, patch int) bool {
|
||||
logger := log.WithName("CompareKubernetesVersion")
|
||||
serverVersion, err := client.ServerVersion()
|
||||
if err != nil {
|
||||
logger.Error(err, "Failed to get kubernetes server version")
|
||||
return false
|
||||
}
|
||||
b, err := isVersionHigher(serverVersion.String(), major, minor, patch)
|
||||
if err != nil {
|
||||
logger.Error(err, "serverVersion", serverVersion.String())
|
||||
return false
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func isVersionHigher(version string, major int, minor int, patch int) (bool, error) {
|
||||
groups := regexVersion.FindStringSubmatch(version)
|
||||
if len(groups) != 4 {
|
||||
return false, fmt.Errorf("invalid version %s. Expected {major}.{minor}.{patch}", version)
|
||||
}
|
||||
currentMajor, err := strconv.Atoi(groups[1])
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to extract major version from %s", version)
|
||||
}
|
||||
currentMinor, err := strconv.Atoi(groups[2])
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to extract minor version from %s", version)
|
||||
}
|
||||
currentPatch, err := strconv.Atoi(groups[3])
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to extract minor version from %s", version)
|
||||
}
|
||||
if currentMajor < major ||
|
||||
(currentMajor == major && currentMinor < minor) ||
|
||||
(currentMajor == major && currentMinor == minor && currentPatch <= patch) {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
42
pkg/utils/kube/version_test.go
Normal file
42
pkg/utils/kube/version_test.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package kube
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func Test_higherVersion(t *testing.T) {
|
||||
v, err := isVersionHigher("invalid.version", 1, 1, 1)
|
||||
assert.Assert(t, v == false && err != nil)
|
||||
|
||||
v, err = isVersionHigher("invalid-version", 0, 0, 0)
|
||||
assert.Assert(t, v == false && err != nil)
|
||||
|
||||
v, err = isVersionHigher("v1.1.1", 1, 1, 1)
|
||||
assert.Assert(t, v == false && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.0.0", 1, 1, 1)
|
||||
assert.Assert(t, v == false && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9", 1, 5, 8)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9+distro", 1, 5, 8)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9+distro", 1, 5, 8)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9-rc2", 1, 5, 9)
|
||||
assert.Assert(t, v == false && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9", 2, 1, 0)
|
||||
assert.Assert(t, v == false && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v2.1.0", 1, 5, 9)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9-x-v1.5.9.x", 1, 5, 8)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
}
|
|
@ -3,15 +3,11 @@ package utils
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
wildcard "github.com/kyverno/kyverno/pkg/utils/wildcard"
|
||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||
"github.com/pkg/errors"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
@ -19,97 +15,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/discovery"
|
||||
)
|
||||
|
||||
var regexVersion = regexp.MustCompile(`v(\d+).(\d+).(\d+)\.*`)
|
||||
|
||||
// CopyMap creates a full copy of the target map
|
||||
func CopyMap(m map[string]interface{}) map[string]interface{} {
|
||||
mapCopy := make(map[string]interface{})
|
||||
for k, v := range m {
|
||||
mapCopy[k] = v
|
||||
}
|
||||
|
||||
return mapCopy
|
||||
}
|
||||
|
||||
// CopySliceOfMaps creates a full copy of the target slice
|
||||
func CopySliceOfMaps(s []map[string]interface{}) []interface{} {
|
||||
sliceCopy := make([]interface{}, len(s))
|
||||
for i, v := range s {
|
||||
sliceCopy[i] = CopyMap(v)
|
||||
}
|
||||
|
||||
return sliceCopy
|
||||
}
|
||||
|
||||
func ToMap(data interface{}) (map[string]interface{}, error) {
|
||||
if m, ok := data.(map[string]interface{}); ok {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mapData := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &mapData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mapData, nil
|
||||
}
|
||||
|
||||
// Contains checks if a string is contained in a list of string
|
||||
func contains(list []string, element string, fn func(string, string) bool) bool {
|
||||
for _, e := range list {
|
||||
if fn(e, element) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsNamepace check if namespace satisfies any list of pattern(regex)
|
||||
func ContainsNamepace(patterns []string, ns string) bool {
|
||||
return contains(patterns, ns, comparePatterns)
|
||||
}
|
||||
|
||||
func ContainsWildcardPatterns(patterns []string, key string) bool {
|
||||
return contains(patterns, key, comparePatterns)
|
||||
}
|
||||
|
||||
func comparePatterns(pattern, ns string) bool {
|
||||
return wildcard.Match(pattern, ns)
|
||||
}
|
||||
|
||||
// CRDsInstalled checks if the Kyverno CRDs are installed or not
|
||||
func CRDsInstalled(discovery dclient.IDiscovery) bool {
|
||||
kyvernoCRDs := []string{"ClusterPolicy", "ClusterPolicyReport", "PolicyReport", "AdmissionReport", "BackgroundScanReport", "ClusterAdmissionReport", "ClusterBackgroundScanReport"}
|
||||
for _, crd := range kyvernoCRDs {
|
||||
if !isCRDInstalled(discovery, crd) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func isCRDInstalled(discoveryClient dclient.IDiscovery, kind string) bool {
|
||||
gvr, err := discoveryClient.GetGVRFromKind(kind)
|
||||
if gvr.Empty() {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("not found")
|
||||
}
|
||||
logging.Error(err, "failed to retrieve CRD", "kind", kind)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ExtractResources extracts the new and old resource as unstructured
|
||||
func ExtractResources(newRaw []byte, request *admissionv1.AdmissionRequest) (unstructured.Unstructured, unstructured.Unstructured, error) {
|
||||
var emptyResource unstructured.Unstructured
|
||||
|
@ -241,7 +148,7 @@ func RedactSecret(resource *unstructured.Unstructured) (unstructured.Unstructure
|
|||
}
|
||||
}
|
||||
if secret.Annotations != nil {
|
||||
metadata, err := ToMap(resource.Object["metadata"])
|
||||
metadata, err := datautils.ToMap(resource.Object["metadata"])
|
||||
if err != nil {
|
||||
return *resource, errors.Wrap(err, "unable to convert metadata to map")
|
||||
}
|
||||
|
@ -257,68 +164,6 @@ func RedactSecret(resource *unstructured.Unstructured) (unstructured.Unstructure
|
|||
return *resource, nil
|
||||
}
|
||||
|
||||
// HigherThanKubernetesVersion compare Kubernetes client version to user given version
|
||||
func HigherThanKubernetesVersion(client discovery.ServerVersionInterface, log logr.Logger, major, minor, patch int) bool {
|
||||
logger := log.WithName("CompareKubernetesVersion")
|
||||
serverVersion, err := client.ServerVersion()
|
||||
if err != nil {
|
||||
logger.Error(err, "Failed to get kubernetes server version")
|
||||
return false
|
||||
}
|
||||
|
||||
b, err := isVersionHigher(serverVersion.String(), major, minor, patch)
|
||||
if err != nil {
|
||||
logger.Error(err, "serverVersion", serverVersion.String())
|
||||
return false
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func isVersionHigher(version string, major int, minor int, patch int) (bool, error) {
|
||||
groups := regexVersion.FindStringSubmatch(version)
|
||||
if len(groups) != 4 {
|
||||
return false, fmt.Errorf("invalid version %s. Expected {major}.{minor}.{patch}", version)
|
||||
}
|
||||
|
||||
currentMajor, err := strconv.Atoi(groups[1])
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to extract major version from %s", version)
|
||||
}
|
||||
|
||||
currentMinor, err := strconv.Atoi(groups[2])
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to extract minor version from %s", version)
|
||||
}
|
||||
|
||||
currentPatch, err := strconv.Atoi(groups[3])
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to extract minor version from %s", version)
|
||||
}
|
||||
|
||||
if currentMajor < major ||
|
||||
(currentMajor == major && currentMinor < minor) ||
|
||||
(currentMajor == major && currentMinor == minor && currentPatch <= patch) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// SliceContains checks whether values are contained in slice
|
||||
func SliceContains(slice []string, values ...string) bool {
|
||||
sliceElementsMap := make(map[string]bool, len(slice))
|
||||
for _, sliceElement := range slice {
|
||||
sliceElementsMap[sliceElement] = true
|
||||
}
|
||||
for _, value := range values {
|
||||
if sliceElementsMap[value] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ApiextensionsJsonToKyvernoConditions takes in user-provided conditions in abstract apiextensions.JSON form
|
||||
// and converts it into []kyverno.Condition or kyverno.AnyAllConditions according to its content.
|
||||
// it also helps in validating the condtions as it returns an error when the conditions are provided wrongfully by the user.
|
||||
|
@ -394,38 +239,3 @@ func OverrideRuntimeErrorHandler() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SeperateWildcards(l []string) (lw []string, rl []string) {
|
||||
for _, val := range l {
|
||||
if wildcard.ContainsWildcard(val) {
|
||||
lw = append(lw, val)
|
||||
} else {
|
||||
rl = append(rl, val)
|
||||
}
|
||||
}
|
||||
return lw, rl
|
||||
}
|
||||
|
||||
func CheckWildcardNamespaces(patterns []string, ns []string) (string, string, bool) {
|
||||
for _, n := range ns {
|
||||
pat, element, boolval := containsNamespaceWithStringReturn(patterns, n)
|
||||
if boolval {
|
||||
return pat, element, true
|
||||
}
|
||||
}
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
func containsWithStringReturn(list []string, element string, fn func(string, string) bool) (string, string, bool) {
|
||||
for _, e := range list {
|
||||
if fn(e, element) {
|
||||
return e, element, true
|
||||
}
|
||||
}
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
// containsNamespaceWithStringReturn check if namespace satisfies any list of pattern(regex)
|
||||
func containsNamespaceWithStringReturn(patterns []string, ns string) (string, string, bool) {
|
||||
return containsWithStringReturn(patterns, ns, comparePatterns)
|
||||
}
|
||||
|
|
|
@ -6,84 +6,6 @@ import (
|
|||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func Test_OriginalMapMustNotBeChanged(t *testing.T) {
|
||||
// no variables
|
||||
originalMap := map[string]interface{}{
|
||||
"rsc": 3711,
|
||||
"r": 2138,
|
||||
"gri": 1908,
|
||||
"adg": 912,
|
||||
}
|
||||
|
||||
mapCopy := CopyMap(originalMap)
|
||||
mapCopy["r"] = 1
|
||||
|
||||
assert.Equal(t, originalMap["r"], 2138)
|
||||
}
|
||||
|
||||
func Test_containsNs(t *testing.T) {
|
||||
var patterns []string
|
||||
var res bool
|
||||
patterns = []string{"*"}
|
||||
res = ContainsNamepace(patterns, "default")
|
||||
assert.Assert(t, res == true)
|
||||
|
||||
patterns = []string{"*", "default"}
|
||||
res = ContainsNamepace(patterns, "default")
|
||||
assert.Assert(t, res == true)
|
||||
|
||||
patterns = []string{"default2", "default"}
|
||||
res = ContainsNamepace(patterns, "default1")
|
||||
assert.Assert(t, res == false)
|
||||
|
||||
patterns = []string{"d*"}
|
||||
res = ContainsNamepace(patterns, "default")
|
||||
assert.Assert(t, res == true)
|
||||
|
||||
patterns = []string{"d*"}
|
||||
res = ContainsNamepace(patterns, "test")
|
||||
assert.Assert(t, res == false)
|
||||
|
||||
patterns = []string{}
|
||||
res = ContainsNamepace(patterns, "test")
|
||||
assert.Assert(t, res == false)
|
||||
}
|
||||
|
||||
func Test_higherVersion(t *testing.T) {
|
||||
v, err := isVersionHigher("invalid.version", 1, 1, 1)
|
||||
assert.Assert(t, v == false && err != nil)
|
||||
|
||||
v, err = isVersionHigher("invalid-version", 0, 0, 0)
|
||||
assert.Assert(t, v == false && err != nil)
|
||||
|
||||
v, err = isVersionHigher("v1.1.1", 1, 1, 1)
|
||||
assert.Assert(t, v == false && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.0.0", 1, 1, 1)
|
||||
assert.Assert(t, v == false && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9", 1, 5, 8)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9+distro", 1, 5, 8)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9+distro", 1, 5, 8)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9-rc2", 1, 5, 9)
|
||||
assert.Assert(t, v == false && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9", 2, 1, 0)
|
||||
assert.Assert(t, v == false && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v2.1.0", 1, 5, 9)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
|
||||
v, err = isVersionHigher("v1.5.9-x-v1.5.9.x", 1, 5, 8)
|
||||
assert.Assert(t, v == true && err == nil)
|
||||
}
|
||||
|
||||
func Test_ConvertResource(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
@ -155,181 +77,3 @@ func Test_ConvertResource(t *testing.T) {
|
|||
break
|
||||
}
|
||||
}
|
||||
|
||||
func Test_SeperateWildcards(t *testing.T) {
|
||||
testcases := []struct {
|
||||
description string
|
||||
inputList []string
|
||||
expList1 []string
|
||||
expList2 []string
|
||||
}{
|
||||
{
|
||||
description: "tc1",
|
||||
inputList: []string{"test*", "default", "default1", "hello"},
|
||||
expList1: []string{"test*"},
|
||||
expList2: []string{"default", "default1", "hello"},
|
||||
},
|
||||
{
|
||||
description: "tc2",
|
||||
inputList: []string{"test*", "default*", "default1?", "hello?"},
|
||||
expList1: []string{"test*", "default*", "default1?", "hello?"},
|
||||
expList2: nil,
|
||||
},
|
||||
{
|
||||
description: "tc3",
|
||||
inputList: []string{"test", "default", "default1", "hello"},
|
||||
expList1: nil,
|
||||
expList2: []string{"test", "default", "default1", "hello"},
|
||||
},
|
||||
{
|
||||
description: "tc4",
|
||||
inputList: nil,
|
||||
expList1: nil,
|
||||
expList2: nil,
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
list1, list2 := SeperateWildcards(tc.inputList)
|
||||
assert.DeepEqual(t, list1, tc.expList1)
|
||||
assert.DeepEqual(t, list2, tc.expList2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CheckWildcardNamespaces(t *testing.T) {
|
||||
testcases := []struct {
|
||||
description string
|
||||
inputPatterns []string
|
||||
inputNs []string
|
||||
expString1 string
|
||||
expString2 string
|
||||
expBool bool
|
||||
}{
|
||||
{
|
||||
description: "tc1",
|
||||
inputPatterns: []string{"default*", "test*"},
|
||||
inputNs: []string{"default", "default1"},
|
||||
expString1: "default*",
|
||||
expString2: "default",
|
||||
expBool: true,
|
||||
},
|
||||
{
|
||||
description: "tc2",
|
||||
inputPatterns: []string{"test*"},
|
||||
inputNs: []string{"default1", "test"},
|
||||
expString1: "test*",
|
||||
expString2: "test",
|
||||
expBool: true,
|
||||
},
|
||||
{
|
||||
description: "tc3",
|
||||
inputPatterns: []string{"*"},
|
||||
inputNs: []string{"default1", "test"},
|
||||
expString1: "*",
|
||||
expString2: "default1",
|
||||
expBool: true,
|
||||
},
|
||||
{
|
||||
description: "tc4",
|
||||
inputPatterns: []string{"a*"},
|
||||
inputNs: []string{"default1", "test"},
|
||||
expString1: "",
|
||||
expString2: "",
|
||||
expBool: false,
|
||||
},
|
||||
{
|
||||
description: "tc5",
|
||||
inputPatterns: nil,
|
||||
inputNs: []string{"default1", "test"},
|
||||
expString1: "",
|
||||
expString2: "",
|
||||
expBool: false,
|
||||
},
|
||||
{
|
||||
description: "tc6",
|
||||
inputPatterns: []string{"*"},
|
||||
inputNs: nil,
|
||||
expString1: "",
|
||||
expString2: "",
|
||||
expBool: false,
|
||||
},
|
||||
{
|
||||
description: "tc7",
|
||||
inputPatterns: nil,
|
||||
inputNs: nil,
|
||||
expString1: "",
|
||||
expString2: "",
|
||||
expBool: false,
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
str1, str2, actualBool := CheckWildcardNamespaces(tc.inputPatterns, tc.inputNs)
|
||||
assert.Equal(t, str1, tc.expString1)
|
||||
assert.Equal(t, str2, tc.expString2)
|
||||
assert.Equal(t, actualBool, tc.expBool)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_containsNamespaceWithStringReturn(t *testing.T) {
|
||||
testcases := []struct {
|
||||
description string
|
||||
inputPattern []string
|
||||
inputNs string
|
||||
expStr1 string
|
||||
expStr2 string
|
||||
expBool bool
|
||||
}{
|
||||
{
|
||||
description: "tc1",
|
||||
inputPattern: []string{"default*"},
|
||||
inputNs: "default",
|
||||
expStr1: "default*",
|
||||
expStr2: "default",
|
||||
expBool: true,
|
||||
},
|
||||
{
|
||||
description: "tc2",
|
||||
inputPattern: []string{"*"},
|
||||
inputNs: "default",
|
||||
expStr1: "*",
|
||||
expStr2: "default",
|
||||
expBool: true,
|
||||
},
|
||||
{
|
||||
description: "tc3",
|
||||
inputPattern: []string{"*"},
|
||||
inputNs: "default",
|
||||
expStr1: "*",
|
||||
expStr2: "default",
|
||||
expBool: true,
|
||||
},
|
||||
{
|
||||
description: "tc4",
|
||||
inputPattern: nil,
|
||||
inputNs: "default",
|
||||
expStr1: "",
|
||||
expStr2: "",
|
||||
expBool: false,
|
||||
},
|
||||
{
|
||||
description: "tc5",
|
||||
inputPattern: nil,
|
||||
inputNs: "",
|
||||
expStr1: "",
|
||||
expStr2: "",
|
||||
expBool: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
str1, str2, actualBool := containsNamespaceWithStringReturn(tc.inputPattern, tc.inputNs)
|
||||
assert.Equal(t, str1, tc.expStr1)
|
||||
assert.Equal(t, str2, tc.expStr2)
|
||||
assert.Equal(t, actualBool, tc.expBool)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,3 +5,32 @@ import "strings"
|
|||
func ContainsWildcard(v string) bool {
|
||||
return strings.Contains(v, "*") || strings.Contains(v, "?")
|
||||
}
|
||||
|
||||
// MatchPatterns check if any text satisfies any pattern
|
||||
func MatchPatterns(patterns []string, names ...string) (string, string, bool) {
|
||||
for _, name := range names {
|
||||
for _, pattern := range patterns {
|
||||
if Match(pattern, name) {
|
||||
return pattern, name, true
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
// CheckPatterns check if any text satisfies any pattern
|
||||
func CheckPatterns(patterns []string, names ...string) bool {
|
||||
_, _, match := MatchPatterns(patterns, names...)
|
||||
return match
|
||||
}
|
||||
|
||||
func SeperateWildcards(l []string) (lw []string, rl []string) {
|
||||
for _, val := range l {
|
||||
if ContainsWildcard(val) {
|
||||
lw = append(lw, val)
|
||||
} else {
|
||||
rl = append(rl, val)
|
||||
}
|
||||
}
|
||||
return lw, rl
|
||||
}
|
||||
|
|
|
@ -87,3 +87,148 @@ func TestContainsWildcard(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckPatterns(t *testing.T) {
|
||||
var patterns []string
|
||||
var res bool
|
||||
patterns = []string{"*"}
|
||||
res = CheckPatterns(patterns, "default")
|
||||
assert.Equal(t, true, res)
|
||||
|
||||
patterns = []string{"*", "default"}
|
||||
res = CheckPatterns(patterns, "default")
|
||||
assert.Equal(t, true, res)
|
||||
|
||||
patterns = []string{"default2", "default"}
|
||||
res = CheckPatterns(patterns, "default1")
|
||||
assert.Equal(t, false, res)
|
||||
|
||||
patterns = []string{"d*"}
|
||||
res = CheckPatterns(patterns, "default")
|
||||
assert.Equal(t, true, res)
|
||||
|
||||
patterns = []string{"d*"}
|
||||
res = CheckPatterns(patterns, "test")
|
||||
assert.Equal(t, false, res)
|
||||
|
||||
patterns = []string{}
|
||||
res = CheckPatterns(patterns, "test")
|
||||
assert.Equal(t, false, res)
|
||||
}
|
||||
|
||||
func Test_MatchPatterns(t *testing.T) {
|
||||
testcases := []struct {
|
||||
description string
|
||||
inputPatterns []string
|
||||
inputNs []string
|
||||
expString1 string
|
||||
expString2 string
|
||||
expBool bool
|
||||
}{
|
||||
{
|
||||
description: "tc1",
|
||||
inputPatterns: []string{"default*", "test*"},
|
||||
inputNs: []string{"default", "default1"},
|
||||
expString1: "default*",
|
||||
expString2: "default",
|
||||
expBool: true,
|
||||
},
|
||||
{
|
||||
description: "tc2",
|
||||
inputPatterns: []string{"test*"},
|
||||
inputNs: []string{"default1", "test"},
|
||||
expString1: "test*",
|
||||
expString2: "test",
|
||||
expBool: true,
|
||||
},
|
||||
{
|
||||
description: "tc3",
|
||||
inputPatterns: []string{"*"},
|
||||
inputNs: []string{"default1", "test"},
|
||||
expString1: "*",
|
||||
expString2: "default1",
|
||||
expBool: true,
|
||||
},
|
||||
{
|
||||
description: "tc4",
|
||||
inputPatterns: []string{"a*"},
|
||||
inputNs: []string{"default1", "test"},
|
||||
expString1: "",
|
||||
expString2: "",
|
||||
expBool: false,
|
||||
},
|
||||
{
|
||||
description: "tc5",
|
||||
inputPatterns: nil,
|
||||
inputNs: []string{"default1", "test"},
|
||||
expString1: "",
|
||||
expString2: "",
|
||||
expBool: false,
|
||||
},
|
||||
{
|
||||
description: "tc6",
|
||||
inputPatterns: []string{"*"},
|
||||
inputNs: nil,
|
||||
expString1: "",
|
||||
expString2: "",
|
||||
expBool: false,
|
||||
},
|
||||
{
|
||||
description: "tc7",
|
||||
inputPatterns: nil,
|
||||
inputNs: nil,
|
||||
expString1: "",
|
||||
expString2: "",
|
||||
expBool: false,
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
str1, str2, actualBool := MatchPatterns(tc.inputPatterns, tc.inputNs...)
|
||||
assert.Equal(t, str1, tc.expString1)
|
||||
assert.Equal(t, str2, tc.expString2)
|
||||
assert.Equal(t, actualBool, tc.expBool)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_SeperateWildcards(t *testing.T) {
|
||||
testcases := []struct {
|
||||
description string
|
||||
inputList []string
|
||||
expList1 []string
|
||||
expList2 []string
|
||||
}{
|
||||
{
|
||||
description: "tc1",
|
||||
inputList: []string{"test*", "default", "default1", "hello"},
|
||||
expList1: []string{"test*"},
|
||||
expList2: []string{"default", "default1", "hello"},
|
||||
},
|
||||
{
|
||||
description: "tc2",
|
||||
inputList: []string{"test*", "default*", "default1?", "hello?"},
|
||||
expList1: []string{"test*", "default*", "default1?", "hello?"},
|
||||
expList2: nil,
|
||||
},
|
||||
{
|
||||
description: "tc3",
|
||||
inputList: []string{"test", "default", "default1", "hello"},
|
||||
expList1: nil,
|
||||
expList2: []string{"test", "default", "default1", "hello"},
|
||||
},
|
||||
{
|
||||
description: "tc4",
|
||||
inputList: nil,
|
||||
expList1: nil,
|
||||
expList2: nil,
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
list1, list2 := SeperateWildcards(tc.inputList)
|
||||
assert.Equal(t, tc.expList1, list1)
|
||||
assert.Equal(t, tc.expList2, list2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||
"gotest.tools/assert"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
)
|
||||
|
@ -144,28 +144,28 @@ func Test_RedactPayload(t *testing.T) {
|
|||
payload, err := newAdmissionRequestPayload(req)
|
||||
assert.NilError(t, err)
|
||||
if payload.Object.Object != nil {
|
||||
data, err := utils.ToMap(payload.Object.Object["data"])
|
||||
data, err := datautils.ToMap(payload.Object.Object["data"])
|
||||
assert.NilError(t, err)
|
||||
for _, v := range data {
|
||||
assert.Assert(t, v == "**REDACTED**")
|
||||
}
|
||||
metadata, err := utils.ToMap(payload.Object.Object["metadata"])
|
||||
metadata, err := datautils.ToMap(payload.Object.Object["metadata"])
|
||||
assert.NilError(t, err)
|
||||
annotations, err := utils.ToMap(metadata["annotations"])
|
||||
annotations, err := datautils.ToMap(metadata["annotations"])
|
||||
assert.NilError(t, err)
|
||||
for _, v := range annotations {
|
||||
assert.Assert(t, v == "**REDACTED**")
|
||||
}
|
||||
}
|
||||
if payload.OldObject.Object != nil {
|
||||
data, err := utils.ToMap(payload.OldObject.Object["data"])
|
||||
data, err := datautils.ToMap(payload.OldObject.Object["data"])
|
||||
assert.NilError(t, err)
|
||||
for _, v := range data {
|
||||
assert.Assert(t, v == "**REDACTED**")
|
||||
}
|
||||
metadata, err := utils.ToMap(payload.OldObject.Object["metadata"])
|
||||
metadata, err := datautils.ToMap(payload.OldObject.Object["metadata"])
|
||||
assert.NilError(t, err)
|
||||
annotations, err := utils.ToMap(metadata["annotations"])
|
||||
annotations, err := datautils.ToMap(metadata["annotations"])
|
||||
assert.NilError(t, err)
|
||||
for _, v := range annotations {
|
||||
assert.Assert(t, v == "**REDACTED**")
|
||||
|
|
Loading…
Add table
Reference in a new issue