我在我的角色中使用了很多YAML锚点和引用来将逻辑保留在一个位置,而不是在多个任务中重复自己。以下是一个非常基本的例子。
- &sometask
name: "Some Task"
some_module: with a lot of parameters
with_items: list_A
- <<: *sometask
name: "Some OTHER Task"
with_items: list_B
这个例子可能没有显示它实际上是如何有用的,但确实如此。想象一下,你循环遍历一个dicts列表,将各个键从各个dict传递给模块,可能有相当复杂的&#34;当&#34;,&#34; failed_when&#34;和&#34; changed_when&#34;条件。你只想干。
因此,不是将整个任务定义两次,而是使用锚点到第一个任务,并将其所有内容合并到一个新任务中,然后覆盖不同的部分。这很好。
为了清楚起见,这是基本的YAML功能,与Ansible本身无关。
上面定义的结果(以及Ansible在解析YAML文件时看到的内容)将评估为:
- name: "Some Task"
some_module: with a lot of parameters
with_items: list_A
- name: "Some Task"
some_module: with a lot of parameters
with_items: list_A
name: "Some OTHER Task"
with_items: list_B
Ansible 2现在有一个功能,可以在任务中多次定义键时进行投诉。它仍然有效,但在运行剧本时会产生不必要的噪音:
TASK [Some OTHER Task] *******************************************************
[WARNING]: While constructing a mapping from /some/file.yml, line 42, column 3, found a duplicate dict key (name). Using last defined value only.
[WARNING]: While constructing a mapping from /some/file.yml, line 42, column 3, found a duplicate dict key (with_items). Using last defined value only.
Ansible配置允许阻止deprecation_warnings
和command_warnings
。有没有办法防止这种警告?
答案 0 :(得分:5)
迟到这里,我将不同意其他答案并支持YAML合并。 Playbook布局非常主观,最适合您的取决于您需要描述的配置。
是的,ansible与includes或with_items / with_dict loops具有类似合并的功能。
我发现YAML合并的用例是任务只有少数异常值,因此可以覆盖的默认值是最紧凑和可读的表示。让ansible抱怨完全有效的语法是令人沮丧的。
relevant ansible code中的评论表明The Devs Know Better比用户更好。
大部分内容来自yaml.constructor.SafeConstructor。我们在这里复制它,以便我们可以在用户有重复的dict键时警告用户(pyyaml默默允许覆盖键)
PyYAML默默地允许“覆盖”密钥,因为密钥优先级在the YAML standard中明确处理。
答案 1 :(得分:2)
从Ansible 2.9.0开始,这可以通过将ANSIBLE_DUPLICATE_YAML_DICT_KEY
环境变量设置为ignore
来实现。此变量的其他可能值是warn
(默认值并保留原始行为),以及error
(使剧本执行失败)。
有关实现的详细信息,请参见this拉取请求。
答案 2 :(得分:0)
还有一个system_warnings
配置选项,但这些选项都不会使您看到的输出无效。
以下是生成该消息的代码
ansible/lib/ansible/parsing/yaml/constructor.py
if key in mapping:
display.warning('While constructing a mapping from {1}, line {2}, column {3}, found a duplicate dict key ({0}). Using last defined value only.'.format(key, *mapping.ansible_pos))
虽然您对YAML参考的使用非常聪明,但我怀疑随着Ansible的核心租户是剧本和任务的人类可读性,这将随时改变。 Blocks将有助于重复任务的条件,尽管它们似乎仅限于剧本中的任务。
您可以随时提交一个拉取请求,添加一个用于禁用这些警告的选项,并查看它的去向。
答案 3 :(得分:0)
要在Ansible的任务级别创建可重用的功能,您应该查看任务包含。任务包含将允许您更自由地执行诸如使用with_items等迭代的事情。在我的雇主中,我们使用锚点/引用,但仅用于变量。鉴于在Ansible中创建可重用任务的几种现有方法,例如任务包含,playbook包含和角色,我们不需要按照您所描述的方式使用任务的锚点/引用。
如果您只想在任务之间复制模块args,您可以采用模板化路径:
args_for_case_x: arg1='some value' arg2=42 arg3='value3'
- name: a task of case x for a particular scenario
the_module: "{{ args_for_case_x }}"
when: condition_a
- name: a different use of case x
the_module: "{{ args_for_case_x }}"
when: condition_b
正如您所看到的,如果您使用上述重用功能之一,则无法轻松支持基于循环迭代更改args。