Home > database >  How to ignore json elements when a nested array has an key:value matching patterm?
How to ignore json elements when a nested array has an key:value matching patterm?

Time:12-29

I have been using jq(1) and getting a similar response back from a kubernetes api (api/v1/nodes).

{
  "kind": "NodeList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/nodes",
    "resourceVersion": "8768"
  },
  "items": [
    {
      "metadata": {
        "name": "ip-101-191-101-101.ec2.internal",
        "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
        "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
        "resourceVersion": "8768",
        "creationTimestamp": "2020-11-19T12:27:05Z",
          },
      "spec": {
        "podCIDR": "101.191.101.101/24",
        "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
        "taints": [
          {
            "key": "worker-group",
            "value": "prometheus",
            "effect": "NoSchedule"
          }
        ]
      }
    }
  ]
}

As you can see there can be many items in the Array. There are some with the .spec.taints and others without it. Some may be empty and some may be full.

My goal is to just ignore all items that have the taints "effect": "NoSchedule"

I'm finding this very troublesome because no matter what I try and I've been searching online for days, i can't get it to work properly.

I've gotten this far but am now stuck

curl api | jq -c '.items[].spec.taints |= map(select(.effect | . != "NoSchedule"))'

any help would be appreciated.

CodePudding user response:

I hope this can be useful, in this example there are 3 items one with effect: NoSchedule, one with effect: anyother and one with taints empty. If am correct, you need only the second one:

{
  "kind": "NodeList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/nodes",
    "resourceVersion": "8768"
  },
  "items": [
    {
      "metadata": {
        "name": "ip-101-191-101-101.ec2.internal",
        "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
        "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
        "resourceVersion": "8768",
        "creationTimestamp": "2020-11-19T12:27:05Z"
          },
      "spec": {
        "podCIDR": "101.191.101.101/24",
        "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
        "taints": [
          {
            "key": "worker-group",
            "value": "prometheus",
            "effect": "NoSchedule"
          }
        ]
      }
    },

  {
      "metadata": {
        "name": "ip-101-191-101-101.ec2.internal",
        "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
        "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
        "resourceVersion": "8768",
        "creationTimestamp": "2020-11-19T12:27:05Z"
          },
      "spec": {
        "podCIDR": "101.191.101.101/24",
        "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
        "taints": [
          {
            "key": "worker-group",
            "value": "prometheus",
            "effect": "anyother"
          }
        ]
      }
    },
    {
      "metadata": {
        "name": "ip-101-191-101-101.ec2.internal",
        "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
        "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
        "resourceVersion": "8768",
        "creationTimestamp": "2020-11-19T12:27:05Z"
          },
      "spec": {
        "podCIDR": "101.191.101.101/24",
        "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
        "taints": [

        ]
      }
    }


  ]

The command will be:

 jq '.items[]|select(.spec.taints[].effect!="NoSchedule") ' data1.jtxt

result:

{
  "metadata": {
    "name": "ip-101-191-101-101.ec2.internal",
    "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
    "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
    "resourceVersion": "8768",
    "creationTimestamp": "2020-11-19T12:27:05Z"
  },
  "spec": {
    "podCIDR": "101.191.101.101/24",
    "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
    "taints": [
      {
        "key": "worker-group",
        "value": "prometheus",
        "effect": "anyother"
      }
    ]
  }
}

Note: I put your data ina a file to simulate input.

CodePudding user response:

Based on the question, my understanding is that the taints could have multiple entries. It could be a mix of NoSchedule and other values. Here's the jq where the item will be ignored if at least one taint with effect value NoSchedule exists.

. as $in | $in * { items: $in.items | map(select(.spec.taints | all(.effect != "NoSchedule"))) }```

CodePudding user response:

This deletes from the .items array every member that has an array in .spec.taints which in turn has at least one object item with .effect set to "NoSchedule". In every other case, i.e. there's only objects with .effect set to something else, or .taints is empty, or there's no .taints at all, or there's no .spec at all, up to just an empty object {} as member of the .items array, that array member will be retained.

.items -= (.items | map(select(.spec.taints[].effect == "NoSchedule")?))

Demo

CodePudding user response:

You can use del to delete the one(s) you intended :

curl api | jq 'del(.items[] | select(.spec.taints[].effect == "NoSchedule")?)'
  • Related