OphyTe
OphyTe

Reputation: 68

Update an object field defined in an anchor

I have a yaml file which looks like this:

item_value: &item_value
  value: true

array:
  - name: item_1
    <<: *item_value
  - name: item_2
    <<: *item_value

I would like to update the value of the first item in order to have something like this:

array:
  - name: item_1
    value: false
  - name: item_2
    value: true

The only way I found to have something similar is with this expression that I found in the yq (v4) documentation:

yq e '( explode(.) | .array.[] | select(.name == "item_1") | .value = false ) as $test | explode(.) | .array.[] |= (. as $cur | $cur * ($test | select(.name == $cur.name)))' test.yaml

This seems really tricky and I noticed that with the following shorter expression I have the same (bad) result (and I don't understand why this one works by the way):

yq e '( explode(.) | .array.[] | select(.name == "item_1") | .value = false ) as $test' test.yaml

And the result:

item_value:
  value: false
array:
  - name: item_1
    value: false
  - name: item_2
    value: false

Upvotes: 0

Views: 915

Answers (2)

OphyTe
OphyTe

Reputation: 68

The solution is to use merge to break persistant links to the alias :

yq e '(.array[] | select(.name=="item_1")) |= explode(.) * {"value": false}' test.yaml

Upvotes: 0

jpseng
jpseng

Reputation: 2210

Using yq (the Python version, not the Go version you are using) I can solve your task.

#!/bin/bash

FILE='
item_value: &item_value
  value: true

array:
  - name: item_1
    <<: *item_value
  - name: item_2
    <<: *item_value
'

yq -y --arg name "item_1" '(.array[] | select(.name == $name) | .value) |= false' <<< "$FILE"

output

item_value:
  value: true
array:
  - value: false
    name: item_1
  - value: true
    name: item_2

Using yq (the Go version you are using) I also get faulty output with the same expression.

yq e '(.array[] | select(.name == "item_1") | .value) |= false' test.yaml

output

item_value: &item_value
  value: false
array:
  - name: item_1
    !!merge <<: *item_value
  - name: item_2
    !!merge <<: *item_value

using as input

array:
  - name: item_1
    value: true
  - name: item_2
    value: true

everything works fine:

yq e '(.array[] | select(.name == "item_1") | .value) |= false' test.yaml

array:
  - name: item_1
    value: false
  - name: item_2
    value: true

So it is a bug in this yq implementation.

Upvotes: 0

Related Questions