Search code examples
kubernetesyq

How to update an element in array using yq by not using the index, but rather some contextual info, like a name


this is the input

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  name: kube-vip
  namespace: kube-system
spec:
  containers:
    - args:
        - start
      env:
        - name: vip_arp
          value: "true"
        - name: vip_leaderelection
          value: "true"
        - name: vip_address
          value: 
        - name: vip_interface
          value: eth0
        - name: vip_leaseduration
          value: "15"
        - name: vip_renewdeadline
          value: "10"
        - name: vip_retryperiod
          value: "2"
      image: ghcr.io/kube-vip/kube-vip:v0.3.5
      imagePullPolicy: IfNotPresent
      name: kube-vip
      resources: {}
      securityContext:
        capabilities:
          add:
            - NET_ADMIN
            - SYS_TIME
      volumeMounts:
        - mountPath: /etc/kubernetes/admin.conf
          name: kubeconfig
  hostNetwork: true
  volumes:
    - hostPath:
        path: /etc/kubernetes/admin.conf
        type: FileOrCreate
      name: kubeconfig
status: {}

and I'd like to update the file and get the output. I can do that by using:

cat $file | yq e '.spec.containers[].env[2].value="sdf"'

But that assumes the index of vip_address env var will be always 2. Is it possible to have something like this

yq e '. | select(.spec.containers[].env[].name=="vip_address") | .value="sdf"'

that will actually work and update the value of vip_address?


Solution

  • Of course it can be done with mikefarah/yq. You need to drop down to the last level list item env and then use the update-select operator |=

    yq '.spec.containers[].env |= map(select(.name=="vip_address").value="sdf")' yaml
    

    Also note that since 4.18.1, yq's eval/e command is the default command and no longer needs to be specified.


    If you want to double-quote the .value field, update the style for the particular node to double i.e.

    yq '.spec.containers[].env |= map(select(.name=="vip_address").value="sdf" | .value style="double")' yaml