Ansible
Ansible - 否定過濾問題
我正在編寫一個 Ansible 劇本,它授予和拒絕對某些目錄的訪問權限。Base 是使用者字典的列表:
users: - {name: 'user1', dirs: ['dir1', 'dir2']} - {name: 'user2', dirs: ['dir1', 'dir3']} - {name: 'user3', dirs: []}
作為輔助事實,我創建了任何使用者記錄中出現的所有目錄的列表。
現在我想將此列表轉換為兩個新列表:
dirs_allowed: - {'dir1': ['user1', 'user2']} - {'dir2': ['user1']} - {'dir3': ['user2']}
這個很簡單,但我找不到這個的解決方案:
dirs_forbidden: - {'dir1': ['user3']} - {'dir2': ['user2', 'user3']} - {'dir3': ['user1', 'user3']}
所以,我的問題是:如何在他們的 ‘dirs’ 屬性中獲取所有沒有目前目錄(=所有目錄的 with_items 循環中的項目)的所有使用者的列表?
當然可以通過輔助變數/事實或任務的“何時”條件以某種方式做到這一點,但我真的很想自己轉換列表,因為我想學習如何處理這種複雜的轉換。它背後的想法是只提供一個字典作為輸入,並從這個字典中提取特定任務所需的所有內容,中間沒有大量的 set_fact-tasks,這會使劇本難以閱讀,並且可能由於未定義的變數而失敗,如果任務被移動到中間變數(尚未)設置的地方。
使用過濾器差異。例如
- set_fact: users_all: "{{ users|json_query('[].name') }}" - set_fact: dirs_forbidden: "{{ dirs_forbidden|default([]) + [ {(item.keys()|list|first): (users_all|difference(item.values()|list|first))}] }}" loop: "{{ dirs_allowed }}" - debug: var: dirs_forbidden
給
"dirs_forbidden": [ { "dir1": [ "user3" ] }, { "dir2": [ "user2", "user3" ] }, { "dir3": [ "user1", "user3" ] } ]
FWIW。在這種情況下,使用字典可以使程式碼更簡單。例如
- set_fact: users_all: "{{ users|json_query('[].name') }}" - set_fact: dirs_all: "{{ users| json_query('[].dirs')|flatten|unique }}" - set_fact: dirs_allowed: "{{ dirs_allowed|default({})| combine({item: users|json_query(query)}) }}" vars: query: "[?dirs.contains(@, '{{ item }}')].name" loop: "{{ dirs_all }}" - debug: var: dirs_allowed - set_fact: dirs_forbidden: "{{ dirs_forbidden|default({})| combine({item: (users_all|difference(dirs_allowed[item]))}) }}" loop: "{{ dirs_all }}" - debug: var: dirs_forbidden
給
"dirs_allowed": { "dir1": [ "user1", "user2" ], "dir2": [ "user1" ], "dir3": [ "user2" ] }
"dirs_forbidden": { "dir1": [ "user3" ], "dir2": [ "user2", "user3" ], "dir3": [ "user1", "user3" ] }