在Python中从for循环生成动态YAML文件



我有一个template.yml,内容如下:

hostname:
image: my_image:latest
script:
- ansible -m command -a "echo Hi"  hostname

使用python,我需要读取具有以下内容的.txt文件:

server1.example.com
server2.example.com
server3.example.com
...

和使用一些循环和替换主机名变量在以上template.yml的两个地方。所有的配置需要放在一个output.yml文件中。

我一直在尝试使用python yaml库及其yaml。更新和yaml。转储特性,但未能将所有生成的配置存储在同一个输出文件中。如有任何帮助,不胜感激。

更新:

我已经在下面添加了我尝试的代码:

import yaml
def generate_yml(host):
with open('template.yml') as f:
config = yaml.safe_load(f)
config['hostname']['script'] = "ansible -m command -a 'echo Hi' " + host
return config
with open('output.yml', 'w') as f:
yaml.dump(config, f, default_flow_style=False)
hostfile = open("test.txt", "r")
for host in hostfile:
host = host.rstrip("n")
generate_yml(host)
myfile.close()

yaml_update,我尝试:

with open('output.yml','r') as f:
config = yaml.load(yamlfile)
config['hostname']['script'] = "ansible -m command -a 'echo Hi' " + host  
config['hostname'].update(config)

with open('output.yml', 'w') as yamlfile:
yaml.dump(config, yamlfile, default_flow_style=False)

这两种方法都只为.txt文件中的最后一个条目写入配置,并且template.yml中的第一个主机名变量也没有被考虑在内。

当前代码中存在一些问题:

  1. 使用return config,您只是退出函数而不写入文件。
  2. 每次以写模式w打开文件,以便内容被覆盖。
  3. 您正在添加script部分作为字符串对象,但它应该是list的正确yaml

正确的实现应该是:

import yaml
def generate_yml(host):
with open('template.yml') as f:
config = yaml.safe_load(f)
config[host] = config['hostname'].copy()
config[host]['script'] = ["ansible -m command -a 'echo Hi' " + host] # add the command as a list for the correct yaml
del config['hostname']   # del the 'hostname' key from config
with open('output.yml', 'a') as f: # open the file in append mode
yaml.dump(config, f, default_flow_style=False)
hostfile = open("test.txt", "r")
for host in hostfile:
host = host.rstrip("n")
generate_yml(host)
hostfile.close()

输出:

server1.example.com:
image: my_image:latest
script:
- ansible -m command -a 'echo Hi' server1.example.com
server2.example.com:
image: my_image:latest
script:
- ansible -m command -a 'echo Hi' server2.example.com
server3.example.com:
image: my_image:latest
script:
- ansible -m command -a 'echo Hi' server3.example.com

YAML不是一个模板引擎。您考虑过使用模板引擎吗?

pystache可以这样做:

import pystache, yaml
input = """
{{#hostnames}}
{{.}}:
image: my_image:latest
script:
- ansible -m command -a "echo Hi"  {{.}}
{{/hostnames}}
"""
vars = """
server1.example.com
server2.example.com
server3.example.com
"""
print(pystache.render(input, {"hostnames": [h for h in vars.splitlines() if h]}))

输出:

server1.example.com:
image: my_image:latest
script:
- ansible -m command -a "echo Hi"  server1.example.com
server2.example.com:
image: my_image:latest
script:
- ansible -m command -a "echo Hi"  server2.example.com
server3.example.com:
image: my_image:latest
script:
- ansible -m command -a "echo Hi"  server3.example.com

与实际将输入解析为YAML相比,使用模板引擎时可以保持格式化(例如注释和原始缩进)。

试试这个。它将模板作为字典加载,并为每个主机使用适当的hostname替换形成一个新字典,并将整个内容转储到output.yml文件中。注意,这需要PyYaml -pip insatll pyyaml

import yaml

with open("./template.yml") as f:
template = yaml.load(f)
HOSTS = [
"host_a",
"host_b",
"host_c"
]
output = {host: template["hostname"] for host in HOSTS}

with open("./output.yml", "w") as f:
yaml.dump(output, f)

相关内容

  • 没有找到相关文章

最新更新