2016-01-22 291 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優先重點明確處理。