【问题标题】:What is the correct way to check for the existence of a nested attribute in Chef?检查 Chef 中是否存在嵌套属性的正确方法是什么?
【发布时间】:2020-08-21 08:42:38
【问题描述】:

有多种方法可以检查 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,但欢迎提供任何解释的答案。

【问题讨论】:

    标签: ruby chef-infra chef-recipe


    【解决方案1】:

    节点属性对象是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

    【讨论】:

      【解决方案2】:

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

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

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

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

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

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

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

      【讨论】:

        【解决方案3】:

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

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

        default[:parent][:child] = nil
        

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

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

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

        【讨论】:

          【解决方案4】:

          查看 chef-sugar 食谱 deep_fetch 扩展,它允许安全引用深层属性。

          【讨论】:

            【解决方案5】:

            我找到了一个非常优雅的解决方案here,它在if 条件的末尾使用rescue NoMethodError

            if node['foo']['bar']['baz']
               do the stuff I want
            end rescue NoMethodError
            

            【讨论】:

            • 这也将挽救由添加到条件中的任何其他子句引起的任何 NoMethodError(因此在扩展至 if node['foo']['bar']['baz'] && shoulddoit? 将吞噬 def shoulddoit? 中引发 NoMethodError 的任何编程错误)。它还将挽救由“做我想做的事情”块引发的任何 NoMethodError。对于绝对微不足道的情况,这是可行的,但是一旦微不足道的情况变得复杂,这将极大地阻碍调试任何东西的能力。不应使用此解决方案。
            • 如果作者在链接的网页中打错了include_recipie "ganglia::default"(食谱中有额外的 i,这是一个相当常见的错字),那么救援会吞下有关错字的错误。
            猜你喜欢
            • 1970-01-01
            • 2019-09-16
            • 2011-10-19
            • 1970-01-01
            • 2013-03-31
            • 2012-04-02
            • 1970-01-01
            • 2019-12-11
            • 2013-10-13
            相关资源
            最近更新 更多