使用变量通过python访问/替换Yaml值



我一直在尝试解决我认为很简单的问题,但无法解决根据变量更新yaml文件的问题

我有什么:

  1. YAML 格式的 ansible 主机文件。 此主机文件并非始终 100% 相同。 它可以有一个包含多个图像值的字典(作为一个例子(,我只想更改一个。

    namespace: demo1
    images:
    image1:
    path: "path1"
    version: "v1"
    image2:
    path: "path2"
    version: "1.2.3"
    user: "root"
    
  2. 一个 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 和任意分隔符(不一定是"."(已解决通过点表示法进行检索的问题。设置只涉及提供两个额外的函数,这些函数接受第二个参数,这是设置并将它们嫁接到CommentedMapresp 的值。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

最新更新