检查Chef中是否存在嵌套属性的正确方法是什么?

bor*_*ing 10 ruby chef-infra chef-recipe

有多种方法可以检查chef中是否存在嵌套属性,我不确定哪个是正确/最好的,如果有的话会导致在节点上存储空属性:

node[:parent] and node[:parent][:child]

node.attribute?(:parent) and node[:parent].attribute?(:child))

node[:parent].nil? and node[:parent][:child].nil?
Run Code Online (Sandbox Code Playgroud)

能够同时检查父母和孩子是非常优先的,但我不知道是否可能.我正在使用厨师10,而不是厨师11,尽管答案解释任何一个都是受欢迎的.

sha*_*zhu 15

节点属性对象是HashMap.您可以使用ruby native API来查找嵌套属性.

Chef Node Object提供了许多辅助方法,例如:

node.attribute?()
node[:foo].attribute?(:bar)
node[:foo].member?(:bar)
Run Code Online (Sandbox Code Playgroud)

node.debug_value()chef 11中还有一个新方法可以帮助您调试节点属性,这也很有用:

node.debug_value(:foo, :bar)
Run Code Online (Sandbox Code Playgroud)

详细信息可以从Chef 11 In-Depth:Attributes Changes一文中找到


lam*_*ont 7

正确的“现代”方法是使用exist?()助手:

if node.exist?('foo', 'bar', 'baz')
  # do stuff with node['foo']['bar']['baz']
end
Run Code Online (Sandbox Code Playgroud)

这取代了旧的 Chef-sugardeep_fetch机制,并且在这一点上已经内置到 Chef-client 中很长时间了。

还有一个read()帮助程序来获取值,如果任何中间键不存在,它将返回 nil:

fizz = node.read('foo', 'bar', 'baz')
Run Code Online (Sandbox Code Playgroud)

它与后来添加到 ruby​​ 的 Hash#dig 方法相同,它也被支持作为别名:

fizz = node.dig('foo', 'bar', 'baz')
Run Code Online (Sandbox Code Playgroud)


bor*_*ing 5

我最近解决这个问题的方法是始终在可能的情况下为菜谱中使用的属性设置默认值.

例如,cookbook/attributes/default.rb将包含:

default[:parent][:child] = nil
Run Code Online (Sandbox Code Playgroud)

在配方中,对属性值的任何检查都可以简化为:

node[:parent][:child].nil?
Run Code Online (Sandbox Code Playgroud)

当然,拥有可用的默认值通常更有用,而且根本不需要检查.