我一直在尝试解决我认为很简单的问题,但无法解决根据变量更新yaml文件的问题
我有什么:
-
YAML 格式的 ansible 主机文件。 此主机文件并非始终 100% 相同。 它可以有一个包含多个图像值的字典(作为一个例子(,我只想更改一个。
namespace: demo1 images: image1: path: "path1" version: "v1" image2: path: "path2" version: "1.2.3" user: "root"
-
一个 YAML 文件,其中包含我要替换的内容的键/值。 我们已经在这个 YAML 中为我们系统的其他部分进行了大量配置,所以我不想拆分为其他类型的配置类型,如果我能帮助它(ini、JSON 等(,我真的希望这是点符号。
schema: v1.0 hostfile: - path: path/to/ansible_hosts_file images: image1.version: v1.1
我正在尝试找到一种从 #1 加载 YAML 的方法,在密钥 hostfile.images 中读取。变量],以替换原始 Ansible 文件并将其写回新值。我一直在变量方面被绊倒,因为今天它可以是 image1.version 和下一个配置它的 image2.path 或同时配置两者。
我认为您的问题主要来自将键值对与虚线符号混合在一起。 即
images:
image1.version: v1.1
而不是做
images.image1.version: v1.1
在此答案中,Python 和任意分隔符(不一定是"."(已解决通过点表示法进行检索的问题。设置只涉及提供两个额外的函数,这些函数接受第二个参数,这是设置并将它们嫁接到CommentedMap
resp 的值。CommentesSeq
(
基于此,您需要根据您的密钥进行预选:
upd = ruamel.yaml.round_trip_load(open('update.yaml')
# schema check here
for hostfile in upd['hostfile']:
data = ruamel.yaml.round_trip_load(open(hostfile['path']))
images = data['images']
for dotted in hostfile['images']:
val = hostfile['images'][dotted]
images.string_set(dotted, val)
实际的string_set
-ting代码可能如下所示(未经测试(:
def mapping_string_set(self, s, val, delimiter=None, key_delim=None):
def p(v):
try:
v = int(v)
except:
pass
return v
# possible extend for primitives like float, datetime, booleans, etc.
if delimiter is None:
delimiter = '.'
if key_delim is None:
key_delim = ','
try:
key, rest = s.split(delimiter, 1)
except ValueError:
key, rest = s, None
if key_delim in key:
key = tuple((p(key) for key in key.split(key_delim)))
else:
key = p(key)
if rest is None:
self[key] = val
return
self[key].string_set(rest, val, delimiter, key_delim)
ruamel.yaml.comments.CommentedMap.string_set = mapping_string_set
def sequence_string_set(self, s, delimiter=None, key_delim=None):
if delimiter is None:
delimiter = '.'
try:
key, rest = s.split(delimiter, 1)
except ValueError:
key, rest = s, None
key = int(key)
if rest is None:
self[key] = val
return
self[key].string_set(rest, val, delimiter, key_delim)
ruamel.yaml.comments.CommentedSeq.string_set = sequence_string_set