Update Yaml with jinja 2 variables in it

I have a use case similar to this post: How can I update a .yml file, ignoring preexisting Jinja syntax, using Python?

I tried to follow the answers given in that but none of those working for my YAML syntax. Following is my YAML:

kind: Service
metadata:
  name: {{ .Chart.Name }}
  labels:
    app: {{ .Chart.Name }}
    service: {{ .Chart.Name }}
spec:
{{- if eq .Values.global.node.networkIpVersion "ipv6" }}
  ipFamily: IPv6
{{- end }}
  type: ClusterIP
  ports:
  - name: http2-8080
    protocol: TCP
    port: 8080
    targetPort: 8080
  selector:
    app: {{ .Chart.Name }}
---
apiVersion: v1
kind: Service
metadata:
  name: {{ .Chart.Name }}-traffic
  labels:
    app: {{ .Chart.Name }}
    service: {{ .Chart.Name }}-traffic
spec:
  ports:
  - name: http-2112
    port: {{ .Values.global.monitor.prometheusExporter.trafficListenPort }}
    protocol: TCP
    targetPort: 2112
  selector:
    app: {{ .Chart.Name }}

Another thing is my YAML has more than one template in it.

My use case is more for Node JS but as I couldn’t find any solution in that language so I turned to Python.

Answer

The problem is that the answer you link to, as well as the version of ruamel.yaml.jinja2 that you are using do not know about the jinja2’s if-statement. During loading the {{ part of {{- is replaced so it can be recognised as YAML, but that causes parsing issues (because it isn’t indented properly nor a key-value pair). Instead it should be turned into some form of comment, as is done in ruamel.yaml.jinja2 version 0.2.6.

With that you can load, update and dump this multidocument YAML file:

import os
import sys
import pathlib
import ruamel.yaml


input = pathlib.Path('input.yaml')

yaml = ruamel.yaml.YAML(typ='jinja2')

print('ruamel.yaml.jinja2 version:', ruamel.yaml.jinja2.__version__)
print('====================')
sys.stdout.flush()
data = list(yaml.load_all(input))
# print(data)
data[0]['spec']['ports'][0]['port'] = 1234  # first document update
data[1]['spec']['ports'][0]['targetPort'] = 5678  # second document update
yaml.dump_all(data, pathlib.Path('output.yaml'))

os.system('diff -u input.yaml output.yaml')

which gives:

ruamel.yaml.jinja2 version: 0.2.6
====================
--- input.yaml  2021-09-23 14:55:42.303722955 +0200
+++ output.yaml 2021-09-23 15:13:14.663716699 +0200
@@ -12,7 +12,7 @@
   ports:
   - name: http2-8080
     protocol: TCP
-    port: 8080
+    port: 1234
     targetPort: 8080
   selector:
     app: {{ .Chart.Name }}
@@ -29,6 +29,6 @@
   - name: http-2112
     port: {{ .Values.global.monitor.prometheusExporter.trafficListenPort }}
     protocol: TCP
-    targetPort: 2112
+    targetPort: 5678
   selector:
     app: {{ .Chart.Name }}