mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
Fix: handling unexpected global-anchor-variable for the apply command (#5590)
Signed-off-by: ansalamdaniel <ansalam.daniel@infracloud.io> Signed-off-by: ansalamdaniel <ansalam.daniel@infracloud.io>
This commit is contained in:
parent
3e44569fe2
commit
9c4f05e883
7 changed files with 192 additions and 1 deletions
pkg/engine/mutate/patch
test/cli/test-mutate/global-anchor
|
@ -137,9 +137,9 @@ func processListOfMaps(logger logr.Logger, pattern, resource *yaml.RNode) error
|
||||||
if hasAnyAnchor {
|
if hasAnyAnchor {
|
||||||
anyGlobalConditionPassed := false
|
anyGlobalConditionPassed := false
|
||||||
var lastGlobalAnchorError error = nil
|
var lastGlobalAnchorError error = nil
|
||||||
|
patternElementCopy := patternElement.Copy()
|
||||||
|
|
||||||
for _, resourceElement := range resourceElements {
|
for _, resourceElement := range resourceElements {
|
||||||
patternElementCopy := patternElement.Copy()
|
|
||||||
if err := preProcessRecursive(logger, patternElementCopy, resourceElement); err != nil {
|
if err := preProcessRecursive(logger, patternElementCopy, resourceElement); err != nil {
|
||||||
logger.V(3).Info("anchor mismatch", "reason", err.Error())
|
logger.V(3).Info("anchor mismatch", "reason", err.Error())
|
||||||
if isConditionError(err) {
|
if isConditionError(err) {
|
||||||
|
@ -163,7 +163,21 @@ func processListOfMaps(logger logr.Logger, pattern, resource *yaml.RNode) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if resource == nil {
|
||||||
|
if err := preProcessRecursive(logger, patternElementCopy, resource); err != nil {
|
||||||
|
logger.V(3).Info("anchor mismatch", "reason", err.Error())
|
||||||
|
if isConditionError(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasGlobalConditions {
|
||||||
|
// global anchor has passed, there is no need to return an error
|
||||||
|
anyGlobalConditionPassed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
if !anyGlobalConditionPassed && lastGlobalAnchorError != nil {
|
if !anyGlobalConditionPassed && lastGlobalAnchorError != nil {
|
||||||
return lastGlobalAnchorError
|
return lastGlobalAnchorError
|
||||||
}
|
}
|
||||||
|
|
|
@ -1278,3 +1278,40 @@ func Test_NestedConditionals(t *testing.T) {
|
||||||
|
|
||||||
assert.DeepEqual(t, toJSON(t, []byte(expectedPattern)), toJSON(t, []byte(resultPattern)))
|
assert.DeepEqual(t, toJSON(t, []byte(expectedPattern)), toJSON(t, []byte(resultPattern)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_GlobalCondition_Fail(t *testing.T) {
|
||||||
|
rawPattern := []byte(`{
|
||||||
|
"metadata": {
|
||||||
|
"annotations": {
|
||||||
|
"+(cluster-autoscaler.kubernetes.io/safe-to-evict)": "true"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"volumes": [
|
||||||
|
{
|
||||||
|
"<(emptyDir)": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
rawResource := []byte(`{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Pod",
|
||||||
|
"metadata": {
|
||||||
|
"name": "pod-without-emptydir-hostpath"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"containers": [
|
||||||
|
{
|
||||||
|
"name": "nginx",
|
||||||
|
"image": "nginx"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
pattern := yaml.MustParse(string(rawPattern))
|
||||||
|
resource := yaml.MustParse(string(rawResource))
|
||||||
|
err := preProcessPattern(logging.GlobalLogger(), pattern, resource)
|
||||||
|
assert.Error(t, err, "global condition failed: could not found \"emptyDir\" key in the resource")
|
||||||
|
}
|
||||||
|
|
28
test/cli/test-mutate/global-anchor/kyverno-test.yaml
Normal file
28
test/cli/test-mutate/global-anchor/kyverno-test.yaml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
name: validate-service-loadbalancer
|
||||||
|
policies:
|
||||||
|
- policy.yaml
|
||||||
|
resources:
|
||||||
|
- resources.yaml
|
||||||
|
results:
|
||||||
|
- policy: add-safe-to-evict
|
||||||
|
rule: annotate-empty-dir
|
||||||
|
resource: pod-without-emptydir-hostpath
|
||||||
|
kind: Pod
|
||||||
|
result: skip
|
||||||
|
- policy: add-safe-to-evict
|
||||||
|
rule: annotate-empty-dir
|
||||||
|
resource: pod-with-emptydir-hostpath
|
||||||
|
patchedResource: patchedResource.yaml
|
||||||
|
kind: Pod
|
||||||
|
result: pass
|
||||||
|
- policy: add-safe-to-evict
|
||||||
|
rule: annotate-empty-dir
|
||||||
|
resource: pod-with-emptydir-hostpath-1
|
||||||
|
patchedResource: patchedResourceWithVolume.yaml
|
||||||
|
kind: Pod
|
||||||
|
result: pass
|
||||||
|
- policy: add-safe-to-evict
|
||||||
|
rule: annotate-empty-dir
|
||||||
|
resource: pod-without-emptydir-hostpath-1
|
||||||
|
kind: Pod
|
||||||
|
result: skip
|
14
test/cli/test-mutate/global-anchor/patchedResource.yaml
Normal file
14
test/cli/test-mutate/global-anchor/patchedResource.yaml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
|
||||||
|
name: pod-with-emptydir-hostpath
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
volumes:
|
||||||
|
- name: demo-volume
|
||||||
|
emptyDir: {}
|
|
@ -0,0 +1,18 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
|
||||||
|
name: pod-with-emptydir-hostpath-1
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /cache
|
||||||
|
name: cache-volume
|
||||||
|
volumes:
|
||||||
|
- name: cache-volume
|
||||||
|
emptyDir:
|
||||||
|
sizeLimit: 500Mi
|
25
test/cli/test-mutate/global-anchor/policy.yaml
Normal file
25
test/cli/test-mutate/global-anchor/policy.yaml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: add-safe-to-evict
|
||||||
|
annotations:
|
||||||
|
policies.kyverno.io/category: Workload Management
|
||||||
|
policies.kyverno.io/description: The Kubernetes cluster autoscaler does not evict pods that
|
||||||
|
use hostPath or emptyDir volumes. To allow eviction of these pods, the annotation
|
||||||
|
cluster-autoscaler.kubernetes.io/safe-to-evict=true must be added to the pods.
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- name: annotate-empty-dir
|
||||||
|
match:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
kinds:
|
||||||
|
- Pod
|
||||||
|
mutate:
|
||||||
|
patchStrategicMerge:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
+(cluster-autoscaler.kubernetes.io/safe-to-evict): "true"
|
||||||
|
spec:
|
||||||
|
volumes:
|
||||||
|
- <(emptyDir): {}
|
55
test/cli/test-mutate/global-anchor/resources.yaml
Normal file
55
test/cli/test-mutate/global-anchor/resources.yaml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: pod-without-emptydir-hostpath
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: pod-with-emptydir-hostpath
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
volumes:
|
||||||
|
- name: demo-volume
|
||||||
|
emptyDir: {}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: pod-with-emptydir-hostpath-1
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /cache
|
||||||
|
name: cache-volume
|
||||||
|
volumes:
|
||||||
|
- name: cache-volume
|
||||||
|
emptyDir:
|
||||||
|
sizeLimit: 500Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: pod-without-emptydir-hostpath-1
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- name: config-vol
|
||||||
|
mountPath: /etc/config
|
||||||
|
volumes:
|
||||||
|
- name: config-vol
|
||||||
|
configMap:
|
||||||
|
name: log-config
|
||||||
|
items:
|
||||||
|
- key: log_level
|
||||||
|
path: log_level
|
Loading…
Add table
Reference in a new issue