Commit 9be5a345 authored by Oren Shomron's avatar Oren Shomron
Browse files

Fix PatchJSON error when no component params are defined.



* PatchJSON guards against missing 'components' key.
* BuildEnvParamsForModule / params_for_module.libsonnet returns empty components key when no component params are found.

Closes #789
Signed-off-by: default avatarOren Shomron <shomron@gmail.com>
parent 5be3b2dd
......@@ -54,6 +54,13 @@ func TestBuildEnvParamsForModule(t *testing.T) {
moduleName: "no-match",
output: "no_match.jsonnet",
},
{
name: "empty input, still output components field",
input: "input_empty.jsonnet",
componentParams: "component_empty.jsonnet",
moduleName: "no-match",
output: "no_match.jsonnet",
},
}
for _, tc := range cases {
......
......@@ -29,8 +29,8 @@ func PatchJSON(jsonObject, patch, patchName string) (string, error) {
var snippetMergeComponentPatch = `
function(target, patch, patchName)
if std.objectHas(patch.components, patchName) then
std.mergePatch(target, patch.components[patchName])
else
target
if std.objectHas(patch, 'components') && std.objectHas(patch.components, patchName) then
std.mergePatch(target, patch.components[patchName])
else
target
`
......@@ -36,3 +36,16 @@ func Test_PatchJSON(t *testing.T) {
test.AssertOutput(t, "rbac-1-patched.json", got)
}
func Test_PatchJSON_EmptyPatch(t *testing.T) {
jsonObject, err := ioutil.ReadFile(filepath.Join("testdata", "rbac-1.json"))
require.NoError(t, err)
patch, err := ioutil.ReadFile(filepath.Join("testdata", "patch-empty.json"))
require.NoError(t, err)
got, err := PatchJSON(string(jsonObject), string(patch), "rbac-1")
require.NoError(t, err)
test.AssertOutput(t, "rbac-1.json", got)
}
......@@ -25,19 +25,19 @@ func init() {
// define files
file2 := &embedded.EmbeddedFile{
Filename: "modularize_params.libsonnet",
FileModTime: time.Unix(1530832602, 0),
FileModTime: time.Unix(1531169022, 0),
Content: string("function(moduleName, params)\n local prefix = if (moduleName == \"/\" || moduleName == \"\") then \"\" else \"%s.\" % moduleName;\n\n local baseObject = if std.objectHas(params, \"global\")\n then {global: params.global}\n else {};\n\n baseObject + {\n components: {\n [\"%s%s\" % [prefix, key]]: params.components[key]\n for key in std.objectFieldsAll(params.components)\n },\n }"),
}
file3 := &embedded.EmbeddedFile{
Filename: "params_for_module.libsonnet",
FileModTime: time.Unix(1530891505, 0),
Content: string("function(moduleName, input)\n local isModule(key) = std.length(std.split(key, \".\")) > 1;\n\n local localizeKey(key) =\n if isModule(key)\n then\n local parts = std.split(key, \".\");\n parts[std.length(parts)-1]\n else key;\n\n local findInRoot(key, value) =\n if isModule(key)\n then {[key]:null}\n else {[key]:value};\n\n local findInModule(moduleName, key, value) =\n if std.startsWith(key, moduleName)\n then {[localizeKey(key)]: value}\n else {[localizeKey(key)]: null};\n\n local findValue(moduleName, key, value) =\n if moduleName == \"/\"\n then findInRoot(key, value)\n else findInModule(moduleName, key, value);\n\n local fn(moduleName, params) = [\n findValue(moduleName, key, params.components[key])\n for key in std.objectFields(params.components)\n ];\n\n local foldFn(aggregate, object) =\n local o = {\n components+: {\n [x]:+ object[x]\n for x in std.objectFields(object)\n if object[x] != null\n },\n };\n\n aggregate + o;\n\n local a = fn(moduleName, input);\n\n std.foldl(foldFn, a, {})\n\n"),
FileModTime: time.Unix(1532616716, 0),
Content: string("function(moduleName, input)\n local isModule(key) = std.length(std.split(key, \".\")) > 1;\n\n local localizeKey(key) =\n if isModule(key)\n then\n local parts = std.split(key, \".\");\n parts[std.length(parts)-1]\n else key;\n\n local findInRoot(key, value) =\n if isModule(key)\n then {[key]:null}\n else {[key]:value};\n\n local findInModule(moduleName, key, value) =\n if std.startsWith(key, moduleName)\n then {[localizeKey(key)]: value}\n else {[localizeKey(key)]: null};\n\n local findValue(moduleName, key, value) =\n if moduleName == \"/\"\n then findInRoot(key, value)\n else findInModule(moduleName, key, value);\n\n local fn(moduleName, params) = [\n findValue(moduleName, key, params.components[key])\n for key in std.objectFields(params.components)\n ];\n\n local foldFn(aggregate, object) =\n local o = {\n components+: {\n [x]:+ object[x]\n for x in std.objectFields(object)\n if object[x] != null\n },\n };\n\n aggregate + o;\n\n local a = fn(moduleName, input);\n\n local init = {components: {}};\n\n std.foldl(foldFn, a, init)\n\n"),
}
// define dirs
dir1 := &embedded.EmbeddedDir{
Filename: "",
DirModTime: time.Unix(1530832602, 0),
DirModTime: time.Unix(1531169022, 0),
ChildFiles: []*embedded.EmbeddedFile{
file2, // "modularize_params.libsonnet"
file3, // "params_for_module.libsonnet"
......@@ -51,7 +51,7 @@ func init() {
// register embeddedBox
embedded.RegisterEmbeddedBox(`scripts`, &embedded.EmbeddedBox{
Name: `scripts`,
Time: time.Unix(1530832602, 0),
Time: time.Unix(1531169022, 0),
Dirs: map[string]*embedded.EmbeddedDir{
"": dir1,
},
......
......@@ -41,5 +41,7 @@ function(moduleName, input)
local a = fn(moduleName, input);
std.foldl(foldFn, a, {})
local init = {components: {}};
std.foldl(foldFn, a, init)
{
global: {
},
// Component-level parameters, defined initially from 'ks prototype use ...'
// Each object below should correspond to a component in the components/ directory
components: {
},
}
{
components: {},
}
\ No newline at end of file
{}
\ No newline at end of file
{
"apiVersion": "rbac.authorization.k8s.io/v1beta1",
"kind": "ClusterRoleBinding",
"metadata": {
"name": "cert-manager",
"labels": {
"app": "cert-manager",
"chart": "cert-manager-0.2.2",
"release": "cert-manager",
"heritage": "Tiller"
}
},
"roleRef": {
"apiGroup": "rbac.authorization.k8s.io",
"kind": "ClusterRole",
"name": "cert-manager"
},
"subjects": [{
"name": "cert-manager",
"namespace": "default",
"kind": "ServiceAccount"
}]
}
\ No newline at end of file
"apiVersion": "rbac.authorization.k8s.io/v1beta1",
"kind": "ClusterRoleBinding",
"metadata": {
"labels": {
"app": "cert-manager",
"chart": "cert-manager-0.2.2",
"heritage": "Tiller",
"release": "cert-manager"
},
"name": "cert-manager"
},
"roleRef": {
"apiGroup": "rbac.authorization.k8s.io",
"kind": "ClusterRole",
"name": "cert-manager"
},
"subjects": [
{
"kind": "ServiceAccount",
"name": "cert-manager",
"namespace": "default"
}
]
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment