mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
Remove contains function (#2346)
* remove contains function Signed-off-by: Maxim Goncharenko <goncharenko.maxim@apriorit.com> * added test for contains issue case Signed-off-by: Maxim Goncharenko <goncharenko.maxim@apriorit.com>
This commit is contained in:
parent
bc88916437
commit
2a375fa1b5
4 changed files with 218 additions and 41 deletions
|
@ -27,7 +27,6 @@ type (
|
|||
// function names
|
||||
var (
|
||||
compare = "compare"
|
||||
contains = "contains"
|
||||
equalFold = "equal_fold"
|
||||
replace = "replace"
|
||||
replaceAll = "replace_all"
|
||||
|
@ -35,7 +34,6 @@ var (
|
|||
toLower = "to_lower"
|
||||
trim = "trim"
|
||||
split = "split"
|
||||
equals = "equals"
|
||||
regexReplaceAll = "regex_replace_all"
|
||||
regexReplaceAllLiteral = "regex_replace_all_literal"
|
||||
regexMatch = "regex_match"
|
||||
|
@ -56,14 +54,6 @@ func getFunctions() []*gojmespath.FunctionEntry {
|
|||
},
|
||||
Handler: jpfCompare,
|
||||
},
|
||||
{
|
||||
Name: contains,
|
||||
Arguments: []ArgSpec{
|
||||
{Types: []JpType{JpString}},
|
||||
{Types: []JpType{JpString}},
|
||||
},
|
||||
Handler: jpfContains,
|
||||
},
|
||||
{
|
||||
Name: equalFold,
|
||||
Arguments: []ArgSpec{
|
||||
|
@ -175,21 +165,6 @@ func jpfCompare(arguments []interface{}) (interface{}, error) {
|
|||
return strings.Compare(a.String(), b.String()), nil
|
||||
}
|
||||
|
||||
func jpfContains(arguments []interface{}) (interface{}, error) {
|
||||
var err error
|
||||
str, err := validateArg(contains, arguments, 0, reflect.String)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
substr, err := validateArg(contains, arguments, 1, reflect.String)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return strings.Contains(str.String(), substr.String()), nil
|
||||
}
|
||||
|
||||
func jpfEqualFold(arguments []interface{}) (interface{}, error) {
|
||||
var err error
|
||||
a, err := validateArg(equalFold, arguments, 0, reflect.String)
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
package validate
|
||||
|
||||
// ValidateTests is E2E Test Config for validation
|
||||
var ValidateTests = []struct {
|
||||
import (
|
||||
"github.com/kyverno/kyverno/test/e2e"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// FluxValidateTests is E2E Test Config for validation
|
||||
var FluxValidateTests = []struct {
|
||||
//TestName - Name of the Test
|
||||
TestName string
|
||||
// PolicyRaw - The Yaml file of the ClusterPolicy
|
||||
|
@ -28,3 +33,36 @@ var ValidateTests = []struct {
|
|||
MustSucceed: true,
|
||||
},
|
||||
}
|
||||
|
||||
var podGVR = e2e.GetGVR("", "v1", "pods")
|
||||
|
||||
var ValidateTests = []struct {
|
||||
//TestDescription - Description of the Test
|
||||
TestDescription string
|
||||
// PolicyName - Name of the Policy
|
||||
PolicyName string
|
||||
// PolicyRaw - The Yaml file of the ClusterPolicy
|
||||
PolicyRaw []byte
|
||||
// ResourceName - Name of the Resource
|
||||
ResourceName string
|
||||
// ResourceNamespace - Namespace of the Resource
|
||||
ResourceNamespace string
|
||||
// ResourceGVR - GVR of the Resource
|
||||
ResourceGVR schema.GroupVersionResource
|
||||
// ResourceRaw - The Yaml file of the ClusterPolicy
|
||||
ResourceRaw []byte
|
||||
// MustSucceed - indicates if validation must succeed
|
||||
MustSucceed bool
|
||||
}{
|
||||
{
|
||||
// Case for https://github.com/kyverno/kyverno/issues/2345 issue
|
||||
TestDescription: "checks that contains function works properly with string list",
|
||||
PolicyName: "drop-cap-net-raw",
|
||||
PolicyRaw: kyverno_2345_policy,
|
||||
ResourceName: "test",
|
||||
ResourceNamespace: "test-validate1",
|
||||
ResourceGVR: podGVR,
|
||||
ResourceRaw: kyverno_2345_resource,
|
||||
MustSucceed: false,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package validate
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Namespace Description
|
||||
var namespaceYaml = []byte(`
|
||||
apiVersion: v1
|
||||
|
@ -8,6 +10,16 @@ metadata:
|
|||
name: test-validate
|
||||
`)
|
||||
|
||||
func newNamespaceYaml(name string) []byte {
|
||||
ns := fmt.Sprintf(`
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: %s
|
||||
`, name)
|
||||
return []byte(ns)
|
||||
}
|
||||
|
||||
// Regression: https://github.com/kyverno/kyverno/issues/2043
|
||||
// Policy: https://github.com/fluxcd/flux2-multi-tenancy/blob/main/infrastructure/kyverno-policies/flux-multi-tenancy.yaml
|
||||
var kyverno_2043_policy = []byte(`
|
||||
|
@ -561,3 +573,61 @@ spec:
|
|||
prune: true
|
||||
validation: client
|
||||
`)
|
||||
|
||||
var kyverno_2345_policy = []byte(`
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: drop-cap-net-raw
|
||||
spec:
|
||||
validationFailureAction: enforce
|
||||
background: false
|
||||
rules:
|
||||
- name: drop-cap-net-raw
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
deny:
|
||||
conditions:
|
||||
any:
|
||||
- key: "{{ request.object.spec.containers[].securityContext.capabilities.drop[] | contains(@, 'NET_RAW') }}"
|
||||
operator: Equals
|
||||
value: false
|
||||
`)
|
||||
|
||||
var kyverno_2345_resource = []byte(`
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test
|
||||
namespace: test-validate1
|
||||
spec:
|
||||
initContainers:
|
||||
- name: jimmy
|
||||
image: defdasdabian:923
|
||||
command: ["/bin/sh", "-c", "sleep infinity"]
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- XXXNET_RAWYYY
|
||||
- SETUID
|
||||
containers:
|
||||
- name: test
|
||||
image: defdasdabian:923
|
||||
command: ["/bin/sh", "-c", "sleep infinity"]
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- XXXNET_RAWYYY
|
||||
- SETUID
|
||||
- CAP_FOO_BAR
|
||||
- name: asdf
|
||||
image: defdasdabian:923
|
||||
command: ["/bin/sh", "-c", "sleep infinity"]
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- CAP_SOMETHING
|
||||
`)
|
||||
|
|
|
@ -8,22 +8,24 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/kyverno/kyverno/test/e2e"
|
||||
commonE2E "github.com/kyverno/kyverno/test/e2e/common"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// Cluster Polict GVR
|
||||
clPolGVR = e2e.GetGVR("kyverno.io", "v1", "clusterpolicies")
|
||||
policyGVR = e2e.GetGVR("kyverno.io", "v1", "clusterpolicies")
|
||||
// Namespace GVR
|
||||
nsGVR = e2e.GetGVR("", "v1", "namespaces")
|
||||
namespaceGVR = e2e.GetGVR("", "v1", "namespaces")
|
||||
// ConfigMap GVR
|
||||
cmGVR = e2e.GetGVR("", "v1", "configmaps")
|
||||
|
||||
crdGVR = e2e.GetGVR("apiextensions.k8s.io", "v1", "customresourcedefinitions")
|
||||
|
||||
// ClusterPolicy Namespace
|
||||
clPolNS = ""
|
||||
policyNamespace = ""
|
||||
// Namespace Name
|
||||
// Hardcoded in YAML Definition
|
||||
nspace = "test-validate"
|
||||
|
@ -31,7 +33,7 @@ var (
|
|||
crdName = "kustomizations.kustomize.toolkit.fluxcd.io"
|
||||
)
|
||||
|
||||
func Test_Validate_Sets(t *testing.T) {
|
||||
func Test_Validate_Flux_Sets(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
if os.Getenv("E2E") == "" {
|
||||
t.Skip("Skipping E2E Test")
|
||||
|
@ -41,21 +43,21 @@ func Test_Validate_Sets(t *testing.T) {
|
|||
e2eClient, err := e2e.NewE2EClient()
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
for _, test := range ValidateTests {
|
||||
for _, test := range FluxValidateTests {
|
||||
By(fmt.Sprintf("Test to validate objects: \"%s\"", test.TestName))
|
||||
|
||||
// Clean up Resources
|
||||
By(fmt.Sprintf("Cleaning Cluster Policies"))
|
||||
e2eClient.CleanClusterPolicies(clPolGVR)
|
||||
e2eClient.CleanClusterPolicies(policyGVR)
|
||||
// Clear Namespace
|
||||
By(fmt.Sprintf("Deleting Namespace: \"%s\"", nspace))
|
||||
e2eClient.DeleteClusteredResource(nsGVR, nspace)
|
||||
e2eClient.DeleteClusteredResource(namespaceGVR, nspace)
|
||||
//CleanUp CRDs
|
||||
e2eClient.DeleteClusteredResource(crdGVR, crdName)
|
||||
|
||||
// Wait Till Deletion of Namespace
|
||||
e2e.GetWithRetry(time.Duration(1*time.Second), 15, func() error {
|
||||
_, err := e2eClient.GetClusteredResource(nsGVR, nspace)
|
||||
_, err := e2eClient.GetClusteredResource(namespaceGVR, nspace)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -64,12 +66,12 @@ func Test_Validate_Sets(t *testing.T) {
|
|||
|
||||
// Create Namespace
|
||||
By(fmt.Sprintf("Creating namespace \"%s\"", nspace))
|
||||
_, err = e2eClient.CreateClusteredResourceYaml(nsGVR, namespaceYaml)
|
||||
_, err = e2eClient.CreateClusteredResourceYaml(namespaceGVR, namespaceYaml)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Create policy
|
||||
By(fmt.Sprintf("Creating policy in \"%s\"", clPolNS))
|
||||
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, test.PolicyRaw)
|
||||
By(fmt.Sprintf("Creating policy in \"%s\"", policyNamespace))
|
||||
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, test.PolicyRaw)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Create Flux CRD
|
||||
|
@ -101,16 +103,16 @@ func Test_Validate_Sets(t *testing.T) {
|
|||
}
|
||||
|
||||
//CleanUp Resources
|
||||
e2eClient.CleanClusterPolicies(clPolGVR)
|
||||
e2eClient.CleanClusterPolicies(policyGVR)
|
||||
|
||||
//CleanUp CRDs
|
||||
e2eClient.DeleteClusteredResource(crdGVR, crdName)
|
||||
|
||||
// Clear Namespace
|
||||
e2eClient.DeleteClusteredResource(nsGVR, nspace)
|
||||
e2eClient.DeleteClusteredResource(namespaceGVR, nspace)
|
||||
// Wait Till Deletion of Namespace
|
||||
e2e.GetWithRetry(time.Duration(1*time.Second), 15, func() error {
|
||||
_, err := e2eClient.GetClusteredResource(nsGVR, nspace)
|
||||
_, err := e2eClient.GetClusteredResource(namespaceGVR, nspace)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -120,3 +122,95 @@ func Test_Validate_Sets(t *testing.T) {
|
|||
By(fmt.Sprintf("Test %s Completed \n\n\n", test.TestName))
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
if os.Getenv("E2E") == "" {
|
||||
t.Skip("Skipping E2E Test")
|
||||
}
|
||||
|
||||
e2eClient, err := e2e.NewE2EClient()
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
for _, test := range ValidateTests {
|
||||
By(fmt.Sprintf("Mutation Test: %s", test.TestDescription))
|
||||
|
||||
By("Deleting Cluster Policies...")
|
||||
_ = e2eClient.CleanClusterPolicies(policyGVR)
|
||||
|
||||
By("Deleting Resource...")
|
||||
_ = e2eClient.DeleteNamespacedResource(test.ResourceGVR, test.ResourceNamespace, test.ResourceName)
|
||||
|
||||
By("Deleting Namespace...")
|
||||
By(fmt.Sprintf("Deleting Namespace: %s...", test.ResourceNamespace))
|
||||
_ = e2eClient.DeleteClusteredResource(namespaceGVR, test.ResourceNamespace)
|
||||
|
||||
By("Wait Till Deletion of Namespace...")
|
||||
err = e2e.GetWithRetry(1*time.Second, 15, func() error {
|
||||
_, err := e2eClient.GetClusteredResource(namespaceGVR, test.ResourceNamespace)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("failed to delete namespace: %v", err)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By(fmt.Sprintf("Creating Namespace: %s...", policyNamespace))
|
||||
_, err = e2eClient.CreateClusteredResourceYaml(namespaceGVR, newNamespaceYaml(test.ResourceNamespace))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Wait Till Creation of Namespace...")
|
||||
err = e2e.GetWithRetry(1*time.Second, 15, func() error {
|
||||
_, err := e2eClient.GetClusteredResource(namespaceGVR, test.ResourceNamespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Creating Policy...")
|
||||
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, test.PolicyRaw)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = commonE2E.PolicyCreated(test.PolicyName)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Creating Resource...")
|
||||
_, err = e2eClient.CreateNamespacedResourceYaml(test.ResourceGVR, test.ResourceNamespace, test.ResourceRaw)
|
||||
|
||||
statusErr, ok := err.(*k8sErrors.StatusError)
|
||||
validationError := (ok && statusErr.ErrStatus.Code == 400) // Validation error is always Bad Request
|
||||
|
||||
if test.MustSucceed || !validationError {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
} else {
|
||||
Expect(err).To(HaveOccurred())
|
||||
}
|
||||
|
||||
By("Deleting Cluster Policies...")
|
||||
err = e2eClient.CleanClusterPolicies(policyGVR)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Deleting Resource...") // if it is present, so ignore an error
|
||||
e2eClient.DeleteNamespacedResource(test.ResourceGVR, test.ResourceNamespace, test.ResourceName)
|
||||
|
||||
By("Deleting Namespace...")
|
||||
err = e2eClient.DeleteClusteredResource(namespaceGVR, test.ResourceNamespace)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Wait Till Creation of Namespace...")
|
||||
e2e.GetWithRetry(1*time.Second, 15, func() error {
|
||||
_, err := e2eClient.GetClusteredResource(namespaceGVR, test.ResourceNamespace)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("failed to delete namespace: %v", err)
|
||||
})
|
||||
|
||||
// Do not fail if waiting fails. Sometimes namespace needs time to be deleted.
|
||||
|
||||
By("Done")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue