Reputation: 24793
I'm trying to use jq
(and yq) to delete a single Kubernetes resource.
I thought I could do with this with del
but it is leaving behind a null
.
$ cat test.yaml | yq -y '. | del(select(.kind == "Namespace" and .metadata.name == "bar"))'
apiVersion: v1
kind: Namespace
metadata:
name: foo
spec: {}
status: {}
--- null
---
apiVersion: v1
kind: Namespace
metadata:
name: baz
spec: {}
status: {}
My test data:
$ cat test.yaml
apiVersion: v1
kind: Namespace
metadata:
name: foo
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
name: bar
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
name: baz
spec: {}
status: {}
How do I get this output?
apiVersion: v1
kind: Namespace
metadata:
name: foo
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
name: baz
spec: {}
status: {}
Upvotes: 0
Views: 588
Reputation: 17930
I am assuming from the syntax that you are using kislyuk yq.
del
is not the right tool for this job. del
takes in a stream of N values and returns a stream of N modified values. In your case it takes in a stream of three values and returns a stream of three values. You observe that it leaves the first and last objects unchanged, but replaces the second with null
. For each value it inputs, it evaluates its argument filter to decide how to change that value - every location emitted by that filter will be removed. You have provided as its argument a select
filter. A select filter takes in a stream of values, and emits a stream of some of those values unmodified, while discarding others, depending on its filter argument. (Actually, it's a little more complicated than that - if you pass it a filter that returns multiple values, it can actually emit more values than it received, but that's not relevant here.)
In this case, your select
filter returns nothing for the first object, because it doesn't match, so the del
changes nothing. For the second object, the select
filter does match the object, so the del
filter is equivalent to del(.)
. The docs aren't terribly clear about what to expect when the filter you pass to del
doesn't pick a key (or index) in the object (or array), but instead the whole thing, but clearly the behaviour in practice is that it replaces it with null
.
If you followed along with that explanation, you may see where this is going. select
is already the tool you want! There is no need for del
here at all. select
is the mechanism to keep only some of a stream of objects. Try:
$ cat ~/scratch/test.yaml | yq -y 'select(.kind != "Namespace" or .metadata.name != "bar")'
apiVersion: v1
kind: Namespace
metadata:
name: foo
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
name: baz
spec: {}
status: {}
Upvotes: 2