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

How to delete a Kubernetes resource entirely with jq

我正在尝试使用 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 个值流,returns 接收 N 个修改值流。在您的情况下,它接受三个值的流和 returns 三个值的流。您观察到它保留第一个和最后一个对象不变,但将第二个对象替换为 null。对于它输入的每个值,它都会评估其参数过滤器以决定如何更改该值——该过滤器发出的每个位置都将被删除。您已提供 select 过滤器作为其参数。 select 过滤器接受一个值流,并发出一个 一些 未修改的值流,同时丢弃其他值,这取决于它的过滤器参数。 (实际上,它比这复杂一点——如果你给它传递一个 returns 多个值的过滤器,它实际上可以发出比它接收到的更多的值,但这与这里无关。)

在这种情况下,您的 select 过滤器 returns 对第一个对象没有任何影响,因为它不匹配,所以 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