Ansible

Ansible - 否定過濾問題

  • January 27, 2020

我正在編寫一個 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"
       ]
   }

引用自:https://unix.stackexchange.com/questions/564151