如何修正Puppet ERB以正确输出Hiera定义的数组?
解决Puppet ERB将Hiera数组转为Elasticsearch格式配置的问题
我明白你现在的需求:要把Hiera里定义的数组,通过Puppet ERB模板生成符合Elasticsearch要求的discovery.zen.ping.unicast.hosts: ["stage-01.com", "stage-02.com"]格式,而不是把数组输出成无引号的拼接字符串。
直接在ERB模板中处理数组的方案
你可以利用Ruby的map和join方法,给数组中的每个元素加上双引号,再用逗号分隔后包裹到方括号里。假设你已经能正确获取到profiles::xxx::master_servers这个数组,对应的ERB代码可以这么写:
discovery.zen.ping.unicast.hosts: ["<%= scope.lookupvar('profiles::xxx::master_servers').map { |host| %Q("#{host}") }.join(', ') %>"]
代码解释:
scope.lookupvar('profiles::xxx::master_servers'):直接从Puppet作用域中获取Hiera定义的数组(如果你的manifest已经把这个数组赋值给了模板的实例变量,比如@master_servers,可以直接替换成@master_servers)。map { |host| %Q("#{host}") }:遍历数组中的每个主机名,用%Q语法给每个元素包裹双引号(避免转义字符的麻烦)。join(', '):把所有带引号的主机名用「逗号+空格」连接起来。
如果你的数组是["stage-01.com", "stage-02.com"],这段代码会精准输出你需要的格式。
另一种方案:在Puppet Manifest中预处理数组
如果你希望模板更简洁,可以把格式化逻辑放在Puppet manifest里完成,再把处理好的字符串传给模板:
- 在manifest中添加处理逻辑:
# 从Hiera获取原始数组 $master_servers = lookup('profiles::xxx::master_servers') # 格式化每个元素为带引号的字符串,再拼接 $formatted_hosts = join($master_servers.map |$host| { "\"${host}\"" }, ', ')
- 在ERB模板中直接使用预处理后的变量:
discovery.zen.ping.unicast.hosts: ["<%= @formatted_hosts %>"]
为什么之前的代码会输出单个字符串?
大概率是你之前直接输出了数组本身(比如<%= @master_servers %>),或者只用了join但没给元素加引号。Ruby数组默认的字符串转换格式是["a", "b"],但Elasticsearch的配置要求每个元素必须是双引号包裹的字符串,所以必须显式处理每个元素的格式。
内容的提问来源于stack exchange,提问作者nitin
相关产品推荐
相关产品推荐

