【问题标题】:Can I use sort and uniq on an array of chef node attributes?我可以在厨师节点属性数组上使用 sort 和 uniq 吗?
【发布时间】:2020-12-06 00:36:13
【问题描述】:

我们有一个生成 bash 脚本的模板,其中包括要根据节点属性(特别是分配给节点的角色)检查的补丁列表。

patchlist=( <%= node['oracledb']['install']['oneoff']['db_oo_apply'] rescue nil %> <%= node['oracledb']['install']['oneoff']['db_psu_num'] rescue nil %> )

我已经剪掉了一些实际的列表,但你明白了。

问题是这些属性之间可能存在重复条目,因此我们希望对它们进行排序并获得一个唯一列表。

此外,更复杂的是,并非每个环境中的所有节点都具有这些属性 - 这就是我们将rescue nil 撒在其中的原因。

我可以将数组构建为

patchlist=( <%= ( node['oracledb']['install']['oneoff']['db_oo_apply'] + ' ' + node['oracledb']['install']['oneoff']['db_psu_num'] rescue nil).split(' ').uniq.sort.join(' ') %> )

如果所有属性都有值,那么它会起作用。

但似乎发生的情况是,如果列表中的任何单个属性为空,rescue nil 就会启动并且整个数组返回为 nil。

我认为在第一个变体中,rescue nil 的范围仅限于特定属性,但在第二个变体中,它适用于整个字符串。

那么,我能否以某种方式构建这个数组,让它排序且唯一,并且仍然控制数组中单个元素可能为空的情况?

【问题讨论】:

  • 如何在厨师食谱中执行属性逻辑并仅使用 ERB 来渲染计算变量?

标签: ruby chef-infra


【解决方案1】:

只需使用纯红宝石,例如:

irb(main):001:0> ([nil] + [2,1]).compact.uniq.sort
=> [1, 2]

简而言之,将数组连接成一个新数组compact 以获取连接数组的副本,其中所有nil 元素已删除,然后应用uniqsort

【讨论】:

    【解决方案2】:

    实现这一点的一种方法是创建一个实际的节点属性数组。在您当前的实现中,它不是数组,只是用空格分隔的属性。

    这在模板上有点逻辑过载,但它应该可以工作。

    示例模板:

    <% p_list = %W( #{node['oracledb']['install']['oneoff']['db_oo_apply']} #{node['oracledb']['install']['oneoff']['db_psu_num']} )
    
    <% p_list_fin = p_list.uniq.sort %>
    
    patchlist=( <% p_list_fin.each do |p| %><% next if p.nil? %><%= p %> <% end %>)
    

    当然,节点属性数组p_list的创建可以在recipe中完成,也可以传入template资源的variables

    【讨论】:

    • p.nil? 检查可能不需要,因为数组的nil 元素似乎无论如何都被省略了。
    最近更新 更多