如何使用 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
已经是你想要的工具了!这里根本不需要del
。 select
是仅保留对象流中的 一些 的机制。尝试:
$ 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
我正在尝试使用 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
已经是你想要的工具了!这里根本不需要del
。 select
是仅保留对象流中的 一些 的机制。尝试:
$ 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