大厨11:任何方式将属性转换为红宝石哈希?

Igo*_*any 8 ruby hash attributes chef-infra

我正在使用chef属性为我的服务生成配置.但是,在某些时候,我需要将属性mash转换为简单的ruby哈希.这曾经在Chef 10中正常工作:

node.myapp.config.to_hash
Run Code Online (Sandbox Code Playgroud)

但是,从Chef 11开始,这不起作用.只有属性的顶级转换为散列,然后嵌套值保持不可变的mash对象.修改它们会导致这样的错误:

Chef :: Exceptions :: ImmutableAttributeModification ------------------------------------------- -----如果未指定要设置的优先级,则节点属性是只读的.要设置属性,请使用类似`node.default ["key"] ="value"'的代码

我已经尝试了一些解决这个问题的方法,但是没有用:

node.myapp.config.dup.to_hash
JSON.parse(node.myapp.config.to_json)
Run Code Online (Sandbox Code Playgroud)

json解析hack,看起来应该很好用,导致:

JSON::ParserError
unexpected token at '"#<Chef::Node::Attribute:0x000000020eee88>"'
Run Code Online (Sandbox Code Playgroud)

有没有任何实际可靠的方法,除了在每个cookbook中包含嵌套解析函数,将属性转换为简单,普通,好的旧ruby哈希?

Igo*_*any 9

在这里以及在opscode chef邮件列表上大声缺乏答案之后,我最终使用了以下hack:

class Chef
  class Node
   class ImmutableMash
      def to_hash
        h = {}
        self.each do |k,v|
          if v.respond_to?('to_hash')
            h[k] = v.to_hash
          else
            h[k] = v
          end
        end
        return h
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我把它放在我的食谱中的图书馆里; 现在我可以在chef 10中使用attribute.to_hash(已经正常工作且不受此猴子补丁影响)和厨师11.我也将此报告为opscode的错误:

如果你不想对你的厨师进行修补,请在这个问题上说说:http: //tickets.opscode.com/browse/CHEF-3857


lam*_*ont 2

这个问题已经修复了很长时间了:

[1] pry(main)> require 'chef/node'
=> true
[2] pry(main)> node = Chef::Node.new
[....]
[3] pry(main)> node.default["fizz"]["buzz"] = { "foo" => [ { "bar" => "baz" } ] }
=> {"foo"=>[{"bar"=>"baz"}]}
[4] pry(main)> buzz = node["fizz"]["buzz"].to_hash
=> {"foo"=>[{"bar"=>"baz"}]}
[5] pry(main)> buzz.class
=> Hash
[6] pry(main)> buzz["foo"].class
=> Array
[7] pry(main)> buzz["foo"][0].class
=> Hash
[8] pry(main)>
Run Code Online (Sandbox Code Playgroud)

可能在 Chef 12.x 或 Chef 13.x 中或周围的某个时间得到修复,这在 Chef 15.x/16.x/17.x 中肯定不再是问题