Chef和ruby模板-如何循环键值对? [英] Chef and ruby templates - how to loop though key value pairs?

查看:69
本文介绍了Chef和ruby模板-如何循环键值对?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

1)我有一个数据袋,如下所示:

1) I have a data bag as follows:

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

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

2) In my recipe I get the hash as follows.

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

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

3) Also in my recipe I have a template as follows:

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)我需要让模板看起来像这样

4) I need to have my template look like this

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

我的问题是这个。如何将哈希传递给模板,以便可以遍历哈希并创建temlplate?我不是一个坚强的红宝石编码员。

My question is this. How do I pass the hash to the template so I can loop through the hash and create the temlplate? I am not a strong ruby coder.

例如:

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


推荐答案

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

There are some slight inconsistencies in your setup. In your data bag, you assign IP addresses a name (by using a hash in your JSON). However, you don't seem to use the name in your generated template at all. This has some implications which you should be aware of:

在使用关联数组(在Ruby中称为哈希或在Javascript中称为对象)时,通常不保留元素的顺序并且在添加其他元素时可能会发生重大变化。尽管在Ruby 1.9上进行了一些工作以在遍历散列时保留插入顺序,但是通常不应该依赖于此。这导致改善数据袋的两种可能的选择。选择哪个选项取决于您的实际用例:

When using associative arrays (called hashes in Ruby or objects in Javascript), the order of the elements is generally not preserved and can significantly change when adding additional elements. While some effort is done on Ruby 1.9 to preserve the insertion order when looping over the hash, you shouldn't generally rely on that. This leads to two possible alternatives to improving your data bag. Which one to choose depends on your actual use case:


  • 使用数组而不是哈希。在数组中,保证顺序被保留。如果您仍然不使用名称(即原始哈希中的键),则可以简单地使用哈希并在此处安全。走这条路时,我们可以遍历模板中的数组并从中生成计数。

  • 如果顺序无关紧要,则应使用哈希中的键命名模板中生成的服务器。现在,您在数据包中使用 server< Number> ,但在模板中使用 server。< Number> 。这样,我们可以使用密钥来命名服务器,并可能覆盖生成的名称。

  • Use an array instead of the hash. In an array, the order is guaranteed to be kept. If you don't use the name anyway (i.e. the key in your original hash), you can simply use a hash and be safe here. When going this road, we can loop over the array in the template and generate the count from that.
  • If the order doesn't matter, you should use the key in the hash to name the server as generated into your template. Right now, you use server<Number> in your data bag but server.<Number> in your template. That way, we can use the key to name your servers and possibly override the generated names.

在数据包中使用数组时,即当您具有以下内容时:

When using the array in your data bag, i.e. when you have something like this:

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

您可以在模板中像这样遍历数组:

you can loop over the array like this in your template:

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

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

This used the ERB template language to create your file. It used the each_with_index method to iterate over each element in the array.

使用哈希变量时,假设您已更改数据包中的密钥为了匹配最终生成文件中的语法,您可以像这样遍历散列:

When using the hash variant instead, assuming you have changed the keys in your data bag to match the syntax in your final generated file, you can loop over the hash like this:

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

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

This uses the each_pair method of the Hash to loop over each key-value pair and thus generates a line of output for each of these pairs.

最后,在配方中将数据传递到模板的语法很奇怪。刚开始,永远不要使用以大写字母开头的名称作为变量(例如您的 ZOOKEEPER 变量)。在Ruby中,这些标识常量(例如值常量,类,模块等)。请改用小写名称。 Ruby习惯上使用snake_case作为变量名。

As a final remark, your syntax to pass data to the template in your recipe is odd. At first, you should never use names that start with an uppercase letter for variables (like your ZOOKEEPER variable). In Ruby, these identify constants (like value constants, classes, modules, ...). Use a lowercase name instead. Ruby uses snake_case for variable names by convention.

将值传递到模板时,只需传递变量即可:

When passing the value to your template, you can then just pass the variable:

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

这篇关于Chef和ruby模板-如何循环键值对?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆