Skip to content

Commit

Permalink
fix(json-ctx): overwrite element each iteration (kyverno#10615)
Browse files Browse the repository at this point in the history
Signed-off-by: Khaled Emara <khaled.emara@nirmata.com>
  • Loading branch information
KhaledEmaraDev authored Jul 5, 2024
1 parent ff192f3 commit aafc4fe
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 28 deletions.
36 changes: 18 additions & 18 deletions pkg/engine/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ type Interface interface {
Reset()

// AddJSON merges the json map with context
addJSON(dataMap map[string]interface{}) error
addJSON(dataMap map[string]interface{}, overwriteMaps bool) error
}

// Context stores the data resources as JSON
Expand Down Expand Up @@ -138,8 +138,8 @@ func NewContextFromRaw(jp jmespath.Interface, raw map[string]interface{}) Interf
}

// addJSON merges json data
func (ctx *context) addJSON(dataMap map[string]interface{}) error {
mergeMaps(dataMap, ctx.jsonRaw)
func (ctx *context) addJSON(dataMap map[string]interface{}, overwriteMaps bool) error {
mergeMaps(dataMap, ctx.jsonRaw, overwriteMaps)
return nil
}

Expand All @@ -166,7 +166,7 @@ func (ctx *context) AddRequest(request admissionv1.AdmissionRequest) error {
return err
}

if err := addToContext(ctx, mapObj, "request"); err != nil {
if err := addToContext(ctx, mapObj, false, "request"); err != nil {
return err
}

Expand All @@ -180,7 +180,7 @@ func (ctx *context) AddVariable(key string, value interface{}) error {
if fields, err := reader.Read(); err != nil {
return err
} else {
return addToContext(ctx, value, fields...)
return addToContext(ctx, value, false, fields...)
}
}

Expand All @@ -190,7 +190,7 @@ func (ctx *context) AddContextEntry(name string, dataRaw []byte) error {
logger.Error(err, "failed to unmarshal the resource")
return err
}
return addToContext(ctx, data, name)
return addToContext(ctx, data, false, name)
}

func (ctx *context) ReplaceContextEntry(name string, dataRaw []byte) error {
Expand All @@ -200,34 +200,34 @@ func (ctx *context) ReplaceContextEntry(name string, dataRaw []byte) error {
return err
}
// Adding a nil entry to clean out any existing data in the context with the entry name
if err := addToContext(ctx, nil, name); err != nil {
if err := addToContext(ctx, nil, false, name); err != nil {
logger.Error(err, "unable to replace context entry", "context entry name", name)
return err
}
return addToContext(ctx, data, name)
return addToContext(ctx, data, false, name)
}

// AddResource data at path: request.object
func (ctx *context) AddResource(data map[string]interface{}) error {
clearLeafValue(ctx.jsonRaw, "request", "object")
return addToContext(ctx, data, "request", "object")
return addToContext(ctx, data, false, "request", "object")
}

// AddOldResource data at path: request.oldObject
func (ctx *context) AddOldResource(data map[string]interface{}) error {
clearLeafValue(ctx.jsonRaw, "request", "oldObject")
return addToContext(ctx, data, "request", "oldObject")
return addToContext(ctx, data, false, "request", "oldObject")
}

// AddTargetResource adds data at path: target
func (ctx *context) SetTargetResource(data map[string]interface{}) error {
clearLeafValue(ctx.jsonRaw, "target")
return addToContext(ctx, data, "target")
return addToContext(ctx, data, false, "target")
}

// AddOperation data at path: request.operation
func (ctx *context) AddOperation(data string) error {
if err := addToContext(ctx, data, "request", "operation"); err != nil {
if err := addToContext(ctx, data, false, "request", "operation"); err != nil {
return err
}

Expand All @@ -238,7 +238,7 @@ func (ctx *context) AddOperation(data string) error {
// AddUserInfo adds userInfo at path request.userInfo
func (ctx *context) AddUserInfo(userRequestInfo kyvernov2.RequestInfo) error {
if data, err := toUnstructured(&userRequestInfo); err == nil {
return addToContext(ctx, data, "request")
return addToContext(ctx, data, false, "request")
} else {
return err
}
Expand All @@ -265,7 +265,7 @@ func (ctx *context) AddServiceAccount(userName string) error {
"serviceAccountName": saName,
"serviceAccountNamespace": saNamespace,
}
if err := ctx.addJSON(data); err != nil {
if err := ctx.addJSON(data, false); err != nil {
return err
}

Expand All @@ -275,7 +275,7 @@ func (ctx *context) AddServiceAccount(userName string) error {

// AddNamespace merges resource json under request.namespace
func (ctx *context) AddNamespace(namespace string) error {
return addToContext(ctx, namespace, "request", "namespace")
return addToContext(ctx, namespace, false, "request", "namespace")
}

func (ctx *context) AddElement(data interface{}, index, nesting int) error {
Expand All @@ -287,7 +287,7 @@ func (ctx *context) AddElement(data interface{}, index, nesting int) error {
"elementIndex": int64(index),
nestedElementIndex: int64(index),
}
return addToContext(ctx, data)
return addToContext(ctx, data, true)
}

func (ctx *context) AddImageInfo(info apiutils.ImageInfo, cfg config.Configuration) error {
Expand All @@ -300,7 +300,7 @@ func (ctx *context) AddImageInfo(info apiutils.ImageInfo, cfg config.Configurati
"tag": info.Tag,
"digest": info.Digest,
}
return addToContext(ctx, data, "image")
return addToContext(ctx, data, false, "image")
}

func (ctx *context) AddImageInfos(resource *unstructured.Unstructured, cfg config.Configuration) error {
Expand All @@ -323,7 +323,7 @@ func (ctx *context) addImageInfos(images map[string]map[string]apiutils.ImageInf
}

logging.V(4).Info("updated image info", "images", utm)
return addToContext(ctx, utm, "images")
return addToContext(ctx, utm, false, "images")
}

func convertImagesToUnstructured(images map[string]map[string]apiutils.ImageInfo) (map[string]interface{}, error) {
Expand Down
12 changes: 6 additions & 6 deletions pkg/engine/context/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

// AddJSONObject merges json data
func AddJSONObject(ctx Interface, data map[string]interface{}) error {
return ctx.addJSON(data)
return ctx.addJSON(data, false)
}

func AddResource(ctx Interface, dataRaw []byte) error {
Expand All @@ -29,12 +29,12 @@ func AddOldResource(ctx Interface, dataRaw []byte) error {
return ctx.AddOldResource(data)
}

func addToContext(ctx *context, data interface{}, tags ...string) error {
func addToContext(ctx *context, data interface{}, overwriteMaps bool, tags ...string) error {
if v, err := convertStructs(data); err != nil {
return err
} else {
dataRaw := push(v, tags...)
return ctx.addJSON(dataRaw)
return ctx.addJSON(dataRaw, overwriteMaps)
}
}

Expand Down Expand Up @@ -90,11 +90,11 @@ func push(data interface{}, tags ...string) map[string]interface{} {
}

// mergeMaps merges srcMap entries into destMap
func mergeMaps(srcMap, destMap map[string]interface{}) {
func mergeMaps(srcMap, destMap map[string]interface{}, overwriteMaps bool) {
for k, v := range srcMap {
if nextSrcMap, ok := v.(map[string]interface{}); ok {
if nextSrcMap, ok := v.(map[string]interface{}); ok && !overwriteMaps {
if nextDestMap, ok := destMap[k].(map[string]interface{}); ok {
mergeMaps(nextSrcMap, nextDestMap)
mergeMaps(nextSrcMap, nextDestMap, overwriteMaps)
} else {
destMap[k] = nextSrcMap
}
Expand Down
34 changes: 30 additions & 4 deletions pkg/engine/context/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestMergeMaps(t *testing.T) {
},
}

mergeMaps(map1, map2)
mergeMaps(map1, map2, false)

assert.Equal(t, "bar1", map2["strVal"])
assert.Equal(t, "bar2", map2["strVal2"])
Expand All @@ -52,7 +52,7 @@ func TestMergeMaps(t *testing.T) {
}

ctxMap := map[string]interface{}{}
mergeMaps(requestObj, ctxMap)
mergeMaps(requestObj, ctxMap, false)

r := ctxMap["request"].(map[string]interface{})
o := r["object"].(map[string]interface{})
Expand All @@ -67,7 +67,7 @@ func TestMergeMaps(t *testing.T) {
},
}

mergeMaps(requestObj2, ctxMap)
mergeMaps(requestObj2, ctxMap, false)
r2 := ctxMap["request"].(map[string]interface{})
o2 := r2["object"].(map[string]interface{})
assert.Equal(t, "bar2", o2["foo"])
Expand All @@ -79,13 +79,39 @@ func TestMergeMaps(t *testing.T) {
},
}

mergeMaps(request3, ctxMap)
mergeMaps(request3, ctxMap, false)
r3 := ctxMap["request"].(map[string]interface{})
o3 := r3["object"].(map[string]interface{})
assert.NotNil(t, o3)
assert.Equal(t, "bar2", o2["foo"])
assert.Equal(t, "bar2", o2["foo2"])
assert.Equal(t, "user1", r3["userInfo"])

request4 := map[string]interface{}{
"request": map[string]interface{}{
"object": map[string]interface{}{
"foo": "bar3",
},
},
}

mergeMaps(request4, ctxMap, false)
r4 := ctxMap["request"].(map[string]interface{})
assert.NotNil(t, r4)
assert.Equal(t, "user1", r4["userInfo"])

request5 := map[string]interface{}{
"request": map[string]interface{}{
"object": map[string]interface{}{
"foo": "bar4",
},
},
}

mergeMaps(request5, ctxMap, true)
r5 := ctxMap["request"].(map[string]interface{})
userInfo := r5["userInfo"]
assert.Nil(t, userInfo)
}

func TestStructToUntypedMap(t *testing.T) {
Expand Down

0 comments on commit aafc4fe

Please sign in to comment.