Chef和ruby模板 - 如何循环键值对?

时间:2012-07-15 09:18:31

标签: ruby chef

1)我有一个数据包如下:

 "zookeeper":{
        "server1":"111.111.111.111",
        "server2":"222.222.222.222"
        },

2)在我的食谱中,我得到如下哈希值。

data_bag("mydb")
db = data_bag_item("mydb", "rtb")
ZOOKEEPER = db['zookeeper']

3)同样在我的食谱中,我有一个模板如下:

template "/etc/zookeeper/conf/zoo.cfg" do
  path "/etc/zookeeper/conf/"
  source "zoo.cfg.erb"
  owner "root"
  group "root"
  mode "0644"
 variables :zookeeper => #{ZOOKEEPER}
end

4)我需要让我的模板看起来像这样

server.1=111.111.111.111:2888:3888
server.2=222.222.222.222:2888:3888

我的问题是这个。如何将哈希传递给模板,以便循环哈希并创建temlplate?我不是一个强大的红宝石编码器。

例如:

count = 1
for server, ipaddress in zookeeper:
      server.count=ipaddress:2888:3888
      count = count + 1

1 个答案:

答案 0 :(得分:26)

您的设置存在一些轻微的不一致。在数据包中,为IP地址分配名称(通过在JSON中使用哈希)。但是,您似乎根本不在生成的模板中使用该名称。这有一些您应该注意的含义:

使用关联数组(在Ruby中称为哈希值或在Javascript中称为对象)时,通常不会保留元素的顺序,并且在添加其他元素时可能会发生显着变化。虽然在Ruby 1.9上做了一些努力来在循环哈希时保留插入顺序,但通常不应该依赖它。这导致了两种可能的替代方案来改进您的数据包。选择哪一个取决于您的实际用例:

  • 使用数组而不是散列。在数组中,保证订单保持不变。如果你不使用该名称(即原始哈希中的键),你可以简单地使用哈希并在这里安全。走这条路的时候,我们可以在模板中循环遍历数组并从中生成计数。
  • 如果订单无关紧要,您应该使用散列中的密钥来命名生成到模板中的服务器。现在,您在数据包中使用server<Number>,但在模板中使用server.<Number>。这样,我们就可以使用密钥命名您的服务器,并可能覆盖生成的名称。

使用数组

在数据包中使用数组时,即当您有这样的内容时:

"zookeeper": [
  "111.111.111.111",
  "222.222.222.222"
],

你可以在模板中循环遍历数组:

<% @zookeeper.each_with_index do |ipaddress, index| %>
<%= "server.#{index}=#{ipaddress}:2888:3888" %>
<% end %>

这使用ERB template language来创建您的文件。它使用each_with_index方法迭代数组中的每个元素。

使用哈希

当使用散列变体时,假设您已更改数据包中的键以匹配最终生成的文件中的语法,则可以循环遍历散列,如下所示:

<% @zookeeper.each_pair do |name, ipaddress| %>
<%= "#{name}=#{ipaddress}:2888:3888" %>
<% end %>

这使用哈希的each_pair method循环遍历每个键值对,从而为每个键对生成一行输出。

将数据传递给模板

最后一点,您将数据传递到配方模板的语法很奇怪。首先,您不应该使用以变量大写字母开头的名称(例如ZOOKEEPER变量)。在Ruby中,这些标识常量(如值常量,类,模块......)。请改用小写名称。 Ruby按惯例使用snake_case作为变量名。

将值传递给模板时,您只需传递变量:

db = data_bag_item("mydb", "rtb")
zookeeper = db['zookeeper']

template "/etc/zookeeper/conf/zoo.cfg" do
  path "/etc/zookeeper/conf/"
  source "zoo.cfg.erb"
  owner "root"
  group "root"
  mode "0644"
  variables :zookeeper => zookeeper
end