How to Add / Replace array elements with "yq" conditionally

Viewed 723

I am looking for some help with using "yq" to replace / add existing array elements by name. Also conditionally? Appreciate your help in this regard.

I have tried the below so far.. but this just merges and I am getting duplicates when I rerun this after updates.

yq eval-all '... comments="" | . as $item ireduce ({}; . *+ $item)' kong-oauth.yaml kong-apikey.yaml

Following scenario, I like to updated "Master.yaml" 'services' array only by name.

Master.yaml

services:
 - name: service1
   url: https://service1.microservice.net
 - name: service2
   url: https://service2.microservice.net

service3.yaml

services:
 - name: service3
   url: https://service3.microservice.net

service2.yaml

services:
 - name: service2
   url: https://service22.microservice.net

Expected YAML

services:
 - name: service1
   url: https://service1.microservice.net
 - name: service2
   url: https://service22.microservice.net
 - name: service3
   url: https://service3.microservice.net

Thanks Sanjay

2 Answers

I don't have enough rep to comment on your answer @kev - but that is super neat. I'm going to clean it up a little and put it into the tips and tricks in the yq docs.

I've made it a little more generic and put it all in one command:

yq ea '.services = (
  ((.services[] | {.name: .}) as $item ireduce ({}; . * $item )) as $uniqueMap
  | ( $uniqueMap  | to_entries | .[]) as $item ireduce([]; . + $item.value)
) | select(fi==0)' *.yaml

Disclosure: I wrote yq

  • ireduce({}; . * $item) - create an object
  • ireduce([]; . + $item) - create an array
yq ea '(.services[] | {.name: .url}) as $item ireduce ({}; . * $item ) | to_entries' Master.yaml service*.yaml |
  yq e '{"services": .[] as $item ireduce([]; . + {"name": $item.key, "url": $item.value})}' -

read more

Related