在Ansible 2中防止重复键警告

时间:2016-01-22 06:29:23

标签: ansible ansible-playbook ansible-2.x

我在我的角色中使用了很多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_warningscommand_warnings。有没有办法防止这种警告?

4 个答案:

答案 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。