在 Chef 中,如何从食谱更新环境属性?

In chef, how do I update environment attributes from a recipe?

我在环境文件中定义了环境属性,用于覆盖节点中的默认设置。 在我的例子中,我想更新配方中的环境属性,所以当 运行ning chef-client on b_node_name 时,环境属性将从这个改变:

default_attributes "hosts" => ["a_node_name"]

对此:

default_attributes "hosts" => ["a_node_name", "b_node_name"]

这样做我想将我 运行 chef-client 添加到数组中的新 b_node_name 这样所有节点都将获得新 chef-client [=73 的更新列表=]s.

这可以吗?我是否应该使用数据包来让所有节点从那里读取和更新该信息?我正在寻找实现这个的最佳方法。 我真的很感激任何帮助。

更新: 我在我的食谱中添加了以下几行:

Chef::Log.info("---> Before update. hosts=#{node.hosts}")
node.override['hosts'] = ["a_hostname", "b_hostname"] 
Chef::Log.info("---> After update. hosts=#{node.hosts}")

我得到了这个输出:

b_hostname 中的第一个主厨客户 运行:

#chef-client --log_level info

[2015-07-29T14:29:13+00:00] INFO: ---> Before update. hosts=["a_hostname"]
[2015-07-29T14:29:13+00:00] INFO: ---> After update. hosts=["a_hostname", "b_hostname"]

b_hostname 中的第二个主厨客户 运行:

#chef-client --log_level info
[2015-07-29T14:30:33+00:00] INFO: ---> Before update. hosts=["a_hostname"]
[2015-07-29T14:30:33+00:00] INFO: ---> After update. hosts=["a_hostname", "b_hostname"]

所以 b_hostname 读取的主机值是 hosts=["a_hostname"],我希望第二个 运行 的主机值是 hosts=["a_hostname", "b_hostname"]

如果我通过 Chef Server UI 到达节点并检查 hosts 属性,我会看到主机设置为 ["a_hostname", "b_hostname"] 而不是 hosts=["a_hostname"]

为什么我在 chef-client 运行 期间得到 hosts=["a_hostname"]

更新 2: 使用 node.set 而不是 node.defaultnode.override 使值持续存在,但仅适用于我 运行 chef-client 所在的节点(不是所有节点),因此上述情况有效但不是以下一个:

c_hostname 中的第一个主厨客户 运行:

[2015-07-29T14:58:51+00:00] INFO: ---> Before update. hosts=["a_hostname"]
[2015-07-29T14:58:51+00:00] INFO: ---> After update. hosts=["a_hostname", "b_hostname"]

我希望看到主机数组设置为 ["a_hostname","b_hostname"] 由 chef-client 运行 在 b_hostname

中完成

在配方中,执行此操作以动态更改属性值。

node.default['hosts'] = ['a_node_name', 'b_node_name']

Chef 每次 运行 都会重置属性,因此您看到的行为是有意的 - 检查 https://docs.chef.io/attributes.html

如果您想在 运行 之间保留节点属性更改,请使用 node.set - 在您的情况下

node.set['hosts'] = ['a_node_name', 'b_node_name']

在 Chef 客户端 运行s 期间更改节点属性时要小心 - Chef 客户端首先编译属性以预先确定节点属性值,然后 运行s 食谱,所以如果你想动态更改值在 运行 期间,您可能需要将 node.set 放入 ruby 区块

已更新以允许按添加时间排序。

您需要使用搜索。与其使用属性来确定列表,不如使用属性来指示给​​定节点属于列表。

node.set['include_me'] = Time.now

然后搜索所有设置了这个的节点,排序,得到他们的fqdn:

sorted = search(:node, 'include_me:*').sort_by { |node| node['include_me'] }
hostnames = sorted.map{ |node| node.fqdn }

这将为您提供一组按添加日期排序的 fqdns hostnames。需要注意的是,它将仅包括已完成 运行 的节点。因此,如果您有并行构建的节点,它们将看不到彼此。此外,当前节点不会出现在它的第一个 运行 上。因此,您将需要更多逻辑来搜索当前节点,然后在缺少时将其添加到列表中。