Search code examples
kubernetesnamespacesgoogle-kubernetes-enginekubectl

How to "filter" and "format" namespaces based on the annotation


I want to filter namespaces based on the annotation. I do not want namespace which has annotation as components\.gke\.io/layer=="addon".

I tried kubectl get ns -o=jsonpath='{.items[?(@.metadata.annotations.components\.gke\.io/layer=="addon")].metadata.name}' command and at least it gives me the result but it is not coming in normal table format, the way it comes when you execute kubectl get ns.

enter image description here

However, this is not what I want, I want the inverse of this, which means filtering out these GKE rows. I tried kubectl get ns -o=jsonpath='{.items[?(@.metadata.annotations.components\.gke\.io/layer=="")].metadata.name}' but it doesn't work, it give empty result.

I tried to format but unable to create the desired command. Anyone has tried this before - (1.) filter out namespaces which has certain annotation (2.) format that output in table format.


Solution

  • I think (!?) you can't use negation with kubectl's implementation of JSONPath.

    Once you use the --output flag with kubectl, you lose the ability to render the command's output using the default table format. With e.g. Bash column can provide similar out.

    Consider using a generic JSON processing tool such as jq.

    An advantage of using a standalone tool is that, once you're familiar with the tool, you can use it with any command that emits JSON (not just with kubectl.

    FILTER='
      ["NAME","STATUS"],
    (.items[]| 
      [
        select(.metadata.annotations["components.gke.io/layer"]!="addon")
        |.metadata.name,.status.phase
      ]
    )
    |@tsv'
    
    kubectl get namespaces --output=json \
    | jq -r "${FILTER}" \
    | column --table --separator $'\t'
    

    Explanation of FILTER:

    1. Returns a JSON array that is piped into @tsv (tab-formatted output)
    2. The first array entry is a an array (!) of column titles
    3. .items is piped through a select that filters Namespaces that don't contain the annotation
    4. Emit not filtered Namespace name and status as JSON array items

    The tab-formatted (no longer JSON) that's emitted by jq is then piped into column which formats the results as a table.