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 ,这会使剧本难以阅读,并且可能会因为未定义的变量而失败,如果任务被移动到中间变量尚未设置的地方。

答案1

使用过滤器不同之处。例如

    - 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"
        ]
    }

相关内容