Puppet 6.28 ERB模板迭代中引入子模板的变量作用域问题
Puppet 6.28 ERB子模板无法访问迭代变量的问题解决
问题本质
你遇到的不是操作错误,而是对Puppet模板作用域的理解偏差:
- Puppet的
template()函数(包括通过scope.call_function调用的)是从Puppet全局/类作用域加载变量,不会共享当前ERB模板迭代过程中的局部Ruby变量(比如erbvar)。 - ERB迭代产生的
erbvar存在于模板渲染的Ruby局部上下文里,而template()函数是在Puppet的Ruby运行时层面执行,两者作用域完全隔离。
解决方案
方案1:使用ERB原生render方法(推荐)
Puppet 6的ERB模板支持render方法引入子模板,它会自动传递当前的Ruby局部上下文,子模板可直接访问迭代变量:
主模板代码:
@puppetvar.each do |erbvar| <%= render('path/to/sub_template.erb') %> end
子模板(sub_template.erb)直接使用erbvar:
# 直接调用迭代变量erbvar 示例值:<%= erbvar['target_key'] %>
方案2:通过template()函数传递变量
如果必须使用template()函数,可在调用时通过第二个参数传递哈希形式的变量,子模板通过@前缀访问:
主模板代码:
@puppetvar.each do |erbvar| <%= scope.call_function('template', ["path/to/sub_template.erb", { 'erbvar' => erbvar }]) %> end
子模板代码:
# 通过@前缀访问传递的变量 示例值:<%= @erbvar['target_key'] %>
注意事项
- 明确区分ERB局部变量(无@前缀)和Puppet模板变量(@前缀):前者仅存在于当前ERB的Ruby上下文,后者来自Puppet的类/全局作用域。
- Puppet 6.28完全支持上述两种方案,无需升级版本。
内容的提问来源于stack exchange,提问作者Mike Williams
相关产品推荐
相关产品推荐

