问题描述
要检查食谱中是否声明了Chef属性, 但它似乎没有按预期运行, 谁能告诉我如何使用“ node.attribute”正确地做到这一点?
这是场景 有一些属性可能在执行Chef-client时未声明,因为此参数是可选参数,可能会在外部将Chef-client -j some.json文件传递给
if node.attribute(node['some']['attr'])
list = node['some']['attr']
else
list = node['defalut_attr']
end
解决方法
在Ruby中,我们可以使用nil
来表示某些内容为空。为了您的目的,可以使用此功能将节点属性最初保留为空。然后根据需要在外部提供一个值。
示例:
在您的attributes/default.rb
中:
default['some']['attr'] = nil
default['default_attr'] = 'one,two,three,four'
在some.json
中:
{
"some": {
"attr": "one,two"
}
}
然后在您的recipes/default.rb
中
list = nil
if node['some']['attr'].nil?
list = node['default_attr']
else
list = node['some']['attr']
end
puts "***** list: #{list}"
现在,如果您通过-j some.json
设置值,则该值将用于list
。否则,list
将设置为node['default_attr']
。
更新:
首次提供-j some.json
时,node attributes已保存。因此,在下一次运行中,['some']['attr']
不再是nil
。要进行这项工作:
- 您将必须
edit node
并删除此属性。 - 以
--override-runlist
模式运行Chef-client(并跳过节点保存)。
示例:
没有some.json
:
~$ chef-client -o recipe[my_cookbook]
Compiling Cookbooks...
***** list: one,four
使用some.json
:
~$ chef-client -o recipe[my_cookbook] -j ./node.json
Compiling Cookbooks...
***** list: one,two
注意:虽然这可以解决此特定要求,但是始终跳过节点保存并不是一个好主意。您可能需要重新考虑利用属性优先级来满足您的用例。
, node.exist?()
助手是专门为它设计的:
list = if node.exist?("some","attr")
node['some']['attr']
else
node['default_attr']
end
还有其他一些使生活更轻松的助手:
# this avoids "trainwrecking" with NoMethodError on NilClass if node["some"] does not exist
# and will return nil if the attribute is not found.
#
list = node.read("some","attr")
# there is also an alias to #dig which was created after Hash#dig was added to ruby:
#
list = node.dig("some","attr")
# this raises a consistent Chef::AttributeNotFound error if the attribute does not exist:
#
list = node.read!("some","attr")
如果确实需要,还可以在子混搭(默认/覆盖/等)上使用所有这些方法:
# this only checks the default level:
node.default.exist?("some","attr")
您可能想考虑一下,如果您正在像这样的各个优先级级别四处浏览,那么您的代码是否对使用方式了解得太深。除了调试目的之外,我会强烈建议不要使用该API。