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



想要检查配方中是否声明了chef属性,但它似乎没有如预期的那样工作,有人能告诉我如何用";node.attribute">

这是一个场景在执行chef-client时,可能没有声明一些属性,因为该参数是可选的,并且可能作为外部传入chef-client-jsome.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时,节点属性已保存。所以在下一次运行中,['some']['attr']不再是nil。实现这一点:

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

示例:

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

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

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

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

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

你可能需要考虑你的代码是否对它的使用方式了解得太多太深,尽管如果你在这样的单个优先级中四处寻找。除了调试目的之外,我强烈反对使用那个API。

最新更新