Search code examples
jqyq

How do I get an intersection of two lists with yq/jq, returning the parent object for matches?


Simplified from my use case a bit, I'm trying to find all Kubernetes deployments whose image (you can assume the container at index 0) is contained in a list of images.

I understand I can subtract two arrays to get the the intersection of these, but what I'm left with is just the list of images; I'd like to keep the full Deployment spec for matches.

Example:

deployments.yaml:

apiVersion: v1
kind: List
metadata:
  resourceVersion: ""
items:
- apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: nginx-deployment
    labels:
      app: nginx
  spec:
    replicas: 3
    selector:
      matchLabels:
        app: nginx
    template:
      metadata:
        labels:
          app: nginx
      spec:
        containers:
        - name: nginx
          image: nginx:1.14.2
          ports:
          - containerPort: 80
- apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: myapp-deployment
    labels:
      app: myapp
  spec:
    replicas: 1
    selector:
      matchLabels:
        app: myapp
    template:
      metadata:
        labels:
          app: myapp
      spec:
        containers:
        - name: myapp
          image: myapp:0.1.2
          ports:
          - containerPort: 8080

images.yaml

searchItems:
- nginx:1.13.1
- nginx:1.14.2

Using this, I can get the list of images for Deployments using one of the images in my list:

yq ea '[.items[].spec.template.spec.containers[0].image] - ([.items[].spec.template.spec.containers[0].image] - .searchItems) | unique' deployments.yaml images.yaml

Output:

- nginx:1.14.2

I'd like to get the entire Deployment object though, not just the image, for any matches.

I am using yq here, but any solution using jq would work fine for me too. I can also solve this by other means, like scripting it one by one, but I am curious about the solution with yq/jq.


Solution

  • You could just map the .items array to contain only those items that match.

    Using mikefarah/yq:

    yq '
      (load("images.yaml").searchItems | unique) as $q | .items
      | map(select(.spec.template.spec.containers[0].image == $q[]))
    ' deployments.yaml
    

    Using kislyuk/yq:

    yq -y '
      (input.searchItems | unique) as $q | .items
      | map(select(.spec.template.spec.containers[0].image == $q[]))
    ' deployments.yaml images.yaml
    

    Using itchyny/gojq:

    gojq --yaml-input --yaml-output '
      (input.searchItems | unique) as $q | .items
      | map(select(.spec.template.spec.containers[0].image == $q[]))
    ' deployments.yaml images.yaml