mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
Merge pull request #1597 from yashvardhan-kukreja/issue-1242/multiline-yaml-string-support
feat: added functionality for delimiting multi-line block by newline characters
This commit is contained in:
commit
bb361df696
2 changed files with 97 additions and 0 deletions
pkg/engine
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/resourcecache"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/dynamic/dynamiclister"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// LoadContext - Fetches and adds external data to the Context.
|
||||
|
@ -193,6 +194,9 @@ func fetchConfigMap(logger logr.Logger, entry kyverno.ContextEntry, lister dynam
|
|||
return nil, fmt.Errorf("failed to convert configmap %s/%s: %v", namespace, name, err)
|
||||
}
|
||||
|
||||
// update the unstructuredObj["data"] to delimit and split the string value (containing "\n") with "\n"
|
||||
unstructuredObj["data"] = parseMultilineBlockBody(unstructuredObj["data"].(map[string]interface{}))
|
||||
|
||||
// extract configmap data
|
||||
contextData["data"] = unstructuredObj["data"]
|
||||
contextData["metadata"] = unstructuredObj["metadata"]
|
||||
|
@ -205,3 +209,25 @@ func fetchConfigMap(logger logr.Logger, entry kyverno.ContextEntry, lister dynam
|
|||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// parseMultilineBlockBody recursively iterates through a map and updates its values in the following way
|
||||
// whenever it encounters a string value containing "\n",
|
||||
// it converts it into a []string by splitting it by "\n"
|
||||
func parseMultilineBlockBody(m map[string]interface{}) map[string]interface{} {
|
||||
for k, v := range m {
|
||||
switch typedValue := v.(type) {
|
||||
case string:
|
||||
trimmedTypedValue := strings.Trim(typedValue, "\n")
|
||||
if strings.Contains(trimmedTypedValue, "\n") {
|
||||
m[k] = strings.Split(trimmedTypedValue, "\n")
|
||||
} else {
|
||||
m[k] = trimmedTypedValue // trimming a str if it has trailing newline characters
|
||||
}
|
||||
case map[string]interface{}:
|
||||
m[k] = parseMultilineBlockBody(typedValue)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
|
71
pkg/engine/jsonContext_test.go
Normal file
71
pkg/engine/jsonContext_test.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_parseMultilineBlockBody(t *testing.T) {
|
||||
tcs := []struct {
|
||||
multilineBlockRaw []byte
|
||||
expectedMultilineBlockRaw []byte
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
multilineBlockRaw: []byte(`{
|
||||
"key1": "value",
|
||||
"key2": "value2",
|
||||
"key3": "word1\nword2\nword3",
|
||||
"key4": "word4\n"
|
||||
}`),
|
||||
expectedMultilineBlockRaw: []byte(`{"key1":"value","key2":"value2","key3":["word1","word2","word3"],"key4":"word4"}`),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
multilineBlockRaw: []byte(`{
|
||||
"key1": "value",
|
||||
"key2": "value2",
|
||||
"key3": "word1\nword2\nword3",
|
||||
"key4": "word4"
|
||||
}`),
|
||||
expectedMultilineBlockRaw: []byte(`{"key1":"value","key2":"value2","key3":["word1","word2","word3"],"key4":"word4"}`),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
multilineBlockRaw: []byte(`{
|
||||
"key1": "value1",
|
||||
"key2": "value2\n",
|
||||
"key3": "word1",
|
||||
"key4": "word2"
|
||||
}`),
|
||||
expectedMultilineBlockRaw: []byte(`{"key1":"value1","key2":["value2",""]}`),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
multilineBlockRaw: []byte(`{
|
||||
"key1": "value1",
|
||||
"key2": "[\"cluster-admin\", \"cluster-operator\", \"tenant-admin\"]"
|
||||
}`),
|
||||
expectedMultilineBlockRaw: []byte(`{"key1":"value1","key2":"[\"cluster-admin\", \"cluster-operator\", \"tenant-admin\"]"}`),
|
||||
expectedErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
var multilineBlock map[string]interface{}
|
||||
err := json.Unmarshal(tc.multilineBlockRaw, &multilineBlock)
|
||||
assert.NilError(t, err)
|
||||
|
||||
parsedMultilineBlock := parseMultilineBlockBody(multilineBlock)
|
||||
parsedMultilineBlockRaw, err := json.Marshal(parsedMultilineBlock)
|
||||
assert.NilError(t, err)
|
||||
|
||||
if tc.expectedErr {
|
||||
assert.Assert(t, bytes.Compare(parsedMultilineBlockRaw, tc.expectedMultilineBlockRaw) != 0)
|
||||
} else {
|
||||
assert.Assert(t, bytes.Compare(parsedMultilineBlockRaw, tc.expectedMultilineBlockRaw) == 0)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue