我有一个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
中的第一个主机名变量也没有被考虑在内。
当前代码中存在一些问题:
- 使用
return config
,您只是退出函数而不写入文件。 - 每次以写模式
w
打开文件,以便内容被覆盖。 - 您正在添加
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)