【问题标题】:Chef and ruby templates - how to loop though key value pairs?Chef 和 ruby​​ 模板 - 如何遍历键值对?
【发布时间】:2012-07-14 12:03:11
【问题描述】:

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

我的问题是这样的。如何将哈希传递给模板,以便循环遍历哈希并创建模板?我不是一个强大的 ruby​​ 程序员。

例如:

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

【问题讨论】:

    标签: ruby chef-infra


    【解决方案1】:

    您的设置存在一些细微的不一致。在您的数据包中,您为 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
    

    【讨论】:

    • 非常非常非常好的答案。你为我解决了很多问题。谢谢
    • 你不需要-%&gt; 而不是%&gt; 用于“do”和“end”语句吗?
    • erb 标签的减号通常仅用于控制标签周围空格的插入。它没有其他目的。因此,循环的正确性不需要它。此外,iirc chef 将 erb 配置为默认省略空格,因此所有 erb 标签都被认为是&lt;%- ... -%&gt;
    猜你喜欢
    • 2014-04-09
    • 2019-04-17
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    • 2016-08-19
    • 2019-12-03
    相关资源
    最近更新 更多