mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
fix anchors in the list of map VS anchors on different list
This commit is contained in:
parent
ff45794455
commit
a70d253828
4 changed files with 23 additions and 606 deletions
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
|
@ -19,19 +20,27 @@ import (
|
|||
func ProcessOverlay(rule kubepolicy.Rule, rawResource []byte, gvk metav1.GroupVersionKind) ([][]byte, error) {
|
||||
|
||||
var resource interface{}
|
||||
var appliedPatches [][]byte
|
||||
err := json.Unmarshal(rawResource, &resource)
|
||||
if err != nil {
|
||||
if err := json.Unmarshal(rawResource, &resource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
patches, err := mutateResourceWithOverlay(resource, *rule.Mutation.Overlay)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
resourceInfo := ParseResourceInfoFromObject(rawResource)
|
||||
patches, err := processOverlayPatches(resource, *rule.Mutation.Overlay)
|
||||
if err != nil && strings.Contains(err.Error(), "Conditions are not met") {
|
||||
glog.Infof("Resource does not meet conditions in overlay pattern, resource=%s, rule=%s\n", resourceInfo, rule.Name)
|
||||
return nil, nil
|
||||
}
|
||||
appliedPatches = append(appliedPatches, patches...)
|
||||
|
||||
return appliedPatches, err
|
||||
return patches, err
|
||||
}
|
||||
|
||||
func processOverlayPatches(resource, overlay interface{}) ([][]byte, error) {
|
||||
|
||||
if !meetConditions(resource, overlay) {
|
||||
return nil, errors.New("Conditions are not met")
|
||||
}
|
||||
|
||||
return mutateResourceWithOverlay(resource, overlay)
|
||||
}
|
||||
|
||||
// mutateResourceWithOverlay is a start of overlaying process
|
||||
|
|
|
@ -143,7 +143,12 @@ func isConditionMet(resource []interface{}, anchors map[string]interface{}) bool
|
|||
continue
|
||||
}
|
||||
|
||||
if ValidateValueWithPattern(value, pattern) {
|
||||
if len(resource) == 1 {
|
||||
if !ValidateValueWithPattern(value, pattern) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
ValidateValueWithPattern(value, pattern)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package engine
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
@ -24,12 +23,3 @@ func patchOverlay(rule kubepolicy.Rule, rawResource []byte) ([][]byte, error) {
|
|||
|
||||
return patches, err
|
||||
}
|
||||
|
||||
func processOverlayPatches(resource, overlay interface{}) ([][]byte, error) {
|
||||
|
||||
if !meetConditions(resource, overlay) {
|
||||
return nil, errors.New("Conditions are not met")
|
||||
}
|
||||
|
||||
return mutateResourceWithOverlay(resource, overlay)
|
||||
}
|
||||
|
|
|
@ -1,587 +0,0 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func TestProcessOverlayPatches_NestedListWithAnchor(t *testing.T) {
|
||||
resourceRaw := []byte(`
|
||||
{
|
||||
"apiVersion":"v1",
|
||||
"kind":"Endpoints",
|
||||
"metadata":{
|
||||
"name":"test-endpoint",
|
||||
"labels":{
|
||||
"label":"test"
|
||||
}
|
||||
},
|
||||
"subsets":[
|
||||
{
|
||||
"addresses":[
|
||||
{
|
||||
"ip":"192.168.10.171"
|
||||
}
|
||||
],
|
||||
"ports":[
|
||||
{
|
||||
"name":"secure-connection",
|
||||
"port":443,
|
||||
"protocol":"TCP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`)
|
||||
|
||||
overlayRaw := []byte(`
|
||||
{
|
||||
"subsets":[
|
||||
{
|
||||
"ports":[
|
||||
{
|
||||
"(name)":"secure-connection",
|
||||
"port":444,
|
||||
"protocol":"UDP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`)
|
||||
|
||||
var resource, overlay interface{}
|
||||
|
||||
json.Unmarshal(resourceRaw, &resource)
|
||||
json.Unmarshal(overlayRaw, &overlay)
|
||||
|
||||
patches, err := processOverlayPatches(resource, overlay)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patches != nil)
|
||||
|
||||
patch := JoinPatches(patches)
|
||||
decoded, err := jsonpatch.DecodePatch(patch)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, decoded != nil)
|
||||
|
||||
patched, err := decoded.Apply(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patched != nil)
|
||||
|
||||
expectedResult := []byte(`
|
||||
{
|
||||
"apiVersion":"v1",
|
||||
"kind":"Endpoints",
|
||||
"metadata":{
|
||||
"name":"test-endpoint",
|
||||
"labels":{
|
||||
"label":"test"
|
||||
}
|
||||
},
|
||||
"subsets":[
|
||||
{
|
||||
"addresses":[
|
||||
{
|
||||
"ip":"192.168.10.171"
|
||||
}
|
||||
],
|
||||
"ports":[
|
||||
{
|
||||
"name":"secure-connection",
|
||||
"port":444.000000,
|
||||
"protocol":"UDP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`)
|
||||
|
||||
compareJSONAsMap(t, expectedResult, patched)
|
||||
}
|
||||
|
||||
func TestProcessOverlayPatches_InsertIntoArray(t *testing.T) {
|
||||
resourceRaw := []byte(`
|
||||
{
|
||||
"apiVersion":"v1",
|
||||
"kind":"Endpoints",
|
||||
"metadata":{
|
||||
"name":"test-endpoint",
|
||||
"labels":{
|
||||
"label":"test"
|
||||
}
|
||||
},
|
||||
"subsets":[
|
||||
{
|
||||
"addresses":[
|
||||
{
|
||||
"ip":"192.168.10.171"
|
||||
}
|
||||
],
|
||||
"ports":[
|
||||
{
|
||||
"name":"secure-connection",
|
||||
"port":443,
|
||||
"protocol":"TCP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`)
|
||||
overlayRaw := []byte(`
|
||||
{
|
||||
"subsets":[
|
||||
{
|
||||
"addresses":[
|
||||
{
|
||||
"ip":"192.168.10.172"
|
||||
},
|
||||
{
|
||||
"ip":"192.168.10.173"
|
||||
}
|
||||
],
|
||||
"ports":[
|
||||
{
|
||||
"name":"insecure-connection",
|
||||
"port":80,
|
||||
"protocol":"UDP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`)
|
||||
|
||||
var resource, overlay interface{}
|
||||
|
||||
json.Unmarshal(resourceRaw, &resource)
|
||||
json.Unmarshal(overlayRaw, &overlay)
|
||||
|
||||
patches, err := processOverlayPatches(resource, overlay)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patches != nil)
|
||||
|
||||
patch := JoinPatches(patches)
|
||||
|
||||
decoded, err := jsonpatch.DecodePatch(patch)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, decoded != nil)
|
||||
|
||||
patched, err := decoded.Apply(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patched != nil)
|
||||
|
||||
expectedResult := []byte(`{
|
||||
"apiVersion":"v1",
|
||||
"kind":"Endpoints",
|
||||
"metadata":{
|
||||
"name":"test-endpoint",
|
||||
"labels":{
|
||||
"label":"test"
|
||||
}
|
||||
},
|
||||
"subsets":[
|
||||
{
|
||||
"addresses":[
|
||||
{
|
||||
"ip":"192.168.10.171"
|
||||
}
|
||||
],
|
||||
"ports":[
|
||||
{
|
||||
"name":"secure-connection",
|
||||
"port":443,
|
||||
"protocol":"TCP"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"addresses":[
|
||||
{
|
||||
"ip":"192.168.10.172"
|
||||
},
|
||||
{
|
||||
"ip":"192.168.10.173"
|
||||
}
|
||||
],
|
||||
"ports":[
|
||||
{
|
||||
"name":"insecure-connection",
|
||||
"port":80,
|
||||
"protocol":"UDP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`)
|
||||
|
||||
compareJSONAsMap(t, expectedResult, patched)
|
||||
}
|
||||
|
||||
func TestProcessOverlayPatches_TestInsertToArray(t *testing.T) {
|
||||
overlayRaw := []byte(`
|
||||
{
|
||||
"spec":{
|
||||
"template":{
|
||||
"spec":{
|
||||
"containers":[
|
||||
{
|
||||
"name":"pi1",
|
||||
"image":"vasylev.perl"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
resourceRaw := []byte(`{
|
||||
"apiVersion":"batch/v1",
|
||||
"kind":"Job",
|
||||
"metadata":{
|
||||
"name":"pi"
|
||||
},
|
||||
"spec":{
|
||||
"template":{
|
||||
"spec":{
|
||||
"containers":[
|
||||
{
|
||||
"name":"piv0",
|
||||
"image":"perl",
|
||||
"command":[
|
||||
"perl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"pi",
|
||||
"image":"perl",
|
||||
"command":[
|
||||
"perl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"piv1",
|
||||
"image":"perl",
|
||||
"command":[
|
||||
"perl"
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy":"Never"
|
||||
}
|
||||
},
|
||||
"backoffLimit":4
|
||||
}
|
||||
}`)
|
||||
|
||||
var resource, overlay interface{}
|
||||
|
||||
json.Unmarshal(resourceRaw, &resource)
|
||||
json.Unmarshal(overlayRaw, &overlay)
|
||||
|
||||
patches, err := processOverlayPatches(resource, overlay)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patches != nil)
|
||||
|
||||
patch := JoinPatches(patches)
|
||||
|
||||
decoded, err := jsonpatch.DecodePatch(patch)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, decoded != nil)
|
||||
|
||||
patched, err := decoded.Apply(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patched != nil)
|
||||
}
|
||||
|
||||
func TestProcessOverlayPatches_ImagePullPolicy(t *testing.T) {
|
||||
overlayRaw := []byte(`{
|
||||
"spec": {
|
||||
"template": {
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"(image)": "*:latest",
|
||||
"imagePullPolicy": "IfNotPresent",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 8080
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
resourceRaw := []byte(`{
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "Deployment",
|
||||
"metadata": {
|
||||
"name": "nginx-deployment",
|
||||
"labels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"replicas": 1,
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"image": "nginx:latest",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ghost",
|
||||
"image": "ghost:latest"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
|
||||
var resource, overlay interface{}
|
||||
|
||||
json.Unmarshal(resourceRaw, &resource)
|
||||
json.Unmarshal(overlayRaw, &overlay)
|
||||
|
||||
patches, err := processOverlayPatches(resource, overlay)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err := ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
expectedResult := []byte(`{
|
||||
"apiVersion":"apps/v1",
|
||||
"kind":"Deployment",
|
||||
"metadata":{
|
||||
"name":"nginx-deployment",
|
||||
"labels":{
|
||||
"app":"nginx"
|
||||
}
|
||||
},
|
||||
"spec":{
|
||||
"replicas":1,
|
||||
"selector":{
|
||||
"matchLabels":{
|
||||
"app":"nginx"
|
||||
}
|
||||
},
|
||||
"template":{
|
||||
"metadata":{
|
||||
"labels":{
|
||||
"app":"nginx"
|
||||
}
|
||||
},
|
||||
"spec":{
|
||||
"containers":[
|
||||
{
|
||||
"image":"nginx:latest",
|
||||
"imagePullPolicy":"IfNotPresent",
|
||||
"name":"nginx",
|
||||
"ports":[
|
||||
{
|
||||
"containerPort":80
|
||||
},
|
||||
{
|
||||
"containerPort":8080
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"image":"ghost:latest",
|
||||
"imagePullPolicy":"IfNotPresent",
|
||||
"name":"ghost",
|
||||
"ports":[
|
||||
{
|
||||
"containerPort":8080
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
|
||||
compareJSONAsMap(t, expectedResult, doc)
|
||||
}
|
||||
|
||||
func TestProcessOverlayPatches_AddingAnchor(t *testing.T) {
|
||||
overlayRaw := []byte(`{
|
||||
"metadata": {
|
||||
"name": "nginx-deployment",
|
||||
"labels": {
|
||||
"+(app)": "should-not-be-here",
|
||||
"+(key1)": "value1"
|
||||
}
|
||||
}
|
||||
}`)
|
||||
resourceRaw := []byte(`{
|
||||
"metadata": {
|
||||
"name": "nginx-deployment",
|
||||
"labels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
}
|
||||
}`)
|
||||
|
||||
var resource, overlay interface{}
|
||||
|
||||
json.Unmarshal(resourceRaw, &resource)
|
||||
json.Unmarshal(overlayRaw, &overlay)
|
||||
|
||||
patches, err := processOverlayPatches(resource, overlay)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err := ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
expectedResult := []byte(`{
|
||||
"metadata":{
|
||||
"labels":{
|
||||
"app":"nginx",
|
||||
"key1":"value1"
|
||||
},
|
||||
"name":"nginx-deployment"
|
||||
}
|
||||
}`)
|
||||
|
||||
compareJSONAsMap(t, expectedResult, doc)
|
||||
}
|
||||
|
||||
func TestProcessOverlayPatches_AddingAnchorInsideListElement(t *testing.T) {
|
||||
overlayRaw := []byte(`
|
||||
{
|
||||
"spec": {
|
||||
"template": {
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"(image)": "*:latest",
|
||||
"+(imagePullPolicy)": "IfNotPresent"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
resourceRaw := []byte(`
|
||||
{
|
||||
"apiVersion":"apps/v1",
|
||||
"kind":"Deployment",
|
||||
"metadata":{
|
||||
"name":"nginx-deployment",
|
||||
"labels":{
|
||||
"app":"nginx"
|
||||
}
|
||||
},
|
||||
"spec":{
|
||||
"replicas":1,
|
||||
"selector":{
|
||||
"matchLabels":{
|
||||
"app":"nginx"
|
||||
}
|
||||
},
|
||||
"template":{
|
||||
"metadata":{
|
||||
"labels":{
|
||||
"app":"nginx"
|
||||
}
|
||||
},
|
||||
"spec":{
|
||||
"containers":[
|
||||
{
|
||||
"image":"nginx:latest"
|
||||
},
|
||||
{
|
||||
"image":"ghost:latest",
|
||||
"imagePullPolicy":"Always"
|
||||
},
|
||||
{
|
||||
"image":"debian:10"
|
||||
},
|
||||
{
|
||||
"image":"ubuntu:18.04",
|
||||
"imagePullPolicy":"Always"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
|
||||
var resource, overlay interface{}
|
||||
|
||||
json.Unmarshal(resourceRaw, &resource)
|
||||
json.Unmarshal(overlayRaw, &overlay)
|
||||
|
||||
patches, err := processOverlayPatches(resource, overlay)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err := ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
expectedResult := []byte(`
|
||||
{
|
||||
"apiVersion":"apps/v1",
|
||||
"kind":"Deployment",
|
||||
"metadata":{
|
||||
"name":"nginx-deployment",
|
||||
"labels":{
|
||||
"app":"nginx"
|
||||
}
|
||||
},
|
||||
"spec":{
|
||||
"replicas":1,
|
||||
"selector":{
|
||||
"matchLabels":{
|
||||
"app":"nginx"
|
||||
}
|
||||
},
|
||||
"template":{
|
||||
"metadata":{
|
||||
"labels":{
|
||||
"app":"nginx"
|
||||
}
|
||||
},
|
||||
"spec":{
|
||||
"containers":[
|
||||
{
|
||||
"image":"nginx:latest",
|
||||
"imagePullPolicy":"IfNotPresent"
|
||||
},
|
||||
{
|
||||
"image":"ghost:latest",
|
||||
"imagePullPolicy":"Always"
|
||||
},
|
||||
{
|
||||
"image":"debian:10"
|
||||
},
|
||||
{
|
||||
"image":"ubuntu:18.04",
|
||||
"imagePullPolicy":"Always"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
compareJSONAsMap(t, expectedResult, doc)
|
||||
}
|
Loading…
Add table
Reference in a new issue