moluzhui
moluzhui

Reputation: 1093

How to patch array data of k8s yaml file on condition using yq?

I have a project that need to update cloneset yaml

YAML document something like:

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  generation: 1
  ...
spec:
  ...
  ...
  volumeClaimTemplates:
  - metadata:
      creationTimestamp: null
      name: data1
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 60G
  - metadata:
      creationTimestamp: null
      name: data2
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 60G
status:
  availableReplicas: 1

I want to patch volumeClaimTemplates based on metadata.name

If name is not specified, storages for all volumeClaimTemplates are updated, and if name is specified and is matched, storages for a specific name are updated, if name is specified, but name don't match, return error

matchVolumeTemplateName=${1-all}
storage="$2"
if [[ ${matchVolumeTemplateName} == "all" ]]; then
  ./bin/yq e -i ".spec.volumeClaimTemplates[].spec.resources.requests.storage = \"${storage}\"" "cloneset_modifystorage.yml"
else
  ./bin/yq e -i ".spec.volumeClaimTemplates[] | select(.metadata.name == "\"${matchVolumeTemplateName}\"").spec.resources.requests.storage |= \"${storage}\"" "cloneset_modifystorage.yml"
fi

However, with the above code, only part of the YAML data will be output if a match is found for the specified name, and the file will be empty if name don't match, for example matchVolumeTemplateName=data3

# cloneset_modifystorage.yml
# matchVolumeTemplateName = data1   storage = 90G

# Other data of K8S YAML is lost
metadata:
  creationTimestamp: null
  name: data1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 90G

As a result, other data information about K8S is missing, and an empty file is printed instead of an error when a name match fails.

I really appreciate any help with this.

Upvotes: 0

Views: 417

Answers (1)

Mike Farah
Mike Farah

Reputation: 2584

You're just missing brackets - so it's first filtering the yaml and then updating (instead of updating a specific portion of the yaml):

./bin/yq e -i "(.spec.volumeClaimTemplates[] | select(.metadata.name == "\"${matchVolumeTemplateName}\"").spec.resources.requests.storage) |= \"${storage}\"" "cloneset_modifystorage.yml"

Disclosure: I wrote yq

Upvotes: 1

Related Questions