如何使用node.attribute检查node属性是否存在?

问题描述

要检查食谱中是否声明了Chef属性, 但它似乎没有按预期运行, 谁能告诉我如何使用“ 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中,我们可以使用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,four

使用some.json

~$ chef-client -o recipe[my_cookbook] -j ./node.json

Compiling Cookbooks...

***** list: one,two

注意:虽然这可以解决此特定要求,但是始终跳过节点保存并不是一个好主意。您可能需要重新考虑利用属性优先级来满足您的用例。

,

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

如果确实需要,还可以在子混搭(默认/覆盖/等)上使用所有这些方法:

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

您可能想考虑一下,如果您正在像这样的各个优先级级别四处浏览,那么您的代码是否对使用方式了解得太深。除了调试目的之外,我会强烈建议不要使用该API。