Ansible:使用 "startswith" 比较从列表创建子列表

Ansible: Create sublist from list using "startswith" comparison

我的系统 (Zabbix) 使用基于“/”定界符的原始 group/subgroup 定义,这些定义在普通列表中定义。

例如: “组(1)” “组(1)/子组(A)” “组(1)/子组(B)” “组(2)” “Grp(2)/Subgrp(X)”

这定义了两个组,Grp(1) 有两个子组(A 和 B),Grp(2) 有一个子组 (X)

如果我逻辑上将用户分配给“Grp(1)”,则预计用户也自动拥有“Grp(1)/Subgrp(A)”和“Grp(1)/Subgrp(B)”的权限

示例 vars 文件如下所示:

---
groups_vars:
  - "Grp(1)"
  - "Grp(1)/Subgrp(A)"
  - "Grp(1)/Subgrp(B)"
  - "Grp(2)"
  - "Grp(2)/Subgrp(X)"

变量用于 ansible galaxy 模块 community.zabbix,Grp(1) 的简化用法:

- name: Ensure user groups are created and right to itself and subgroups are assigned
  community.zabbix.zabbix_usergroup:
    name: Grp(1)
    rights:
      - {host_group: ["Grp(1)","Grp(1)/Subgrp(A)","Grp(1)/Subgrp(B)"], permission: "read-write" }

我已尝试将输入变量“set_fact”转换为更适合 Ansible 循环的格式:

--- 
groups_vars: 
  - 
    name: Grp(1)
    rights: 
      host_group: 
        - Grp(1)
        - Grp(1)/Subgrp(A)
        - Grp(1)/Subgrp(B)
      permission: read-write
  - 
    name: Grp(1)/Subgrp(A)
    rights: 
      host_group: 
        - Grp(1)/Subgrp(A)
      permission: read-write
  - 
    name: Grp(1)/Subgrp(B)
    rights: 
      host_group: 
        - Grp(1)/Subgrp(B)
      permission: read-write
  - 
    name: Grp(2)
    rights: 
      host_group: 
        - Grp(2)
        - Grp(1)/Subgrp(X)
      permission: read-write
  - 
    name: Grp(2)/Subgrp(X)
    rights: 
      host_group: 
        - Grp(2)/Subgrp(X)
      permission: read-write

但是我没有定义转换。我尝试用于过滤的 select('match', ) 函数是基于正则表达式的,但它本身可以包含正则表达式指令(名称“Grp(1)”包含作为正则表达式指令的括号),我无法找到任何用于查找子组的“startswith”方法。 我的想法是,对于上面定义的原始 group_vars 中的每个组,我找到所有以组名开头的项目(因此对于“Grp(2)”,我会找到“Grp(2)”和“Grp( 2)/Subgrp(X)", 对于 "Grp(2)/Subgrp(X)" 我只会找到 "Grp(2)/Subgrp(X)" 本身)

请问如何解决这个问题? 可能我的做法完全错误,如果有更优雅的解决方案,请帮忙

我终于找到了解决问题的方法。

我创建了简单的 Python 脚本来生成可用于简单的普通 ansible 循环的数据。 通过生成复杂结构(字典数组)来模拟内部循环

有源YML文件:

---
groups_vars:
  - "z_JC(015)"
  - "z_JC(015)/Pisek(022)"
  - "z_HK(055)"

有转换后的YML文件,内循环由"rights:"下的数组模拟

usergroups_vars:
- group: z_JC(015)
  rights:
  - host_group: z_JC(015)
    permission: read-write
  - host_group: z_JC(015)/Pisek(022)
    permission: read-write
- group: z_JC(015)/Pisek(022)
  rights:
  - host_group: z_JC(015)/Pisek(022)
    permission: read-write
- group: z_HK(055)
  rights:
  - host_group: z_HK(055)
    permission: read-write

该剧本使用简单的普通循环简单地处理转换后的 YML 文件:

- name: Ensure z_ prefixed Zabbix UserGroups are present and linked to eponymous HostGroups and subhostgroups
      community.zabbix.zabbix_usergroup:
        server_url: "{{ static_hostvars.server_url }}"
        login_user: "{{ static_hostvars.login_user }}"
        login_password: "{{ static_hostvars.login_password }}"
        state: "present"
        name: "{{ item.group }}"
        rights: "{{ item.rights }}"
      loop: "{{ usergroups_vars }}"

有Python转换脚本的例子(使用pyyaml库):

import yaml

# Press the green button in the gutter to run the script.
if __name__ == '__main__':

    # Load and parse host group var yaml file
    hostgroups = None
    with open('groups_vars.yaml') as f:
        hostgroups = yaml.load(f, Loader=yaml.FullLoader)

    # Create eponymous usergroups for hostgroups with prefix 'z_'
    usergroups = []
    for hostgroup in hostgroups.get('groups_vars'):
        if hostgroup.startswith('z_'):
            usergroups.append(hostgroup)


    # Find subgroups ut of list og groups delimited by '/'
    # (E.g array ['grp1','grp1/subgrp1'] defined one group 'grp1' and one subgroup 'subgrp1')
    usergrpsubgrps = []
    for onegrp in usergroups:
        # Find subgroups (including the group itself)
        subgrps = []
        for onesubgroup in usergroups:
            if onesubgroup.startswith(onegrp):
                subgrps.append({'host_group': onesubgroup, 'permission': 'read-write'})

        usergrpsubgrps.append({'group': onegrp, 'rights': subgrps})
    out_yaml = yaml.dump({'usergroups_vars' : usergrpsubgrps})
    print(out_yaml)

    # Write output yaml to the output ansible vars file
    out_file = open('usergroups_vars.yaml','w')
    out_file.write(out_yaml)
    out_file.close()