mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-29 10:55:05 +00:00
move mutation to subpackage pkg/engine/mutate
This commit is contained in:
parent
3cf9141f4d
commit
472fa29fce
22 changed files with 283 additions and 269 deletions
|
@ -1,4 +1,4 @@
|
|||
package engine
|
||||
package mutate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -18,15 +18,16 @@ import (
|
|||
"github.com/nirmata/kyverno/pkg/engine/anchor"
|
||||
"github.com/nirmata/kyverno/pkg/engine/context"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"github.com/nirmata/kyverno/pkg/engine/variables"
|
||||
)
|
||||
|
||||
// processOverlay processes validation patterns on the resource
|
||||
func processOverlay(ctx context.EvalInterface, rule kyverno.Rule, resource unstructured.Unstructured) (resp response.RuleResponse, patchedResource unstructured.Unstructured) {
|
||||
func ProcessOverlay(ctx context.EvalInterface, rule kyverno.Rule, resource unstructured.Unstructured) (resp response.RuleResponse, patchedResource unstructured.Unstructured) {
|
||||
startTime := time.Now()
|
||||
glog.V(4).Infof("started applying overlay rule %q (%v)", rule.Name, startTime)
|
||||
resp.Name = rule.Name
|
||||
resp.Type = Mutation.String()
|
||||
resp.Type = utils.Mutation.String()
|
||||
defer func() {
|
||||
resp.RuleStats.ProcessingTime = time.Since(startTime)
|
||||
glog.V(4).Infof("finished applying overlay rule %q (%v)", resp.Name, resp.RuleStats.ProcessingTime)
|
||||
|
@ -83,10 +84,10 @@ func processOverlay(ctx context.EvalInterface, rule kyverno.Rule, resource unstr
|
|||
}
|
||||
|
||||
var patchResource []byte
|
||||
patchResource, err = ApplyPatches(resourceRaw, patches)
|
||||
patchResource, err = utils.ApplyPatches(resourceRaw, patches)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to apply JSON patches: %v", err)
|
||||
glog.V(2).Infof("%s, patches=%s", msg, string(JoinPatches(patches)))
|
||||
glog.V(2).Infof("%s, patches=%s", msg, string(utils.JoinPatches(patches)))
|
||||
resp.Success = false
|
||||
resp.Message = msg
|
||||
return resp, resource
|
||||
|
@ -285,7 +286,7 @@ func applyOverlayToArrayOfMaps(resource, overlay []interface{}, path string) ([]
|
|||
lastElementIdx := len(resource)
|
||||
for i, overlayElement := range overlay {
|
||||
typedOverlay := overlayElement.(map[string]interface{})
|
||||
anchors := getAnchorsFromMap(typedOverlay)
|
||||
anchors := utils.GetAnchorsFromMap(typedOverlay)
|
||||
|
||||
if len(anchors) > 0 {
|
||||
// If we have anchors - choose corresponding resource element and mutate it
|
||||
|
@ -430,7 +431,7 @@ func removeAnchroFromMap(overlay map[string]interface{}) map[string]interface{}
|
|||
func hasOnlyAnchors(overlay interface{}) bool {
|
||||
switch typed := overlay.(type) {
|
||||
case map[string]interface{}:
|
||||
if anchors := getAnchorsFromMap(typed); len(anchors) == len(typed) {
|
||||
if anchors := utils.GetAnchorsFromMap(typed); len(anchors) == len(typed) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -456,7 +457,7 @@ func hasOnlyAnchors(overlay interface{}) bool {
|
|||
func hasNestedAnchors(overlay interface{}) bool {
|
||||
switch typed := overlay.(type) {
|
||||
case map[string]interface{}:
|
||||
if anchors := getAnchorsFromMap(typed); len(anchors) > 0 {
|
||||
if anchors := utils.GetAnchorsFromMap(typed); len(anchors) > 0 {
|
||||
return true
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package engine
|
||||
package mutate
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -1,4 +1,4 @@
|
|||
package engine
|
||||
package mutate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
|
@ -1,4 +1,4 @@
|
|||
package engine
|
||||
package mutate
|
||||
|
||||
import "fmt"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package engine
|
||||
package mutate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
|
@ -69,7 +70,7 @@ func TestProcessOverlayPatches_NestedListWithAnchor(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{}))
|
||||
assert.Assert(t, patches != nil)
|
||||
|
||||
patch := JoinPatches(patches)
|
||||
patch := utils.JoinPatches(patches)
|
||||
decoded, err := jsonpatch.DecodePatch(patch)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, decoded != nil)
|
||||
|
@ -169,7 +170,7 @@ func TestProcessOverlayPatches_InsertIntoArray(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{}))
|
||||
assert.Assert(t, patches != nil)
|
||||
|
||||
patch := JoinPatches(patches)
|
||||
patch := utils.JoinPatches(patches)
|
||||
|
||||
decoded, err := jsonpatch.DecodePatch(patch)
|
||||
assert.NilError(t, err)
|
||||
|
@ -290,7 +291,7 @@ func TestProcessOverlayPatches_TestInsertToArray(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{}))
|
||||
assert.Assert(t, patches != nil)
|
||||
|
||||
patch := JoinPatches(patches)
|
||||
patch := utils.JoinPatches(patches)
|
||||
|
||||
decoded, err := jsonpatch.DecodePatch(patch)
|
||||
assert.NilError(t, err)
|
||||
|
@ -373,7 +374,7 @@ func TestProcessOverlayPatches_ImagePullPolicy(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{}))
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err := ApplyPatches(resourceRaw, patches)
|
||||
doc, err := utils.ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
expectedResult := []byte(`{
|
||||
"apiVersion":"apps/v1",
|
||||
|
@ -461,7 +462,7 @@ func TestProcessOverlayPatches_ImagePullPolicy(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(err, overlayError{}))
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err = ApplyPatches(resourceRaw, patches)
|
||||
doc, err = utils.ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
|
||||
compareJSONAsMap(t, expectedResult, doc)
|
||||
|
@ -526,7 +527,7 @@ func TestProcessOverlayPatches_AddingAnchor(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{}))
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err := ApplyPatches(resourceRaw, patches)
|
||||
doc, err := utils.ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
expectedResult := []byte(`{
|
||||
"metadata":{
|
||||
|
@ -611,7 +612,7 @@ func TestProcessOverlayPatches_AddingAnchorInsideListElement(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{}))
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err := ApplyPatches(resourceRaw, patches)
|
||||
doc, err := utils.ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
expectedResult := []byte(`
|
||||
{
|
||||
|
@ -689,7 +690,7 @@ func TestProcessOverlayPatches_AddingAnchorInsideListElement(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(err, overlayError{}))
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err = ApplyPatches(resourceRaw, patches)
|
||||
doc, err = utils.ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
|
||||
compareJSONAsMap(t, expectedResult, doc)
|
||||
|
@ -753,7 +754,7 @@ func TestProcessOverlayPatches_anchorOnPeer(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{}))
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err := ApplyPatches(resourceRaw, patches)
|
||||
doc, err := utils.ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
expectedResult := []byte(` {
|
||||
"apiVersion":"v1",
|
||||
|
@ -892,7 +893,7 @@ func TestProcessOverlayPatches_insertWithCondition(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{}))
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err := ApplyPatches(resourceRaw, patches)
|
||||
doc, err := utils.ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
expectedResult := []byte(`{
|
||||
"apiVersion": "apps/v1",
|
||||
|
@ -1003,7 +1004,7 @@ func TestProcessOverlayPatches_InsertIfNotPresentWithConditions(t *testing.T) {
|
|||
assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{}))
|
||||
assert.Assert(t, len(patches) != 0)
|
||||
|
||||
doc, err := ApplyPatches(resourceRaw, patches)
|
||||
doc, err := utils.ApplyPatches(resourceRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expectedResult := []byte(`
|
||||
|
@ -1154,5 +1155,5 @@ func TestApplyOverlay_ConditionOnArray(t *testing.T) {
|
|||
]`)
|
||||
p, err := applyOverlay(resource, overlay, "/")
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, string(JoinPatches(p)) == string(expectedPatches))
|
||||
assert.Assert(t, string(utils.JoinPatches(p)) == string(expectedPatches))
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package engine
|
||||
package mutate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -6,72 +6,24 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// JoinPatches joins array of serialized JSON patches to the single JSONPatch array
|
||||
func JoinPatches(patches [][]byte) []byte {
|
||||
var result []byte
|
||||
if len(patches) == 0 {
|
||||
return result
|
||||
}
|
||||
|
||||
result = append(result, []byte("[\n")...)
|
||||
for index, patch := range patches {
|
||||
result = append(result, patch...)
|
||||
if index != len(patches)-1 {
|
||||
result = append(result, []byte(",\n")...)
|
||||
}
|
||||
}
|
||||
result = append(result, []byte("\n]")...)
|
||||
return result
|
||||
}
|
||||
|
||||
// applyPatch applies patch for resource, returns patched resource.
|
||||
func applyPatch(resource []byte, patchRaw []byte) ([]byte, error) {
|
||||
patchesList := [][]byte{patchRaw}
|
||||
return ApplyPatches(resource, patchesList)
|
||||
return utils.ApplyPatches(resource, patchesList)
|
||||
}
|
||||
|
||||
// ApplyPatches patches given resource with given patches and returns patched document
|
||||
func ApplyPatches(resource []byte, patches [][]byte) ([]byte, error) {
|
||||
joinedPatches := JoinPatches(patches)
|
||||
patch, err := jsonpatch.DecodePatch(joinedPatches)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
patchedDocument, err := patch.Apply(resource)
|
||||
if err != nil {
|
||||
return resource, err
|
||||
}
|
||||
return patchedDocument, err
|
||||
}
|
||||
|
||||
//ApplyPatchNew patches given resource with given joined patches
|
||||
func ApplyPatchNew(resource, patch []byte) ([]byte, error) {
|
||||
jsonpatch, err := jsonpatch.DecodePatch(patch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
patchedResource, err := jsonpatch.Apply(resource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return patchedResource, err
|
||||
|
||||
}
|
||||
|
||||
func processPatches(rule kyverno.Rule, resource unstructured.Unstructured) (resp response.RuleResponse, patchedResource unstructured.Unstructured) {
|
||||
func ProcessPatches(rule kyverno.Rule, resource unstructured.Unstructured) (resp response.RuleResponse, patchedResource unstructured.Unstructured) {
|
||||
startTime := time.Now()
|
||||
glog.V(4).Infof("started JSON patch rule %q (%v)", rule.Name, startTime)
|
||||
resp.Name = rule.Name
|
||||
resp.Type = Mutation.String()
|
||||
resp.Type = utils.Mutation.String()
|
||||
defer func() {
|
||||
resp.RuleStats.ProcessingTime = time.Since(startTime)
|
||||
glog.V(4).Infof("finished JSON patch rule %q (%v)", resp.Name, resp.RuleStats.ProcessingTime)
|
|
@ -1,4 +1,4 @@
|
|||
package engine
|
||||
package mutate
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -7,6 +7,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
types "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
)
|
||||
|
||||
const endpointsDocument string = `{
|
||||
|
@ -36,11 +37,11 @@ const endpointsDocument string = `{
|
|||
|
||||
func TestProcessPatches_EmptyPatches(t *testing.T) {
|
||||
var emptyRule = types.Rule{}
|
||||
resourceUnstructured, err := ConvertToUnstructured([]byte(endpointsDocument))
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured([]byte(endpointsDocument))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rr, _ := processPatches(emptyRule, *resourceUnstructured)
|
||||
rr, _ := ProcessPatches(emptyRule, *resourceUnstructured)
|
||||
assert.Check(t, rr.Success)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
}
|
||||
|
@ -69,14 +70,14 @@ func makeRuleWithPatches(patches []types.Patch) types.Rule {
|
|||
|
||||
func TestProcessPatches_EmptyDocument(t *testing.T) {
|
||||
rule := makeRuleWithPatch(makeAddIsMutatedLabelPatch())
|
||||
rr, _ := processPatches(rule, unstructured.Unstructured{})
|
||||
rr, _ := ProcessPatches(rule, unstructured.Unstructured{})
|
||||
assert.Assert(t, !rr.Success)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
}
|
||||
|
||||
func TestProcessPatches_AllEmpty(t *testing.T) {
|
||||
emptyRule := types.Rule{}
|
||||
rr, _ := processPatches(emptyRule, unstructured.Unstructured{})
|
||||
rr, _ := ProcessPatches(emptyRule, unstructured.Unstructured{})
|
||||
assert.Check(t, !rr.Success)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
}
|
||||
|
@ -85,11 +86,11 @@ func TestProcessPatches_AddPathDoesntExist(t *testing.T) {
|
|||
patch := makeAddIsMutatedLabelPatch()
|
||||
patch.Path = "/metadata/additional/is-mutated"
|
||||
rule := makeRuleWithPatch(patch)
|
||||
resourceUnstructured, err := ConvertToUnstructured([]byte(endpointsDocument))
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured([]byte(endpointsDocument))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rr, _ := processPatches(rule, *resourceUnstructured)
|
||||
rr, _ := ProcessPatches(rule, *resourceUnstructured)
|
||||
assert.Check(t, !rr.Success)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
}
|
||||
|
@ -97,11 +98,11 @@ func TestProcessPatches_AddPathDoesntExist(t *testing.T) {
|
|||
func TestProcessPatches_RemovePathDoesntExist(t *testing.T) {
|
||||
patch := types.Patch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||
rule := makeRuleWithPatch(patch)
|
||||
resourceUnstructured, err := ConvertToUnstructured([]byte(endpointsDocument))
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured([]byte(endpointsDocument))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rr, _ := processPatches(rule, *resourceUnstructured)
|
||||
rr, _ := ProcessPatches(rule, *resourceUnstructured)
|
||||
assert.Check(t, rr.Success)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
}
|
||||
|
@ -110,11 +111,11 @@ func TestProcessPatches_AddAndRemovePathsDontExist_EmptyResult(t *testing.T) {
|
|||
patch1 := types.Patch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||
patch2 := types.Patch{Path: "/spec/labels/label3", Operation: "add", Value: "label3Value"}
|
||||
rule := makeRuleWithPatches([]types.Patch{patch1, patch2})
|
||||
resourceUnstructured, err := ConvertToUnstructured([]byte(endpointsDocument))
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured([]byte(endpointsDocument))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rr, _ := processPatches(rule, *resourceUnstructured)
|
||||
rr, _ := ProcessPatches(rule, *resourceUnstructured)
|
||||
assert.Check(t, !rr.Success)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
}
|
||||
|
@ -124,11 +125,11 @@ func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_NotEmptyResul
|
|||
patch2 := types.Patch{Path: "/spec/labels/label2", Operation: "remove", Value: "label2Value"}
|
||||
patch3 := types.Patch{Path: "/metadata/labels/label3", Operation: "add", Value: "label3Value"}
|
||||
rule := makeRuleWithPatches([]types.Patch{patch1, patch2, patch3})
|
||||
resourceUnstructured, err := ConvertToUnstructured([]byte(endpointsDocument))
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured([]byte(endpointsDocument))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rr, _ := processPatches(rule, *resourceUnstructured)
|
||||
rr, _ := ProcessPatches(rule, *resourceUnstructured)
|
||||
assert.Check(t, rr.Success)
|
||||
assert.Assert(t, len(rr.Patches) != 0)
|
||||
assertEqStringAndData(t, `{"path":"/metadata/labels/label3","op":"add","value":"label3Value"}`, rr.Patches[0])
|
||||
|
@ -137,11 +138,11 @@ func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_NotEmptyResul
|
|||
func TestProcessPatches_RemovePathDoesntExist_EmptyResult(t *testing.T) {
|
||||
patch := types.Patch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||
rule := makeRuleWithPatch(patch)
|
||||
resourceUnstructured, err := ConvertToUnstructured([]byte(endpointsDocument))
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured([]byte(endpointsDocument))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rr, _ := processPatches(rule, *resourceUnstructured)
|
||||
rr, _ := ProcessPatches(rule, *resourceUnstructured)
|
||||
assert.Check(t, rr.Success)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
}
|
||||
|
@ -150,11 +151,11 @@ func TestProcessPatches_RemovePathDoesntExist_NotEmptyResult(t *testing.T) {
|
|||
patch1 := types.Patch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||
patch2 := types.Patch{Path: "/metadata/labels/label2", Operation: "add", Value: "label2Value"}
|
||||
rule := makeRuleWithPatches([]types.Patch{patch1, patch2})
|
||||
resourceUnstructured, err := ConvertToUnstructured([]byte(endpointsDocument))
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured([]byte(endpointsDocument))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rr, _ := processPatches(rule, *resourceUnstructured)
|
||||
rr, _ := ProcessPatches(rule, *resourceUnstructured)
|
||||
assert.Check(t, rr.Success)
|
||||
assert.Assert(t, len(rr.Patches) == 1)
|
||||
assertEqStringAndData(t, `{"path":"/metadata/labels/label2","op":"add","value":"label2Value"}`, rr.Patches[0])
|
47
pkg/engine/mutate/utils.go
Normal file
47
pkg/engine/mutate/utils.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package mutate
|
||||
|
||||
import (
|
||||
"github.com/nirmata/kyverno/pkg/engine/anchor"
|
||||
)
|
||||
|
||||
// removeAnchor remove special characters around anchored key
|
||||
func removeAnchor(key string) string {
|
||||
if anchor.IsConditionAnchor(key) {
|
||||
return key[1 : len(key)-1]
|
||||
}
|
||||
|
||||
if anchor.IsExistanceAnchor(key) || anchor.IsAddingAnchor(key) || anchor.IsEqualityAnchor(key) || anchor.IsNegationAnchor(key) {
|
||||
return key[2 : len(key)-1]
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
func getRawKeyIfWrappedWithAttributes(str string) string {
|
||||
if len(str) < 2 {
|
||||
return str
|
||||
}
|
||||
|
||||
if str[0] == '(' && str[len(str)-1] == ')' {
|
||||
return str[1 : len(str)-1]
|
||||
} else if (str[0] == '$' || str[0] == '^' || str[0] == '+' || str[0] == '=') && (str[1] == '(' && str[len(str)-1] == ')') {
|
||||
return str[2 : len(str)-1]
|
||||
} else {
|
||||
return str
|
||||
}
|
||||
}
|
||||
|
||||
// getAnchorAndElementsFromMap gets the condition anchor map and resource map without anchor
|
||||
func getAnchorAndElementsFromMap(anchorsMap map[string]interface{}) (map[string]interface{}, map[string]interface{}) {
|
||||
anchors := make(map[string]interface{})
|
||||
elementsWithoutanchor := make(map[string]interface{})
|
||||
for key, value := range anchorsMap {
|
||||
if anchor.IsConditionAnchor(key) {
|
||||
anchors[key] = value
|
||||
} else if !anchor.IsAddingAnchor(key) {
|
||||
elementsWithoutanchor[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return anchors, elementsWithoutanchor
|
||||
}
|
19
pkg/engine/mutate/utils_test.go
Normal file
19
pkg/engine/mutate/utils_test.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package mutate
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func TestRemoveAnchor_ConditionAnchor(t *testing.T) {
|
||||
assert.Equal(t, removeAnchor("(abc)"), "abc")
|
||||
}
|
||||
|
||||
func TestRemoveAnchor_ExistanceAnchor(t *testing.T) {
|
||||
assert.Equal(t, removeAnchor("^(abc)"), "abc")
|
||||
}
|
||||
|
||||
func TestRemoveAnchor_EmptyExistanceAnchor(t *testing.T) {
|
||||
assert.Equal(t, removeAnchor("^()"), "")
|
||||
}
|
|
@ -7,9 +7,10 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/mutate"
|
||||
"github.com/nirmata/kyverno/pkg/engine/rbac"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"github.com/nirmata/kyverno/pkg/engine/variables"
|
||||
"github.com/nirmata/kyverno/pkg/engine/rbac"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -80,7 +81,7 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
|||
// Process Overlay
|
||||
if rule.Mutation.Overlay != nil {
|
||||
var ruleResponse response.RuleResponse
|
||||
ruleResponse, patchedResource = processOverlay(ctx, rule, patchedResource)
|
||||
ruleResponse, patchedResource = mutate.ProcessOverlay(ctx, rule, patchedResource)
|
||||
if ruleResponse.Success == true && ruleResponse.Patches == nil {
|
||||
// overlay pattern does not match the resource conditions
|
||||
glog.V(4).Infof(ruleResponse.Message)
|
||||
|
@ -96,7 +97,7 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
|||
// Process Patches
|
||||
if rule.Mutation.Patches != nil {
|
||||
var ruleResponse response.RuleResponse
|
||||
ruleResponse, patchedResource = processPatches(rule, patchedResource)
|
||||
ruleResponse, patchedResource = mutate.ProcessPatches(rule, patchedResource)
|
||||
glog.Infof("Mutate patches in rule '%s' successfully applied on %s/%s/%s", rule.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName())
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse)
|
||||
incrementAppliedRuleCount()
|
||||
|
@ -110,7 +111,7 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
|||
|
||||
if strings.Contains(PodControllers, resource.GetKind()) {
|
||||
var ruleResponse response.RuleResponse
|
||||
ruleResponse, patchedResource = processOverlay(ctx, podTemplateRule, patchedResource)
|
||||
ruleResponse, patchedResource = mutate.ProcessOverlay(ctx, podTemplateRule, patchedResource)
|
||||
if !ruleResponse.Success {
|
||||
glog.Errorf("Failed to insert annotation to podTemplate of %s/%s/%s: %s", resource.GetKind(), resource.GetNamespace(), resource.GetName(), ruleResponse.Message)
|
||||
continue
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/context"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
|
@ -67,7 +68,7 @@ func Test_VariableSubstitutionOverlay(t *testing.T) {
|
|||
|
||||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
ctx := context.NewContext()
|
||||
ctx.AddResource(rawResource)
|
||||
|
|
|
@ -350,7 +350,6 @@ func validatePattern(patternElement interface{}, path string, supportedAnchors [
|
|||
default:
|
||||
return path, fmt.Errorf("Validation rule failed at '%s', pattern contains unknown type", path)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func validateMap(patternMap map[string]interface{}, path string, supportedAnchors []anchor.IsAnchor) (string, error) {
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/anchor"
|
||||
"github.com/nirmata/kyverno/pkg/engine/operator"
|
||||
"github.com/nirmata/kyverno/pkg/utils"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -208,44 +207,6 @@ func ParseNamespaceFromObject(bytes []byte) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// getAnchorsFromMap gets the conditional anchor map
|
||||
func getAnchorsFromMap(anchorsMap map[string]interface{}) map[string]interface{} {
|
||||
result := make(map[string]interface{})
|
||||
|
||||
for key, value := range anchorsMap {
|
||||
if anchor.IsConditionAnchor(key) {
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// getAnchorAndElementsFromMap gets the condition anchor map and resource map without anchor
|
||||
func getAnchorAndElementsFromMap(anchorsMap map[string]interface{}) (map[string]interface{}, map[string]interface{}) {
|
||||
anchors := make(map[string]interface{})
|
||||
elementsWithoutanchor := make(map[string]interface{})
|
||||
for key, value := range anchorsMap {
|
||||
if anchor.IsConditionAnchor(key) {
|
||||
anchors[key] = value
|
||||
} else if !anchor.IsAddingAnchor(key) {
|
||||
elementsWithoutanchor[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return anchors, elementsWithoutanchor
|
||||
}
|
||||
|
||||
func getAnchorFromMap(anchorsMap map[string]interface{}) (string, interface{}) {
|
||||
for key, value := range anchorsMap {
|
||||
if anchor.IsConditionAnchor(key) || anchor.IsExistanceAnchor(key) {
|
||||
return key, value
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func findKind(kinds []string, kindGVK string) bool {
|
||||
for _, kind := range kinds {
|
||||
if kind == kindGVK {
|
||||
|
@ -255,28 +216,6 @@ func findKind(kinds []string, kindGVK string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// func isConditionAnchor(str string) bool {
|
||||
// if len(str) < 2 {
|
||||
// return false
|
||||
// }
|
||||
|
||||
// return (str[0] == '(' && str[len(str)-1] == ')')
|
||||
// }
|
||||
|
||||
func getRawKeyIfWrappedWithAttributes(str string) string {
|
||||
if len(str) < 2 {
|
||||
return str
|
||||
}
|
||||
|
||||
if str[0] == '(' && str[len(str)-1] == ')' {
|
||||
return str[1 : len(str)-1]
|
||||
} else if (str[0] == '$' || str[0] == '^' || str[0] == '+' || str[0] == '=') && (str[1] == '(' && str[len(str)-1] == ')') {
|
||||
return str[2 : len(str)-1]
|
||||
} else {
|
||||
return str
|
||||
}
|
||||
}
|
||||
|
||||
func isStringIsReference(str string) bool {
|
||||
if len(str) < len(operator.ReferenceSign) {
|
||||
return false
|
||||
|
@ -285,48 +224,7 @@ func isStringIsReference(str string) bool {
|
|||
return str[0] == '$' && str[1] == '(' && str[len(str)-1] == ')'
|
||||
}
|
||||
|
||||
// removeAnchor remove special characters around anchored key
|
||||
func removeAnchor(key string) string {
|
||||
if anchor.IsConditionAnchor(key) {
|
||||
return key[1 : len(key)-1]
|
||||
}
|
||||
|
||||
if anchor.IsExistanceAnchor(key) || anchor.IsAddingAnchor(key) || anchor.IsEqualityAnchor(key) || anchor.IsNegationAnchor(key) {
|
||||
return key[2 : len(key)-1]
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
type resourceInfo struct {
|
||||
Resource unstructured.Unstructured
|
||||
Gvk *metav1.GroupVersionKind
|
||||
}
|
||||
|
||||
func ConvertToUnstructured(data []byte) (*unstructured.Unstructured, error) {
|
||||
resource := &unstructured.Unstructured{}
|
||||
err := resource.UnmarshalJSON(data)
|
||||
if err != nil {
|
||||
glog.V(4).Infof("failed to unmarshall resource: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
type RuleType int
|
||||
|
||||
const (
|
||||
Mutation RuleType = iota
|
||||
Validation
|
||||
Generation
|
||||
All
|
||||
)
|
||||
|
||||
func (ri RuleType) String() string {
|
||||
return [...]string{
|
||||
"Mutation",
|
||||
"Validation",
|
||||
"Generation",
|
||||
"All",
|
||||
}[ri]
|
||||
}
|
||||
|
|
95
pkg/engine/utils/utils.go
Normal file
95
pkg/engine/utils/utils.go
Normal file
|
@ -0,0 +1,95 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"github.com/nirmata/kyverno/pkg/engine/anchor"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
type RuleType int
|
||||
|
||||
const (
|
||||
Mutation RuleType = iota
|
||||
Validation
|
||||
Generation
|
||||
All
|
||||
)
|
||||
|
||||
func (ri RuleType) String() string {
|
||||
return [...]string{
|
||||
"Mutation",
|
||||
"Validation",
|
||||
"Generation",
|
||||
"All",
|
||||
}[ri]
|
||||
}
|
||||
|
||||
// ApplyPatches patches given resource with given patches and returns patched document
|
||||
func ApplyPatches(resource []byte, patches [][]byte) ([]byte, error) {
|
||||
joinedPatches := JoinPatches(patches)
|
||||
patch, err := jsonpatch.DecodePatch(joinedPatches)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
patchedDocument, err := patch.Apply(resource)
|
||||
if err != nil {
|
||||
return resource, err
|
||||
}
|
||||
return patchedDocument, err
|
||||
}
|
||||
|
||||
//ApplyPatchNew patches given resource with given joined patches
|
||||
func ApplyPatchNew(resource, patch []byte) ([]byte, error) {
|
||||
jsonpatch, err := jsonpatch.DecodePatch(patch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
patchedResource, err := jsonpatch.Apply(resource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return patchedResource, err
|
||||
|
||||
}
|
||||
|
||||
// JoinPatches joins array of serialized JSON patches to the single JSONPatch array
|
||||
func JoinPatches(patches [][]byte) []byte {
|
||||
var result []byte
|
||||
if len(patches) == 0 {
|
||||
return result
|
||||
}
|
||||
|
||||
result = append(result, []byte("[\n")...)
|
||||
for index, patch := range patches {
|
||||
result = append(result, patch...)
|
||||
if index != len(patches)-1 {
|
||||
result = append(result, []byte(",\n")...)
|
||||
}
|
||||
}
|
||||
result = append(result, []byte("\n]")...)
|
||||
return result
|
||||
}
|
||||
|
||||
func ConvertToUnstructured(data []byte) (*unstructured.Unstructured, error) {
|
||||
resource := &unstructured.Unstructured{}
|
||||
err := resource.UnmarshalJSON(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
// getAnchorsFromMap gets the conditional anchor map
|
||||
func GetAnchorsFromMap(anchorsMap map[string]interface{}) map[string]interface{} {
|
||||
result := make(map[string]interface{})
|
||||
|
||||
for key, value := range anchorsMap {
|
||||
if anchor.IsConditionAnchor(key) {
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
26
pkg/engine/utils/utils_test.go
Normal file
26
pkg/engine/utils/utils_test.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package utils
|
||||
|
||||
import(
|
||||
"testing"
|
||||
"encoding/json"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func TestGetAnchorsFromMap_ThereAreNoAnchors(t *testing.T) {
|
||||
rawMap := []byte(`{
|
||||
"name":"nirmata-*",
|
||||
"notAnchor1":123,
|
||||
"namespace":"kube-?olicy",
|
||||
"notAnchor2":"sample-text",
|
||||
"object":{
|
||||
"key1":"value1",
|
||||
"(key2)":"value2"
|
||||
}
|
||||
}`)
|
||||
|
||||
var unmarshalled map[string]interface{}
|
||||
json.Unmarshal(rawMap, &unmarshalled)
|
||||
|
||||
actualMap := GetAnchorsFromMap(unmarshalled)
|
||||
assert.Assert(t, len(actualMap) == 0)
|
||||
}
|
|
@ -1,33 +1,14 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestGetAnchorsFromMap_ThereAreNoAnchors(t *testing.T) {
|
||||
rawMap := []byte(`{
|
||||
"name":"nirmata-*",
|
||||
"notAnchor1":123,
|
||||
"namespace":"kube-?olicy",
|
||||
"notAnchor2":"sample-text",
|
||||
"object":{
|
||||
"key1":"value1",
|
||||
"(key2)":"value2"
|
||||
}
|
||||
}`)
|
||||
|
||||
var unmarshalled map[string]interface{}
|
||||
json.Unmarshal(rawMap, &unmarshalled)
|
||||
|
||||
actualMap := getAnchorsFromMap(unmarshalled)
|
||||
assert.Assert(t, len(actualMap) == 0)
|
||||
}
|
||||
|
||||
// Match multiple kinds
|
||||
func TestResourceDescriptionMatch_MultipleKind(t *testing.T) {
|
||||
rawResource := []byte(`{
|
||||
|
@ -68,7 +49,7 @@ func TestResourceDescriptionMatch_MultipleKind(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}`)
|
||||
resource, err := ConvertToUnstructured(rawResource)
|
||||
resource, err := utils.ConvertToUnstructured(rawResource)
|
||||
if err != nil {
|
||||
t.Errorf("unable to convert raw resource to unstructured: %v", err)
|
||||
|
||||
|
@ -125,7 +106,7 @@ func TestResourceDescriptionMatch_Name(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}`)
|
||||
resource, err := ConvertToUnstructured(rawResource)
|
||||
resource, err := utils.ConvertToUnstructured(rawResource)
|
||||
if err != nil {
|
||||
t.Errorf("unable to convert raw resource to unstructured: %v", err)
|
||||
|
||||
|
@ -183,7 +164,7 @@ func TestResourceDescriptionMatch_Name_Regex(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}`)
|
||||
resource, err := ConvertToUnstructured(rawResource)
|
||||
resource, err := utils.ConvertToUnstructured(rawResource)
|
||||
if err != nil {
|
||||
t.Errorf("unable to convert raw resource to unstructured: %v", err)
|
||||
|
||||
|
@ -241,7 +222,7 @@ func TestResourceDescriptionMatch_Label_Expression_NotMatch(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}`)
|
||||
resource, err := ConvertToUnstructured(rawResource)
|
||||
resource, err := utils.ConvertToUnstructured(rawResource)
|
||||
if err != nil {
|
||||
t.Errorf("unable to convert raw resource to unstructured: %v", err)
|
||||
|
||||
|
@ -307,7 +288,7 @@ func TestResourceDescriptionMatch_Label_Expression_Match(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}`)
|
||||
resource, err := ConvertToUnstructured(rawResource)
|
||||
resource, err := utils.ConvertToUnstructured(rawResource)
|
||||
if err != nil {
|
||||
t.Errorf("unable to convert raw resource to unstructured: %v", err)
|
||||
|
||||
|
@ -375,7 +356,7 @@ func TestResourceDescriptionExclude_Label_Expression_Match(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}`)
|
||||
resource, err := ConvertToUnstructured(rawResource)
|
||||
resource, err := utils.ConvertToUnstructured(rawResource)
|
||||
if err != nil {
|
||||
t.Errorf("unable to convert raw resource to unstructured: %v", err)
|
||||
|
||||
|
@ -411,15 +392,3 @@ func TestResourceDescriptionExclude_Label_Expression_Match(t *testing.T) {
|
|||
|
||||
assert.Assert(t, !MatchesResourceDescription(*resource, rule))
|
||||
}
|
||||
|
||||
func TestRemoveAnchor_ConditionAnchor(t *testing.T) {
|
||||
assert.Equal(t, removeAnchor("(abc)"), "abc")
|
||||
}
|
||||
|
||||
func TestRemoveAnchor_ExistanceAnchor(t *testing.T) {
|
||||
assert.Equal(t, removeAnchor("^(abc)"), "abc")
|
||||
}
|
||||
|
||||
func TestRemoveAnchor_EmptyExistanceAnchor(t *testing.T) {
|
||||
assert.Equal(t, removeAnchor("^()"), "")
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/nirmata/kyverno/pkg/engine/context"
|
||||
"github.com/nirmata/kyverno/pkg/engine/rbac"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"github.com/nirmata/kyverno/pkg/engine/validate"
|
||||
"github.com/nirmata/kyverno/pkg/engine/variables"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -168,7 +169,7 @@ func validatePatterns(ctx context.EvalInterface, resource unstructured.Unstructu
|
|||
startTime := time.Now()
|
||||
glog.V(4).Infof("started applying validation rule %q (%v)", rule.Name, startTime)
|
||||
resp.Name = rule.Name
|
||||
resp.Type = Validation.String()
|
||||
resp.Type = utils.Validation.String()
|
||||
defer func() {
|
||||
resp.RuleStats.ProcessingTime = time.Since(startTime)
|
||||
glog.V(4).Infof("finished applying validation rule %q (%v)", resp.Name, resp.RuleStats.ProcessingTime)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
|
@ -23,7 +24,7 @@ func TestGetAnchorsFromMap_ThereAreAnchors(t *testing.T) {
|
|||
var unmarshalled map[string]interface{}
|
||||
json.Unmarshal(rawMap, &unmarshalled)
|
||||
|
||||
actualMap := getAnchorsFromMap(unmarshalled)
|
||||
actualMap := utils.GetAnchorsFromMap(unmarshalled)
|
||||
assert.Equal(t, len(actualMap), 2)
|
||||
assert.Equal(t, actualMap["(name)"].(string), "nirmata-*")
|
||||
assert.Equal(t, actualMap["(namespace)"].(string), "kube-?olicy")
|
||||
|
@ -115,7 +116,7 @@ func TestValidate_ServiceTest(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
|
@ -213,7 +214,7 @@ func TestValidate_MapHasFloats(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
assert.Assert(t, len(er.PolicyResponse.Rules) == 0)
|
||||
|
@ -304,7 +305,7 @@ func TestValidate_image_tag_fail(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
msgs := []string{
|
||||
"Validation rule 'validate-tag' succeeded.",
|
||||
|
@ -402,7 +403,7 @@ func TestValidate_image_tag_pass(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
msgs := []string{
|
||||
"Validation rule 'validate-tag' succeeded.",
|
||||
|
@ -479,7 +480,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation error: A namespace is required; Validation rule check-default-namespace anyPattern[0] failed at path /metadata/namespace/.;Validation rule check-default-namespace anyPattern[1] failed at path /metadata/namespace/."}
|
||||
|
@ -560,7 +561,7 @@ func TestValidate_host_network_port(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation error: Host network and port are not allowed; Validation rule 'validate-host-network-port' failed at path '/spec/containers/0/ports/0/hostPort/'"}
|
||||
|
@ -649,7 +650,7 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'validate-host-path' succeeded."}
|
||||
|
@ -737,7 +738,7 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation error: Host path '/var/lib/' is not allowed; Validation rule 'validate-host-path' failed at path '/spec/volumes/0/hostPath/path/'"}
|
||||
|
@ -806,7 +807,7 @@ func TestValidate_anchor_map_notfound(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'pod rule 2' succeeded."}
|
||||
|
@ -878,7 +879,7 @@ func TestValidate_anchor_map_found_valid(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'pod rule 2' succeeded."}
|
||||
|
@ -950,7 +951,7 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation error: pod: validate run as non root user; Validation rule 'pod rule 2' failed at path '/spec/securityContext/runAsNonRoot/'"}
|
||||
|
@ -1024,7 +1025,7 @@ func TestValidate_AnchorList_pass(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'pod image rule' succeeded."}
|
||||
|
@ -1098,7 +1099,7 @@ func TestValidate_AnchorList_fail(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
// msgs := []string{"Validation rule 'pod image rule' failed at '/spec/containers/1/name/' for resource Pod//myapp-pod."}
|
||||
|
@ -1172,7 +1173,7 @@ func TestValidate_existenceAnchor_fail(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
// msgs := []string{"Validation rule 'pod image rule' failed at '/spec/containers/' for resource Pod//myapp-pod."}
|
||||
|
@ -1247,7 +1248,7 @@ func TestValidate_existenceAnchor_pass(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'pod image rule' succeeded."}
|
||||
|
@ -1334,7 +1335,7 @@ func TestValidate_negationAnchor_deny(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation error: Host path is not allowed; Validation rule 'validate-host-path' failed at path '/spec/volumes/0/hostPath/'"}
|
||||
|
@ -1420,7 +1421,7 @@ func TestValidate_negationAnchor_pass(t *testing.T) {
|
|||
var policy kyverno.ClusterPolicy
|
||||
json.Unmarshal(rawPolicy, &policy)
|
||||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'validate-host-path' succeeded."}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine"
|
||||
engineutils "github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"k8s.io/api/admission/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -95,7 +95,7 @@ func processResourceWithPatches(patch []byte, resource []byte) []byte {
|
|||
return nil
|
||||
}
|
||||
|
||||
resource, err := engine.ApplyPatchNew(resource, patch)
|
||||
resource, err := engineutils.ApplyPatchNew(resource, patch)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to patch resource: %v", err)
|
||||
return nil
|
||||
|
@ -143,7 +143,7 @@ func extractResources(newRaw []byte, request *v1beta1.AdmissionRequest) (unstruc
|
|||
|
||||
// convertResource converts raw bytes to an unstructured object
|
||||
func convertResource(raw []byte, group, version, kind, namespace string) (unstructured.Unstructured, error) {
|
||||
obj, err := engine.ConvertToUnstructured(raw)
|
||||
obj, err := engineutils.ConvertToUnstructured(raw)
|
||||
if err != nil {
|
||||
return unstructured.Unstructured{}, fmt.Errorf("failed to convert raw to unstructured: %v", err)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/nirmata/kyverno/pkg/engine"
|
||||
"github.com/nirmata/kyverno/pkg/engine/context"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"github.com/nirmata/kyverno/pkg/webhooks/generate"
|
||||
v1beta1 "k8s.io/api/admission/v1beta1"
|
||||
)
|
||||
|
@ -14,7 +15,7 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
|||
var engineResponses []response.EngineResponse
|
||||
|
||||
// convert RAW to unstructured
|
||||
resource, err := engine.ConvertToUnstructured(request.Object.Raw)
|
||||
resource, err := utils.ConvertToUnstructured(request.Object.Raw)
|
||||
if err != nil {
|
||||
//TODO: skip applying the admission control ?
|
||||
glog.Errorf("unable to convert raw resource to unstructured: %v", err)
|
||||
|
|
|
@ -3,9 +3,10 @@ package webhooks
|
|||
import (
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
engine "github.com/nirmata/kyverno/pkg/engine"
|
||||
"github.com/nirmata/kyverno/pkg/engine"
|
||||
"github.com/nirmata/kyverno/pkg/engine/context"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
engineutils "github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
policyctr "github.com/nirmata/kyverno/pkg/policy"
|
||||
"github.com/nirmata/kyverno/pkg/utils"
|
||||
v1beta1 "k8s.io/api/admission/v1beta1"
|
||||
|
@ -101,7 +102,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resou
|
|||
|
||||
if isResponseSuccesful(engineResponses) {
|
||||
sendStat(false)
|
||||
patch := engine.JoinPatches(patches)
|
||||
patch := engineutils.JoinPatches(patches)
|
||||
return true, patch, ""
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine"
|
||||
"github.com/nirmata/kyverno/pkg/engine/utils"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
|
@ -31,7 +31,7 @@ func TestGeneratePodControllerRule_NilAnnotation(t *testing.T) {
|
|||
patches, errs := generatePodControllerRule(policy)
|
||||
assert.Assert(t, len(errs) == 0)
|
||||
|
||||
p, err := engine.ApplyPatches(policyRaw, patches)
|
||||
p, err := utils.ApplyPatches(policyRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expectedPolicy := []byte(`{
|
||||
|
@ -83,7 +83,7 @@ func TestGeneratePodControllerRule_ExistOtherAnnotation(t *testing.T) {
|
|||
patches, errs := generatePodControllerRule(policy)
|
||||
assert.Assert(t, len(errs) == 0)
|
||||
|
||||
p, err := engine.ApplyPatches(policyRaw, patches)
|
||||
p, err := utils.ApplyPatches(policyRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expectedPolicy := []byte(`{
|
||||
|
@ -233,7 +233,7 @@ func TestGeneratePodControllerRule(t *testing.T) {
|
|||
patches, errs := generatePodControllerRule(policy)
|
||||
assert.Assert(t, len(errs) == 0)
|
||||
|
||||
p, err := engine.ApplyPatches(policyRaw, patches)
|
||||
p, err := utils.ApplyPatches(policyRaw, patches)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expectPolicy := []byte(`{
|
||||
|
|
Loading…
Add table
Reference in a new issue