Ansible 组变量合并和重叠

问题描述 投票:0回答:1

我已经使用 Ansible 好几年了,但我一直在努力解决以下主题。

让我举一个简单的例子。我编写了一个角色来处理安装包。有时需要在主机级别(packages_installhost变量)定义应安装哪些软件包,其他时候则应在组级别定义。然而主机可以属于多个组,那么 Ansible 的概念是什么?我确信,Ansible 对于这种日常需求根本没有概念。

以前,我只是多次定义基于组的变量,并让 Ansible 合并它,但该方法不久前已被弃用(hash_behaviour=merge)。这让我有点震惊,因为这是我能想到的最直观的方法。

从那时起,我根据他们的组成员身份构建了逻辑来合并角色中的字典/列表。这确实有效,但(至少)还剩下两个问题:

  1. 对于用户来说,在每个主机都可以访问它的 group_vars/all.yml 中定义变量 packages_installgroup 是违反直觉的。用户直观地希望在组变量内定义基于组的变量,例如group_vars/environment_A.yml.
  1. 对于我创建的几乎每个角色,我都必须编写大量逻辑才能使其发挥作用。这既麻烦又乏味。

最终我希望拥有灵活性和力量,有意义。我的角色的用户应该能够定义变量,引用我的角色,然后就高兴了。我确信,当用户觉得需要在他的剧本中嵌入额外的逻辑时,我的角色还不够好。

variables ansible
1个回答
0
投票

下面介绍的解决方案是为了解决我们的用例而创建的,该用例与您的用例非常匹配。它只需要在变量命名方面进行一些训练。让我们以您的示例为例,其中各个主机组、主机以及可能的角色默认值都希望安装一些软件包。在每个适当的位置定义一个列表变量,并使用相同的前缀命名所有变量,但使用每个定义它们的位置唯一的后缀。如果使用前缀

packages_
,那么您最终可能会得到
packages_myhost
packages_group_a
packages_group_b
packages_group_q
packages_role_foo_defaults
packages_role_bar_defaults
。可能还有更多;这些可以说是
myhost
可见的。

这些变量都不需要相互“了解”。但是,您需要确保它们具有足够独特的后缀才能使该技术发挥作用。他们在实际安装软件包的任务中聚集在一起。在那里,您可以使用诸如 mergevars 查找插件之类的东西合并列表:

"{{ lookup('mergevars', regex='^packages_.*') }}"

除了可选的正则表达式之外,

mergevars
还将采用变量名称,并按列出的顺序合并。任何名称也匹配
regex
的显式列出的变量将仅合并一次。通过
regex
选择的变量将合并在明确列出的变量之后,并按名称字母顺序排列。

"{{ lookup('mergevars', 'alpha_z', 'alpha_y', regex='^alpha_.*' }}"

mergevars
也不限于列表。如果你的变量是字典,它会像
combine
过滤器一样合并它们。只要确保所有变量的“形状”都相同:所有列表或所有字典。

您也不限于变量名称。您可以传入结构化数据,或按值(即不带引号)而不是按名称传入变量。但在这种情况下,匹配相同变量的

regex
不会注意到它已经包含在内,并且会合并它两次,所以要小心!

"{{ lookup('mergevars', {'a': 3}, beta_dict, {'z': 99}, regex='^alpha_dicts_.*' }}"

至少有一个

-v
mergevars
将记录其合并的变量的顺序和名称。还有一个
dedup
选项用于删除结果列表的重复项,以及一个
recursive
选项用于深度合并字典,这两个选项都默认为
true
。 (所以你不必担心 group_vars 和 host_vars 文件都请求一些相同的包。)

© www.soinside.com 2019 - 2024. All rights reserved.