Theo Chatzimichos e53270
#!/usr/bin/python3
Theo Chatzimichos e53270
Theo Chatzimichos e53270
# For description and usage, see the argparse options at the end of the file
Theo Chatzimichos e53270
Theo Chatzimichos e53270
import argparse
Theo Chatzimichos e53270
import os
fab69c
from sys import exit
Theo Chatzimichos e53270
ac656a
import yaml
ac656a
Theo Chatzimichos 3f50ca
Christian Boltz 25cb76
def read_file_skip_jinja(filename):
Christian Boltz 25cb76
    ''' reads a file and returns its content, except lines starting with '{%' '''
Christian Boltz 25cb76
    non_jinja_lines = []
Christian Boltz 25cb76
Christian Boltz 25cb76
    with open(filename) as f:
Christian Boltz 25cb76
        for line in f.read().split('\n'):
065bd6
            if not ('{%' in line or '{{' in line or '{#' in line):
Christian Boltz 25cb76
                non_jinja_lines.append(line)
Christian Boltz 25cb76
Christian Boltz 25cb76
    return '\n'.join(non_jinja_lines)
Christian Boltz 25cb76
Theo Chatzimichos e53270
Theo Chatzimichos 4f2316
def get_roles_of_one_minion(minion):
195d04
    if not minion.endswith('.sls'):
d3a52a
      if '.' not in minion and '_' not in minion:
195d04
        minion = f'{minion}.infra.opensuse.org'
195d04
      minion = minion.replace('.', '_') + '.sls'
195d04
    file = f'pillar/id/{minion}'
195d04
    try:
195d04
        content = read_file_skip_jinja(file)
195d04
    except FileNotFoundError:
195d04
        print(f'File {file} not found.')
b18f9b
        return []
Theo Chatzimichos 274e9c
    try:
4fa650
        roles = yaml.safe_load(content)['roles']
Theo Chatzimichos 274e9c
    except KeyError:
Theo Chatzimichos 274e9c
        roles = []
Theo Chatzimichos 274e9c
Theo Chatzimichos 274e9c
    return roles
Theo Chatzimichos 274e9c
Theo Chatzimichos 274e9c
f75887
def get_minions_with_role(role):
f75887
    minions = []
f75887
    for sls in os.listdir('pillar/id'):
f75887
      if sls.endswith('.sls'):
f75887
          for item in get_roles_of_one_minion(sls):
f75887
              if item == role:
f75887
                  minions.append(os.path.splitext(sls)[0].replace('_', '.'))
f75887
f75887
    return sorted(minions)
f75887
f75887
7b2779
def get_roles(with_base=False):
84e92b
    roles = []
Theo Chatzimichos e53270
Theo Chatzimichos e53270
    for sls in os.listdir('pillar/id'):
Christian Boltz 2570f4
        if sls == 'README.md':
Christian Boltz 2570f4
            continue
Christian Boltz 2570f4
Theo Chatzimichos 4f2316
        _roles = get_roles_of_one_minion(sls)
Christian Boltz 25cb76
        for item in _roles:
Christian Boltz 25cb76
            roles.append(item)
Theo Chatzimichos e53270
Theo Chatzimichos e53270
    roles = sorted(set(roles))
7b2779
7b2779
    if with_base:
7b2779
      roles = ['base'] + roles
7b2779
Theo Chatzimichos e53270
    return roles
Theo Chatzimichos e53270
Theo Chatzimichos e53270
fab69c
def get_roles_including(query):
fab69c
    """
fab69c
    Return roles including the specified string in their state SLS file.
fab69c
    """
fab69c
    roles = []
fab69c
    for role in get_roles():
18d198
        role2 = role.replace('.', '/')
18d198
        file = f'salt/role/{role2}.sls'
18d198
        if not os.path.isfile(file):
18d198
          file = f'salt/role/{role2}/init.sls'
18d198
        role_sls = read_file_skip_jinja(file)
fab69c
        if query in role_sls:
fab69c
            roles.append(role)
fab69c
    return roles
fab69c
fab69c
Theo Chatzimichos e53270
def print_roles():
Theo Chatzimichos e53270
    parser = argparse.ArgumentParser('Collects all the roles that are assigned to a minion, and returns them as a python array, a yaml list or a plain list (parsable by bash)')
a6ef48
    parser.add_argument('-o', '--out', choices=['bash', 'python', 'yaml'], help='Select different output format. Options: bash (default), python, yaml')
fab69c
    parser.add_argument('-i', '--including', help='Only print roles including the specified string in their state file.')
195d04
    parser.add_argument('-m', '--minion', help='Only print roles assigned to the specified minion.')
f75887
    parser.add_argument('-r', '--role', help='Print minions the specified role is assigned to.')
Theo Chatzimichos e53270
    args = parser.parse_args()
Theo Chatzimichos e53270
195d04
    if args.including and args.minion:
195d04
      print('Combining --including and --minion is not supported. But you can send a patch for it. :)')
195d04
      exit(1)
195d04
f75887
    if ( args.including or args.minion ) and args.role:
f75887
      print('Combining --role with --including or --minion is not possible.')
f75887
      exit(1)
f75887
fab69c
    if args.including:
fab69c
        roles = get_roles_including(args.including)
195d04
    elif args.minion:
195d04
        roles = get_roles_of_one_minion(args.minion)
f75887
    elif args.role:
f75887
        roles = get_minions_with_role(args.role)
fab69c
    else:
84e92b
        roles = get_roles()
a6ef48
    if args.out == 'python':
Theo Chatzimichos e53270
        print(roles)
a6ef48
    elif args.out == 'yaml':
dc3f8e
        print(yaml.dump({'roles': roles}, default_flow_style=False))
Theo Chatzimichos e53270
    else:
Theo Chatzimichos 053051
        print('\n'.join(roles))
Theo Chatzimichos e53270
Theo Chatzimichos e53270
Theo Chatzimichos e53270
if __name__ == "__main__":
Theo Chatzimichos e53270
    print_roles()