如何使用jq完全删除Kubernetes资源



我试图使用jq(和yq)来删除单个Kubernetes资源。我想我可以用del来做这个,但它留下了一个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: {}

我的测试数据:

$ 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: {}

我如何得到这个输出?

apiVersion: v1
kind: Namespace
metadata:
name: foo
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
name: baz
spec: {}
status: {}

我从语法中假设您正在使用kislyuk yq。

del不是适合这项工作的工具。del接受一个N个值的流,并返回一个N个修改值的流。在你的例子中,它接受三个值的流并返回三个值的流。您可以观察到,它使第一个和最后一个对象保持不变,但将第二个对象替换为null。对于它输入的每个值,它计算其参数过滤器以决定如何更改该值—该过滤器发出的每个位置都将被删除。您已经提供了一个select过滤器作为它的参数。一个select过滤器接受一个值流,并发出一个流,其中一些值未经修改,同时丢弃其他值,这取决于它的过滤器参数。(实际上,它比这更复杂一点——如果你给它传递一个返回多个值的过滤器,它实际上可以发出比它接收到的更多的值,但这在这里不相关。)

在本例中,您的select过滤器对第一个对象不返回任何内容,因为它不匹配,因此del不更改任何内容。对于第二个对象,select过滤器不匹配该对象,因此del过滤器等同于del(.)。当您传递给del的过滤器不选择对象(或数组)中的键(或索引),而是整个事情时,文档并不是非常清楚会发生什么,但显然实践中的行为是它将其替换为null

如果你遵循这个解释,你可能会看到这是怎么回事。select已经是你想要的工具!这里根本不需要delselect是只保留对象流中的部分的机制。试一试:

$ 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: {}

您可以使用gojq, jq的Go实现:

gojq --yaml-input --yaml-output 'select(.metadata.name != "bar")' test.yaml

最新更新