mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-13 19:28:55 +00:00
fix: add policy validation for ValidationFailureActionOverride field (#4784)
Signed-off-by: ansalamdaniel <ansalam.daniel@infracloud.io>
This commit is contained in:
parent
f659f7791c
commit
27de93a3d2
4 changed files with 715 additions and 3 deletions
|
@ -123,6 +123,14 @@ func Validate(policy kyvernov1.PolicyInterface, client dclient.Interface, mock b
|
|||
if errs := policy.Validate(clusterResources); len(errs) != 0 {
|
||||
return nil, errs.ToAggregate()
|
||||
}
|
||||
|
||||
if !namespaced {
|
||||
err := validateNamespaces(spec, specPath.Child("validationFailureActionOverrides"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
rules := autogen.ComputeRules(policy)
|
||||
rulesPath := specPath.Child("rules")
|
||||
for i, rule := range rules {
|
||||
|
@ -1071,3 +1079,61 @@ func validateKinds(kinds []string, mock bool, client dclient.Interface, p kyvern
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateWildcardsWithNamespaces(enforce, audit, enforceW, auditW []string) error {
|
||||
pat, ns, notOk := utils.CheckWildcardNamespaces(auditW, enforce)
|
||||
if notOk {
|
||||
return fmt.Errorf("wildcard pattern '%s' matches with namespace '%s'", pat, ns)
|
||||
}
|
||||
pat, ns, notOk = utils.CheckWildcardNamespaces(enforceW, audit)
|
||||
if notOk {
|
||||
return fmt.Errorf("wildcard pattern '%s' matches with namespace '%s'", pat, ns)
|
||||
}
|
||||
|
||||
pat1, pat2, notOk := utils.CheckWildcardNamespaces(auditW, enforceW)
|
||||
if notOk {
|
||||
return fmt.Errorf("wildcard pattern '%s' conflicts with the pattern '%s'", pat1, pat2)
|
||||
}
|
||||
pat1, pat2, notOk = utils.CheckWildcardNamespaces(enforceW, auditW)
|
||||
if notOk {
|
||||
return fmt.Errorf("wildcard pattern '%s' conflicts with the pattern '%s'", pat1, pat2)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateNamespaces(s *kyvernov1.Spec, path *field.Path) error {
|
||||
action := map[string]sets.String{
|
||||
string(kyvernov1.Enforce): sets.NewString(),
|
||||
string(kyvernov1.Audit): sets.NewString(),
|
||||
"enforceW": sets.NewString(),
|
||||
"auditW": sets.NewString(),
|
||||
}
|
||||
|
||||
for i, vfa := range s.ValidationFailureActionOverrides {
|
||||
patternList, nsList := utils.SeperateWildcards(vfa.Namespaces)
|
||||
|
||||
if vfa.Action == kyvernov1.Audit {
|
||||
if action[string(kyvernov1.Enforce)].HasAny(nsList...) {
|
||||
return fmt.Errorf("conflicting namespaces found in path: %s: %s", path.Index(i).Child("namespaces").String(),
|
||||
strings.Join(action[string(kyvernov1.Enforce)].Intersection(sets.NewString(nsList...)).List(), ", "))
|
||||
}
|
||||
action["auditW"].Insert(patternList...)
|
||||
} else if vfa.Action == kyvernov1.Enforce {
|
||||
if action[string(kyvernov1.Audit)].HasAny(nsList...) {
|
||||
return fmt.Errorf("conflicting namespaces found in path: %s: %s", path.Index(i).Child("namespaces").String(),
|
||||
strings.Join(action[string(kyvernov1.Audit)].Intersection(sets.NewString(nsList...)).List(), ", "))
|
||||
}
|
||||
action["enforceW"].Insert(patternList...)
|
||||
}
|
||||
action[string(vfa.Action)].Insert(nsList...)
|
||||
|
||||
err := validateWildcardsWithNamespaces(action[string(kyvernov1.Enforce)].List(),
|
||||
action[string(kyvernov1.Audit)].List(), action["enforceW"].List(), action["auditW"].List())
|
||||
if err != nil {
|
||||
return fmt.Errorf("path: %s: %s", path.Index(i).Child("namespaces").String(), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,15 +2,17 @@ package policy
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/openapi"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
|
||||
"gotest.tools/assert"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
func Test_Validate_ResourceDescription_Empty(t *testing.T) {
|
||||
|
@ -1032,6 +1034,7 @@ func Test_Validate_ApiCall(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Wildcards_Kind(t *testing.T) {
|
||||
rawPolicy := []byte(`
|
||||
{
|
||||
|
@ -1442,3 +1445,434 @@ func Test_PodControllerAutoGenExclusion_None_Policy(t *testing.T) {
|
|||
}
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func Test_ValidateNamespace(t *testing.T) {
|
||||
testcases := []struct {
|
||||
description string
|
||||
spec *kyverno.Spec
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
description: "tc1",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("conflicting namespaces found in path: spec.validationFailureActionOverrides[1].namespaces: default"),
|
||||
},
|
||||
{
|
||||
description: "tc2",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Mutation: kyverno.Mutation{
|
||||
RawPatchStrategicMerge: &apiextv1.JSON{Raw: []byte(`"metadata": {"labels": {"app-name": "{{request.object.metadata.name}}"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("conflicting namespaces found in path: spec.validationFailureActionOverrides[1].namespaces: default"),
|
||||
},
|
||||
{
|
||||
description: "tc3",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default*",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern 'default*' matches with namespace 'default'"),
|
||||
},
|
||||
{
|
||||
description: "tc4",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"*",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '*' matches with namespace 'default'"),
|
||||
},
|
||||
{
|
||||
description: "tc5",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"?*",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '?*' matches with namespace 'default'"),
|
||||
},
|
||||
{
|
||||
description: "tc6",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default?",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"default1",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern 'default?' matches with namespace 'default1'"),
|
||||
},
|
||||
{
|
||||
description: "tc7",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default*",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"?*",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '?*' matches with namespace 'test'"),
|
||||
},
|
||||
{
|
||||
description: "tc8",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"*",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"?*",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '?*' conflicts with the pattern '*'"),
|
||||
},
|
||||
{
|
||||
description: "tc9",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default*",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
"test*",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern 'test*' matches with namespace 'test'"),
|
||||
},
|
||||
{
|
||||
description: "tc10",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"*efault",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '*efault' matches with namespace 'default'"),
|
||||
},
|
||||
{
|
||||
description: "tc11",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default-*",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "tc12",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default*?",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
"test*",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "tc13",
|
||||
spec: &kyverno.Spec{
|
||||
ValidationFailureAction: kyverno.Enforce,
|
||||
ValidationFailureActionOverrides: []kyverno.ValidationFailureActionOverride{
|
||||
{
|
||||
Action: kyverno.Enforce,
|
||||
Namespaces: []string{
|
||||
"default?",
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: kyverno.Audit,
|
||||
Namespaces: []string{
|
||||
"default",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []kyverno.Rule{
|
||||
{
|
||||
Name: "require-labels",
|
||||
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
|
||||
Validation: kyverno.Validation{
|
||||
Message: "label 'app.kubernetes.io/name' is required",
|
||||
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
err := validateNamespaces(tc.spec, field.NewPath("spec").Child("validationFailureActionOverrides"))
|
||||
if tc.expectedError != nil {
|
||||
assert.Error(t, err, tc.expectedError.Error())
|
||||
} else {
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -358,3 +358,38 @@ 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)
|
||||
}
|
||||
|
|
|
@ -202,5 +202,182 @@ func Test_ConvertResource(t *testing.T) {
|
|||
assert.Assert(t, resource.GetNamespace() == test.expectedNamespace)
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue