Search code examples
kubernetesyamlyq

yq split kinds and unique name: -s is not keeping unique kind and metadata.name


Below is my testfile.yaml:

---
kind: Pod
metadata:
  name: amazing-application
---
kind: Deployment
metadata:
  name: amazing-deployment
---
kind: Service
metadata:
  name: amazing-deployment
---
kind: Service
metadata:
  name: tea-service

My goal is to split this into 4 files where the filename is .metadata.name and the dir that file goes into is .kind.

I have achieved what I want with this:

for kind in $(yq e '.kind' testfile.yaml | awk '!/^(---)/' | uniq); 
do 
  mkdir "$kind"
  cd "$kind"
  yq 'select(.kind == "'$kind'")' ../testfile.yaml | yq -s '.metadata.name' 
  cd ..;
done

What I want to know is how to get a unique together mapping, or somehow using multple criteria to split the testfile rather than through the loop.

Is there a way to use yq and -s or select to select where kind and metadata.name are unique together in that individual document (document as in separated by '---')?

Because if you do yq -s '.kind' testfile.yaml it will yield three yaml files, not four. Same for yq -s '.metadata.name' testfile.yaml; we get three files as not all name are unique - one gets lost.


Solution

  • There are a few ways you can do this direct in yq.

    First of, you can use string concatenation with another property to comeup with a unique filename:

    yq -s '(.kind | downcase) + "_" + .metadata.name' testfile.yaml
    

    That will create files like:

    deployment_amazing-deployment.yml
    pod_amazing-application.yml
    service_amazing-deployment.yml
    service_tea-service.yml
    

    Or you can use the built in $index to make the filenames unique:

    yq -s '.metadata.name + "_" + $index'
    

    Which will create:

    amazing-application_0.yml
    amazing-deployment_1.yml
    amazing-deployment_2.yml
    tea-service_3.yml
    

    Disclaimer: I wrote yq