In Jsonnet’s standard libraries, there’s an std.prune function which will recursively go through an object and remove any empty field in the object which is quite handy, usually. In my case I wanted to prune all empty fields in a container object but spare the legit empty emptyDir field so the std.prune may cause some trouble:
// source
{
containers: {
local container = {
image: 'nginx:latest',
env: [],
args: [],
volumeMounts: [
{
name: 'test',
emptyDir: {}
}
],
},
test: std.prune(container),
},
}
// output
{
"containers": {
"test": {
"image": "nginx:latest", // removed emtpy env and args
"volumeMounts": [
{
"name": "test"
// the emptyDir should not be removed here
}
]
}
}
}So I wrote my own prune function which only clean up empty field matching a list of names, here’s what it looks like:
// source
{
containers: {
local prune(obj) =
local field_list = ['args', 'env'];
{
[if std.member(field_list, f) && std.length(obj[f]) == 0 then null else f]: obj[f]
for f in std.objectFields(obj)
},
local container = {
image: 'nginx:latest',
env: [],
args: [],
volumeMounts: [
{
name: 'test',
emptyDir: {}
}
],
},
test: prune(container),
},
}
// output
{
"containers": {
"test": {
"image": "nginx:latest",
"volumeMounts": [
{
"emptyDir": {},
"name": "test"
}
]
}
}
}This works for the sample but obviously it only goes through the first-level fields. Let’s get recursive!
// source
{
containers: {
local pruneExcept(a, ex=[]) =
if std.isObject(a) then{
[if std.member(ex, f) || std.length(a[f]) > 0 then f else null]: $.prune(a[f],ex)
for f in std.objectFields(a)
} else if std.isArray(a) then [
$.prune(nf, ex) for nf in a
] else a,
local container = {
image: 'nginx:latest',
env: [],
args: [],
volumeMounts: [
{
name: 'test',
emptyDir: {},
rubbish: {}
}
],
resources: {
requests: {
cpu: '0.5',
rubbish: []
},
rubbish: [],
}
},
test: pruneExcept(container, 'emptyDir'),
},
}
// output
{
"containers": {
"test": {
"image": "nginx:latest",
"resources": {
"requests": {
"cpu": "0.5"
}
},
"volumeMounts": [
{
"emptyDir": {},
"name": "test"
}
]
}
}It works but why should I stop here? I had a look at the source code of std.prune and proposed a PR here. 🙂
