jq错误不能迭代null但需要做出不同的选择

jq error cannot iterate over null but need to make a different choice

我有一个 jq 过滤器可以选择我需要的行。但有时这些行可能是空的,然后一切都中断,规则不起作用。我尝试使用 if-then-else 构造但无济于事。

如果您处理以下 json:

,则该规则有效

.metadata.namespace as $ns | (.spec.rules[0].match.any[].resources.kinds[] / "/") | [select(.[1])[0] // null, select(.[2])[1] // null, last] as [$version,$group,$kind] | {namespace: $ns, kind: $kind, group: $version, version: $group} | with_entries(select(.value!=null))

合适json:

{
  "apiVersion": "kyverno.io/v1",
  "kind": "posdfsdf",
  "metadata": {
    "name": "e-eion",
    "namespace": "kke",
    "annotations": {
      "policies.kyverno.io/title": "Dation",
      "policies.kyverno.io/category": "Pod Security Standards (Restricted)",
      "policies.kyverno.io/severity": "medium",
      "policies.kyverno.io/subject": "Pod",
      "kyverno.io/kyverno-version": "1.6.0",
      "kyverno.io/kubernetes-version": "1.22-1.23",
      "policies.kyverno.io/description": "se`.      "
    }
  },
  "spec": {
    "validationFailureAction": "audit",
    "background": true,
    "rules": [
      {
        "name": "tion",
        "match": {
          "any": [
            {
              "resources": {
                "kinds": [
                  "Pod"
                ]
              }
            }
          ]
        },
        "validate": {
          "message": "Prisd",
          "pattern": {
            "spec": {
              "=(eners)": [
                {
                  "secxt": {
                    "altion": "false"
                  }
                }
              ],
              "=(i)": [
                {
                  "sext": {
                    "alcalation": "false"
                  }
                }
              ],
              "containers": [
                {
                  "setext": {
                    "an": "false"
                  }
                }
              ]
            }
          }
        }
      }
    ]
  }
}

规则停止工作的示例:

{
  "apiVersion": "k/v1",
  "kind": "Picy",
  "metadata": {
    "name": "denylation",
    "namespace": "what",
  },
  "spec": {
    "validationFailureAction": "audit",
    "background": true,
    "rules": [
      {
        "name": "deny-privilege-escalation",
        "match": {
          "resources": {
            "kinds": [
              "Pod"
            ]
          }
        },
        "validate": {
          "message": "Priviles[*].securityContext.allowPrind spec.initContalse`.",
          "pattern": {
            "spec": {
              "=(iners)": [
                {
                  "=(seext)": {
                    "=(aln)": "false"
                  }
                }
              ],
              "containers": [
                {
                  "=(stext)": {
                    "=(al)": "false"
                  }
                }
              ]
            }
          }
        }
      }
    ]
  }
}

如何解决这个问题?我需要规则在任何情况下都能解决并给出输出

失败的 json 给出了以下错误:

parse error: Expected another key-value pair at line 7, column 3

这是由此处的尾随逗号引起的:

"metadata": {
    "name": "denylation",
    "namespace": "what",
},

删除那个逗号,抛出以下错误:

jq: error (at :44): Cannot iterate over null (null)

这是由于 match 对象中缺少 any 键造成的。

我们可以 'catch' 使用 ? (docs):

这个错误
(.spec.rules[0].match.any[]?.resources.kinds[] / "/") 
                           ^

但是由于缺少键,过滤器没有找到任何东西,输出为空。


Updated jqPlay

这应该有效:

.metadata.namespace as $ns |
((.spec.rules[0].match | .. | (objects | .resources.kinds[]?)) / "/") |
[select(.[1])[0] // null, select(.[2])[1] // null, last] as [$version,$group,$kind] |
{namespace: $ns, kind: $kind, group: $version, version: $group} |
with_entries(select(.value!=null))