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

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? 我不是一个强大的ruby编码器。

例如:

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

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

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

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

使用数组

在数据包中使用数组时,即当你有这样的东西时:

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

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

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

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

使用哈希

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

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

这使用Hash的each_pair方法遍历每个键值对,从而为这些对中的每一对生成一行输出。

将数据传递给模板

最后一点,您将数据传递到配方模板的语法很奇怪。 首先,您不应该使用以大写字母开头的变量名称(例如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