mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 16:06:56 +00:00
173 lines
4 KiB
Go
Executable file
173 lines
4 KiB
Go
Executable file
package engine
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/golang/glog"
|
|
)
|
|
|
|
func meetConditions(resource, overlay interface{}) bool {
|
|
// overlay has no anchor, return true
|
|
if !hasNestedAnchors(overlay) {
|
|
return true
|
|
}
|
|
|
|
// resource item exists but has different type
|
|
// return false if anchor exists in overlay
|
|
// conditon never be true in this case
|
|
if reflect.TypeOf(resource) != reflect.TypeOf(overlay) {
|
|
if hasNestedAnchors(overlay) {
|
|
glog.V(3).Infof("Found anchor on different types of element: overlay %T, resource %T\nSkip processing overlay.", overlay, resource)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
return checkConditions(resource, overlay)
|
|
}
|
|
|
|
func checkConditions(resource, overlay interface{}) bool {
|
|
switch typedOverlay := overlay.(type) {
|
|
case map[string]interface{}:
|
|
typedResource := resource.(map[string]interface{})
|
|
return checkConditionOnMap(typedResource, typedOverlay)
|
|
case []interface{}:
|
|
typedResource := resource.([]interface{})
|
|
return checkConditionOnArray(typedResource, typedOverlay)
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
|
|
func checkConditionOnMap(resourceMap, overlayMap map[string]interface{}) bool {
|
|
anchors := getAnchorsFromMap(overlayMap)
|
|
if len(anchors) > 0 {
|
|
if !isConditionMetOnMap(resourceMap, anchors) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
for key, value := range overlayMap {
|
|
resourcePart, ok := resourceMap[key]
|
|
|
|
if ok && !isAddingAnchor(key) {
|
|
if !meetConditions(resourcePart, value) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
// key does not exist or isAddingAnchor
|
|
return true
|
|
}
|
|
|
|
func checkConditionOnArray(resource, overlay []interface{}) bool {
|
|
if 0 == len(resource) {
|
|
return false
|
|
}
|
|
|
|
if 0 == len(overlay) {
|
|
return true
|
|
}
|
|
|
|
if reflect.TypeOf(resource[0]) != reflect.TypeOf(overlay[0]) {
|
|
glog.Warningf("Overlay array and resource array have elements of different types: %T and %T", overlay[0], resource[0])
|
|
return false
|
|
}
|
|
|
|
return checkConditionsOnArrayOfSameTypes(resource, overlay)
|
|
}
|
|
|
|
func checkConditionsOnArrayOfSameTypes(resource, overlay []interface{}) bool {
|
|
switch overlay[0].(type) {
|
|
case map[string]interface{}:
|
|
return checkConditionsOnArrayOfMaps(resource, overlay)
|
|
default:
|
|
glog.Warningf("Anchors not supported in overlay of array type %T\n", overlay[0])
|
|
return false
|
|
}
|
|
}
|
|
|
|
func checkConditionsOnArrayOfMaps(resource, overlay []interface{}) bool {
|
|
for _, overlayElement := range overlay {
|
|
typedOverlay := overlayElement.(map[string]interface{})
|
|
anchors, overlayWithoutAnchor := getElementsFromMap(typedOverlay)
|
|
|
|
if len(anchors) > 0 {
|
|
if !validAnchorMap(anchors) {
|
|
return false
|
|
}
|
|
|
|
if !isConditionMet(resource, anchors) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
for key, val := range overlayWithoutAnchor {
|
|
if hasNestedAnchors(val) {
|
|
for _, resourceElement := range resource {
|
|
typedResource := resourceElement.(map[string]interface{})
|
|
|
|
if resourcePart, ok := typedResource[key]; ok {
|
|
if !meetConditions(resourcePart, val) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func validAnchorMap(anchors map[string]interface{}) bool {
|
|
for _, val := range anchors {
|
|
switch val.(type) {
|
|
case map[string]interface{}, []interface{}:
|
|
glog.Warning("Maps and arrays as patterns are not supported")
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func isConditionMet(resource []interface{}, anchors map[string]interface{}) bool {
|
|
for _, resourceElement := range resource {
|
|
typedResource := resourceElement.(map[string]interface{})
|
|
for key, pattern := range anchors {
|
|
key = key[1 : len(key)-1]
|
|
|
|
value, ok := typedResource[key]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if len(resource) == 1 {
|
|
if !ValidateValueWithPattern(value, pattern) {
|
|
return false
|
|
}
|
|
} else {
|
|
ValidateValueWithPattern(value, pattern)
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func isConditionMetOnMap(resource, anchors map[string]interface{}) bool {
|
|
for key, pattern := range anchors {
|
|
key = key[1 : len(key)-1]
|
|
|
|
value, ok := resource[key]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if !ValidateValueWithPattern(value, pattern) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|