Chef 自定义资源:可变 属性 或替代方案

Chef Custom Resources : mutable property or an alternative

我读到 2016 OpsCode 反对 LWRP 和替代 HWRP。他们更推荐使用 custom resources.

虽然这是有道理的,但在利用 ruby 方面还有很多不足之处(除非我误解了?)

我希望能够根据一些布尔属性修改数组。然后我可以使用该数组传递给模板,如:

property :get_iptables_info, [TrueClass, FalseClass], default: false
property :get_pkglist, [TrueClass, FalseClass], default: false
property :cw_logs, Array, default: [], required: false

action :create do

  ruby_block 'cw_iptables' do
    block do
      new_resource.cw_logs.push({ "#{new_resource.custom_dir}/iptables/iptables.txt" => { "log_group_name" => new_resource.log_group_name+"/iptables"}})
    end
    action :run
    only_if {new_resource.get_iptables_info}
  end

  template "my_template" do
    variables ({:logstreams => cw_logs})
  end

end

然后在我的模板中:

<% @logstreams.each_pair do |path, _object| %>
["#{path}"]
log_group_name = _object["log_group_name"]
<% end %>

问题是属性 immutable。所以我得到错误:

RuntimeError
------------
ruby_block[cw_iptables] (/tmp/kitchen/cache/cookbooks/custom_cw/resources/logs.rb line 43) had an error: RuntimeError: can't modify frozen Array

正确的做法是什么?在资源中编写 ruby 代码以使其更加模块化并使用 methods/functions 的正确方法是什么?

改变自定义资源内的属性通常不是一个好主意(也有例外,但这不是其中之一)。更好的方法是使用局部变量。相关的,当您已经在自定义资源的操作中时,您不需要像那样使用 ruby_block:

action :create do
  cw_logs = new_resource.cw_logs
  if new_resource.get_iptables_info
    cw_logs += [whatever extra stuff you want]
  end

  template "my_template" do
    variables logstreams: cw_logs
  end
end

值得注意的是,它使用的是 += 而不是推送,它不会改变原始内容。如果你使用 push 你会想要 cw_logs = new_resource.cw_logs.dup 或类似的。