I want to add additional tag value to below yaml contents.
Base Yaml
infra:
etcd:
container:
replica_count: 3
resource:
limit_memory: 1000Mi
limit_cpu: 1000m
requests_memory: 1000Mi
requests_cpu: 1000m
volume:
storageClaim: 5Gi
storageCapacity: 5Gi
kafka:
container:
replica_count: 3
resource:
limit_memory: 2000Mi
limit_cpu: 1000m
requests_memory: 2000Mi
requests_cpu: 1000m
volume:
storageClaim: 10Gi
storageCapacity: 10Gi
zk:
container:
replica_count: 3
resource:
limit_memory: 500Mi
limit_cpu: 1000m
requests_memory: 500Mi
requests_cpu: 1000m
volume:
storageClaim: 10Gi
storageCapacity: 10Gi
After Update
infra:
etcd:
container:
**image:
tag: etcd-21.3.4**
replica_count: 3
resource:
limit_memory: 1000Mi
limit_cpu: 1000m
requests_memory: 1000Mi
requests_cpu: 1000m
volume:
storageClaim: 5Gi
storageCapacity: 5Gi
kafka:
container:
**image:
tag: kafka-21.3.4**
replica_count: 3
resource:
limit_memory: 2000Mi
limit_cpu: 1000m
requests_memory: 2000Mi
requests_cpu: 1000m
volume:
storageClaim: 10Gi
storageCapacity: 10Gi
zk:
container:
**image:
tag: zk-21.3.4**
replica_count: 3
resource:
limit_memory: 500Mi
limit_cpu: 1000m
requests_memory: 500Mi
requests_cpu: 1000m
volume:
storageClaim: 10Gi
storageCapacity: 10Gi
I am new to python and yaml handling, Any reference will help. I am able open & close the files but not able to get specific guideline to add/remove/update the new tag & value. even contents.update is removing the data after the first image tag update.
import yaml
# Read the YAML file
with open ('in.yaml', 'r') as read_file:
contents = yaml.safe_load(read_file)
contents['infra']['etcd'] = 'Image'
# Write the YAML file with sort_keys=False to retain same order
with open('in.yaml', 'w') as write_file:
yaml.dump(contents, write_file, sort_keys=False)
CodePudding user response:
Your YAML loads into a Python datastructure, where the value for key 'etcd'
is a dictionary. If
you replace that dictionary by doing:
contents['infra']['etcd'] = 'Image'
you replace the value (i.e. the dictionary) with a single string and you won't get the output that you show.
To get the part between **
, you need to update the value for container with a
dict`:
import sys
from pathlib import Path
import ruamel.yaml
file_in = Path('input.yaml')
yaml = ruamel.yaml.YAML()
data = yaml.load(file_in)
for key in ['etcd', 'kafka', 'zk']:
data['infra'][key]['container'].insert(0, 'image', dict(tag=f'{key}-21.3.4'))
yaml.dump(data, sys.stdout)
which gives:
infra:
etcd:
container:
image:
tag: etcd-21.3.4
replica_count: 3
resource:
limit_memory: 1000Mi
limit_cpu: 1000m
requests_memory: 1000Mi
requests_cpu: 1000m
volume:
storageClaim: 5Gi
storageCapacity: 5Gi
kafka:
container:
image:
tag: kafka-21.3.4
replica_count: 3
resource:
limit_memory: 2000Mi
limit_cpu: 1000m
requests_memory: 2000Mi
requests_cpu: 1000m
volume:
storageClaim: 10Gi
storageCapacity: 10Gi
zk:
container:
image:
tag: zk-21.3.4
replica_count: 3
resource:
limit_memory: 500Mi
limit_cpu: 1000m
requests_memory: 500Mi
requests_cpu: 1000m
volume:
storageClaim: 10Gi
storageCapacity: 10Gi
I am using my ruamel.yaml
package which is an improvement of PyYAML, supporting the newer YAML 1.2 standard (released in 2009).
It also allows you to insert (i.e. update at a specific position wrt the list of keys) in the mapping/dict
that you loaded from YAML (to get the key image
in the first position), and will also preserves
any comments, aliases, key orderinng, etc that you might have in your file. (If needed you can also preserve superfluous quotes around scalars, but you don't have any in your input)