2016-01-22 287 views
0

我在我的角色中使用了大量的YAML锚点和引用来将逻辑保留在一个地方,而不是在多个任务中重复自己。以下是一个非常基本的例子。在Ansible 2中防止重复键警告

- &sometask 
    name: "Some Task" 
    some_module: with a lot of parameters 
    with_items: list_A 

- <<: *sometask 
    name: "Some OTHER Task" 
    with_items: list_B 

这个例子可能不会显示这个实际上是如何是有用的,但它是。想象一下,你循环了一系列的字典,将每个字典中的各个键传递给模块,可能有相当复杂的“when”,“failed_when”和“changed_when”条件。你只是想干。

因此,而不是定义两次全年任务的,我用一个锚的第一个和它的所有内容合并成一个新的任务,然后覆盖不同部分。这工作正常。

需要说明的是,这是基本的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。有没有办法来防止这种警告?

回答

1

还有一个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将帮助重复任务的条件,虽然他们似乎只限于目前的剧本中的任务..

你总是可以提交一个拉取请求,添加一个选项来禁用这些警告,看看它去哪里。

+0

这里有趣的是我正要提交一个拉请求来使这个确切的警告致命,因为它掩盖了剧本中的实际错误。现在我想知道是否应该有某种' - 警告是致命的'标志,而不是...... – larsks

0

要在Ansible中的任务级别创建可重用的功能,您应该查看任务包括。任务包括允许您更自由地执行诸如迭代使用with_items之类的事情。在我的雇主中,我们使用锚/引用,但仅限于变量。鉴于在Ansible中创建可重用任务的几种现有方法,例如任务包括,剧本书包含和角色,我们不需要按照您所描述的方式使用锚/参考任务。

如果你只是想将模块参数传递给任务之间进行复制,你可以去模板路线:

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中如果您使用了上述重复使用功能之一,则可以获得。

4

在这里晚些时候我会不同意其他答案并认可YAML合并。 Playbook布局是非常主观的,最适合你的取决于你需要描述的配置。

是,ansible与includes或with_items/with_dict loops合并一样的功能。

我发现用于YAML合并的用例是任务只有少数异常值的地方,因此可以覆盖的默认值是最紧凑和可读的表示形式。对完美有效的语法抱怨是令人沮丧的。

relevant ansible code中的评论建议The Devs Know比用户好。

其中大部分来自yaml.constructor.SafeConstructor。在这里,我们复制它,这样当他们有重复的字典键,我们可以警告用户(pyyaml默默允许覆盖键)

PyYAML默默允许“覆盖”键,因为在the YAML standard优先重点明确处理。