From d0bbefc059688d920d1d31cd2000a1c605a5f5f5 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 29 2021 07:36:41 +0000 Subject: Include the sync_fas_group utility script This script is used to sync group membership from FAS to pagure for all the groups set/used in pagure. Signed-off-by: Pierre-Yves Chibon --- diff --git a/MANIFEST.in b/MANIFEST.in index 715a2e0..68d02c8 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,6 +4,7 @@ include dist_git_auth.py include dist_git_auth_tests.py include pagure_poc.py include load_from_disk.py +include sync_fas_group.py recursive-include template * recursive-include pagure_distgit * recursive-include scripts * diff --git a/sync_fas_group.py b/sync_fas_group.py new file mode 100644 index 0000000..2273d0f --- /dev/null +++ b/sync_fas_group.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python + +""" + +Utility script used to load the database based on the data present on disk +for the pagure instance over Fedora's git repositories. + +""" + + +import argparse +import collections +import getpass +import logging +import os + +import requests +from fedora.client import AccountSystem + +if 'PAGURE_CONFIG' not in os.environ \ + and os.path.exists('/etc/pagure/pagure.cfg'): + print 'Using configuration file `/etc/pagure/pagure.cfg`' + os.environ['PAGURE_CONFIG'] = '/etc/pagure/pagure.cfg' + +import pagure +import pagure.lib +import pagure.lib.model + +FAS = 'https://admin.fedoraproject.org/accounts' +URL = 'https://src.fedoraproject.org/' + +_log = logging.getLogger(__name__) + +_fas_username = raw_input("FAS user: ") +_fas_password = getpass.getpass("FAS password: ") +FASCLIENT = AccountSystem( + FAS, + username=_fas_username, + password=_fas_password, +) + +groups = [ + "alt-gtk-de-sig", + "astro-sig", + "eclipse-sig", + "gnome-sig", + "infra-sig", + "kde-sig", + "lxqt-sig", + "neuro-sig", + "nodejs-sig", + "python-sig", + "qa-tools-sig", + "robotics-sig", + "rpm-software-management-sig", + "ruby-packagers-sig", + "rust-sig", + "virtmaint-sig", + "packager", +] + + +def get_pagure_group(): + """ Get the membership info for all the groups in pagure. + Returns dict of {group_name: [members]} + """ + output = collections.defaultdict(set) + base_url = URL.rstrip('/') + req = requests.get(url='%s/api/0/groups' % base_url, timeout=30) + data = req.json() + for grp in data['groups']: + req = requests.get( + url='%s/api/0/group/%s' % (base_url, grp), timeout=30) + data = req.json() + output[grp].update(data['members']) + output[grp].update([data['creator']['name']]) + + return output + + +def get_fas_groups(groups): + """ Return a dict containing for each group specified in the list passed + as argument the list of its members. + """ + output = {} + for group in groups: + members = [it.username for it in FASCLIENT.group_members(group)] + output[group] = members + return output + + +def main(): + """ Core part of this script. + Logic: + - Get all the groups in pagure/dist-git + - For each group, get the membership + - Query FAS for membership of each group + - Adjust pagure's database + + """ + _log.info('Getting groups from pagure') + pagure_groups = get_pagure_group() + _log.info('Getting membership from FAS') + fas_groups = get_fas_groups(pagure_groups.keys()) + + for group in groups: + _log.info('Processing group %s' % (group)) + upstream = set(fas_groups.get(group, [])) + downstream = set(pagure_groups.get(group, [])) + to_add = upstream - downstream + to_rm = downstream - upstream + if 'releng' in to_rm: + to_rm.remove('releng') + + group_obj = pagure.lib.search_groups( + session=pagure.SESSION, + group_name=group + ) + for user in to_rm: + _log.info(' - Removing user %s from group %s' % (user, group)) + pagure.lib.delete_user_of_group( + session=pagure.SESSION, + username=user, + groupname=group, + user='releng', + is_admin=True, + force=False + ) + pagure.SESSION.commit() + for user in to_add: + _log.info(' + Adding user %s to group %s' % (user, group)) + try: + pagure.lib.add_user_to_group( + session=pagure.SESSION, + username=user, + group=group_obj, + user='releng', + is_admin=True) + except pagure.exceptions.PagureException as err: + _log.error('ERROR: %s', err) + pagure.SESSION.commit() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='Script syncing FAS groups membership to pagure' + ) + parser.add_argument( + '--debug', dest='debug', action='store_true', default=False, + help='Print the debugging output') + + args = parser.parse_args() + logging.basicConfig() + if args.debug: + _log.setLevel(logging.DEBUG) + else: + _log.setLevel(logging.WARNING) + + main()