编辑:我想出了我认为是这个最好的方法。 感谢人们回答我的问题 – 一路上有所帮助。 我要发布我的解决scheme,以便其他人可以find它,如果他们想要的。
原问题:
我想用puppet自动configuration一些我们的NFS文件系统。 但是,我希望清单能够确保在正确的networking上拥有知识产权。
Puppet通过
interfaces
和ipaddress_***
事实有助于提供关于机器分配的IP的事实。 问题是我需要检查所有的接口(我宁愿不要假设它们是如何连接的)。
- 如何将string转换为Puppet中的整数?
- 基本木偶:用ENC编写基础架构configuration,样式,方法?
- 我们如何在傀儡环境中实现自动联网?
- 如何安全地禁止用户的密码通过木偶?
- 我怎样才能在puppet需要一些资源?
问题1:木偶可以通过事实列表循环吗? 例如:
for $if in $interfaces { //do something }
问题2:如果Puppet能够做到这一点,是否有一种方法来评估一个string作为一个variables。
interfaces
提供了一个非常好的方法来知道有多lessipaddress_***
和network_***
variables,但即使我可以循环它的值,我需要做一些事情:for $if in $interfaces { $net_var = eval("network_${if}") if $net_var = /^192\.168\.2\.0$/ { //do something } }
这可能吗? 我是否完全错误(对木偶有点新鲜)?
我最终做了什么:
Puppet允许您为模块定义自定义分析器函数。 这些自定义函数只是ruby,所以你可以有效地做任何你想要的内容,包括循环。
你把它们放在<module_dir>/lib/puppet/parser/functions/
。 为了做我想做的,我创build了<module_dir>/lib/puppet/parser/functions/has_network.rb
以下内容:
#has_network.rb require 'ipaddr' module Puppet::Parser::Functions newfunction(:has_network, :type => :rvalue) do |args| retcon = "" if not /^[0-9]{1,3}(\.[0-9]{1,3}){3}\/[0-2]?[0-9]$/.match(args[0]) then raise Puppet::ParseError, "Network provided was not valid. Provide 192.168.0.0/16 format" else requested_network = IPAddr.new(args[0]) interfaces_fact = lookupvar('interfaces') interfaces = interfaces_fact.split(",") interfaces.each do |interface| ip = IPAddr.new(lookupvar("ipaddress_#{interface}")) if requested_network.include?(ip) retcon = "true" end end end retcon end end
这增加了一个新的函数,我可以在我的名为has_network的清单中使用。 如果机器的一个IP地址在提供给该function的networking上,则返回true。 现在我可以做如下的事情:
if has_network("192.168.1.0/24"){ //do something }
一些关于自定义函数的注释
lookupvar
来对Facter事实进行操作。 你不能在客户端上使用其中的一个来创build文件。 正如@Zoredache提到的那样,Puppet中没有循环。 但是你可以通过使用一个定义来解决这个问题,例如:
define show_ip { $inf = "ipaddress_${name}" $ip = inline_template('<%= scope.lookupvar(inf) %>') if $ip =~ /192\.168\.3.*/ { notify {"Found IP $ip": } } } $ifs = split($interfaces, ',') show_ip { $ifs: }
当直接调用时,Belows是输出:
# puppet manifests/defines/net.pp warning: Implicit invocation of 'puppet apply' by passing files (or flags) directly to 'puppet' is deprecated, and will be removed in the 2.8 series. Please invoke 'puppet apply' directly in the future. notice: Found IP 192.168.3.118 notice: /Stage[main]//Show_ip[eth1]/Notify[Found IP 192.168.3.118]/message: defined 'message' as 'Found IP 192.168.3.118' notice: Finished catalog run in 0.07 seconds
资料来源: https : //blog.kumina.nl/tag/puppet-tips-and-tricks/
傀儡中没有循环或迭代。
多了一些,在这里有一个替代版本,应该适用于单个接口上的任意数量的ips,而不使用eval。 to_hash.keys
返回所有variables名称的数组, find_all
过滤基于正则expression式的列表, map
ping用于查找variables的实际值,最后将结果合并回一个string。
$iplist=inline_template('<%= scope.to_hash.keys.find_all{|i| i =~ /ipaddress_.*/}.map{|j| scope.lookupvar(j)}.join(",")%>') if $iplist =~ /10\.2\.93.*/ { notify {"found $iplist": } } # on the client with a matching address we see "notice: found 10.2.93.5,127.0.0.1"
我有一些工作,但我不知道这是真正的最好的解决scheme,或安全。 基本上我想你可以使用inline_template。 在内联模板中,我们分离了接口事实,它是所有接口的列表。 我们使用一个映射来构build一个新的所有接口的IP地址数组,最后我们将数组重新join到一个string中。
我最担心的是我正在做一个基本上由客户端系统提供的东西。 我不完全确定这是多么的邪恶。
如果接口有多个地址,或者接口没有地址,这也会中断。 也许别人可以build议一些改进。 我只是在学习ruby。
$iplist=inline_template('<%= interfaces.split(",").map{|x| eval ("ipaddress_"+x)}.join(",")%>') if $iplist =~ /10\.2\.93.*/ { notify {"found $iplist": } } # on the client with a matching address we see "notice: found 10.2.93.5,127.0.0.1"