1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00
Added validation tests
This commit is contained in:
belyshevdenis 2019-06-04 17:33:21 +03:00
parent f3d1d26875
commit 18842b81a1
2 changed files with 780 additions and 24 deletions

View file

@ -60,8 +60,14 @@ func validateMap(resourcePart, patternPart interface{}) error {
key = key[1 : len(key)-1]
}
if err := validateMapElement(resource[key], value); err != nil {
return err
if value == "*" && resource[key] != nil {
continue
} else if value == "*" && resource[key] == nil {
return fmt.Errorf("validating error: field %s must be present", key)
} else {
if err := validateMapElement(resource[key], value); err != nil {
return err
}
}
}

View file

@ -88,8 +88,21 @@ func TestCheckForWildcard_QuestionMark(t *testing.T) {
func TestSkipArrayObject_OneAnchor(t *testing.T) {
rawAnchors := []byte(`{"(name)": "nirmata-*"}`)
rawResource := []byte(`{"name": "nirmata-resource", "namespace": "kube-policy", "object": { "label": "app", "array": [ 1, 2, 3 ]}}`)
rawAnchors := []byte(`{
"(name)":"nirmata-*"
}`)
rawResource := []byte(`{
"name":"nirmata-resource",
"namespace":"kube-policy",
"object":{
"label":"app",
"array":[
1,
2,
3
]
}
}`)
var resource, anchor map[string]interface{}
@ -101,8 +114,22 @@ func TestSkipArrayObject_OneAnchor(t *testing.T) {
func TestSkipArrayObject_OneNumberAnchorPass(t *testing.T) {
rawAnchors := []byte(`{"(count)": 1}`)
rawResource := []byte(`{"name": "nirmata-resource", "count": 1, "namespace": "kube-policy", "object": { "label": "app", "array": [ 1, 2, 3 ]}}`)
rawAnchors := []byte(`{
"(count)":1
}`)
rawResource := []byte(`{
"name":"nirmata-resource",
"count":1,
"namespace":"kube-policy",
"object":{
"label":"app",
"array":[
1,
2,
3
]
}
}`)
var resource, anchor map[string]interface{}
@ -113,8 +140,22 @@ func TestSkipArrayObject_OneNumberAnchorPass(t *testing.T) {
}
func TestSkipArrayObject_TwoAnchorsPass(t *testing.T) {
rawAnchors := []byte(`{"(name)": "nirmata-*", "(namespace)": "kube-?olicy"}`)
rawResource := []byte(`{"name": "nirmata-resource", "namespace": "kube-policy", "object": { "label": "app", "array": [ 1, 2, 3 ]}}`)
rawAnchors := []byte(`{
"(name)":"nirmata-*",
"(namespace)":"kube-?olicy"
}`)
rawResource := []byte(`{
"name":"nirmata-resource",
"namespace":"kube-policy",
"object":{
"label":"app",
"array":[
1,
2,
3
]
}
}`)
var resource, anchor map[string]interface{}
@ -125,8 +166,22 @@ func TestSkipArrayObject_TwoAnchorsPass(t *testing.T) {
}
func TestSkipArrayObject_TwoAnchorsSkip(t *testing.T) {
rawAnchors := []byte(`{"(name)": "nirmata-*", "(namespace)": "some-?olicy"}`)
rawResource := []byte(`{"name": "nirmata-resource", "namespace": "kube-policy", "object": { "label": "app", "array": [ 1, 2, 3 ]}}`)
rawAnchors := []byte(`{
"(name)":"nirmata-*",
"(namespace)":"some-?olicy"
}`)
rawResource := []byte(`{
"name":"nirmata-resource",
"namespace":"kube-policy",
"object":{
"label":"app",
"array":[
1,
2,
3
]
}
}`)
var resource, anchor map[string]interface{}
@ -137,7 +192,16 @@ func TestSkipArrayObject_TwoAnchorsSkip(t *testing.T) {
}
func TestGetAnchorsFromMap_ThereAreAnchors(t *testing.T) {
rawMap := []byte(`{"(name)": "nirmata-*", "notAnchor1": 123, "(namespace)": "kube-?olicy", "notAnchor2": "sample-text", "object": { "key1": "value1", "(key2)": "value2"}}`)
rawMap := []byte(`{
"(name)":"nirmata-*",
"notAnchor1":123,
"(namespace)":"kube-?olicy",
"notAnchor2":"sample-text",
"object":{
"key1":"value1",
"(key2)":"value2"
}
}`)
var unmarshalled map[string]interface{}
json.Unmarshal(rawMap, &unmarshalled)
@ -149,7 +213,16 @@ func TestGetAnchorsFromMap_ThereAreAnchors(t *testing.T) {
}
func TestGetAnchorsFromMap_ThereAreNoAnchors(t *testing.T) {
rawMap := []byte(`{"name": "nirmata-*", "notAnchor1": 123, "namespace": "kube-?olicy", "notAnchor2": "sample-text", "object": { "key1": "value1", "(key2)": "value2"}}`)
rawMap := []byte(`{
"name":"nirmata-*",
"notAnchor1":123,
"namespace":"kube-?olicy",
"notAnchor2":"sample-text",
"object":{
"key1":"value1",
"(key2)":"value2"
}
}`)
var unmarshalled map[string]interface{}
json.Unmarshal(rawMap, &unmarshalled)
@ -159,8 +232,93 @@ func TestGetAnchorsFromMap_ThereAreNoAnchors(t *testing.T) {
}
func TestValidateMap(t *testing.T) {
rawPattern := []byte(`{ "spec": { "template": { "spec": { "containers": [ { "name": "?*", "resources": { "requests": { "cpu": "<4|8" } } } ] } } } }`)
rawMap := []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "name": "nginx-deployment", "labels": { "app": "nginx" } }, "spec": { "replicas": 3, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "labels": { "app": "nginx" } }, "spec": { "securityContext": { "runAsNonRoot": true }, "containers": [ { "name": "nginx", "image": "https://nirmata/nginx:latest", "imagePullPolicy": "Always", "readinessProbe": { "exec": { "command": [ "cat", "/tmp/healthy" ] }, "initialDelaySeconds": 5, "periodSeconds": 10 }, "livenessProbe": { "tcpSocket": { "port": 8080 }, "initialDelaySeconds": 15, "periodSeconds": 11 }, "resources": { "limits": { "memory": "2Gi", "cpu": 8 }, "requests": { "memory": "512Mi", "cpu": "8" } }, "ports": [ { "containerPort": 80 } ] } ] } } } }`)
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":[
{
"name":"?*",
"resources":{
"requests":{
"cpu":"<4|8"
}
}
}
]
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"Deployment",
"metadata":{
"name":"nginx-deployment",
"labels":{
"app":"nginx"
}
},
"spec":{
"replicas":3,
"selector":{
"matchLabels":{
"app":"nginx"
}
},
"template":{
"metadata":{
"labels":{
"app":"nginx"
}
},
"spec":{
"securityContext":{
"runAsNonRoot":true
},
"containers":[
{
"name":"nginx",
"image":"https://nirmata/nginx:latest",
"imagePullPolicy":"Always",
"readinessProbe":{
"exec":{
"command":[
"cat",
"/tmp/healthy"
]
},
"initialDelaySeconds":5,
"periodSeconds":10
},
"livenessProbe":{
"tcpSocket":{
"port":8080
},
"initialDelaySeconds":15,
"periodSeconds":11
},
"resources":{
"limits":{
"memory":"2Gi",
"cpu":8
},
"requests":{
"memory":"512Mi",
"cpu":"8"
}
},
"ports":[
{
"containerPort":80
}
]
}
]
}
}
}
}`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
@ -169,9 +327,398 @@ func TestValidateMap(t *testing.T) {
assert.NilError(t, validateMap(resource, pattern))
}
func TestValidateMap_AsteriskForInt(t *testing.T) {
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":[
{
"name":"*",
"livenessProbe":{
"periodSeconds":"*"
}
}
]
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"StatefulSet",
"metadata":{
"name":"game-web",
"labels":{
"originalLabel":"isHere"
}
},
"spec":{
"selector":{
"matchLabels":{
"app":"nginxo"
}
},
"serviceName":"nginxo",
"replicas":3,
"template":{
"metadata":{
"labels":{
"app":"nginxo"
}
},
"spec":{
"terminationGracePeriodSeconds":10,
"containers":[
{
"name":"nginxo",
"image":"k8s.gcr.io/nginx-but-no-slim:0.8",
"ports":[
{
"containerPort":8780,
"name":"webp"
}
],
"volumeMounts":[
{
"name":"www",
"mountPath":"/usr/share/nginxo/html"
}
],
"livenessProbe":{
"periodSeconds":11
}
}
]
}
},
"volumeClaimTemplates":[
{
"metadata":{
"name":"www"
},
"spec":{
"accessModes":[
"ReadWriteOnce"
],
"storageClassName":"my-storage-class",
"resources":{
"requests":{
"storage":"1Gi"
}
}
}
}
]
}
}
`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.NilError(t, validateMap(resource, pattern))
}
func TestValidateMap_AsteriskForMap(t *testing.T) {
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":[
{
"name":"*",
"livenessProbe":"*"
}
]
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"StatefulSet",
"metadata":{
"name":"game-web",
"labels":{
"originalLabel":"isHere"
}
},
"spec":{
"selector":{
"matchLabels":{
"app":"nginxo"
}
},
"serviceName":"nginxo",
"replicas":3,
"template":{
"metadata":{
"labels":{
"app":"nginxo"
}
},
"spec":{
"terminationGracePeriodSeconds":10,
"containers":[
{
"name":"nginxo",
"image":"k8s.gcr.io/nginx-but-no-slim:0.8",
"ports":[
{
"containerPort":8780,
"name":"webp"
}
],
"volumeMounts":[
{
"name":"www",
"mountPath":"/usr/share/nginxo/html"
}
],
"livenessProbe":{
"periodSeconds":11
}
}
]
}
},
"volumeClaimTemplates":[
{
"metadata":{
"name":"www"
},
"spec":{
"accessModes":[
"ReadWriteOnce"
],
"storageClassName":"my-storage-class",
"resources":{
"requests":{
"storage":"1Gi"
}
}
}
}
]
}
}`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.NilError(t, validateMap(resource, pattern))
}
func TestValidateMap_AsteriskForArray(t *testing.T) {
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":"*"
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"StatefulSet",
"metadata":{
"name":"game-web",
"labels":{
"originalLabel":"isHere"
}
},
"spec":{
"selector":{
"matchLabels":{
"app":"nginxo"
}
},
"serviceName":"nginxo",
"replicas":3,
"template":{
"metadata":{
"labels":{
"app":"nginxo"
}
},
"spec":{
"terminationGracePeriodSeconds":10,
"containers":[
{
"name":"nginxo",
"image":"k8s.gcr.io/nginx-but-no-slim:0.8",
"ports":[
{
"containerPort":8780,
"name":"webp"
}
],
"volumeMounts":[
{
"name":"www",
"mountPath":"/usr/share/nginxo/html"
}
],
"livenessProbe":{
"periodSeconds":11
}
}
]
}
},
"volumeClaimTemplates":[
{
"metadata":{
"name":"www"
},
"spec":{
"accessModes":[
"ReadWriteOnce"
],
"storageClassName":"my-storage-class",
"resources":{
"requests":{
"storage":"1Gi"
}
}
}
}
]
}
}`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.NilError(t, validateMap(resource, pattern))
}
func TestValidateMap_AsteriskFieldIsMissing(t *testing.T) {
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":[
{
"name":"*",
"livenessProbe":"*"
}
]
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"StatefulSet",
"metadata":{
"name":"game-web",
"labels":{
"originalLabel":"isHere"
}
},
"spec":{
"selector":{
"matchLabels":{
"app":"nginxo"
}
},
"serviceName":"nginxo",
"replicas":3,
"template":{
"metadata":{
"labels":{
"app":"nginxo"
}
},
"spec":{
"terminationGracePeriodSeconds":10,
"containers":[
{
"name":"nginxo",
"image":"k8s.gcr.io/nginx-but-no-slim:0.8",
"ports":[
{
"containerPort":8780,
"name":"webp"
}
],
"volumeMounts":[
{
"name":"www",
"mountPath":"/usr/share/nginxo/html"
}
],
"livenessProbe":null
}
]
}
},
"volumeClaimTemplates":[
{
"metadata":{
"name":"www"
},
"spec":{
"accessModes":[
"ReadWriteOnce"
],
"storageClassName":"my-storage-class",
"resources":{
"requests":{
"storage":"1Gi"
}
}
}
}
]
}
}`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.Assert(t, validateMap(resource, pattern) != nil)
}
func TestValidateMapElement_TwoElementsInArrayOnePass(t *testing.T) {
rawPattern := []byte(`[ { "(name)": "nirmata-*", "object": [ { "(key1)": "value*", "key2": "value*" } ] } ]`)
rawMap := []byte(`[ { "name": "nirmata-1", "object": [ { "key1": "value1", "key2": "value2" } ] }, { "name": "nirmata-1", "object": [ { "key1": "not_value", "key2": "not_value" } ] } ]`)
rawPattern := []byte(`[
{
"(name)":"nirmata-*",
"object":[
{
"(key1)":"value*",
"key2":"value*"
}
]
}
]`)
rawMap := []byte(`[
{
"name":"nirmata-1",
"object":[
{
"key1":"value1",
"key2":"value2"
}
]
},
{
"name":"nirmata-1",
"object":[
{
"key1":"not_value",
"key2":"not_value"
}
]
}
]`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
@ -181,8 +728,28 @@ func TestValidateMapElement_TwoElementsInArrayOnePass(t *testing.T) {
}
func TestValidateMapElement_OneElementInArrayPass(t *testing.T) {
rawPattern := []byte(`[ { "(name)": "nirmata-*", "object": [ { "(key1)": "value*", "key2": "value*" } ] } ]`)
rawMap := []byte(`[ { "name": "nirmata-1", "object": [ { "key1": "value1", "key2": "value2" } ] } ]`)
rawPattern := []byte(`[
{
"(name)":"nirmata-*",
"object":[
{
"(key1)":"value*",
"key2":"value*"
}
]
}
]`)
rawMap := []byte(`[
{
"name":"nirmata-1",
"object":[
{
"key1":"value1",
"key2":"value2"
}
]
}
]`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
@ -192,8 +759,28 @@ func TestValidateMapElement_OneElementInArrayPass(t *testing.T) {
}
func TestValidateMapElement_OneElementInArrayNotPass(t *testing.T) {
rawPattern := []byte(`[{"(name)": "nirmata-*", "object":[{"(key1)": "value*", "key2": "value*"}]}]`)
rawMap := []byte(`[ { "name": "nirmata-1", "object": [ { "key1": "value5", "key2": "1value1" } ] } ]`)
rawPattern := []byte(`[
{
"(name)":"nirmata-*",
"object":[
{
"(key1)":"value*",
"key2":"value*"
}
]
}
]`)
rawMap := []byte(`[
{
"name":"nirmata-1",
"object":[
{
"key1":"value5",
"key2":"1value1"
}
]
}
]`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
@ -203,8 +790,87 @@ func TestValidateMapElement_OneElementInArrayNotPass(t *testing.T) {
}
func TestValidate_ServiceTest(t *testing.T) {
rawPolicy := []byte(`{ "apiVersion": "kyverno.nirmata.io/v1alpha1", "kind": "Policy", "metadata": { "name": "policy-service" }, "spec": { "rules": [ { "name": "ps1", "resource": { "kinds": [ "Service" ], "name": "game-service*" }, "mutate": { "patches": [ { "path": "/metadata/labels/isMutated", "op": "add", "value": "true" }, { "path": "/metadata/labels/secretLabel", "op": "replace", "value": "weKnow" }, { "path": "/metadata/labels/originalLabel", "op": "remove" }, { "path": "/spec/selector/app", "op": "replace", "value": "mutedApp" } ] }, "validate": { "message": "This resource is broken", "pattern": { "spec": { "ports": [ { "name": "hs", "protocol": 32 } ] } } } } ] } }`)
rawResource := []byte(`{ "kind": "Service", "apiVersion": "v1", "metadata": { "name": "game-service", "labels": { "originalLabel": "isHere", "secretLabel": "thisIsMySecret" } }, "spec": { "selector": { "app": "MyApp" }, "ports": [ { "name": "http", "protocol": "TCP", "port": 80, "targetPort": 9376 } ] } }`)
rawPolicy := []byte(`{
"apiVersion":"kyverno.nirmata.io/v1alpha1",
"kind":"Policy",
"metadata":{
"name":"policy-service"
},
"spec":{
"rules":[
{
"name":"ps1",
"resource":{
"kinds":[
"Service"
],
"name":"game-service*"
},
"mutate":{
"patches":[
{
"path":"/metadata/labels/isMutated",
"op":"add",
"value":"true"
},
{
"path":"/metadata/labels/secretLabel",
"op":"replace",
"value":"weKnow"
},
{
"path":"/metadata/labels/originalLabel",
"op":"remove"
},
{
"path":"/spec/selector/app",
"op":"replace",
"value":"mutedApp"
}
]
},
"validate":{
"message":"This resource is broken",
"pattern":{
"spec":{
"ports":[
{
"name":"hs",
"protocol":32
}
]
}
}
}
}
]
}
}`)
rawResource := []byte(`{
"kind":"Service",
"apiVersion":"v1",
"metadata":{
"name":"game-service",
"labels":{
"originalLabel":"isHere",
"secretLabel":"thisIsMySecret"
}
},
"spec":{
"selector":{
"app":"MyApp"
},
"ports":[
{
"name":"http",
"protocol":"TCP",
"port":80,
"targetPort":9376
}
]
}
}
`)
var policy kubepolicy.Policy
json.Unmarshal(rawPolicy, &policy)
@ -217,8 +883,92 @@ func TestValidate_ServiceTest(t *testing.T) {
}
func TestValidate_MapHasFloats(t *testing.T) {
rawPolicy := []byte(`{ "apiVersion": "kyverno.nirmata.io/v1alpha1", "kind": "Policy", "metadata": { "name": "policy-deployment-changed" }, "spec": { "rules": [ { "name": "First policy v2", "resource": { "kinds": [ "Deployment" ], "name": "nginx-*" }, "mutate": { "patches": [ { "path": "/metadata/labels/isMutated", "op": "add", "value": "true" }, { "path": "/metadata/labels/app", "op": "replace", "value": "nginx_is_mutated" } ] }, "validate": { "message": "replicas number is wrong", "pattern": { "metadata": { "labels": { "app": "*" } }, "spec": { "replicas": 3 } } } } ] } }`)
rawResource := []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "name": "nginx-deployment", "labels": { "app": "nginx" } }, "spec": { "replicas": 3, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:1.7.9", "ports": [ { "containerPort": 80 } ] } ] } } } }`)
rawPolicy := []byte(`{
"apiVersion":"kyverno.nirmata.io/v1alpha1",
"kind":"Policy",
"metadata":{
"name":"policy-deployment-changed"
},
"spec":{
"rules":[
{
"name":"First policy v2",
"resource":{
"kinds":[
"Deployment"
],
"name":"nginx-*"
},
"mutate":{
"patches":[
{
"path":"/metadata/labels/isMutated",
"op":"add",
"value":"true"
},
{
"path":"/metadata/labels/app",
"op":"replace",
"value":"nginx_is_mutated"
}
]
},
"validate":{
"message":"replicas number is wrong",
"pattern":{
"metadata":{
"labels":{
"app":"*"
}
},
"spec":{
"replicas":3
}
}
}
}
]
}
}`)
rawResource := []byte(`{
"apiVersion":"apps/v1",
"kind":"Deployment",
"metadata":{
"name":"nginx-deployment",
"labels":{
"app":"nginx"
}
},
"spec":{
"replicas":3,
"selector":{
"matchLabels":{
"app":"nginx"
}
},
"template":{
"metadata":{
"labels":{
"app":"nginx"
}
},
"spec":{
"containers":[
{
"name":"nginx",
"image":"nginx:1.7.9",
"ports":[
{
"containerPort":80
}
]
}
]
}
}
}
}
`)
var policy kubepolicy.Policy
json.Unmarshal(rawPolicy, &policy)