1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-09 09:26:54 +00:00
kyverno/pkg/engine/wildcards/wildcards.go
Jim Bugwadia a9fef256c7
updates for foreach and mutate (#2891)
* updates for foreach and mutate

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* allow tests to pass on Windows

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix tests

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix linter check

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add elementIndex variable

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fmt

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix jsonResult usage

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add mutate validation and fix error in validate.foreach

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* format

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* update message

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* do not skip validation for all array entries when one is skipped

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add foreach tests

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix fmt

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix format errors

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* remove unused declarations

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* revert namespaceWithLabelYaml

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix mutate of element list

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* update CRDs

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* Update api/kyverno/v1/policy_types.go

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update pkg/engine/forceMutate.go

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update pkg/engine/forceMutate.go

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update pkg/engine/forceMutate.go

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update pkg/engine/mutation.go

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update pkg/engine/mutation.go

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update pkg/engine/mutation.go

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update pkg/engine/validate/validate.go

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update pkg/engine/validate/validate.go

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update test/cli/test/custom-functions/policy.yaml

Co-authored-by: Steven E. Harris <seh@panix.com>

* Update test/cli/test/foreach/policies.yaml

Co-authored-by: Steven E. Harris <seh@panix.com>

* accept review comments and format

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add comments to strategicMergePatch buffer

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* load context and evaluate preconditions foreach element

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add test for foreach mutate context and precondition

* precondition testcase

* address review comments

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* update message

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* format

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

Co-authored-by: Steven E. Harris <seh@panix.com>
Co-authored-by: Vyankatesh Kudtarkar <vyankateshkd@gmail.com>
2022-01-05 09:36:33 +08:00

162 lines
4.5 KiB
Go

package wildcards
import (
"strings"
commonAnchor "github.com/kyverno/kyverno/pkg/engine/anchor"
"github.com/minio/pkg/wildcard"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ReplaceInSelector replaces label selector keys and values containing
// wildcard characters with matching keys and values from the resource labels.
func ReplaceInSelector(labelSelector *metav1.LabelSelector, resourceLabels map[string]string) {
result := replaceWildcardsInMapKeyValues(labelSelector.MatchLabels, resourceLabels)
labelSelector.MatchLabels = result
}
// replaceWildcardsInMap will expand the "key" and "value" and will replace wildcard characters
// It also does not handle anchors as these are not expected in selectors
func replaceWildcardsInMapKeyValues(patternMap map[string]string, resourceMap map[string]string) map[string]string {
result := map[string]string{}
for k, v := range patternMap {
if hasWildcards(k) || hasWildcards(v) {
matchK, matchV := expandWildcards(k, v, resourceMap, true, true)
result[matchK] = matchV
} else {
result[k] = v
}
}
return result
}
func hasWildcards(s string) bool {
return strings.Contains(s, "*") || strings.Contains(s, "?")
}
func expandWildcards(k, v string, resourceMap map[string]string, matchValue, replace bool) (key string, val string) {
for k1, v1 := range resourceMap {
if wildcard.Match(k, k1) {
if !matchValue {
return k1, v1
} else if wildcard.Match(v, v1) {
return k1, v1
}
}
}
if replace {
k = replaceWildCardChars(k)
v = replaceWildCardChars(v)
}
return k, v
}
// replaceWildCardChars will replace '*' and '?' characters which are not
// supported by Kubernetes with a '0'.
func replaceWildCardChars(s string) string {
s = strings.Replace(s, "*", "0", -1)
s = strings.Replace(s, "?", "0", -1)
return s
}
// ExpandInMetadata substitutes wildcard characters in map keys for metadata.labels and
// metadata.annotations that are present in a validation pattern. Values are not substituted
// here, as they are evaluated separately while processing the validation pattern. Anchors
// on the tags (e.g. "=(kubernetes.io/*)" will be preserved when the values are expanded.
func ExpandInMetadata(patternMap, resourceMap map[string]interface{}) map[string]interface{} {
_, patternMetadata := getPatternValue("metadata", patternMap)
if patternMetadata == nil {
return patternMap
}
resourceMetadata := resourceMap["metadata"]
if resourceMetadata == nil {
return patternMap
}
metadata := patternMetadata.(map[string]interface{})
labelsKey, labels := expandWildcardsInTag("labels", patternMetadata, resourceMetadata)
if labels != nil {
metadata[labelsKey] = labels
}
annotationsKey, annotations := expandWildcardsInTag("annotations", patternMetadata, resourceMetadata)
if annotations != nil {
metadata[annotationsKey] = annotations
}
return patternMap
}
func getPatternValue(tag string, pattern map[string]interface{}) (string, interface{}) {
for k, v := range pattern {
k2, _ := commonAnchor.RemoveAnchor(k)
if k2 == tag {
return k, v
}
}
return "", nil
}
// expandWildcardsInTag
func expandWildcardsInTag(tag string, patternMetadata, resourceMetadata interface{}) (string, map[string]interface{}) {
patternKey, patternData := getValueAsStringMap(tag, patternMetadata)
if patternData == nil {
return "", nil
}
_, resourceData := getValueAsStringMap(tag, resourceMetadata)
if resourceData == nil {
return "", nil
}
results := replaceWildcardsInMapKeys(patternData, resourceData)
return patternKey, results
}
func getValueAsStringMap(key string, data interface{}) (string, map[string]string) {
if data == nil {
return "", nil
}
dataMap := data.(map[string]interface{})
patternKey, val := getPatternValue(key, dataMap)
if val == nil {
return "", nil
}
result := map[string]string{}
for k, v := range val.(map[string]interface{}) {
result[k] = v.(string)
}
return patternKey, result
}
// replaceWildcardsInMapKeys will expand only the "key" and not replace wildcard characters in the key or values
// It also preserves anchors in keys
func replaceWildcardsInMapKeys(patternData, resourceData map[string]string) map[string]interface{} {
results := map[string]interface{}{}
for k, v := range patternData {
if hasWildcards(k) {
anchorFreeKey, anchorPrefix := commonAnchor.RemoveAnchor(k)
matchK, _ := expandWildcards(anchorFreeKey, v, resourceData, false, false)
if anchorPrefix != "" {
matchK = commonAnchor.AddAnchor(matchK, anchorPrefix)
}
results[matchK] = v
} else {
results[k] = v
}
}
return results
}