有多种方法可以检查chef中是否存在嵌套属性,我不确定哪个是正确的/最好的,如果有的话会导致在节点上存储空属性:
node[:parent] and node[:parent][:child]
node.attribute?(:parent) and node[:parent].attribute?(:child))
node[:parent].nil? and node[:parent][:child].nil?
能够同时检查父母和孩子是非常优先的,但我不知道这是否可行。我使用厨师10,而不是厨师11,但欢迎解答任何一个。
答案 0 :(得分:15)
节点属性对象是HashMap。您可以使用ruby native API来查找嵌套属性。
Chef Node Object提供了许多辅助方法,如:
node.attribute?()
node[:foo].attribute?(:bar)
node[:foo].member?(:bar)
Chef 11中还有一个新方法node.debug_value()
来帮助您调试节点属性,这也很有帮助:
node.debug_value(:foo, :bar)
答案 1 :(得分:5)
我最近解决这个问题的方法是尽可能为菜谱中使用的属性设置默认值。
例如,cookbook/attributes/default.rb
将包含:
default[:parent][:child] = nil
在配方中,对属性值的任何检查都可以简化为:
node[:parent][:child].nil?
当然,拥有可用的默认值通常更有用,而且根本不需要检查。
答案 2 :(得分:2)
查看chef-sugar cookbook deep_fetch
扩展程序,以便安全引用深层属性。
答案 3 :(得分:2)
正确的“现代”方法是使用exist?()
帮助器:
if node.exist?('foo', 'bar', 'baz')
# do stuff with node['foo']['bar']['baz']
end
这取代了旧的厨师-糖deep_fetch
机制,并且在很长一段时间内已被内置到厨师-客户端中。
还有一个read()
助手来获取值,如果中间键不存在,它将返回nil:
fizz = node.read('foo', 'bar', 'baz')
它与后来添加到ruby的Hash#dig方法相同,后者也支持作为别名:
fizz = node.dig('foo', 'bar', 'baz')
答案 4 :(得分:1)
我发现了一个非常优雅的解决方案here,它在rescue NoMethodError
条件的末尾使用if
。
if node['foo']['bar']['baz']
do the stuff I want
end rescue NoMethodError