【问题标题】:how to use node.attribute to check if node attribute exist or not?如何使用 node.attribute 检查节点属性是否存在?
【发布时间】:2020-12-03 11:51:34
【问题描述】:

想检查是否在食谱中声明了厨师属性, 但它似乎没有按预期工作, 谁能告诉我如何使用“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 chef-infra cookbook


    【解决方案1】:

    在 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。要完成这项工作:

    1. 您必须edit node 并删除此属性。
    2. --override-runlist 模式运行chef-client(并跳过节点保存)。

    例子:

    没有some.json

    ~$ chef-client -o recipe[my_cookbook]
    
    Compiling Cookbooks...
    
    ***** list: one, two, three, four
    

    some.json:

    ~$ chef-client -o recipe[my_cookbook] -j ./node.json
    
    Compiling Cookbooks...
    
    ***** list: one, two
    

    注意:虽然这将解决这个特殊要求,但始终跳过节点保存并不是一个好主意。您可能需要重新考虑使用属性优先级来为您的用例工作。

    【讨论】:

    • some.json 文件包含 "some":{ "attr":"one,two"} ,但是通过 "default_attr" = "one,two,three, fouur,five", 没有运行 chef - 带有 some.json 的客户端,它应该采用 default_attr ,但在运行结果中它采用 ['some']['attr']
    • default_attr 是否也在some.json 中定义?我认为你应该在attributes/default.rb 中声明default['default_attr']
    • 是的,它在外部 json 和内部属性默认文件中都被声明了
    • some.json 指定的属性可能会在 chef-client 完成时保存在节点上。我会更新我的答案。
    • 不知道究竟是什么问题,但它今天早上开始工作,甚至没有在默认属性文件中声明 nil 属性。
    【解决方案2】:

    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")
    

    另外,如果你真的需要,你可以在 sub-Mashes 上使用所有这些方法(默认/覆盖/等):

    # this only checks the default level:
    node.default.exist?("some", "attr")
    

    您可能想要考虑您的代码是否对它的使用方式了解得太深,但如果您在这样的各个优先级中四处寻找。除了用于调试目的之外,我强烈反对使用该 API。

    【讨论】:

      猜你喜欢
      • 2021-06-06
      • 1970-01-01
      • 2023-04-03
      • 2019-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-30
      • 1970-01-01
      相关资源
      最近更新 更多