mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-05 15:37:19 +00:00
NK-31: SerializePatches decomposed to ProcessPatches and JoinPatches. Implemented new tests for ProcessPatches, used it in mutation webhook. Added options for behavior on errors while patching. Improved and refactored code for mutation webhook. Added dependency from json-patch lib.
This commit is contained in:
parent
e2b7444271
commit
85c84046af
4 changed files with 170 additions and 247 deletions
|
@ -18,4 +18,8 @@ required = ["k8s.io/code-generator/cmd/client-gen"]
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/gotestyourself/gotest.tools"
|
name = "github.com/gotestyourself/gotest.tools"
|
||||||
|
branch = "master"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/evanphx/json-patch"
|
||||||
branch = "master"
|
branch = "master"
|
|
@ -1,7 +1,6 @@
|
||||||
package webhooks
|
package webhooks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
@ -40,12 +39,9 @@ func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.Ad
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var allPatches []types.PolicyPatch
|
var allPatches []PatchBytes
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
stopOnError := true
|
patchingSets := getPolicyPatchingSets(policy)
|
||||||
if policy.Spec.FailurePolicy != nil && *policy.Spec.FailurePolicy == "continueOnError" {
|
|
||||||
stopOnError = false
|
|
||||||
}
|
|
||||||
|
|
||||||
for ruleIdx, rule := range policy.Spec.Rules {
|
for ruleIdx, rule := range policy.Spec.Rules {
|
||||||
err := rule.Validate()
|
err := rule.Validate()
|
||||||
|
@ -54,36 +50,29 @@ func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.Ad
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if IsRuleApplicableToRequest(rule.Resource, request) {
|
mw.logger.Printf("Applying policy %s, rule #%d", policy.ObjectMeta.Name, ruleIdx)
|
||||||
mw.logger.Printf("Applying policy %s, rule #%d", policy.ObjectMeta.Name, ruleIdx)
|
rulePatches, err := mw.applyRule(request, rule, patchingSets)
|
||||||
rulePatches, err := mw.applyRule(request, rule, stopOnError)
|
|
||||||
// If at least one error is detected in the rule, the entire rule will not be applied:
|
if err != nil {
|
||||||
// it can be changed in the future by varying the policy.Spec.FailurePolicy values.
|
errStr := fmt.Sprintf("Unable to apply rule #%d: %s", ruleIdx, err)
|
||||||
if err != nil {
|
mw.logger.Printf("Denying the request because of error: %s", errStr)
|
||||||
errStr := fmt.Sprintf("Unable to apply rule #%d: %s", ruleIdx, err)
|
mw.controller.LogPolicyError(policy.Name, errStr)
|
||||||
mw.logger.Print(errStr)
|
return errorToAdmissionResponse(err, true)
|
||||||
mw.controller.LogPolicyError(policy.Name, errStr)
|
}
|
||||||
if stopOnError {
|
|
||||||
mw.logger.Printf("/!\\ Denying the request according to FailurePolicy spec /!\\")
|
rulePatchesProcessed, err := ProcessPatches(rulePatches, request.Object.Raw, patchingSets)
|
||||||
}
|
if rulePatches != nil {
|
||||||
return errorToAdmissionResponse(err, !stopOnError)
|
allPatches = append(allPatches, rulePatchesProcessed...)
|
||||||
}
|
mw.logger.Printf("Prepared %d patches", len(rulePatchesProcessed))
|
||||||
if rulePatches != nil {
|
} else {
|
||||||
allPatches = append(allPatches, rulePatches...)
|
mw.logger.Print("No patches prepared")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
patchesBytes, err := SerializePatches(allPatches)
|
|
||||||
if err != nil {
|
|
||||||
mw.logger.Printf("Error occerred while serializing JSONPathch: %v", err)
|
|
||||||
return errorToAdmissionResponse(err, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &v1beta1.AdmissionResponse{
|
return &v1beta1.AdmissionResponse{
|
||||||
Allowed: true,
|
Allowed: true,
|
||||||
Patch: patchesBytes,
|
Patch: JoinPatches(allPatches),
|
||||||
PatchType: func() *v1beta1.PatchType {
|
PatchType: func() *v1beta1.PatchType {
|
||||||
pt := v1beta1.PatchTypeJSONPatch
|
pt := v1beta1.PatchTypeJSONPatch
|
||||||
return &pt
|
return &pt
|
||||||
|
@ -91,28 +80,28 @@ func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.Ad
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applies all rule to the created object and returns list of JSON patches.
|
func getPolicyPatchingSets(policy types.Policy) PatchingSets {
|
||||||
// May return nil patches if it is not necessary to create patches for requested object.
|
// failurePolicy property is the only available way for now to define behavior on patching error.
|
||||||
func (mw *MutationWebhook) applyRule(request *v1beta1.AdmissionRequest, rule types.PolicyRule, stopOnError bool) ([]types.PolicyPatch, error) {
|
// TODO: define new failurePolicy values specific for patching and other policy features.
|
||||||
rulePatches, err := mw.applyRulePatches(request, rule)
|
if policy.Spec.FailurePolicy != nil && *policy.Spec.FailurePolicy == "continueOnError" {
|
||||||
if err != nil {
|
return PatchingSetsContinueAlways
|
||||||
mw.logger.Printf("Error occurred while applying patches according to the policy: %v", err)
|
|
||||||
} else {
|
|
||||||
mw.logger.Printf("Prepared %v patches", len(rulePatches))
|
|
||||||
}
|
}
|
||||||
|
return PatchingSetsDefault
|
||||||
if err == nil || !stopOnError {
|
|
||||||
err = mw.applyRuleGenerators(request, rule)
|
|
||||||
}
|
|
||||||
|
|
||||||
return rulePatches, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets patches from "patch" section in PolicyRule
|
// Applies all rule to the created object and returns list of JSON patches.
|
||||||
func (mw *MutationWebhook) applyRulePatches(request *v1beta1.AdmissionRequest, rule types.PolicyRule) ([]types.PolicyPatch, error) {
|
// May return nil patches if it is not necessary to create patches for requested object.
|
||||||
var patches []types.PolicyPatch
|
func (mw *MutationWebhook) applyRule(request *v1beta1.AdmissionRequest, rule types.PolicyRule, errorBehavior PatchingSets) ([]types.PolicyPatch, error) {
|
||||||
patches = append(patches, rule.Patches...)
|
if !IsRuleApplicableToRequest(rule.Resource, request) {
|
||||||
return patches, nil
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mw.applyRuleGenerators(request, rule)
|
||||||
|
if err != nil && errorBehavior == PatchingSetsStopOnError {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return rule.Patches, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applies "configMapGenerator" and "secretGenerator" described in PolicyRule
|
// Applies "configMapGenerator" and "secretGenerator" described in PolicyRule
|
||||||
|
@ -158,37 +147,6 @@ func (mw *MutationWebhook) applyConfigGenerator(generator *types.PolicyConfigGen
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts JSON patches to byte array
|
|
||||||
func SerializePatches(patches []types.PolicyPatch) ([]byte, error) {
|
|
||||||
var result []byte
|
|
||||||
if len(patches) == 0 {
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
result = append(result, []byte("[\n")...)
|
|
||||||
for index, patch := range patches {
|
|
||||||
patchBytes, err := serializePatch(patch)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result = append(result, patchBytes...)
|
|
||||||
if index != (len(patches) - 1) {
|
|
||||||
result = append(result, []byte(",\n")...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = append(result, []byte("\n]")...)
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializePatch(patch types.PolicyPatch) ([]byte, error) {
|
|
||||||
err := patch.Validate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return json.Marshal(patch)
|
|
||||||
}
|
|
||||||
|
|
||||||
func errorToAdmissionResponse(err error, allowed bool) *v1beta1.AdmissionResponse {
|
func errorToAdmissionResponse(err error, allowed bool) *v1beta1.AdmissionResponse {
|
||||||
return &v1beta1.AdmissionResponse{
|
return &v1beta1.AdmissionResponse{
|
||||||
Result: &metav1.Status{
|
Result: &metav1.Status{
|
||||||
|
|
|
@ -1,167 +0,0 @@
|
||||||
package webhooks_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"gotest.tools/assert"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/nirmata/kube-policy/webhooks"
|
|
||||||
|
|
||||||
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSerializePatches_Empty(t *testing.T) {
|
|
||||||
var patches []types.PolicyPatch
|
|
||||||
bytes, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.Assert(t, nil == err)
|
|
||||||
assert.Assert(t, 0 == len(bytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializePatches_SingleStringValid(t *testing.T) {
|
|
||||||
patch := types.PolicyPatch{
|
|
||||||
Path: "/metadata/labels/is-mutated",
|
|
||||||
Operation: "add",
|
|
||||||
Value: "true",
|
|
||||||
}
|
|
||||||
patches := []types.PolicyPatch{patch}
|
|
||||||
bytes, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.Assert(t, nil == err)
|
|
||||||
assertEqStringAndData(t, `[
|
|
||||||
{"path":"/metadata/labels/is-mutated","op":"add","value":"true"}
|
|
||||||
]`, bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializePatches_SingleStringInvalid(t *testing.T) {
|
|
||||||
patch := types.PolicyPatch{
|
|
||||||
Path: "/metadata/labels/is-mutated",
|
|
||||||
Value: "true",
|
|
||||||
}
|
|
||||||
patches := []types.PolicyPatch{patch}
|
|
||||||
_, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.Assert(t, nil != err)
|
|
||||||
patches[0].Path = ""
|
|
||||||
patches[0].Operation = "delete"
|
|
||||||
_, err = webhooks.SerializePatches(patches)
|
|
||||||
assert.Assert(t, nil != err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializePatches_MultipleStringsValid(t *testing.T) {
|
|
||||||
patch1 := types.PolicyPatch{
|
|
||||||
Path: "/metadata/labels/is-mutated",
|
|
||||||
Operation: "add",
|
|
||||||
Value: "true",
|
|
||||||
}
|
|
||||||
patch2 := types.PolicyPatch{
|
|
||||||
Path: "/metadata/labels/newLabel",
|
|
||||||
Operation: "add",
|
|
||||||
Value: "newValue",
|
|
||||||
}
|
|
||||||
patches := []types.PolicyPatch{patch1, patch2}
|
|
||||||
bytes, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.Assert(t, nil == err)
|
|
||||||
assertEqStringAndData(t, `[
|
|
||||||
{"path":"/metadata/labels/is-mutated","op":"add","value":"true"},
|
|
||||||
{"path":"/metadata/labels/newLabel","op":"add","value":"newValue"}
|
|
||||||
]`, bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializePatches_SingleIntegerValid(t *testing.T) {
|
|
||||||
const ordinaryInt int = 42
|
|
||||||
patch := types.PolicyPatch{
|
|
||||||
Path: "/spec/replicas",
|
|
||||||
Operation: "add",
|
|
||||||
Value: ordinaryInt,
|
|
||||||
}
|
|
||||||
patches := []types.PolicyPatch{patch}
|
|
||||||
bytes, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assertEqStringAndData(t, `[
|
|
||||||
{"path":"/spec/replicas","op":"add","value":42}
|
|
||||||
]`, bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializePatches_SingleIntegerBigValid(t *testing.T) {
|
|
||||||
const bigInt uint64 = 100500100500
|
|
||||||
patch := types.PolicyPatch{
|
|
||||||
Path: "/spec/somethingHuge",
|
|
||||||
Operation: "add",
|
|
||||||
Value: bigInt,
|
|
||||||
}
|
|
||||||
patches := []types.PolicyPatch{patch}
|
|
||||||
bytes, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assertEqStringAndData(t, `[
|
|
||||||
{"path":"/spec/somethingHuge","op":"add","value":100500100500}
|
|
||||||
]`, bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializePatches_SingleFloatValid(t *testing.T) {
|
|
||||||
const ordinaryFloat float32 = 2.71828
|
|
||||||
patch := types.PolicyPatch{
|
|
||||||
Path: "/spec/consts/e",
|
|
||||||
Operation: "add",
|
|
||||||
Value: ordinaryFloat,
|
|
||||||
}
|
|
||||||
patches := []types.PolicyPatch{patch}
|
|
||||||
bytes, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assertEqStringAndData(t, `[
|
|
||||||
{"path":"/spec/consts/e","op":"add","value":2.71828}
|
|
||||||
]`, bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializePatches_SingleFloatBigValid(t *testing.T) {
|
|
||||||
const bigFloat float64 = 3.1415926535
|
|
||||||
patch := types.PolicyPatch{
|
|
||||||
Path: "/spec/consts/pi",
|
|
||||||
Operation: "add",
|
|
||||||
Value: bigFloat,
|
|
||||||
}
|
|
||||||
patches := []types.PolicyPatch{patch}
|
|
||||||
bytes, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assertEqStringAndData(t, `[
|
|
||||||
{"path":"/spec/consts/pi","op":"add","value":3.1415926535}
|
|
||||||
]`, bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializePatches_MultipleBoolValid(t *testing.T) {
|
|
||||||
patch1 := types.PolicyPatch{
|
|
||||||
Path: "/status/is-mutated",
|
|
||||||
Operation: "add",
|
|
||||||
Value: true,
|
|
||||||
}
|
|
||||||
patch2 := types.PolicyPatch{
|
|
||||||
Path: "/status/is-unreal",
|
|
||||||
Operation: "add",
|
|
||||||
Value: false,
|
|
||||||
}
|
|
||||||
patches := []types.PolicyPatch{patch1, patch2}
|
|
||||||
bytes, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assertEqStringAndData(t, `[
|
|
||||||
{"path":"/status/is-mutated","op":"add","value":true},
|
|
||||||
{"path":"/status/is-unreal","op":"add","value":false}
|
|
||||||
]`, bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializePatches_MultitypeMap(t *testing.T) {
|
|
||||||
valuesMap := make(map[string]interface{})
|
|
||||||
valuesMap["some_string"] = "value1"
|
|
||||||
valuesMap["number"] = 42
|
|
||||||
nestedMap := make(map[string]interface{})
|
|
||||||
nestedMap["label"] = "other value"
|
|
||||||
nestedMap["nested"] = true
|
|
||||||
valuesMap["additional"] = nestedMap
|
|
||||||
|
|
||||||
patch := types.PolicyPatch{
|
|
||||||
Path: "/spec/values",
|
|
||||||
Operation: "add",
|
|
||||||
Value: valuesMap,
|
|
||||||
}
|
|
||||||
patches := []types.PolicyPatch{patch}
|
|
||||||
bytes, err := webhooks.SerializePatches(patches)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assertEqStringAndData(t, `[
|
|
||||||
{"path":"/spec/values","op":"add","value":{"additional":{"label":"other value","nested":true},"number":42,"some_string":"value1"}}
|
|
||||||
]`, bytes)
|
|
||||||
}
|
|
128
webhooks/patches_test.go
Normal file
128
webhooks/patches_test.go
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
package webhooks_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gotest.tools/assert"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nirmata/kube-policy/webhooks"
|
||||||
|
|
||||||
|
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const endpointsDocument string = `{
|
||||||
|
"kind": "Endpoints",
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"metadata": {
|
||||||
|
"name": "my-endpoint-service",
|
||||||
|
"labels": {
|
||||||
|
"originalLabel": "isHere"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"subsets": [
|
||||||
|
{
|
||||||
|
"addresses": [
|
||||||
|
{
|
||||||
|
"ip": "1.2.3.4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ports": [
|
||||||
|
{
|
||||||
|
"port": 9376
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
func TestProcessPatches_EmptyPatches(t *testing.T) {
|
||||||
|
var empty []types.PolicyPatch
|
||||||
|
patches, err := webhooks.ProcessPatches(empty, []byte(endpointsDocument), webhooks.PatchingSetsDefault)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Assert(t, len(patches) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeAddIsMutatedLabelPatch() types.PolicyPatch {
|
||||||
|
return types.PolicyPatch{
|
||||||
|
Path: "/metadata/labels/is-mutated",
|
||||||
|
Operation: "add",
|
||||||
|
Value: "true",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessPatches_EmptyDocument(t *testing.T) {
|
||||||
|
var patches []types.PolicyPatch
|
||||||
|
patches = append(patches, makeAddIsMutatedLabelPatch())
|
||||||
|
patchesBytes, err := webhooks.ProcessPatches(patches, nil, webhooks.PatchingSetsDefault)
|
||||||
|
assert.Assert(t, err != nil)
|
||||||
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessPatches_AllEmpty(t *testing.T) {
|
||||||
|
patchesBytes, err := webhooks.ProcessPatches(nil, nil, webhooks.PatchingSetsDefault)
|
||||||
|
assert.Assert(t, err != nil)
|
||||||
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessPatches_AddPathDoesntExist_StopOnError(t *testing.T) {
|
||||||
|
patch := makeAddIsMutatedLabelPatch()
|
||||||
|
patch.Path = "/metadata/additional/is-mutated"
|
||||||
|
patches := []types.PolicyPatch{patch}
|
||||||
|
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsStopOnError)
|
||||||
|
assert.Assert(t, err != nil)
|
||||||
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessPatches_AddPathDoesntExist_ContinueOnError(t *testing.T) {
|
||||||
|
patch := makeAddIsMutatedLabelPatch()
|
||||||
|
patch.Path = "/metadata/additional/is-mutated"
|
||||||
|
patches := []types.PolicyPatch{patch}
|
||||||
|
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueAlways)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessPatches_RemovePathDoesntExist_StopOnError(t *testing.T) {
|
||||||
|
patch := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||||
|
patches := []types.PolicyPatch{patch}
|
||||||
|
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsStopOnError)
|
||||||
|
assert.Assert(t, err != nil)
|
||||||
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_EmptyResult(t *testing.T) {
|
||||||
|
patch1 := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||||
|
patch2 := types.PolicyPatch{Path: "/spec/labels/label3", Operation: "add", Value: "label3Value"}
|
||||||
|
patches := []types.PolicyPatch{patch1, patch2}
|
||||||
|
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueAlways)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_NotEmptyResult(t *testing.T) {
|
||||||
|
patch1 := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||||
|
patch2 := types.PolicyPatch{Path: "/spec/labels/label2", Operation: "remove", Value: "label2Value"}
|
||||||
|
patch3 := types.PolicyPatch{Path: "/metadata/labels/label3", Operation: "add", Value: "label3Value"}
|
||||||
|
patches := []types.PolicyPatch{patch1, patch2, patch3}
|
||||||
|
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueAlways)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Assert(t, len(patchesBytes) == 1)
|
||||||
|
assertEqStringAndData(t, `{"path":"/metadata/labels/label3","op":"add","value":"label3Value"}`, patchesBytes[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessPatches_RemovePathDoesntExist_IgnoreRemoveFailures_EmptyResult(t *testing.T) {
|
||||||
|
patch := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||||
|
patches := []types.PolicyPatch{patch}
|
||||||
|
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueOnRemoveFailure)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessPatches_RemovePathDoesntExist_IgnoreRemoveFailures_NotEmptyResult(t *testing.T) {
|
||||||
|
patch1 := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||||
|
patch2 := types.PolicyPatch{Path: "/metadata/labels/label2", Operation: "add", Value: "label2Value"}
|
||||||
|
patches := []types.PolicyPatch{patch1, patch2}
|
||||||
|
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueOnRemoveFailure)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Assert(t, len(patchesBytes) == 1)
|
||||||
|
assertEqStringAndData(t, `{"path":"/metadata/labels/label2","op":"add","value":"label2Value"}`, patchesBytes[0])
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue