Chef infra 在chef中,如何从菜谱更新环境属性?

Chef infra 在chef中,如何从菜谱更新环境属性?,chef-infra,chef-recipe,Chef Infra,Chef Recipe,我在环境文件中定义了环境属性,用于覆盖节点中的默认设置。 在我的情况下,我希望更新配方中的环境属性,以便在b_节点_name上运行chef-client时,环境属性将从此更改: default_attributes "hosts" => ["a_node_name"] 为此: default_attributes "hosts" => ["a_node_name", "b_node_name"] 执行此操作时,我希望将运行chef-client的新b_节点\u名称添加到数组中,以

我在环境文件中定义了环境属性,用于覆盖节点中的默认设置。 在我的情况下,我希望更新配方中的环境属性,以便在
b_节点_name
上运行
chef-client
时,环境属性将从此更改:

default_attributes "hosts" => ["a_node_name"]
为此:

default_attributes "hosts" => ["a_node_name", "b_node_name"]
执行此操作时,我希望将运行
chef-client
的新
b_节点\u名称添加到数组中,以便所有节点都将获得新
chef-client
运行的更新列表

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

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

Chef::Log.info("---> Before update. hosts=#{node.hosts}")
node.override['hosts'] = ["a_hostname", "b_hostname"] 
Chef::Log.info("---> After update. hosts=#{node.hosts}")
我得到了这个输出:

第一个chef客户端在
b_主机名
中运行:

#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"]
#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"]
[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"]
第二个chef客户端在
b_主机名
中运行:

#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"]
#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"]
[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"]
所以
b_hostname
读取的hosts值是
hosts=[“a_hostname”]
,我希望在第二次运行时它是
hosts=[“a_hostname”,“b_hostname”]

如果我通过Chef Server UI进入节点并检查
hosts
属性,我会看到hosts设置为
[“a_主机名”,“b_主机名”]
,而不是
hosts=[“a_主机名”]

为什么在
chef-client
运行期间我会得到
hosts=[“a_-hostname”]

更新2: 使用
node.set
而不是
node.default
node.override
使该值保持不变,但仅适用于我运行chef client的节点(不是所有节点),因此上述场景可行,但不适用于以下场景:

第一个chef客户端在
c_主机名
中运行:

#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"]
#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"]
[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会在每次运行时重置属性,以便您看到的行为符合预期-检查

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

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

在chef客户端运行期间更改节点属性时要小心-chef客户端首先编译属性以预先确定节点属性值,然后运行配方,因此如果要在运行期间动态更改值,可能需要将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 }

这将为您提供按添加日期排序的FQDN主机名数组。需要注意的是,它将只包括已完成运行的节点。因此,如果节点并行构建,它们将无法相互看到。此外,当前节点在第一次运行时不会显示。因此,您需要更多的逻辑来搜索当前节点,如果缺少,则将其添加到列表中。

这只会更新当前节点中的属性。因此,如果我在另一个节点中运行相同的配方,它将获得原始列表,而不是更新的列表,如果您将此添加到配方中,任何运行配方的节点都会将属性设置为新的数组值。如果我通过Chef server UI进行检查,我可以看到该属性在节点中得到更新,但在配方中我仍然读取原始列表。请检查我在这个问题上的更新,好吗?在这种情况下,该属性仍然存在,但如果我在第三个节点“c_hostname”中运行chef client,我仍然可以看到环境文件中设置的原始值[“a_hostname”]。如何在每次chef客户端运行时使更新的hosts属性对所有节点可见?不幸的是,这是不可能的,每个节点都有属于该节点的唯一属性集,仔细查看您的代码,您真正想要的是设置节点['node_name']值设置为该节点的名称,然后如果需要其他节点的名称,请搜索节点并获取这些节点的名称-签出,而不是让每个节点请求其他节点的名称。我希望每个节点更新全局主机阵列,以便其他节点在每次运行时都可以使用该阵列。这就是为什么我认为也许数据包很适合这个。我考虑使用数组,因为我想知道顺序,因此,chef客户端运行后的每个节点都会附加到主机阵列。是的,不幸的是,我认为这是不可能的,这也是我在chef项目中遇到的一个限制-数据包无法工作,因为数据包可以通过两种方式进行编辑:使用刀子或使用chef管理控制台-而不是通过配方进行编辑。看起来它们可以根据配方编辑:需要保留列表是因为我想知道附加到列表中的节点的顺序。我担心搜索不会告诉我这方面的任何信息。已将其更新为包含按时间添加的排序。还是和以前一样的警告,但它让你更接近。非常感谢,这解决了我的问题。到目前为止,我正在使用数据包项目,但这需要为我的客户端节点设置管理员权限。这种选择要好得多。谢谢您可能希望使用
node.set_,除非['include_me']=Time。现在
这样,一旦节点标记了它的时间,它就不会在每次chef客户端运行时更新。