【问题标题】:Update Yaml with jinja 2 variables in it使用 jinja 2 变量更新 Yaml
【发布时间】:2021-11-16 19:53:44
【问题描述】:

我有一个类似于这篇文章的用例: How can I update a .yml file, ignoring preexisting Jinja syntax, using Python?

我尝试遵循其中给出的答案,但没有一个适用于我的 YAML 语法。以下是我的 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 }}

另一件事是我的 YAML 中有多个模板。

我的用例更多用于 Node JS,但由于我找不到该语言的任何解决方案,所以我转向 Python。

【问题讨论】:

  • 如果您的用例是在不解释模板指令的情况下修改显示的输入,那么您需要一个可以表示该结构的数据模型,包括模板指令。通常,在您使用 Jinja 处理输入之前,您的输入不是有效的 YAML,因此您无法使用 YAML 解析器加载未处理的输入。 OTOH,Jinja 是一个解释器,据我所知,它不提供对模板结构的 API 访问——即使提供了,非 Jinja 部分也会是断开的字符串,可能不会解析为独立的 YAML 片段。这是在工作中使用错误工具的情况。
  • 现在的问题是,什么是正确的工具?有可能,但没有明确的答案。最重要的是,XML 有可能在其 DOM 中表示处理指令。您也可以尝试直接在 YAML 中编码您的模板指令,而不是使用 Jinja,这通常可以使用本地标签(例如 !expr .Chart.Name 而不是 {{ .Chart.Name}}),但是当您想要将字符串连接到一个值时很快就会变得混乱。您可能想要编辑您的问题以更详细地说明您的用例,但总的来说,这对于 SO 来说太复杂了。

标签: python node.js yaml pyyaml ruamel.yaml


【解决方案1】:

问题是你链接到的答案,以及ruamel.yaml.jinja2的版本 您正在使用的不知道 jinja2 的 if 语句。装载期间 {{-{{ 部分被替换,因此它可以被识别为 YAML,但这会导致解析问题 (因为它没有正确缩进,也没有键值对)。 相反,它应该变成某种形式的注释,就像在 ruamel.yaml.jinja2 版本 0.2.6 中所做的那样。

您可以加载、更新和转储此多文档 YAML 文件:

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')

给出:

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 }}

【讨论】:

  • 现在它说最新版本是 0.2.4,尽管我可以在 pypi.org 上看到更新的版本。不确定是否需要时间通过 pip 进行反映
  • 我可以安装它,我的一些配置问题,它也能正常工作。现在我有另一个问题:我们在这里解析 helm bundles,它可能包含任何带有任何 jinja 变量的文件。那么我可以期望这个库能够处理所有这些场景,还是仍然有某些类型尚不支持?
  • 我最初只为{{ }}样式变量设置它。我从来没有看过 jinja2,也不知道它的完整语法是什么。
猜你喜欢
  • 2022-01-10
  • 2018-11-03
  • 1970-01-01
  • 1970-01-01
  • 2022-08-08
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多