yq:如何读取兄弟元素的值?

yq: how to read a sibling element value?

我正在探索 yq 以修改我的 YAML,我想在 ImageStream 的 spec 下添加一个新元素 name == openshift45

apiVersion: v1
items:
- apiVersion: image.openshift.io/v1
  kind: ImageStream
  metadata:
    annotations:
      openshift.io/generated-by: OpenShiftNewApp
    creationTimestamp: null
    labels:
      app: openshift45
      app.kubernetes.io/component: openshift45
      app.kubernetes.io/instance: openshift45
    name: nodejs-10
  spec:
    lookupPolicy:
      local: false
    tags:
    - annotations:
        openshift.io/imported-from: registry.access.redhat.com/ubi8/nodejs-10
      from:
        kind: DockerImage
        name: registry.access.redhat.com/ubi8/nodejs-10
      generation: null
      importPolicy: {}
      name: latest
      referencePolicy:
        type: ""
  status:
    dockerImageRepository: ""
- apiVersion: image.openshift.io/v1
  kind: ImageStream
  metadata:
    annotations:
      openshift.io/generated-by: OpenShiftNewApp
    creationTimestamp: null
    labels:
      app: openshift45
      app.kubernetes.io/component: openshift45
      app.kubernetes.io/instance: openshift45
    name: openshift45
  spec:
    lookupPolicy:
      local: false
  status:
    dockerImageRepository: ""

下面的命令 returns 有效的 metadata 元素。现在,我想移动到父级,然后选择 spec。这可能与 yq - https://github.com/mikefarah/yq?

yq r openshift45.yaml --printMode pv "items(kind==ImageStream).(name==openshift45)"

returns

items.[1].metadata:
  annotations:
    openshift.io/generated-by: OpenShiftNewApp
  creationTimestamp: null
  labels:
    app: openshift45
    app.kubernetes.io/component: openshift45
    app.kubernetes.io/instance: openshift45
  name: openshift45

预期输出:

apiVersion: v1
items:
- apiVersion: image.openshift.io/v1
  kind: ImageStream
  metadata:
    annotations:
      openshift.io/generated-by: OpenShiftNewApp
    creationTimestamp: null
    labels:
      app: openshift45
      app.kubernetes.io/component: openshift45
      app.kubernetes.io/instance: openshift45
    name: nodejs-10
  spec:
    lookupPolicy:
      local: false
    tags:
    - annotations:
        openshift.io/imported-from: registry.access.redhat.com/ubi8/nodejs-10
      from:
        kind: DockerImage
        name: registry.access.redhat.com/ubi8/nodejs-10
      generation: null
      importPolicy: {}
      name: latest
      referencePolicy:
        type: ""
  status:
    dockerImageRepository: ""
- apiVersion: image.openshift.io/v1
  kind: ImageStream
  metadata:
    annotations:
      openshift.io/generated-by: OpenShiftNewApp
    creationTimestamp: null
    labels:
      app: openshift45
      app.kubernetes.io/component: openshift45
      app.kubernetes.io/instance: openshift45
    name: openshift45
  spec:
    *dockerImageRepository: <$MYREGISTRY>/<$MYNAMESPACE>/<$MYPROJECT>*
    lookupPolicy:
      local: false
  status:
    dockerImageRepository: ""

目前在yq中是不可能的。您将必须在变量中获取第一个命令的输出并将该变量传递给下一个。

yq 是 jq 的包装器,但它没有自定义函数的功能。自定义函数可以在一个地方使用文档的任何层次结构中的任何值。

感谢 Inian 指出 OP 没有使用包装器 yq 版本。不幸的是,目前使用的版本也不允许使用自定义函数。

Path Expressions in mikefarah/yq 没有完整的文档来展示如何使用多个条件来获得所需对象的真实示例。因此,对于有问题的 YAML,使用一个独特的条件,您可以执行如下操作。在 yq version 3.3.2

中验证
yq w openshift45.yaml 'items.(metadata.name == openshift45).spec.dockerImageRepository' '<$MYREGISTRY>/<$MYNAMESPACE>/<$MYPROJECT>'

您可以使用 -i 标记和 write 来修改 YAML in-place。参见 Updating files in-place

如果这不是您想要的,并且您需要多个条件选择才能获得所需的对象,建议您在 GitHub 页面上提出问题 - https://github.com/mikefarah/yq/issues 请求相同的正确语法。