15

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

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

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

node[:parent].nil? and node[:parent][:child].nil?

最好能够同时检查父母和孩子,但我不知道这是否可能。我使用的是 Chef 10,而不是 Chef 11,但欢迎提供任何解释的答案。

4

5 回答 5

15

节点属性对象是HashMap。您可以使用 ruby​​ 原生 API 来查找嵌套属性。

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

node.attribute?()
node[:foo].attribute?(:bar)
node[:foo].member?(:bar)

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

node.debug_value(:foo, :bar)

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

于 2013-09-25T00:58:46.947 回答
8

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

if node.exist?('foo', 'bar', 'baz')
  # do stuff with node['foo']['bar']['baz']
end

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

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

fizz = node.read('foo', 'bar', 'baz')

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

fizz = node.dig('foo', 'bar', 'baz')
于 2020-08-21T00:42:38.060 回答
5

我最近解决这个问题的方法是尽可能为食谱中使用的属性设置默认值。

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

default[:parent][:child] = nil

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

node[:parent][:child].nil?

当然,拥有一个可用的默认值并且根本不需要检查通常更有用。

于 2014-07-09T22:13:40.153 回答
2

查看deep_fetch可安全引用深层属性的 chef-sugar 食谱扩展。

于 2014-07-08T23:58:23.263 回答
1

我在这里找到了一个非常优雅的解决方案,它rescue NoMethodErrorif条件结束时使用。

if node['foo']['bar']['baz']
   do the stuff I want
end rescue NoMethodError
于 2020-07-02T20:49:16.913 回答