如何在哈希中指定params

时间:2015-05-21 05:47:31

标签: ruby chef

我有一个用于安装JRuby的社区厨师食谱。我无法指定要安装的Gem版本。我确实尝试过我能想到的哈希,键,弦等各种组合。

以下是代码的相关部分:

default[:jruby][:gems] = ["some-gem", "another-one"]

是的,这是一个字符串数组,但是应该可以使用哈希数组。

以下摘录阅读:

node[:jruby][:gems].each do |gem|
  Chef::Log.info "Installing Jruby Gem #{gem}"
  if gem.is_a? Hash
    name = gem.delete(:name)
  else
    name = gem
    gem = nil
  end
  jruby_gem name, gem || {}
end

最终掌握在这个定义的手中:

define :jruby_gem, :source => nil, :version => nil do
  gem_package params[:name] do
    gem_binary "#{node[:jruby][:install_path]}/bin/gem"
    source params[:source] if params[:source]
    version params[:version] if params[:version]
  end
end

鉴于该代码,哈希的哈希值将填充结果定义中的:name:version值?

我尝试的事情在以下领域...

[
  {:name => "some-gem", :version => "0.1.2"},
  {:name => "another-one"} # I don't need to constrain every Gem to a version
]

修改

所以感谢完全正确的Ruby-esque响应,但实际上我在转向SO之前尝试了几种变体中的哈希方法。疲劳让我误解了最初出现在我的问题中的结构。

我看到的问题似乎与Chef和您在上面看到的定义有关。我得到的错误如下......

Node attributes are read-only when you do not specify which precedence level to set. To set an attribute use code like `node.default["key"] = "value"'

  Cookbook Trace:
  ---------------
    /var/chef/cache/cookbooks/jruby/recipes/default.rb:48:in `block in from_file'
    /var/chef/cache/cookbooks/jruby/recipes/default.rb:45:in `each'
    /var/chef/cache/cookbooks/jruby/recipes/default.rb:45:in `from_file'

  Relevant File Content:
  ----------------------
  /var/chef/cache/cookbooks/jruby/recipes/default.rb:

   41:    notifies :create_if_missing, "file[/etc/profile.d/jruby.sh]"
   42:  end
   43:
   44:  # install all gems defined in the module
   45:  node[:jruby][:gems].each do |gem|
   46:    Chef::Log.info "Installing Jruby Gem #{gem}"
   47:    if gem.is_a? Hash
   48>>     name = gem.delete(:name)
   49:    else
   50:      name = gem
   51:      gem = nil
   52:    end
   53:    jruby_gem name, gem || {}
   54:  end
   55:

2 个答案:

答案 0 :(得分:1)

不幸的是,这里的问题不是你的属性,而是你的实际食谱。

你(和我,今天!)正在使用的jruby cookbook的实现与Chef 11+不兼容。看到这个链接:

https://www.chef.io/blog/2013/02/05/chef-11-in-depth-attributes-changes/

  

现在,您必须在设置属性时指定要写入的优先级;直接访问节点上的属性仅用于读取。

这里出错的行正是这样做的:

if gem.is_a? Hash
  name = gem.delete(:name) <- This is modifying node.jruby.gems.some_gem!

因此,如果你想使用它,你必须采取以下几种方法之一:

  1. 将犹豫的食谱分开并修好。它非常古老,没有一个现有的直接叉子支持厨师11,所以如果你想要接管它,你可以变得像一个小神。
  2. 完全使用单独的食谱进行宝石安装(这是我们到目前为止所做的工作)。
  3. 创建一个包装器食谱,其中包含jruby cookbook ,不用设置jruby.gems,并添加一个属性和自己的Ruby块,将事物设置为“正确”。方式。
  4. 一个例子是:

    my_gems = node['jruby']['my_gems'].dup
    
    my_gems.each do |gem|
      if gem.is_a? Hash
        name = gem.delete('name')
      else
        name = gem
        gem = nil
      end
      jruby_gem name, gem || {}
    end
    

    考虑到适当的调整量,这实际上是有效的。使用此精确块的示例Chef客户端输出将是:

    > Recipe: mycompany-jruby::default 
    > * gem_package[some-package] action install 
    > - install version #.#.# of package some-package 
    

答案 1 :(得分:0)

尝试:

[
  {:name => "some-gem", :version => "0.1.2"},
  {:name => "another-one"} # I don't need to constrain every Gem to a version
]

请注意,内部数据结构是用花括号定义的,而不是方括号。

  • []制作一个数组
  • {}制作哈希

你正在创建一个数组数组,但你真正想要的是一个哈希数组。

修改

文档似乎表明你可以尝试以下方面:

default[:jruby].set[:gems] = ["some-gem", "another-one"]

这是我从简短的浏览中得到的: https://www.chef.io/blog/2013/02/05/chef-11-in-depth-attributes-changes/