0

I have system (Zabbix) that uses crude group/subgroup definition based on "/" delimiter which are defined in plain list.

For example: "Grp(1)" "Grp(1)/Subgrp(A)" "Grp(1)/Subgrp(B)" "Grp(2)" "Grp(2)/Subgrp(X)"

This defines two groups, Grp(1) with two subgroups (A and B) and Grp(2) with one subgroup (X)

If I logically assign user to "Grp(1)" it is expected that user also automatically have right to "Grp(1)/Subgrp(A)" and "Grp(1)/Subgrp(B)"

Example vars file looks like:

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

The vars are used in ansible galaxy module community.zabbix, there is simplified usage for 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" }

I have tried to achieve "set_fact" transformation of input vars into format more suitable for ansible loop:

--- 
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

But I failed to define the transformation. The select('match', ) function that I try to use for filtering is regex based but itself can contain regex directives (name "Grp(1)" contains parenthesis that are regex directives) and I cannot fing any "startswith" method for finding subgroups. My idea was, that for each group from original group_vars defined above I find all items, that begins with the group name (so for "Grp(2)" I will find "Grp(2)" and "Grp(2)/Subgrp(X)", for "Grp(2)/Subgrp(X)" I will find only "Grp(2)/Subgrp(X)" itself)

Please any ideas how to solve the problem? Maybe my approach is complete wrong, if there is any more elegant solution, please help.

Karlik_B
  • 189
  • 2
  • 2
  • 11
  • If I understand, you're trying to transform from your first definition of `groups_vars` to the second one? Why not simply using directly the second form in your vars files? It will be simpler to transform it to the first definition of needed (`{{ groups_vars | map(attribute='name') }}`) – zigarn Apr 02 '21 at 06:05
  • The first simple flat-list variant is output from export of other system that I need to reflect in zabbix. It is posssible to write external Pyhtoin script that transform flat-list into necessary format but I am trying to have my devops pipeline as simple as posible. – Karlik_B Apr 02 '21 at 07:38

1 Answers1

0

I finally found working approach for the problem.

I created simple Python script that generates data usable for simple plain ansible loop.

The inner loop is emulated by generation of complex structure (array of dictionaries)

There is source YML file:

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

There is trasformed YML file, the inner loop is emulated by array under "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

The playbook works simply with trasformed YML file usin simple plain loop:

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

There is example of the Python transformation script (using pyyaml library):

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()
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Karlik_B
  • 189
  • 2
  • 2
  • 11