From 047f95f0ffe6985446710edb9b6ba7467811ff60 Mon Sep 17 00:00:00 2001 From: petjere <none@none> Date: Tue, 21 Jun 2022 07:38:14 +0200 Subject: [PATCH] Adding any untracked (non-dirty) files before git migration lk:31512102896748 --- bin/leankit_mindmap.py | 163 ++++++ bin/redmine_create_repo.py | 104 ++++ bin/redmine_create_sc_projects.py | 760 ++++++++++++++++++++++++++++ bin/redmine_fetch_changeset.py | 94 ++++ bin/redmine_issue | 226 +++++++++ bin/redmine_leankit_create_issue | 32 +- bin/sid_user.py | 170 +++++-- bin/synchronize_home_Users.pl | 422 +++++++++++++++ bin/synchronize_redmine_projects.py | 760 ++++++++++++++++++++++++++++ bin/synchronize_redmine_users.py | 80 +++ 10 files changed, 2768 insertions(+), 43 deletions(-) create mode 100755 bin/leankit_mindmap.py create mode 100755 bin/redmine_create_repo.py create mode 100755 bin/redmine_create_sc_projects.py create mode 100755 bin/redmine_fetch_changeset.py create mode 100755 bin/redmine_issue create mode 100755 bin/synchronize_home_Users.pl create mode 100755 bin/synchronize_redmine_projects.py create mode 100755 bin/synchronize_redmine_users.py diff --git a/bin/leankit_mindmap.py b/bin/leankit_mindmap.py new file mode 100755 index 0000000..a95d407 --- /dev/null +++ b/bin/leankit_mindmap.py @@ -0,0 +1,163 @@ + +#!/opt/gvenv/venv_leankit/bin/python3 +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, print_function + +import os +import sys + +import configparser as ConfigParser +import logging +import argparse +import inspect +import traceback +import shlex +import re +from subprocess import check_output, STDOUT, CalledProcessError +from json import dumps as json_dumps + +hostname = os.uname()[1] +whoami = sys._getframe().f_code.co_name +script = os.path.basename(__file__).split(".")[0] + +for pylib in list(sys.path): + if '/usr/local/lib' in pylib: + sys.path.remove(pylib) + continue + elif '/export/home/snet/.local' in pylib: + sys.path.remove(pylib) + continue + +''' BASE CONFIG ''' +global_iniFile = '/opt/etc/ini/global.ini' +config_global = ConfigParser.RawConfigParser() +config_global.optionxform(str()) +config_global.optionxform = str +config_global.read(global_iniFile) +sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY')) + +import snet.sloggly + +sys.path.append('/opt/auth/') +import library.leankit as leankit + +try: + logger = snet.sloggly.setup_custom_logger(script, logging.INFO) +except Exception as e: + print("\n=======\n") + title = "Something went wrong. Please inform SS team." + msg = "Error initializing the snet logger: " + str(e) + " :: " + traceback.format_exc(5) + print(msg) + whoami = sys._getframe().f_code.co_name + messages = [hostname, script, title, whoami, msg] + traceback.print_exc() + sys.exit(1) + + +def obj_dump(obj): + ''' + Object dumper + ''' + for attr in dir(obj): + if '_' in attr: + continue + try: + print("obj.%s = %s" % (attr, str(getattr(obj, attr)))) + except: # noqa: E722 + print("obj.%s = %s" % (attr, getattr(obj, attr))) + + for name, data in inspect.getmembers(obj): + if inspect.isclass(data): + print('name:%s' % (name)) + print(data) + + +def obj_dump_r(obj, level=0, deepth=2): + ''' + Recursive Object dumper + ''' + for attr in dir(obj): + if '_' in attr: + continue + try: + msg = 2 * level * ' ' + msg += ("obj.%s = %s" % (attr, str(getattr(obj, attr)))) + print(msg) + except: # noqa: E722 + msg = 2 * level * ' ' + msg += ("obj.%s = %s" % (attr, getattr(obj, attr))) + print(msg) + + if level >= deepth: + continue + + try: + obj_dump_r(getattr(obj, attr), level=level + 1) + except: # noqa: E722 + msg = 2 * level * ' ' + msg = 2 * level * ' ' + msg += "Dump is stinking... crashed." + print(msg) + + +if 'http_proxy' in os.environ: + del os.environ['http_proxy'] +if 'https_proxy' in os.environ: + del os.environ['https_proxy'] + +CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem' +CA_bundle = '/etc/ssl/certs/ca-certificates.crt' + +parser = argparse.ArgumentParser() +parser.add_argument('--leankit-board', type=str, required=False, + help='The leankit board name for the card creation', dest='leankit_board') +parser.add_argument('--leankit-board-id', type=int, required=False, + help='The leankit board id for the card creation', dest='leankit_board_id') +args = parser.parse_args() + +# leankit validation: +if args.leankit_board is None and args.leankit_board_id is None: + logger.error("leankit_board or leankit_board_id is not provided.") + logger.error("This is incompatible.") + print(parser.format_help()) + sys.exit(1) + +leankit_board_id = None + +if args.leankit_board_id is not None: + leankit_board_id = args.leankit_board_id + +elif args.leankit_board is not None: + leankit_res = leankit.get_board(args.leankit_board) + # print(leankit_res) + ''' + {'pageMeta': {'totalRecords': 2, 'offset': 0, 'limit': 100, 'startRow': 1, 'endRow': 2}, 'boards': [{'id': '31512088856393', 'title': 'DEV', 'description': '', 'boardRoleId': 4, 'isWelcome': False, 'boardRole': 'boardAdministrator', 'level': {'id': '31512085971730', 'depth': 3, 'maxDepth': 3, 'label': 'Team', 'color': '#ff841f'}}, {'id': '31512088544453', 'title': 'DEV-NMS3-phasein', 'description': '', 'boardRoleId': 4, 'isWelcome': False, 'boardRole': 'boardAdministrator'}]} + ''' + if leankit_res is None: + logger.error("Leankit board '%s': id is not found. Check the board name parameter." % args.leankit_board) + sys.exit(1) + + leankit_board_id = leankit_res['id'] + +# check lane +leankit_res = leankit.get_board_detail(leankit_board_id) +# print(json_dumps(leankit_res, sort_keys=True, indent=4)) + +leankit_lanes = dict() +for ll in leankit_res['lanes']: + leankit_lanes[ll['id']] = ll['name'] + +# Get Users +leankit_users = dict() +for ll in leankit_res['users']: + leankit_users[ll['id']] = ll['fullName'] + +# Get board contents +leankit_cards = dict() +# leankit_res = leankit.get_board_detail(leankit_board_id) +# limit 500 is max. +leankit_res = leankit.get_cards(board_id=leankit_board_id, limit=500, offset=0) +print(json_dumps(leankit_res, sort_keys=True, indent=4)) +# print(leankit_res) diff --git a/bin/redmine_create_repo.py b/bin/redmine_create_repo.py new file mode 100755 index 0000000..28570c1 --- /dev/null +++ b/bin/redmine_create_repo.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, print_function + +import os +import sys + +import configparser as ConfigParser +import pprint +import inspect +import traceback +import shlex +import re +import requests +import time +from subprocess import check_output, STDOUT, CalledProcessError + +pp = pprint.PrettyPrinter(indent=4) + +PROGNAME = os.path.basename(sys.argv[0]).split(".")[0] +script = os.path.basename(__file__).split(".")[0] + +global_iniFile = '/opt/etc/ini/global.ini' +config_global = ConfigParser.RawConfigParser() +config_global.optionxform(str()) +config_global.optionxform = str +config_global.read(global_iniFile) +sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY')) + +from redminelib import Redmine + +if 'http_proxy' in os.environ: + del os.environ['http_proxy'] +if 'https_proxy' in os.environ: + del os.environ['https_proxy'] + +# find /opt/SNet/scm -path '*/.hg' -prune -o -type d -path '*/.hg' | grep -v '^.hg$' | sed 's/\/\.hg$//' | xargs -n1 -P1 -I% echo % && sudo -u www-data RAILS_ENV=production bundle exec rails runner "Repository.find_by_url('%').fetch_changesets" + +CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem' +CA_bundle = '/etc/ssl/certs/ca-certificates.crt' + +redmine_config_global = ConfigParser.RawConfigParser() +redmine_config_global.read(config_global.get('INI', 'Redmine')) + +# Parse config +REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST') +REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO') +REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey') +REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY') + +redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle}, version='3.4.4') + +project_name = "bind9-bindhg-snet" +repo_url = "/opt/SNet/scm/pkg/bind9-snet/bind9-bindhg-snet" + +# +u = redmine.project.get(project_name, include='enabled_modules,repositories') + +print('%s:%s:%s' % (u.id, u.identifier, u.name)) + +if 'repository' not in u.enabled_modules: + print("Repository is not activated for repo %s:%s (%s)" % (u.id, u.identifier, u.name)) + sys.exit(1) +# continue + +elif len(u.repositories) > 0: + print("Repository is not defined for repo %s:%s (%s)" % (u.id, u.identifier, u.name)) + sys.exit(1) +# continue + +redmine_url = "%s://%s/sys/projects/%s/repository?key=%s" % (REDMINE_PROTO, REDMINE_HOSTNAME, u.id, REDMINE_WS_KEY) +# print('curl -s "%s"' % (redmine_url)) +# curl -v -H "Content-Type: application/json" -X POST -d '{"id": "3581", "vendor": "Mercurial", "repository": {"url": "/opt/SNet/scm/pkg/bind9-snet/bind9-bindhg-snet", "identifier":"bind9-bindhg-snet"}}' "https://redmine.snmc.cec.eu.int/sys/projects/3581/repository?key=tU0LvEthIX4cMzCI9YPI" + +print('curl -v -H "Content-Type: application/json" -X POST -d \'{"id": "%s", "vendor": "Mercurial", "repository": {"identifier": "%s", "url": "%s"}}\' "%s"' % (u.id, u.name, repo_url, redmine_url)) + +''' + time.sleep(120) + + try: + response = requests.get(redmine_url, + allow_redirects=True, + # headers=headers, + verify=CA_bundle) + except requests.exceptions.SSLError as e: + print('%s: %s' % (redmine_url, str(e))) + time.sleep(360) + continue + except Exception as e: + print('Generic: %s' % (str(e))) + time.sleep(360) + continue + + if response.status_code == 200: + print(response.content) + else: + print('ERROR') + print(response.status_code) + print(response.content) + time.sleep(360) +''' + +sys.exit(0) diff --git a/bin/redmine_create_sc_projects.py b/bin/redmine_create_sc_projects.py new file mode 100755 index 0000000..e5395c4 --- /dev/null +++ b/bin/redmine_create_sc_projects.py @@ -0,0 +1,760 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, print_function + +import os +import sys + +import configparser as ConfigParser +import pprint +import inspect +import traceback +import shlex +import re +import requests +from subprocess import check_output, STDOUT, CalledProcessError + +pp = pprint.PrettyPrinter(indent=4) + +PROGNAME = os.path.basename(sys.argv[0]).split(".")[0] +script = os.path.basename(__file__).split(".")[0] + +global_iniFile = '/opt/etc/ini/global.ini' +config_global = ConfigParser.RawConfigParser() +config_global.optionxform(str()) +config_global.optionxform = str +config_global.read(global_iniFile) +sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY')) + +from redminelib import Redmine + +if 'http_proxy' in os.environ: + del os.environ['http_proxy'] +if 'https_proxy' in os.environ: + del os.environ['https_proxy'] + +CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem' +CA_bundle = '/etc/ssl/certs/ca-certificates.crt' + +basedir = '/opt/SNet/scm' + +wanted_membership = {} +wanted_membership['com'] = 'Reporter' +wanted_membership['mgt'] = 'Reporter' +wanted_membership['officials'] = 'Reporter' +wanted_membership['net'] = 'Developer' +wanted_membership['pi'] = 'Developer' +wanted_membership['sd'] = 'Developer' +wanted_membership['sec'] = 'Developer' +wanted_membership['sup'] = 'Developer' +wanted_membership['tda'] = 'Developer' +wanted_membership['pm'] = 'Manager' + +cmd = ("ssh vcodebox-lu find %s -path '\*/.hg' -prune -o -type d -path '\*/.hg' | grep -v '^.hg$'" % (basedir)) + +try: + output = check_output((shlex.split(cmd)), stderr=STDOUT, shell=False) +except CalledProcessError as ex: + output = ex.output +# print(output) + +folder_projects = [] +for l in output.splitlines(): + if not l.startswith(basedir): + continue + if not l.endswith('/.hg'): + continue + if l == basedir + '/.hg': + continue + if 'archive_' in l: + continue + pat = l.replace('/.hg', '').replace(basedir + '/', '') + + # print("%s %s" % (l, pat)) + folder_projects.append(pat) + + +def obj_dump(obj): + ''' + Object dumper + ''' + for attr in dir(obj): + if '_' in attr: + continue + try: + print("obj.%s = %s" % (attr, str(getattr(obj, attr)))) + except: + print("obj.%s = %s" % (attr, getattr(obj, attr))) + + for name, data in inspect.getmembers(obj): + if inspect.isclass(data): + print('name:%s' % (name)) + print(data) + + +def obj_dump_r(obj, level=0, deepth=2): + ''' + Recursive Object dumper + ''' + for attr in dir(obj): + if '_' in attr: + continue + try: + msg = 2*level*' ' + msg += ("obj.%s = %s" % (attr, str(getattr(obj, attr)))) + print(msg) + except: + msg = 2*level*' ' + msg += ("obj.%s = %s" % (attr, getattr(obj, attr))) + print(msg) + + if level >= deepth: + continue + + try: + obj_dump_r(getattr(obj, attr), level=level+1) + except: + msg = 2*level*' ' + msg += "Dump is stinking... crashed." + print(msg) + + +def redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, pj_id, pj_ident, repository_url): + + ''' + curl -v -H "Content-Type: application/json" -X POST -d '{"id": "3581", "vendor": "Mercurial", "repository": {"url": "/opt/SNet/scm/pkg/bind9-snet/bind9-bindhg-snet", "identifier":"bind9-bindhg-snet"}}' "https://redmine.snmc.cec.eu.int/sys/projects/3581/repository?key=tU0LvEthIX4cMzCI9YPI" + ''' + + redmine_url = "%s://%s/sys/projects/%s/repository?key=%s" % (REDMINE_PROTO, REDMINE_HOSTNAME, pj_id, REDMINE_WS_KEY) + playload = {} + playload['id'] = pj_id + playload['vendor'] = 'Mercurial' + playload['repository'] = {} + playload['repository']['identifier'] = pj_ident + playload['repository']['url'] = repository_url + + try: + response = requests.post(redmine_url, + json=playload, + allow_redirects=True, + verify=CA_bundle) + + except requests.exceptions.SSLError as e: + self.logger.error('%s: %s' % (redmine_url, str(e))) + return None + except Exception as e: + self.logger.error('Generic: %s' % (str(e))) + return None + + if response.status_code == 201: + print('OK') + print(response.content) + return None + else: + print('ERROR') + print(response.status_code) + print(response.content) + return None + + +redmine_config_global = ConfigParser.RawConfigParser() +redmine_config_global.read(config_global.get('INI', 'Redmine')) + +# Parse config +REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST') +REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO') +REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey') +REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY') + +redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle}, version='3.4.4') + +all_red_parent = {} +all_red_pj = {} +all_red_cross_pj = {} +red_projects = redmine.project.all(offset=0, limit=1000, include='enabled_modules,repositories,trackers') + +for u in red_projects: + # print(u) + # print('%s' % (u.id)) + # print('%s' % (u.name)) + # print('%s' % (u.identifier)) + all_red_pj[u.identifier] = {} + all_red_pj[u.identifier]['id'] = u.id + all_red_pj[u.identifier]['name'] = u.name + all_red_pj[u.identifier]['identifier'] = u.identifier + all_red_pj[u.identifier]['enabled_modules'] = u.enabled_modules + all_red_pj[u.identifier]['repositories'] = u.repositories + if hasattr(u, 'is_public'): + all_red_pj[u.identifier]['is_public'] = u.is_public + else: + all_red_pj[u.identifier]['is_public'] = False + + if 'parent' in dir(u): + # print('parent:%s' % (u.parent)) + all_red_pj[u.identifier]['parent'] = {} + all_red_pj[u.identifier]['parent']['name'] = u.parent.name + all_red_pj[u.identifier]['parent']['id'] = u.parent.id + # all_red_pj[u.identifier]['parent']['identifier'] = u.parent.identifier + all_red_parent[u.parent.name+'/'+u.name] = u.identifier + + if u.identifier == 'refconfig': + pp.pprint(all_red_pj[u.identifier]) + # obj_dump(u) + # obj_dump_r(u, level=0, deepth=1) + print(u.enabled_modules) + print(u.repositories) + print(u.is_public) + print(list(u)) + # sys.exit(0) + + if u.name != u.identifier: + all_red_cross_pj[u.name] = u.identifier + # pp.pprint(all_red_cross_pj[u.name]) + + continue + print('%s' % (u.id)) + print('%s' % (u.name)) + print('%s' % (u.identifier)) + if 'parent' in u: + print('%s' % (u.parent)) + +pp.pprint(all_red_parent) + +red_groups = redmine.group.all() +all_red_grp = {} +for g in red_groups: + all_red_grp[g.name] = {} + all_red_grp[g.name]['id'] = g.id + all_red_grp[g.id] = {} + all_red_grp[g.id]['name'] = g.name +# print(pp.pformat(all_red_grp)) + +red_roles = redmine.role.all() +all_red_rl = {} +for r in red_roles: + all_red_rl[r.name] = {} + all_red_rl[r.name]['id'] = r.id + all_red_rl[r.id] = {} + all_red_rl[r.id]['name'] = r.name +# print(pp.pformat(all_red_rl)) + +# sys.exit(1) + +limit = 3000 +cpt = 0 +for pj in sorted(folder_projects): + if cpt > limit: + break + cpt += 1 + + print("----%s" % (pj)) + if '/' in pj: + (parent, pjj) = pj.rsplit('/', 1) + if '/' in parent: + cnt = parent.count('/') + if cnt == 1: + if parent in all_red_parent: + parent = all_red_parent[parent] + else: + print("Parent '%s' with 1/ but not found (%s), creating pre-parent" % (parent, pj)) + + prepa, ppa = parent.split('/') + prepa_ident = prepa.lower().replace('.', '-') + ppa_ident = ppa.lower().replace('.', '-') + ''' Pre-parent check-up. ''' + if prepa_ident in all_red_pj: + print("Pre-Parent '%s' is found" % (prepa)) + prepa_id = all_red_pj[prepa_ident]['id'] + elif prepa in all_red_cross_pj: + print("Pre-Parent '%s' is found in the bad list" % (prepa)) + prepa_id = all_red_pj[all_red_cross_pj[prepa]]['id'] + else: + print("Pre-Parent '%s:%s' need to be created" % (prepa, prepa_ident)) + + try: + project = redmine.project.new() + project.name = prepa + project.identifier = prepa_ident + project.description = prepa + project.homepage = None + project.is_public = True + project.inherit_members = False + project.parent_id = None + project.enabled_module_names = [] + project.save() + except Exception as e: + print('The creation of the ressources project "%s" did not suceed: %s' % (parent, str(e))) + print(traceback.format_exc(5)) + sys.exit(1) + prepa_id = project.id + + all_red_pj[project.identifier] = {} + all_red_pj[project.identifier]['id'] = project.id + all_red_pj[project.identifier]['name'] = project.name + all_red_pj[project.identifier]['identifier'] = project.identifier + all_red_pj[project.identifier]['enabled_modules'] = project.enabled_modules + all_red_pj[project.identifier]['repositories'] = project.repositories + if hasattr(project, 'is_public'): + all_red_pj[project.identifier]['is_public'] = project.is_public + else: + all_red_pj[project.identifier]['is_public'] = False + + # Preparent membership + + print("membership prepa_id is %s." % (prepa_id)) + + pj_wanted_membership = dict(wanted_membership) + pj_membership_del = [] + real_membership = redmine.project_membership.filter(project_id=prepa_id) + + for mb in real_membership: + if hasattr(mb, 'user'): + continue + ''' + print("------------") + print("membership") + print("mb.project: %s %s" % (mb.project.id, mb.project.name)) + print("mb.group: %s %s" % (mb.group.id, mb.group.name)) + print("mb.roles") + for rl in mb.roles: + print("%s %s" % (rl.id, rl.name)) + ''' + if mb.group.name in pj_wanted_membership: + for rl in mb.roles: + if pj_wanted_membership[mb.group.name] == rl.name: + del(pj_wanted_membership[mb.group.name]) + else: + for rl in mb.roles: + pj_membership_del.append(mb.id) + + else: + pj_membership_del.append(mb.id) + + pp.pprint(pj_wanted_membership) + for gr in pj_wanted_membership: + membership = redmine.project_membership.new() + membership.project_id = prepa_id + # http://www.redmine.org/issues/17904 group is user... + membership.user_id = all_red_grp[gr]['id'] + membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']] + membership.save() + + pp.pprint(pj_membership_del) + for mb in pj_membership_del: + membership = redmine.project_membership.get(prepa_id) + membership.delete(mb) + + ''' Parent check-up. ''' + if ppa_ident in all_red_pj: + print("Parent '%s' is found" % (ppa)) + ppa_id = all_red_pj[ppa_ident]['id'] + elif ppa in all_red_cross_pj: + print("Parent '%s' is found in the bad list" % (ppa)) + ppa_id = all_red_pj[all_red_cross_pj[ppa]]['id'] + else: + print("Parent '%s:%s' need to be created" % (ppa, ppa_ident)) + + try: + project = redmine.project.new() + project.name = ppa + project.identifier = ppa_ident + project.description = ppa + project.homepage = None + project.is_public = True + project.inherit_members = False + project.parent_id = prepa_id + project.enabled_module_names = [] + project.save() + except Exception as e: + print('The creation of the ressources project "%s" did not suceed: %s' % (ppa, str(e))) + print(traceback.format_exc(5)) + sys.exit(1) + ppa_id = project.id + + all_red_pj[project.identifier] = {} + all_red_pj[project.identifier]['id'] = project.id + all_red_pj[project.identifier]['name'] = project.name + all_red_pj[project.identifier]['identifier'] = project.identifier + all_red_pj[project.identifier]['enabled_modules'] = project.enabled_modules + if hasattr(project, 'is_public'): + all_red_pj[project.identifier]['is_public'] = project.is_public + else: + all_red_pj[project.identifier]['is_public'] = False + + all_red_pj[project.identifier]['parent'] = {} + all_red_pj[project.identifier]['parent']['name'] = project.parent.name + all_red_pj[project.identifier]['parent']['id'] = project.parent.id + all_red_parent[project.parent.name+'/'+project.name] = project.identifier + + else: + match = re.search(r'^.*/([^/]+/[^/]+)$', parent) + if match.group(1) in all_red_parent: + parent = all_red_parent[match.group(1)] + else: + print("Parent '%s' need to be decomposed for %s, skipping for now" % (parent, pj)) + continue + else: + parent = None + pjj = pj + + print("%s:%s" % (parent, pjj)) + if parent: + parent_ident = parent.lower().replace('.', '-') + pj_ident = pjj.lower().replace('.', '-') + + ''' + PARENT + ''' + + if parent and parent_ident in all_red_pj: + print("Parent '%s' is found" % (parent)) + parent_id = all_red_pj[parent_ident]['id'] + elif parent and parent in all_red_cross_pj: + print("Parent '%s' is found in the bad list" % (parent)) + parent_id = all_red_pj[all_red_cross_pj[parent]]['id'] + elif parent: + print("Parent '%s:%s' need to be created" % (parent, parent_ident)) + + try: + project = redmine.project.new() + project.name = parent + project.identifier = parent_ident + project.description = parent + project.homepage = None + project.is_public = True + project.inherit_members = False + project.parent_id = None + project.enabled_module_names = [] + # project.enabled_modules = [] readonly attribute + # project.custom_fields = [{'id': 1, 'value': 'PE'}, {'id': 11, 'value': 'scm'}] + # list(project) + project.save() + except Exception as e: + print('The creation of the ressources project "%s" did not suceed: %s' % (parent, str(e))) + print(traceback.format_exc(5)) + break + + all_red_pj[project.identifier] = {} + all_red_pj[project.identifier]['id'] = project.id + all_red_pj[project.identifier]['name'] = project.name + all_red_pj[project.identifier]['identifier'] = project.identifier + all_red_pj[project.identifier]['is_public'] = True + parent_id = project.id + + else: + parent_id = None + + if parent_id is not None: + + project = redmine.project.get(parent_id) + project.is_public = True + project.inherit_members = False + project.save() + + if 'enabled_modules' not in all_red_pj[parent_ident]: + print("No repository module activated for parent, OK") + + elif 'repository' not in all_red_pj[parent_ident]['enabled_modules']: + print("No repository for parent, OK") + + elif len(all_red_pj[parent_ident]['repositories']) == 0: + print("No repository for parent, OK") + + else: + print("repository activated for parent should not") + + print("membership parent_id is %s." % (parent_id)) + + pj_wanted_membership = dict(wanted_membership) + pj_membership_del = [] + real_membership = redmine.project_membership.filter(project_id=parent_id) + + for mb in real_membership: + if hasattr(mb, 'user'): + continue + ''' + print("------------") + print("membership") + print("mb.project: %s %s" % (mb.project.id, mb.project.name)) + print("mb.group: %s %s" % (mb.group.id, mb.group.name)) + print("mb.roles") + for rl in mb.roles: + print("%s %s" % (rl.id, rl.name)) + ''' + if mb.group.name in pj_wanted_membership: + for rl in mb.roles: + if pj_wanted_membership[mb.group.name] == rl.name: + del(pj_wanted_membership[mb.group.name]) + else: + for rl in mb.roles: + pj_membership_del.append(mb.id) + + else: + pj_membership_del.append(mb.id) + + pp.pprint(pj_wanted_membership) + for gr in pj_wanted_membership: + membership = redmine.project_membership.new() + membership.project_id = parent_id + # http://www.redmine.org/issues/17904 group is user... + membership.user_id = all_red_grp[gr]['id'] + membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']] + membership.save() + + pp.pprint(pj_membership_del) + for mb in pj_membership_del: + membership = redmine.project_membership.get(parent_id) + membership.delete(mb) + + ''' + ITSELF + ''' + + if pjj in all_red_pj: + print("The project '%s' is found in all_red_pj." % (pjj)) + repository_url = os.path.join(basedir, pj) + print("hg:%s:%s" % (pj_ident, repository_url)) + pp.pprint(all_red_pj[pjj]) + + if parent and 'parent' in all_red_pj[pjj]: + if parent != all_red_pj[pjj]['parent']['name']: + print("Not the same parent %s:%s" % (parent, all_red_pj[pjj]['parent']['name'])) + project = redmine.project.get(all_red_pj[pjj]['id']) + project.parent_id = parent_id + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.save() + + elif parent: + print("Not the same parent %s:None" % (parent)) + project = redmine.project.get(all_red_pj[pjj]['id']) + project.parent_id = parent_id + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url) + + if 'repository' not in all_red_pj[pjj]['enabled_modules']: + print("Repository is not activated for repo %s:%s" % (pjj, pj_ident)) + project = redmine.project.get(all_red_pj[pjj]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url) + + elif len(all_red_pj[pjj]['repositories']) == 0: + print("Repository URL is empty for repo %s:%s (%s)" % (pjj, pj_ident, os.path.join(basedir, pj))) + project = redmine.project.get(all_red_pj[pjj]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url) + + elif os.path.join(basedir, pj) != all_red_pj[pjj]['repositories'][0]['url']: + print("Repository URL is bad for repo %s:%s (%s <> %s)" + % (pjj, pj_ident, os.path.join(basedir, pj), all_red_pj[pjj]['repositories'][0]['url'])) + + # if all_red_pj[pjj]['is_public']: + # reset verything to is_public false + project = redmine.project.get(all_red_pj[pjj]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + + print("membership all_red_pj id %s." % (all_red_pj[pjj]['id'])) + + pj_wanted_membership = dict(wanted_membership) + pj_membership_del = [] + real_membership = redmine.project_membership.filter(project_id=all_red_pj[pjj]['id']) + # print('%s' % (pp.pprint(pj_wanted_membership))) + + for mb in real_membership: + if hasattr(mb, 'user'): + continue + ''' + print("------------") + print("membership") + print(list(mb)) + print("mb.project: %s %s" % (mb.project.id, mb.project.name)) + print("mb.group: %s %s" % (mb.group.id, mb.group.name)) + print("mb.roles") + for rl in mb.roles: + print("%s %s" % (rl.id, rl.name)) + if 'inherited' in mb: + if mb.inherited == True: + print("inherited = True") + else: + print("inherited = False") + ''' + if mb.group.name in pj_wanted_membership: + for rl in mb.roles: + if mb.group.name in pj_wanted_membership and pj_wanted_membership[mb.group.name] == rl.name: + del(pj_wanted_membership[mb.group.name]) + else: + for rl in mb.roles: + pj_membership_del.append(mb.id) + + else: + pj_membership_del.append(mb.id) + + pp.pprint(pj_wanted_membership) + for gr in pj_wanted_membership: + membership = redmine.project_membership.new() + membership.project_id = all_red_pj[pjj]['id'] + # http://www.redmine.org/issues/17904 group is user... + membership.user_id = all_red_grp[gr]['id'] + membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']] + membership.save() + + pp.pprint(pj_membership_del) + for mb in pj_membership_del: + membership = redmine.project_membership.get(all_red_pj[pjj]['id']) + membership.delete(mb) + + elif pjj in all_red_cross_pj: + print("The project '%s' is found in all_red_cross_pj." % (pjj)) + repository_url = os.path.join(basedir, pj) + print("hg:%s:%s" % (pj_ident, repository_url)) + pp.pprint(all_red_pj[all_red_cross_pj[pjj]]) + if parent and 'parent' in all_red_pj[all_red_cross_pj[pjj]]: + if parent != all_red_pj[all_red_cross_pj[pjj]]['parent']['name']: + print("Not the same parent %s:%s" % (parent, all_red_pj[all_red_cross_pj[pjj]]['parent']['name'])) + elif parent: + print("Not the same parent %s:None" % (parent)) + elif 'parent' in all_red_pj[all_red_cross_pj[pjj]]: + print("Not the same parent None:%s" % (all_red_pj[all_red_cross_pj[pjj]]['parent']['name'])) + + if 'repository' not in all_red_pj[all_red_cross_pj[pjj]]['enabled_modules']: + print("Repository is not activated for repo %s:%s" % (pjj, pj_ident)) + project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[all_red_cross_pj[pjj]]['id'], pj_ident, repository_url) + + elif len(all_red_pj[all_red_cross_pj[pjj]]['repositories']) == 0: + print("Repository URL is empty for repo %s:%s (%s)" % (pjj, pj_ident, repository_url)) + project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[all_red_cross_pj[pjj]]['id'], pj_ident, repository_url) + + elif os.path.join(basedir, pj) != all_red_pj[all_red_cross_pj[pjj]]['repositories'][0]['url']: + print("Repository URL is bad for repo %s:%s (%s <> %s)" + % (pjj, pj_ident, os.path.join(basedir, pj), all_red_pj[all_red_cross_pj[pjj]]['repositories'][0]['url'])) + + # if all_red_pj[pjj]['is_public']: + # reset verything to is_public false + project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + + print("membership all_red_cross_pj id %s." % (all_red_pj[all_red_cross_pj[pjj]]['id'])) + + pj_wanted_membership = dict(wanted_membership) + pj_membership_del = [] + real_membership = redmine.project_membership.filter(project_id=all_red_pj[all_red_cross_pj[pjj]]['id']) + + for mb in real_membership: + if hasattr(mb, 'user'): + continue + ''' + print("------------") + print("membership") + print("mb.project: %s %s" % (mb.project.id, mb.project.name)) + print("mb.group: %s %s" % (mb.group.id, mb.group.name)) + print("mb.roles") + for rl in mb.roles: + print("%s %s" % (rl.id, rl.name)) + ''' + if mb.group.name in pj_wanted_membership: + for rl in mb.roles: + if pj_wanted_membership[mb.group.name] == rl.name: + del(pj_wanted_membership[mb.group.name]) + else: + for rl in mb.roles: + pj_membership_del.append(mb.id) + + else: + pj_membership_del.append(mb.id) + + pp.pprint(pj_wanted_membership) + for gr in pj_wanted_membership: + membership = redmine.project_membership.new() + membership.project_id = all_red_pj[all_red_cross_pj[pjj]]['id'] + # http://www.redmine.org/issues/17904 group is user... + membership.user_id = all_red_grp[gr]['id'] + membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']] + membership.save() + + pp.pprint(pj_membership_del) + for mb in pj_membership_del: + membership = redmine.project_membership.get(all_red_pj[all_red_cross_pj[pjj]]['id']) + membership.delete(mb) + + # break + + else: + print("The project '%s' need to be created." % (pj)) + print("hg:%s:%s" % (pj_ident, os.path.join(basedir, pj))) + + if parent and parent in all_red_pj: + print("Parent '%s' is found" % (parent)) + elif parent and parent in all_red_cross_pj: + print("Parent '%s' is found in the bad list" % (parent)) + + try: + print('id:%s' % (pj_ident)) + project = redmine.project.new() + project.name = pjj + project.identifier = pj_ident + project.description = pjj + project.homepage = None + project.is_public = True + project.inherit_members = False + project.parent_id = parent_id + # project.enabled_modules = ['repository'] Readonly attribute + # project.custom_fields = [{'id': 1, 'value': 'PE'}, {'id': 11, 'value': 'scm'}] + project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}] + # list(project) + project.save() + except Exception as e: + print('The creation of the ressources project "%s" did not suceed: %s' % (pjj, str(e))) + print(traceback.format_exc(5)) + break + + # try: + # project = redmine.project.get(pjj) + # except ResourceNotFoundError as e: + # print('The ressources is not found') + +sys.exit(0) diff --git a/bin/redmine_fetch_changeset.py b/bin/redmine_fetch_changeset.py new file mode 100755 index 0000000..b7883ea --- /dev/null +++ b/bin/redmine_fetch_changeset.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, print_function + +import os +import sys + +import configparser as ConfigParser +import pprint +import inspect +import traceback +import shlex +import re +import requests +import time +from subprocess import check_output, STDOUT, CalledProcessError + +pp = pprint.PrettyPrinter(indent=4) + +PROGNAME = os.path.basename(sys.argv[0]).split(".")[0] +script = os.path.basename(__file__).split(".")[0] + +global_iniFile = '/opt/etc/ini/global.ini' +config_global = ConfigParser.RawConfigParser() +config_global.optionxform(str()) +config_global.optionxform = str +config_global.read(global_iniFile) +sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY')) + +from redminelib import Redmine + +if 'http_proxy' in os.environ: + del os.environ['http_proxy'] +if 'https_proxy' in os.environ: + del os.environ['https_proxy'] + +# find /opt/SNet/scm -path '*/.hg' -prune -o -type d -path '*/.hg' | grep -v '^.hg$' | sed 's/\/\.hg$//' | xargs -n1 -P1 -I% echo % && sudo -u www-data RAILS_ENV=production bundle exec rails runner "Repository.find_by_url('%').fetch_changesets" + +CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem' +CA_bundle = '/etc/ssl/certs/ca-certificates.crt' + +redmine_config_global = ConfigParser.RawConfigParser() +redmine_config_global.read(config_global.get('INI', 'Redmine')) + +# Parse config +REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST') +REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO') +REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey') +REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY') + +redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle}, version='3.4.4') + +red_projects = redmine.project.all(offset=0, limit=1000, include='enabled_modules,repositories,trackers') + +for u in red_projects: + print('%s:%s:%s' % (u.id, u.identifier, u.name)) + + if 'repository' not in u.enabled_modules: + print("Repository is not activated for repo %s:%s (%s)" % (u.id, u.identifier, u.name)) + continue + + elif len(u.repositories) == 0: + print("Repository is not defined for repo %s:%s (%s)" % (u.id, u.identifier, u.name)) + continue + + redmine_url = "%s://%s/sys/fetch_changesets?key=%s&id=%s" % (REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, u.id) + # print('curl -s "%s"' % (redmine_url)) + + time.sleep(120) + + try: + response = requests.get(redmine_url, + allow_redirects=True, + # headers=headers, + verify=CA_bundle) + except requests.exceptions.SSLError as e: + print('%s: %s' % (redmine_url, str(e))) + time.sleep(360) + continue + except Exception as e: + print('Generic: %s' % (str(e))) + time.sleep(360) + continue + + if response.status_code == 200: + print(response.content) + else: + print('ERROR') + print(response.status_code) + print(response.content) + time.sleep(360) + +sys.exit(0) diff --git a/bin/redmine_issue b/bin/redmine_issue new file mode 100755 index 0000000..088c67b --- /dev/null +++ b/bin/redmine_issue @@ -0,0 +1,226 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, print_function + +import os +import sys + +import configparser as ConfigParser +import argparse +import pprint +import inspect +# import traceback +import shlex +import re +# import requests +from subprocess import check_output, STDOUT, CalledProcessError + +pp = pprint.PrettyPrinter(indent=4) + +PROGNAME = os.path.basename(sys.argv[0]).split(".")[0] +script = os.path.basename(__file__).split(".")[0] + +global_iniFile = '/opt/etc/ini/global.ini' +config_global = ConfigParser.RawConfigParser() +config_global.optionxform(str()) +config_global.optionxform = str +config_global.read(global_iniFile) +sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY')) + +from redminelib import Redmine + +if 'http_proxy' in os.environ: + del os.environ['http_proxy'] +if 'https_proxy' in os.environ: + del os.environ['https_proxy'] + +CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem' +CA_bundle = '/etc/ssl/certs/ca-certificates.crt' + +basedir = '/opt/SNet/scm' + +parser = argparse.ArgumentParser() +parser.add_argument('-p', '--project', type=str, default='local', + help='The project to restrict: ALL for all', + dest='project') +args = parser.parse_args() + +project_filter = 'ALL' +project_filter = args.project + +redmine_config_global = ConfigParser.RawConfigParser() +redmine_config_global.read(config_global.get('INI', 'Redmine')) + +# Parse config +REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST') +REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO') +REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey') +REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY') +REDMINE_VERSION = redmine_config_global.get('GLOBAL', 'VERSION') +redmine = None + + +def obj_dump(obj): + ''' + Object dumper + ''' + for attr in dir(obj): + if '_' in attr: + continue + try: + print("obj.%s = %s" % (attr, str(getattr(obj, attr)))) + except: + print("obj.%s = %s" % (attr, getattr(obj, attr))) + + for name, data in inspect.getmembers(obj): + if inspect.isclass(data): + print('name:%s' % (name)) + print(data) + + +def obj_dump_r(obj, level=0, deepth=2): + ''' + Recursive Object dumper + ''' + for attr in dir(obj): + if '_' in attr: + continue + try: + msg = 2*level*' ' + msg += ("obj.%s = %s" % (attr, str(getattr(obj, attr)))) + print(msg) + except: + msg = 2*level*' ' + msg += ("obj.%s = %s" % (attr, getattr(obj, attr))) + print(msg) + + if level >= deepth: + continue + + if isinstance(getattr(obj, attr), (int, str, unicode)): + continue + + try: + obj_dump_r(getattr(obj, attr), level=level+1) + except: + msg = 2*level*' ' + msg += "Dump is stinking... crashed." + print(msg) + + +if project_filter == 'local': + # cmd = ("pwd") + # cmd = ("hg config paths.default || git config --get remote.origin.url") + cmds = [] + cmds.append("hg config paths.default") + cmds.append("git config --get remote.origin.url") + + vcs = '' + for cmd in cmds: + # print("hg-git cmd: %s" % (cmd)) + # print("hg-git cmd: %s" % (shlex.split(cmd))) + + try: + output = check_output((shlex.split(cmd)), + stderr=STDOUT, + shell=False) + except CalledProcessError as ex: + output = ex.output + + # print("hg-git output: '%s'" % (output)) + if output == '': + continue + if ':/' in output and '.git' in output: + vcs = 'git' + break + elif '//' in output: + vcs = 'hg' + break + + if vcs == '': + print("bad repo: %s, abort." % (output)) + sys.exit(1) + if vcs == 'hg': + match = re.search(r'^.*/(/.*)$', output) + elif vcs == 'git': + match = re.search(r'^.*:(/.*)$', output) + if match: + repo = match.group(1) + else: + print("bad repo: %s, abort." % (output)) + sys.exit(1) + + print("repo: %s" % (repo)) + + redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), + key=REDMINE_KEY, requests={'verify': CA_bundle}, + version='3.4.4') + + red_projects = redmine.project.all(offset=0, limit=1000, include='enabled_modules,repositories') + for u in red_projects: + if 'repository' not in u.enabled_modules: + continue + if 'issue_tracking' not in u.enabled_modules: + continue + + # if obj.trackers + # print(u) + pp.pprint(u) + # obj_dump(u) + # obj_dump_r(u, level=0, deepth=1) + print("'%s' '%s' '%s'" % (u.id, u.name, u.identifier)) + print(u.enabled_modules) + + try: + if len(u.repositories) == 0: + continue + except Exception as e: + print('no repository: %s' % (str(e))) + continue + + if str(repo) == u.repositories[0]['url']: + print("found project %s" % (u.name)) + project_filter = u.name + break + +if redmine is None: + redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), + key=REDMINE_KEY, requests={'verify': CA_bundle}, + version=REDMINE_VERSION) + +if project_filter == 'ALL': + issues = redmine.issue.filter(status_id='open', sort='project:asc,id:asc') +else: + issues = redmine.issue.filter(status_id='open', project_id=project_filter, sort='project:asc,id:asc') + +for i in issues: + msg = ('#%s' % (i.id)) + if project_filter == 'ALL': + msg += (' p:%s\n' % (i.project)) + msg += (' status_id:%s\n' % (i.status)) + msg += (' priority_id:%s\n' % (i.priority)) + msg += (' tracker_id:%s\n' % (i.tracker)) + else: + msg += (' subject:%s\n' % (i.subject)) + try: + msg += (' assigned:%s\n' % (i.assigned_to.name)) + except Exception as e: + pass + obj_dump(i) + print(dir(i)) + print(i.custom_fields) + obj_dump(i.custom_fields) + print(redmine.custom_field.all()) + print('cs:' + str(i.custom_fields.get(41))) + for cs in i.custom_fields: + print(cs) + # print('cs:' + str(i.custom_fields.['leankit'])) + print(msg) + + # print('project:%s' % (i.project)) + # print('category:%s' % (i.category)) + # i.url + # print('%s' % (u.identifier)) + +sys.exit(0) diff --git a/bin/redmine_leankit_create_issue b/bin/redmine_leankit_create_issue index 538224d..aa1c2b7 100755 --- a/bin/redmine_leankit_create_issue +++ b/bin/redmine_leankit_create_issue @@ -114,7 +114,7 @@ basedir = '/opt/SNet/scm' Tracker_List = ['Bug', 'Feature', 'Service Improvement'] leankit_tracker_conversion = dict() -leankit_tracker_conversion['Bug'] = 'Defect' +leankit_tracker_conversion['Bug'] = 'Task' leankit_tracker_conversion['Feature'] = 'Task' parser = argparse.ArgumentParser() @@ -139,6 +139,10 @@ parser.add_argument('--leankit-board', type=str, required=False, help='The leankit board name for the card creation', dest='leankit_board') parser.add_argument('--leankit-board-id', type=int, required=False, help='The leankit board id for the card creation', dest='leankit_board_id') +parser.add_argument('--leankit-story-point', type=int, required=False, default=1, + help='The leankit story point associated with the issue', dest='leankit_story_point') +parser.add_argument('--leankit-header', type=str, required=False, default='', + help='The leankit card header for the card creation', dest='leankit_header') args = parser.parse_args() # leankit validation: @@ -214,6 +218,18 @@ if leankit_card_id is not None: if args.leankit_create is True and args.leankit_board_id is not None: leankit_board_id = args.leankit_board_id + leankit_res = leankit.get_board_detail(args.leankit_board_id) + # print(leankit_res) + ''' + {'pageMeta': {'totalRecords': 2, 'offset': 0, 'limit': 100, 'startRow': 1, 'endRow': 2}, 'boards': [{'id': '31512088856393', 'title': 'DEV', 'description': '', 'boardRoleId': 4, 'isWelcome': False, 'boardRole': 'boardAdministrator', 'level': {'id': '31512085971730', 'depth': 3, 'maxDepth': 3, 'label': 'Team', 'color': '#ff841f'}}, {'id': '31512088544453', 'title': 'DEV-NMS3-phasein', 'description': '', 'boardRoleId': 4, 'isWelcome': False, 'boardRole': 'boardAdministrator'}]} + ''' + if leankit_res is None: + logger.error("Leankit board '%s': id is not found. Check the board name parameter." % args.leankit_board) + sys.exit(1) + + leankit_board_id = leankit_res['id'] + leankit_board_name = leankit_res['title'] + elif args.leankit_create is True and args.leankit_board is not None: leankit_res = leankit.get_board(args.leankit_board) # print(leankit_res) @@ -225,6 +241,7 @@ elif args.leankit_create is True and args.leankit_board is not None: sys.exit(1) leankit_board_id = leankit_res['id'] + leankit_board_name = leankit_res['title'] if args.leankit_create is True: leankit_res = leankit.get_cardtype_from_board(leankit_board_id) @@ -472,7 +489,18 @@ if args.leankit_create is True: leankit_card["description"] = args.title leankit_card["laneId"] = leankit_board_lane_id leankit_card["priority"] = "normal" - leankit_card["size"] = 1 + leankit_card["size"] = args.leankit_story_point + + if leankit_board_name == 'DEV': + if args.tracker == 'Bug': + leankit_card["customIconId"] = "31512101365737" + + # leankit_card["customId"] = dict() + # leankit_card["customId"]["value"] = args.leankit_header + # leankit_card["customId"]["prefix"] = '[' + leankit_board_name + '] ' + # leankit_card["customId"]["url"] = None + leankit_card["customId"] = args.leankit_header + leankit_card["customFields"] = list() t = dict() t["fieldId"] = "31512088868633" diff --git a/bin/sid_user.py b/bin/sid_user.py index bdf135d..0ab71ba 100755 --- a/bin/sid_user.py +++ b/bin/sid_user.py @@ -108,7 +108,7 @@ def snet_ldap_get(): attributes=uattributes) for entry in ldap_con.response: - print(entry) + # print(entry) if uattributes[0] in entry['attributes']: if isinstance(entry['attributes'][uattributes[0]], list): uid = entry['attributes'][uattributes[0]][0] @@ -388,15 +388,15 @@ def sid_create_update_user_approver_scheduler_change_management(diego, dfqdn, re ty2 = [] #print(results) 666060597 if 'has as act' in results['properties'] : - if (isinstance(results['properties']['has as act'], list)): + if (isinstance(results['properties']['has as act'], list)): for act in results['properties']['has as act'] : - ty.append(act['name']) - else : - ty.append(results['properties']['has as act']['name']) - + ty.append(act['name']) + else : + ty.append(results['properties']['has as act']['name']) + if typeAdd not in ty : - ty.append(typeAdd) - #new relation to workaround Polymorphism + ty.append(typeAdd) + #new relation to workaround Polymorphism if create : block_to_update = { 'uid': uid, @@ -406,8 +406,8 @@ def sid_create_update_user_approver_scheduler_change_management(diego, dfqdn, re 'is a specialization of' : typeAdd, 'type': typeAdd, } - - #new version "has as act" + + #new version "has as act" block_to_update = { 'uid': uid, 'name': user, @@ -461,6 +461,8 @@ def main(): help="increase output verbosity", dest='verbose') parser.add_argument('-d', '--debug', action="store_true", default=False, help="increase output verbosity a lot", dest='debug') + parser.add_argument('--parameter', default=False, + help="the login parameter to debug", dest='param') parser.add_argument('-e', '--env', default=False, help="Set the wanted env", dest='env', nargs='?', choices=('dev', 'acc', 'prod')) parser.add_argument('--dryrun', action="store_true", default=False, @@ -470,8 +472,13 @@ def main(): args = parser.parse_args() dryrun = args.dryrun + debug = args.debug + logindebug = args.param res_rw_user = args.rw_user + if debug: + logger.setLevel(logging.DEBUG) + verify = True if args.env is False: logger.debug('Using the automatic env.') @@ -491,8 +498,7 @@ def main(): logger.error('should not happen') sys.exit(1) - print(fqdn) - #exit(1) + print('Using the SID backend: ' + fqdn) snet_groups = 'com,mgt,net,pm,sd,sec,sup,tda'.split(',') official_groups = ['officials'] @@ -503,25 +509,40 @@ def main(): # They are all members of C4-TA. So do not add someone not member of C4-TA. The C4-TA is hard-coded below. # first_request before 10/2021 # last reminder request: 01/2022 + # last reminder request: 04/2022 : used to remove the relations for others users official_broken_leg = ['tsigref', 'wagnejl', 'hautari', 'durmeda', 'stoiama'] - nis_transition = ['alcobcr', 'bellimi', 'belotbe', 'culeaso', 'cultrro', 'dobolch', 'florihe', 'hainmar', 'kollepa', 'noronnu', 'panteer', 'plesspa', 'sanzale', 'soulech'] + departments = ['DIGIT.C.4', 'DIGIT.C.4.001', 'DIGIT.C.4.002', 'DIGIT.C.4.003', 'DIGIT.C.4.006', 'DIGIT.C.4.007', 'DIGIT.C.4.008'] - departments = ['DIGIT.C.4', 'DIGIT.C.4.002', 'DIGIT.C.4.003', 'DIGIT.C.4.006', 'DIGIT.C.4.007', 'DIGIT.C.4.008'] - - - # last reminder request: 04/2022 : used to remove the relations for others users approver_scheduler_list = ['fournla', 'chevaju', 'gondago'] + snet_results = dict() snet_results = snet_ldap_get() - logger.debug(pformat(snet_results)) + if debug: + if logindebug: + logger.debug("debuging " + logindebug) + if 'users' in snet_results and logindebug in snet_results['users']: + logger.debug(pformat(snet_results['users'][logindebug])) + else: + logger.debug(logindebug + " not found in snet_results.") + else: + logger.debug(pformat(snet_results)) ec_results = dict() ec_ldap_users = list(snet_results['users'].keys()) ec_ldap_users += official_broken_leg ec_results = ec_ldap_get_user(ec_ldap_users) - logger.debug(pformat(ec_results)) + if debug: + if logindebug: + logger.debug("debuging " + logindebug) + if 'users' in snet_results and logindebug in snet_results['users']: + logger.debug(pformat(ec_results['users'][logindebug])) + else: + logger.debug(logindebug + " not found in snet_results.") + else: + logger.debug(pformat(ec_results)) + ''' 'yildmes': {'building': 'B-28', 'c': 'BE', @@ -602,12 +623,22 @@ def main(): logger.info('Snet User snet_mail_index: ' + pformat(snet_mail_index)) logger.info('Snet User snet_account_index: ' + pformat(snet_account_index)) + diego = Diego(fqdn=fqdn, verify=verify) params = {'name': '","'.join(departments)} sid_results = diego.diego_run_dieget_by_name('sid_user_check', params) context_uid = 666000002 - logger.info('SID User: ' + pformat(sid_results[1])) + if debug: + if logindebug: + logger.debug("debuging " + logindebug) + if sid_results and logindebug in sid_results[1]: + logger.debug(pformat(sid_results[1][logindebug])) + else: + logger.debug(logindebug + " not found in sid_results.") + else: + logger.debug('SID User: ' + pformat(sid_results[1])) + ''' 'yildmes': {'belongs to': 'SNet NET', 'has as directorate general': 'DIGIT', @@ -626,8 +657,7 @@ def main(): for user in sid_results[1]: if user in devnull_del_user: continue - if user in nis_transition: - # TODO: not nice, but avoid errors for now + if debug and logindebug and logindebug != user: continue if user not in snet_account_index: logger.info('SID user ' + user + ' should be updated to resigned. User missing from the snet_account_index.') @@ -643,6 +673,9 @@ def main(): for user in snet_account_index: if user in devnull_user: continue + if debug and logindebug and logindebug != user: + continue + need_to_create = False need_to_update = False if user in sid_results[1]: @@ -671,12 +704,26 @@ def main(): block_to_update['properties']['has as role'] = list() block_to_update['properties']['has as role'].append(t) + if 'has write access to' not in block_to_update['properties']: + block_to_update['properties']['has write access to'] = list() + elif 'has write access to' in block_to_update['properties'] and not isinstance(block_to_update['properties']['has write access to'], list): + t = block_to_update['properties']['has write access to'] + block_to_update['properties']['has write access to'] = list() + block_to_update['properties']['has write access to'].append(t) + if 'belongs to' not in block_to_update['properties']: block_to_update['properties']['belongs to'] = list() elif 'belongs to' in block_to_update['properties'] and not isinstance(block_to_update['properties']['belongs to'], list): t = block_to_update['properties']['belongs to'] block_to_update['properties']['belongs to'] = list() block_to_update['properties']['belongs to'].append(t) + else: + if 'has write access to' not in block_to_update['properties']: + block_to_update['properties']['has write access to'] = list() + elif 'has write access to' in block_to_update['properties'] and not isinstance(block_to_update['properties']['has write access to'], list): + t = block_to_update['properties']['has write access to'] + block_to_update['properties']['has write access to'] = list() + block_to_update['properties']['has write access to'].append(t) if 'has as short name' not in block_to_update['properties'] or block_to_update['properties']['has as short name'] is None or '': block_to_update['properties']['has as short name'] = ec_results['users'][user]['givenName'][0] + ec_results['users'][user]['sn'][:2] @@ -703,7 +750,7 @@ def main(): block_to_update['properties']['has as status'] = 'active' block_to_update['properties']['has e-mail address'] = ec_results['users'][user]['mail'] - if 'ecInternationalTelephoneNumber' in ec_results['users'][user] : + if 'ecInternationalTelephoneNumber' in ec_results['users'][user] : block_to_update['properties']['has telephone number'] = ec_results['users'][user]['ecInternationalTelephoneNumber'] if 'departmentNumber' in ec_results['users'][user] : @@ -723,7 +770,7 @@ def main(): # "has access to easiCAPs feature" should be edited to contain "Port History" and "Profile Support". for mb in snet_results['users'][user]['membership']: - # 'com,mgt,net,pm,sd,sec,sup,tda' + # 'com,mgt,net,pm,sd,sec,sup,tda,officials' if mb == 'com': if need_to_update is False and need_to_create is True: if 'SNet COM' not in block_to_update['properties']['belongs to']: @@ -777,6 +824,7 @@ def main(): if 'Visual' not in block_to_update['properties']['has access to application program']: block_to_update['properties']['has access to application program'].append('Visual') + elif mb == 'pm': if need_to_update is False and need_to_create is True: block_to_update['properties']['belongs to'].append('SNet PM') @@ -786,7 +834,7 @@ def main(): if 'Visual' not in block_to_update['properties']['has access to application program']: block_to_update['properties']['has access to application program'].append('Visual') - + elif mb == 'sd': if need_to_update is False and need_to_create is True: block_to_update['properties']['belongs to'].append('Snet NOC/SD') @@ -833,33 +881,65 @@ def main(): if 'Visual' not in block_to_update['properties']['has access to application program']: block_to_update['properties']['has access to application program'].append('Visual') + elif mb == 'officials': + ''' + if need_to_update is False and need_to_create is True: + if 'SNet SUP' not in block_to_update['properties']['belongs to']: + block_to_update['properties']['belongs to'].append('SNet SUP') + if 'Developer' not in block_to_update['properties']['has as role']: + block_to_update['properties']['has as role'].append('Developer') + if 'edit object (Visual action)' not in block_to_update['properties']['is authorized to']: + block_to_update['properties']['is authorized to'].append('edit object (Visual action)') + if 'edit relation (SID action)' not in block_to_update['properties']['is authorized to']: + block_to_update['properties']['is authorized to'].append('edit relation (SID action)') + if 'CRUD' not in block_to_update['properties']['has access to application program']: + block_to_update['properties']['has access to application program'].append('CRUD') + + ''' + if 'SnetInventory' not in block_to_update['properties']['has access to application program']: + block_to_update['properties']['has access to application program'].append('SnetInventory') + + ''' + if 'Visual' not in block_to_update['properties']['has access to application program']: + block_to_update['properties']['has access to application program'].append('Visual') + ''' + if need_to_update is False and need_to_create is True and 'departmentNumber' in ec_results['users'][user]: if ec_results['users'][user]['departmentNumber'] == 'DIGIT.C.4.007': block_to_update['properties']['belongs to'].append('NIS') + block_to_update['properties']['belongs to'].append('OIS') + + if 'OIS' not in block_to_update['properties']['has as role']: + block_to_update['properties']['has write access to'].append('wireless access point') if 'belongs to' in block_to_update['properties'] and len(block_to_update['properties']['belongs to']) == 1: block_to_update['properties']['belongs to'] = block_to_update['properties']['belongs to'][0] if 'has as role' in block_to_update['properties'] and len(block_to_update['properties']['has as role']) == 1: block_to_update['properties']['has as role'] = block_to_update['properties']['has as role'][0] + if 'has write access to' in block_to_update['properties'] and len(block_to_update['properties']['has write access to']) == 1: + block_to_update['properties']['has write access to'] = block_to_update['properties']['has write access to'][0] + if len(block_to_update['properties']['is authorized to']) == 1: block_to_update['properties']['is authorized to'] = block_to_update['properties']['is authorized to'][0] if len(block_to_update['properties']['has access to application program']) == 1: block_to_update['properties']['has access to application program'] = block_to_update['properties']['has access to application program'][0] + if len(block_to_update['properties']['has write access to']) == 1: + block_to_update['properties']['has write access to'] = block_to_update['properties']['has write access to'][0] # has as role (OQM, Product Owner, SDM) # print("This '%s' is a PM -> also need to add a 'is a' 'approver' + 'scheduler'" % user) if user in sid_results[1] and 'has as role' in sid_results[1][user] : if isinstance(sid_results[1][user]['has as role'], list): for role in sid_results[1][user]['has as role']: - if role == 'OQM' or role == 'Product Owner' or role == 'SDM' : + if role == 'OQM' or role == 'Product Owner' or role == 'SDM' : sid_need_approver.append(user) - sid_need_scheduler.append(user) + sid_need_scheduler.append(user) else : - role = sid_results[1][user]['has as role'] - if role == 'OQM' or role == 'Product Owner' or role == 'SDM' : + role = sid_results[1][user]['has as role'] + if role == 'OQM' or role == 'Product Owner' or role == 'SDM' : sid_need_approver.append(user) - sid_need_scheduler.append(user) - + sid_need_scheduler.append(user) + # check and cleanup the data before scrat dict_keys = list(block_to_update['properties'].keys()) for prop in dict_keys: @@ -888,6 +968,9 @@ def main(): to_print = pformat(block_to_update) for i in list(range(0, int(round(len(to_print) / 250)) + 1)): logger.info('scrat %s cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)])) + + sys.exit(1) + params = {} sid_s_results = diego.diego_run_dieget_by_name('sid_sheduler_check', params) for user in sid_s_results[1]: @@ -896,14 +979,14 @@ def main(): if user not in sid_need_scheduler or user not in approver_scheduler_list: logger.error('SID user ' + user + ' should not be an scheduler.') if not dryrun: - if user in sid_results[1] : + if user in sid_results[1] : sid_update_user_exlude_approver_scheduler_change_management(diego, fqdn, res_rw_user, user, sid_results[1][user]['uid'], 'scheduler') #pass else: logger.error('dry run, user not removed from the scheduler role.') continue - - print(sid_need_scheduler, "SCHESDULER-LIST") + + print(sid_need_scheduler, "SCHEDULERS-LIST") for user in sid_need_scheduler: if user in devnull_user: continue @@ -916,15 +999,14 @@ def main(): need_to_create = True logger.debug('SID user ' + user + ' should be addded to scheduler.') #create the relation if not exists - + if not dryrun : sid_create_update_user_approver_scheduler_change_management(diego, fqdn, res_rw_user, user, sid_results[1][user]['uid'], 'scheduler', need_to_update) #pass else: logger.error('dry run, user not add/update from the scheduler role in "has as act"') continue - - + params = {} sid_a_results = diego.diego_run_dieget_by_name('sid_approver_check', params) for user in sid_a_results[1]: @@ -935,11 +1017,10 @@ def main(): if not dryrun : if user in sid_results[1] : sid_update_user_exlude_approver_scheduler_change_management(diego, fqdn, res_rw_user, user, sid_results[1][user]['uid'], 'approver') - #pass else: logger.error('dry run, user not removed from the approver role.') continue - + print(sid_need_approver, "APRROVERS-LIST") for user in sid_need_approver: if user in devnull_user: @@ -952,10 +1033,10 @@ def main(): elif user not in sid_a_results[1]: need_to_create = True logger.debug('SID user ' + user + ' should be addded to approver.') + #create the relation if not exists if not dryrun: sid_create_update_user_approver_scheduler_change_management(diego, fqdn, res_rw_user, user, sid_results[1][user]['uid'], 'approver', need_to_update) - #pass else: logger.error('dry run, user not add/update from the approver role in "has as act".') continue @@ -971,6 +1052,13 @@ def main(): logger.info(sid_d_results[1]) if 'has as member' in sid_d_results[1][department] and sid_d_results[1][department]['has as member'] is not None: + if not isinstance(sid_d_results[1][department]['has as member'], list): + # This is not a list, so this is a single value: + t = sid_d_results[1][department]['has as member'] + sid_d_results[1][department]['has as member'] = list() + sid_d_results[1][department]['has as member'].append(t) + logger.info(sid_d_results[1]) + for user in sid_d_results[1][department]['has as member']: if user in devnull_del_user: logger.debug("Skipping the user in the dev_null:" + user) @@ -983,7 +1071,7 @@ def main(): continue if 'departmentNumber' in ec_results['users'][user] and ec_results['users'][user]['departmentNumber'] != department: continue - if 'has as member' in sid_d_results[1][department] and sid_d_results[1][department]['has as member'] is not None: + if 'has as member' in sid_d_results[1][department] and sid_d_results[1][department]['has as member'] is not None and user not in sid_d_results[1][department]['has as member']: logger.info('SID user ' + user + ' should be addded to department ' + department + '.') if not dryrun: logger.info('dryrun') diff --git a/bin/synchronize_home_Users.pl b/bin/synchronize_home_Users.pl new file mode 100755 index 0000000..fb90e2e --- /dev/null +++ b/bin/synchronize_home_Users.pl @@ -0,0 +1,422 @@ +#!/usr/bin/perl + +# ------------------------------------------------------------------------------ +# $Id$ +# +# ------------------------------------------------------------------------------ + +use strict; +use warnings; +use Getopt::Long; +use Data::Dumper; +use Config::IniFiles; +use Net::LDAP; +use File::Copy; +use File::Basename; +use Sys::Hostname; +use Cwd; +#use Net::OpenSSH::Compat 'Net::SSH2'; + +# unbuffered output: +$| = 1; + +use lib ( new Config::IniFiles( -file => "/opt/etc/ini/global.ini" )->val( 'APPLICATION', 'LIBRARY' ) ); + +BEGIN { + my $iniFile = new Config::IniFiles( -file => "/opt/etc/ini/global.ini" ); + push( @INC, $iniFile->val( 'APPLICATION', 'LIBRARY' ) ); +} + +use SNET::common; +use SNET::snmpd; +use SNET::LdapNS qw(:all); +#use SNET::SSHDeviceInterfacer::Linux; + +use vars qw($verbose $debug $help $force $cli_mode $dry_run ); +$verbose = 0; +$debug = 0; +$cli_mode = 1; + +my $PROGNAME = basename( $0 ); +$PROGNAME =~ s/\.p[lm]$//; + +my %options = ( + "help" => \$help, + "debug" => \$debug, + "verbose" => \$verbose, + "force" => \$force, + "dry-run" => \$dry_run, +); + +my $SNMP_ENTERPRISEOID = "99"; +my $SNMP_OID = "1.3.6.1.4.1.99999.$SNMP_ENTERPRISEOID"; +my $SNMP_GEN = "6"; +my $SNMP_SPE = "1"; +my $msg = ''; +my $title = "Cacti ImportUser"; + +help() if !GetOptions( %options ) or $help; +$verbose = 1 if $debug; + +# ldap_find_users_and_groups() +# +# Read users and groups from SNet LDAP. + +sub ldap_find_users_and_groups ($$$$$$$$$$) +{ + my ( + $cfg_ldap_server, $cfg_ldap_user, $cfg_ldap_passwd, $cfg_ldap_group_search, $cfg_ldap_search_scope, + $cfg_ldap_group_search_filter, $cfg_ldap_group_attribute, $cfg_ldap_groupname, $hostname, $cfg_ldap_cafile + ) = @_; + + my %users; + + # Connect to the LDAP server + metaprint( 'verbose', "Initiating connection to LDAP server <$cfg_ldap_server>:" ) if $verbose; + my $ldap = Net::LDAP->new( + $cfg_ldap_server, + async => 0, + onerror => ( + ( $debug == 0 ) ? sub { return $_[0] } : sub { + my $message = shift; + my $error = defined( $message->error_desc ) ? $message->error_desc : $message->error(); + $msg = "Ldap: Unable to process request: $error."; + metaprint( 'error', $title . ": " . $msg ); + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + return $message; + } + ), + ); + if ( !$ldap ) { + $msg = "LDAP connection to <$cfg_ldap_server> failed."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + metaprint( 'verbose', "* LDAP connection completed successfully." ) if $verbose; + + my $message; + eval { + print STDERR 'Starting tls' . "\n" if ( $debug ); + $message = $ldap->start_tls( verify => 'require', + cafile => $cfg_ldap_cafile, ); + if ( $message->is_error() ) { + $msg = "Could not encrypt LDAP connection."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + }; + if ( $@ ) { + $msg = "Crash - Could not encrypt LDAP connection."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + + eval { + print STDERR 'binding' . "\n" if ( $debug ); + $message = $ldap->bind( + $cfg_ldap_user, + password => $cfg_ldap_passwd, + version => 3, + ); + if ( $message->is_error() ) { + $msg = "LDAP bind error occurred."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + }; + if ( $@ ) { + $msg = "Crash - LDAP bind error occurred ('" . $message->error_name . "')."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + + metaprint( 'verbose', "* LDAP bind operation completed successfully." ) if $verbose; + + # Search AD for objects in a particular group using LDAP + + metaprint( 'info', "Getting the LDAP member with expiration." ) if $verbose; + my %searchargs; + $searchargs{base} = 'ou=posix,' . $cfg_ldap_group_search; + $searchargs{scope} = $cfg_ldap_search_scope; + $searchargs{filter} = $cfg_ldap_group_search_filter; + $searchargs{attrs} = $cfg_ldap_group_attribute; + + print Dumper( \%searchargs ) if $verbose; + + my $results; + eval { $results = $ldap->search( %searchargs ); }; + if ( $@ ) { + my $title = "Check Password"; + my $msg = "Crash - LDAP Users Search."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + + if ( $results->is_error() ) { + metaprint( 'error', 'search failed: ' . $results->error_text ); + metaprint( 'error', 'search failed: ' . $results->code ); + metaprint( 'error', 'search failed: ' . $results->error ); + } elsif ( $results->count() == 0 ) { + metaprint( 'error', 'no result' ); + } else { + metaprint( 'verbose', "* Search returned " . $results->count . " object." ) if $verbose; + print Dumper( $results->as_struct() ) if $verbose; + my $ldap_hash = $results->as_struct(); + + my $attribute = $searchargs{attrs}[0]; + if ( defined( $ldap_hash->{ "cn=$cfg_ldap_groupname," . $searchargs{base} }{$attribute} ) ) { + foreach my $url ( @{ $ldap_hash->{ "cn=$cfg_ldap_groupname," . $searchargs{base} }{$attribute} } ) { + + print "$url\n" if $verbose; + push( @{ $users{$url}{'groups'} }, $cfg_ldap_groupname ); + + # fetch the user gecos + my %usersearch; + $usersearch{base} = $cfg_ldap_group_search; + $usersearch{base} =~ s/groups/people/; + $usersearch{attrs} = [ 'gecos', 'uid' ]; + $usersearch{scope} = 'sub'; + $usersearch{filter} = '(&(objectClass=posixAccount)(uid=' . $url . '))'; + print Dumper( \%usersearch ) if $verbose; + + my $userresults; + eval { $userresults = $ldap->search( %usersearch ); }; + if ( $@ ) { + my $title = "Check Password"; + my $msg = "Crash - LDAP Mail Users Search."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + if ( $userresults->is_error() ) { + metaprint( 'error', 'search failed: ' . $userresults->error_text ); + metaprint( 'error', 'search failed: ' . $userresults->code ); + metaprint( 'error', 'search failed: ' . $userresults->error ); + } elsif ( $userresults->count() == 0 ) { + metaprint( 'error', 'no result' ); + } else { + metaprint( 'info', "* Search returned " . $userresults->count . " url for '$url'." ) if $verbose; + print Dumper ( $userresults ) if $verbose; + + foreach my $uid ( $userresults->entries ) { + print "'" . $uid->get_value( 'uid' ) . "'\n" if $verbose; + if ( !defined( $uid->get_value( 'gecos' ) ) ) { + $users{ $uid->get_value( 'uid' ) } = ''; + } else { + $users{ $uid->get_value( 'uid' ) }{'gecos'} = $uid->get_value( 'gecos' ); + } + } + } + + } + } else { + metaprint( 'error', "Could not parse the hash result: {" . "cn=$cfg_ldap_groupname," . $searchargs{base} . "} { " . $attribute . " }" ); + } + } + + print "\nClosing LDAP connection.\n" if $verbose; + $ldap->unbind; + return %users; +} + +# +# Global Declarations +# +# load the INI +metaprint( "info", "Loading INI file Parameters" ); +my $global_iniFile = new Config::IniFiles( -file => "/opt/etc/ini/global.ini" ); + +my $CiniFile = new Config::IniFiles( -file => $global_iniFile->val( 'INI', 'RME' ) ); +metaprint( "error", "error value of CiniFile is undefined" ) if ( !defined( $CiniFile ) ); + +my $outpath = $CiniFile->val( 'GLOBAL', 'OUTPATH' ); +metaprint( "error", "The defined outpath is not valid, please correct-it" ) if ( !defined( $outpath ) ); + +my $AiniFile = new Config::IniFiles( -file => $global_iniFile->val( 'INI', 'LDAP' ) ); +metaprint( "error", "error value of AiniFile is undefined" ) if ( !defined( $AiniFile ) ); + +my $cfg_ldap_server = $AiniFile->val( 'LDAP_SNET_NG', 'SERVER' ); +metaprint( "error", "error value of cfg_ldap_server is undefined" ) if ( !defined( $cfg_ldap_server ) ); +my $cfg_ldap_user = $AiniFile->val( 'LDAP_SNET_NG', 'USER' ); +metaprint( "error", "error value of cfg_ldap_user is undefined" ) if ( !defined( $cfg_ldap_user ) ); +my $cfg_ldap_passwd = $AiniFile->val( 'LDAP_SNET_NG', 'PASSWORD' ); +metaprint( "error", "error value of cfg_ldap_passwd is undefined" ) if ( !defined( $cfg_ldap_passwd ) ); +my $cfg_ldap_group_search = $AiniFile->val( 'LDAP_SNET_NG', 'GRP_SEARCH' ); +metaprint( "error", "error value of cfg_ldap_group_search is undefined" ) if ( !defined( $cfg_ldap_group_search ) ); +my $cfg_ldap_group_search_filter = $AiniFile->val( 'LDAP_SNET_NG', 'FILTER' ); +metaprint( "error", "error value of cfg_ldap_group_search_filter is undefined" ) if ( !defined( $cfg_ldap_group_search_filter ) ); +$cfg_ldap_group_search_filter = "(&(objectclass=posixGroup)(cn=REPLACE))"; +my $cfg_ldap_group_attribute = $AiniFile->val( 'LDAP_SNET_NG', 'GRP_ATTRIBUTE' ); +metaprint( "error", "error value of cfg_ldap_group_attribute is undefined" ) if ( !defined( $cfg_ldap_group_attribute ) ); +$cfg_ldap_group_attribute = ["memberuid"]; +my $cfg_ldap_search_scope = $AiniFile->val( 'LDAP_SNET_NG', 'SEARCH_SCOPE' ); +metaprint( "error", "error value of cfg_ldap_search_scope is undefined" ) if ( !defined( $cfg_ldap_search_scope ) ); +my $cfg_ldap_cafile = $AiniFile->val( 'LDAP_SNET_NG', 'CA' ); +metaprint( "error", "error value of cfg_ldap_cafile is undefined" ) if ( !defined( $cfg_ldap_cafile ) ); + +# vSHARE credentails configuration +my $LiniFile = new Config::IniFiles( -file => $global_iniFile->val( 'INI', 'RME' ) ); +metaprint( "error", "error value of LiniFile is undefined" ) if ( !defined( $LiniFile ) ); +my $vshare_servers = $LiniFile->val( 'vshare', 'SERVERS' ); +metaprint( "error", "error value of vshare_servers is undefined" ) if ( !defined( $vshare_servers ) ); +my $vshare_user = $LiniFile->val( 'vshare', 'USER' ); +metaprint( "error", "error value of vshare_user is undefined" ) if ( !defined( $vshare_user ) ); +my $vshare_passwd = $LiniFile->val( 'vshare', 'PASSWD' ); +metaprint( "error", "error value of vshare_passwd is undefined" ) if ( !defined( $vshare_passwd ) ); + +my @filters; +push( @filters, 'com' ); +push( @filters, 'mgt' ); +push( @filters, 'net' ); +push( @filters, 'pi' ); +push( @filters, 'pm' ); +push( @filters, 'sd' ); +push( @filters, 'sec' ); +push( @filters, 'sup' ); +push( @filters, 'tda' ); +push( @filters, 'officials' ); + +my $hostname = hostname(); + +# Main Application +metaprint( "info", "Starting users synchro" ); + +my $errors = 0; + +my $already_defined_users = {}; +my $ssh; +my $out; + +metaprint( 'info', "processing vshare servers..." ); +foreach my $server ( split( /,/, $vshare_servers ) ) { + + # SSH to server. + metaprint 'info', 'Working on ' . $server . '...'; + $ssh = new SNET::SSHDeviceInterfacer::Linux( $debug, $server, $vshare_user, $vshare_passwd ); + if ( !$cli_mode ) { + $ssh->set_webmode( 1 ); + } + + if ( $ssh->openSSHConnection() ) { + metaprint 'info', "-> ok connected"; + } else { + metaprint 'error', "-> connection failed"; + $errors++; + next; + } + + my $cln = (); + $cln->{'uid'} = 3; + $cln->{'gid'} = 4; + $cln->{'name'} = 9; + + $out = $ssh->sendCMD( "/bin/ls -aildn /opt/home/*" ); + if ( $out =~ m/\s\/opt\/home\/\w+/i ) { + foreach my $line ( split( /\n/, $out ) ) { + chomp $line; + next if ( $line =~ /ls -aildn/ ); + next if ( $line =~ /\/export\/home\/snet/ ); + next if ( $line =~ /lost\+found/ ); + $line =~ s/^\s*//; + print Dumper ( $line ) if $debug; + + my $tmp = (); + @$tmp = split( /\s+/, $line ); + $tmp->[ $cln->{'name'} ] =~ s/\/*$//g; + $tmp->[ $cln->{'name'} ] =~ s/^\/.*\///; + print Dumper ( $tmp ) if $debug; + + # 3 : uid + # 4 : gid + # 9 : name + foreach my $pos ( keys %$cln ) { + $already_defined_users->{ $tmp->[ $cln->{'name'} ] }{$pos} = $tmp->[ $cln->{$pos} ]; + } + } + last; + } else { + $errors++; + next; + } + +} + +if ( $errors ) { + metaprint( 'error', "Some errors have been found, please contact SS Team!" . nl() . "Please copy/paste the output to the email!" ); + exit 1; +} + +#Print Users from Cacti +print Dumper ( $already_defined_users ) if $verbose; + +# -- Create the import file +my $cpt = 0; +my $cpt_del = 0; + +foreach my $filter ( @filters ) { + + metaprint "info", "Checking groups '$filter'."; + my $cfg_ldap_group_search_f = $cfg_ldap_group_search_filter; + $cfg_ldap_group_search_f =~ s/REPLACE/$filter/; + print "$cfg_ldap_group_search_f\n" if $verbose; + my %ldap_users = ldap_find_users_and_groups( $cfg_ldap_server, $cfg_ldap_user, $cfg_ldap_passwd, $cfg_ldap_group_search, $cfg_ldap_search_scope, + $cfg_ldap_group_search_f, $cfg_ldap_group_attribute, $filter, $hostname, $cfg_ldap_cafile ); + + print Dumper ( \%ldap_users ) if $verbose; + + foreach my $u ( keys %ldap_users ) { + if ( defined( $already_defined_users->{$u} ) && ( $already_defined_users->{$u} ) ) { + metaprint( "info", "Skipping user $u import, user is already defined, but user need to be checked." ) if $verbose; + + # TODO check uid:gid + $already_defined_users->{$u}{'found'} = 1; + next; + } + + next if ( $ldap_users{$u} =~ /^$/ ); + my $cmd = "sudo mkdir /mnt/home/$u && sudo chown $u:snmc /mnt/home/$u"; + metaprint( "info", "$u need to be created: '$cmd'." ); + if ( !$dry_run ) { + eval { $out = $ssh->sendCMD( $cmd ); }; + if ( $out =~ m/password/i ) { + $out = $ssh->sendCMD( $vshare_passwd ); + } + print $out; + } + $cpt++; + } +} + +my $local_user_no_del = (); +$local_user_no_del->{'snet'} = 1; +$local_user_no_del->{'quotas'} = 1; +$local_user_no_del->{'casuser'} = 1; +$local_user_no_del->{'ns-vernada'} = 1; + +metaprint "info", "Checking all others vshare home directory users defined."; +foreach my $u ( keys %$already_defined_users ) { + if ( defined( $already_defined_users->{$u} ) + && ( $already_defined_users->{$u} ) + && defined( $already_defined_users->{$u}{'found'} ) + && ( $already_defined_users->{$u}{'found'} ) ) { + next; + } elsif ( defined( $local_user_no_del->{$u} ) ) { + next; + } else { + metaprint( "error", "User $u need to be deleted manually." ); + metaprint( "error", "MANUAL: sudo tar -jcf /mnt/home/_OLD/$u.tbz /mnt/home/$u ; sudo rm -rf /mnt/home/$u" ); + $cpt_del++; + } +} +eval { $out = $ssh->sendCMD( "exit" ); }; + +metaprint( "info", "$cpt user(s) created." ); +metaprint( "info", "$cpt_del user(s) need to be deleted." ); +metaprint( "info", "--- Process Done ---" ); +exit( 0 ); diff --git a/bin/synchronize_redmine_projects.py b/bin/synchronize_redmine_projects.py new file mode 100755 index 0000000..e5395c4 --- /dev/null +++ b/bin/synchronize_redmine_projects.py @@ -0,0 +1,760 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, print_function + +import os +import sys + +import configparser as ConfigParser +import pprint +import inspect +import traceback +import shlex +import re +import requests +from subprocess import check_output, STDOUT, CalledProcessError + +pp = pprint.PrettyPrinter(indent=4) + +PROGNAME = os.path.basename(sys.argv[0]).split(".")[0] +script = os.path.basename(__file__).split(".")[0] + +global_iniFile = '/opt/etc/ini/global.ini' +config_global = ConfigParser.RawConfigParser() +config_global.optionxform(str()) +config_global.optionxform = str +config_global.read(global_iniFile) +sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY')) + +from redminelib import Redmine + +if 'http_proxy' in os.environ: + del os.environ['http_proxy'] +if 'https_proxy' in os.environ: + del os.environ['https_proxy'] + +CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem' +CA_bundle = '/etc/ssl/certs/ca-certificates.crt' + +basedir = '/opt/SNet/scm' + +wanted_membership = {} +wanted_membership['com'] = 'Reporter' +wanted_membership['mgt'] = 'Reporter' +wanted_membership['officials'] = 'Reporter' +wanted_membership['net'] = 'Developer' +wanted_membership['pi'] = 'Developer' +wanted_membership['sd'] = 'Developer' +wanted_membership['sec'] = 'Developer' +wanted_membership['sup'] = 'Developer' +wanted_membership['tda'] = 'Developer' +wanted_membership['pm'] = 'Manager' + +cmd = ("ssh vcodebox-lu find %s -path '\*/.hg' -prune -o -type d -path '\*/.hg' | grep -v '^.hg$'" % (basedir)) + +try: + output = check_output((shlex.split(cmd)), stderr=STDOUT, shell=False) +except CalledProcessError as ex: + output = ex.output +# print(output) + +folder_projects = [] +for l in output.splitlines(): + if not l.startswith(basedir): + continue + if not l.endswith('/.hg'): + continue + if l == basedir + '/.hg': + continue + if 'archive_' in l: + continue + pat = l.replace('/.hg', '').replace(basedir + '/', '') + + # print("%s %s" % (l, pat)) + folder_projects.append(pat) + + +def obj_dump(obj): + ''' + Object dumper + ''' + for attr in dir(obj): + if '_' in attr: + continue + try: + print("obj.%s = %s" % (attr, str(getattr(obj, attr)))) + except: + print("obj.%s = %s" % (attr, getattr(obj, attr))) + + for name, data in inspect.getmembers(obj): + if inspect.isclass(data): + print('name:%s' % (name)) + print(data) + + +def obj_dump_r(obj, level=0, deepth=2): + ''' + Recursive Object dumper + ''' + for attr in dir(obj): + if '_' in attr: + continue + try: + msg = 2*level*' ' + msg += ("obj.%s = %s" % (attr, str(getattr(obj, attr)))) + print(msg) + except: + msg = 2*level*' ' + msg += ("obj.%s = %s" % (attr, getattr(obj, attr))) + print(msg) + + if level >= deepth: + continue + + try: + obj_dump_r(getattr(obj, attr), level=level+1) + except: + msg = 2*level*' ' + msg += "Dump is stinking... crashed." + print(msg) + + +def redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, pj_id, pj_ident, repository_url): + + ''' + curl -v -H "Content-Type: application/json" -X POST -d '{"id": "3581", "vendor": "Mercurial", "repository": {"url": "/opt/SNet/scm/pkg/bind9-snet/bind9-bindhg-snet", "identifier":"bind9-bindhg-snet"}}' "https://redmine.snmc.cec.eu.int/sys/projects/3581/repository?key=tU0LvEthIX4cMzCI9YPI" + ''' + + redmine_url = "%s://%s/sys/projects/%s/repository?key=%s" % (REDMINE_PROTO, REDMINE_HOSTNAME, pj_id, REDMINE_WS_KEY) + playload = {} + playload['id'] = pj_id + playload['vendor'] = 'Mercurial' + playload['repository'] = {} + playload['repository']['identifier'] = pj_ident + playload['repository']['url'] = repository_url + + try: + response = requests.post(redmine_url, + json=playload, + allow_redirects=True, + verify=CA_bundle) + + except requests.exceptions.SSLError as e: + self.logger.error('%s: %s' % (redmine_url, str(e))) + return None + except Exception as e: + self.logger.error('Generic: %s' % (str(e))) + return None + + if response.status_code == 201: + print('OK') + print(response.content) + return None + else: + print('ERROR') + print(response.status_code) + print(response.content) + return None + + +redmine_config_global = ConfigParser.RawConfigParser() +redmine_config_global.read(config_global.get('INI', 'Redmine')) + +# Parse config +REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST') +REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO') +REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey') +REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY') + +redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle}, version='3.4.4') + +all_red_parent = {} +all_red_pj = {} +all_red_cross_pj = {} +red_projects = redmine.project.all(offset=0, limit=1000, include='enabled_modules,repositories,trackers') + +for u in red_projects: + # print(u) + # print('%s' % (u.id)) + # print('%s' % (u.name)) + # print('%s' % (u.identifier)) + all_red_pj[u.identifier] = {} + all_red_pj[u.identifier]['id'] = u.id + all_red_pj[u.identifier]['name'] = u.name + all_red_pj[u.identifier]['identifier'] = u.identifier + all_red_pj[u.identifier]['enabled_modules'] = u.enabled_modules + all_red_pj[u.identifier]['repositories'] = u.repositories + if hasattr(u, 'is_public'): + all_red_pj[u.identifier]['is_public'] = u.is_public + else: + all_red_pj[u.identifier]['is_public'] = False + + if 'parent' in dir(u): + # print('parent:%s' % (u.parent)) + all_red_pj[u.identifier]['parent'] = {} + all_red_pj[u.identifier]['parent']['name'] = u.parent.name + all_red_pj[u.identifier]['parent']['id'] = u.parent.id + # all_red_pj[u.identifier]['parent']['identifier'] = u.parent.identifier + all_red_parent[u.parent.name+'/'+u.name] = u.identifier + + if u.identifier == 'refconfig': + pp.pprint(all_red_pj[u.identifier]) + # obj_dump(u) + # obj_dump_r(u, level=0, deepth=1) + print(u.enabled_modules) + print(u.repositories) + print(u.is_public) + print(list(u)) + # sys.exit(0) + + if u.name != u.identifier: + all_red_cross_pj[u.name] = u.identifier + # pp.pprint(all_red_cross_pj[u.name]) + + continue + print('%s' % (u.id)) + print('%s' % (u.name)) + print('%s' % (u.identifier)) + if 'parent' in u: + print('%s' % (u.parent)) + +pp.pprint(all_red_parent) + +red_groups = redmine.group.all() +all_red_grp = {} +for g in red_groups: + all_red_grp[g.name] = {} + all_red_grp[g.name]['id'] = g.id + all_red_grp[g.id] = {} + all_red_grp[g.id]['name'] = g.name +# print(pp.pformat(all_red_grp)) + +red_roles = redmine.role.all() +all_red_rl = {} +for r in red_roles: + all_red_rl[r.name] = {} + all_red_rl[r.name]['id'] = r.id + all_red_rl[r.id] = {} + all_red_rl[r.id]['name'] = r.name +# print(pp.pformat(all_red_rl)) + +# sys.exit(1) + +limit = 3000 +cpt = 0 +for pj in sorted(folder_projects): + if cpt > limit: + break + cpt += 1 + + print("----%s" % (pj)) + if '/' in pj: + (parent, pjj) = pj.rsplit('/', 1) + if '/' in parent: + cnt = parent.count('/') + if cnt == 1: + if parent in all_red_parent: + parent = all_red_parent[parent] + else: + print("Parent '%s' with 1/ but not found (%s), creating pre-parent" % (parent, pj)) + + prepa, ppa = parent.split('/') + prepa_ident = prepa.lower().replace('.', '-') + ppa_ident = ppa.lower().replace('.', '-') + ''' Pre-parent check-up. ''' + if prepa_ident in all_red_pj: + print("Pre-Parent '%s' is found" % (prepa)) + prepa_id = all_red_pj[prepa_ident]['id'] + elif prepa in all_red_cross_pj: + print("Pre-Parent '%s' is found in the bad list" % (prepa)) + prepa_id = all_red_pj[all_red_cross_pj[prepa]]['id'] + else: + print("Pre-Parent '%s:%s' need to be created" % (prepa, prepa_ident)) + + try: + project = redmine.project.new() + project.name = prepa + project.identifier = prepa_ident + project.description = prepa + project.homepage = None + project.is_public = True + project.inherit_members = False + project.parent_id = None + project.enabled_module_names = [] + project.save() + except Exception as e: + print('The creation of the ressources project "%s" did not suceed: %s' % (parent, str(e))) + print(traceback.format_exc(5)) + sys.exit(1) + prepa_id = project.id + + all_red_pj[project.identifier] = {} + all_red_pj[project.identifier]['id'] = project.id + all_red_pj[project.identifier]['name'] = project.name + all_red_pj[project.identifier]['identifier'] = project.identifier + all_red_pj[project.identifier]['enabled_modules'] = project.enabled_modules + all_red_pj[project.identifier]['repositories'] = project.repositories + if hasattr(project, 'is_public'): + all_red_pj[project.identifier]['is_public'] = project.is_public + else: + all_red_pj[project.identifier]['is_public'] = False + + # Preparent membership + + print("membership prepa_id is %s." % (prepa_id)) + + pj_wanted_membership = dict(wanted_membership) + pj_membership_del = [] + real_membership = redmine.project_membership.filter(project_id=prepa_id) + + for mb in real_membership: + if hasattr(mb, 'user'): + continue + ''' + print("------------") + print("membership") + print("mb.project: %s %s" % (mb.project.id, mb.project.name)) + print("mb.group: %s %s" % (mb.group.id, mb.group.name)) + print("mb.roles") + for rl in mb.roles: + print("%s %s" % (rl.id, rl.name)) + ''' + if mb.group.name in pj_wanted_membership: + for rl in mb.roles: + if pj_wanted_membership[mb.group.name] == rl.name: + del(pj_wanted_membership[mb.group.name]) + else: + for rl in mb.roles: + pj_membership_del.append(mb.id) + + else: + pj_membership_del.append(mb.id) + + pp.pprint(pj_wanted_membership) + for gr in pj_wanted_membership: + membership = redmine.project_membership.new() + membership.project_id = prepa_id + # http://www.redmine.org/issues/17904 group is user... + membership.user_id = all_red_grp[gr]['id'] + membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']] + membership.save() + + pp.pprint(pj_membership_del) + for mb in pj_membership_del: + membership = redmine.project_membership.get(prepa_id) + membership.delete(mb) + + ''' Parent check-up. ''' + if ppa_ident in all_red_pj: + print("Parent '%s' is found" % (ppa)) + ppa_id = all_red_pj[ppa_ident]['id'] + elif ppa in all_red_cross_pj: + print("Parent '%s' is found in the bad list" % (ppa)) + ppa_id = all_red_pj[all_red_cross_pj[ppa]]['id'] + else: + print("Parent '%s:%s' need to be created" % (ppa, ppa_ident)) + + try: + project = redmine.project.new() + project.name = ppa + project.identifier = ppa_ident + project.description = ppa + project.homepage = None + project.is_public = True + project.inherit_members = False + project.parent_id = prepa_id + project.enabled_module_names = [] + project.save() + except Exception as e: + print('The creation of the ressources project "%s" did not suceed: %s' % (ppa, str(e))) + print(traceback.format_exc(5)) + sys.exit(1) + ppa_id = project.id + + all_red_pj[project.identifier] = {} + all_red_pj[project.identifier]['id'] = project.id + all_red_pj[project.identifier]['name'] = project.name + all_red_pj[project.identifier]['identifier'] = project.identifier + all_red_pj[project.identifier]['enabled_modules'] = project.enabled_modules + if hasattr(project, 'is_public'): + all_red_pj[project.identifier]['is_public'] = project.is_public + else: + all_red_pj[project.identifier]['is_public'] = False + + all_red_pj[project.identifier]['parent'] = {} + all_red_pj[project.identifier]['parent']['name'] = project.parent.name + all_red_pj[project.identifier]['parent']['id'] = project.parent.id + all_red_parent[project.parent.name+'/'+project.name] = project.identifier + + else: + match = re.search(r'^.*/([^/]+/[^/]+)$', parent) + if match.group(1) in all_red_parent: + parent = all_red_parent[match.group(1)] + else: + print("Parent '%s' need to be decomposed for %s, skipping for now" % (parent, pj)) + continue + else: + parent = None + pjj = pj + + print("%s:%s" % (parent, pjj)) + if parent: + parent_ident = parent.lower().replace('.', '-') + pj_ident = pjj.lower().replace('.', '-') + + ''' + PARENT + ''' + + if parent and parent_ident in all_red_pj: + print("Parent '%s' is found" % (parent)) + parent_id = all_red_pj[parent_ident]['id'] + elif parent and parent in all_red_cross_pj: + print("Parent '%s' is found in the bad list" % (parent)) + parent_id = all_red_pj[all_red_cross_pj[parent]]['id'] + elif parent: + print("Parent '%s:%s' need to be created" % (parent, parent_ident)) + + try: + project = redmine.project.new() + project.name = parent + project.identifier = parent_ident + project.description = parent + project.homepage = None + project.is_public = True + project.inherit_members = False + project.parent_id = None + project.enabled_module_names = [] + # project.enabled_modules = [] readonly attribute + # project.custom_fields = [{'id': 1, 'value': 'PE'}, {'id': 11, 'value': 'scm'}] + # list(project) + project.save() + except Exception as e: + print('The creation of the ressources project "%s" did not suceed: %s' % (parent, str(e))) + print(traceback.format_exc(5)) + break + + all_red_pj[project.identifier] = {} + all_red_pj[project.identifier]['id'] = project.id + all_red_pj[project.identifier]['name'] = project.name + all_red_pj[project.identifier]['identifier'] = project.identifier + all_red_pj[project.identifier]['is_public'] = True + parent_id = project.id + + else: + parent_id = None + + if parent_id is not None: + + project = redmine.project.get(parent_id) + project.is_public = True + project.inherit_members = False + project.save() + + if 'enabled_modules' not in all_red_pj[parent_ident]: + print("No repository module activated for parent, OK") + + elif 'repository' not in all_red_pj[parent_ident]['enabled_modules']: + print("No repository for parent, OK") + + elif len(all_red_pj[parent_ident]['repositories']) == 0: + print("No repository for parent, OK") + + else: + print("repository activated for parent should not") + + print("membership parent_id is %s." % (parent_id)) + + pj_wanted_membership = dict(wanted_membership) + pj_membership_del = [] + real_membership = redmine.project_membership.filter(project_id=parent_id) + + for mb in real_membership: + if hasattr(mb, 'user'): + continue + ''' + print("------------") + print("membership") + print("mb.project: %s %s" % (mb.project.id, mb.project.name)) + print("mb.group: %s %s" % (mb.group.id, mb.group.name)) + print("mb.roles") + for rl in mb.roles: + print("%s %s" % (rl.id, rl.name)) + ''' + if mb.group.name in pj_wanted_membership: + for rl in mb.roles: + if pj_wanted_membership[mb.group.name] == rl.name: + del(pj_wanted_membership[mb.group.name]) + else: + for rl in mb.roles: + pj_membership_del.append(mb.id) + + else: + pj_membership_del.append(mb.id) + + pp.pprint(pj_wanted_membership) + for gr in pj_wanted_membership: + membership = redmine.project_membership.new() + membership.project_id = parent_id + # http://www.redmine.org/issues/17904 group is user... + membership.user_id = all_red_grp[gr]['id'] + membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']] + membership.save() + + pp.pprint(pj_membership_del) + for mb in pj_membership_del: + membership = redmine.project_membership.get(parent_id) + membership.delete(mb) + + ''' + ITSELF + ''' + + if pjj in all_red_pj: + print("The project '%s' is found in all_red_pj." % (pjj)) + repository_url = os.path.join(basedir, pj) + print("hg:%s:%s" % (pj_ident, repository_url)) + pp.pprint(all_red_pj[pjj]) + + if parent and 'parent' in all_red_pj[pjj]: + if parent != all_red_pj[pjj]['parent']['name']: + print("Not the same parent %s:%s" % (parent, all_red_pj[pjj]['parent']['name'])) + project = redmine.project.get(all_red_pj[pjj]['id']) + project.parent_id = parent_id + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.save() + + elif parent: + print("Not the same parent %s:None" % (parent)) + project = redmine.project.get(all_red_pj[pjj]['id']) + project.parent_id = parent_id + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url) + + if 'repository' not in all_red_pj[pjj]['enabled_modules']: + print("Repository is not activated for repo %s:%s" % (pjj, pj_ident)) + project = redmine.project.get(all_red_pj[pjj]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url) + + elif len(all_red_pj[pjj]['repositories']) == 0: + print("Repository URL is empty for repo %s:%s (%s)" % (pjj, pj_ident, os.path.join(basedir, pj))) + project = redmine.project.get(all_red_pj[pjj]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url) + + elif os.path.join(basedir, pj) != all_red_pj[pjj]['repositories'][0]['url']: + print("Repository URL is bad for repo %s:%s (%s <> %s)" + % (pjj, pj_ident, os.path.join(basedir, pj), all_red_pj[pjj]['repositories'][0]['url'])) + + # if all_red_pj[pjj]['is_public']: + # reset verything to is_public false + project = redmine.project.get(all_red_pj[pjj]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': repository_url}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + + print("membership all_red_pj id %s." % (all_red_pj[pjj]['id'])) + + pj_wanted_membership = dict(wanted_membership) + pj_membership_del = [] + real_membership = redmine.project_membership.filter(project_id=all_red_pj[pjj]['id']) + # print('%s' % (pp.pprint(pj_wanted_membership))) + + for mb in real_membership: + if hasattr(mb, 'user'): + continue + ''' + print("------------") + print("membership") + print(list(mb)) + print("mb.project: %s %s" % (mb.project.id, mb.project.name)) + print("mb.group: %s %s" % (mb.group.id, mb.group.name)) + print("mb.roles") + for rl in mb.roles: + print("%s %s" % (rl.id, rl.name)) + if 'inherited' in mb: + if mb.inherited == True: + print("inherited = True") + else: + print("inherited = False") + ''' + if mb.group.name in pj_wanted_membership: + for rl in mb.roles: + if mb.group.name in pj_wanted_membership and pj_wanted_membership[mb.group.name] == rl.name: + del(pj_wanted_membership[mb.group.name]) + else: + for rl in mb.roles: + pj_membership_del.append(mb.id) + + else: + pj_membership_del.append(mb.id) + + pp.pprint(pj_wanted_membership) + for gr in pj_wanted_membership: + membership = redmine.project_membership.new() + membership.project_id = all_red_pj[pjj]['id'] + # http://www.redmine.org/issues/17904 group is user... + membership.user_id = all_red_grp[gr]['id'] + membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']] + membership.save() + + pp.pprint(pj_membership_del) + for mb in pj_membership_del: + membership = redmine.project_membership.get(all_red_pj[pjj]['id']) + membership.delete(mb) + + elif pjj in all_red_cross_pj: + print("The project '%s' is found in all_red_cross_pj." % (pjj)) + repository_url = os.path.join(basedir, pj) + print("hg:%s:%s" % (pj_ident, repository_url)) + pp.pprint(all_red_pj[all_red_cross_pj[pjj]]) + if parent and 'parent' in all_red_pj[all_red_cross_pj[pjj]]: + if parent != all_red_pj[all_red_cross_pj[pjj]]['parent']['name']: + print("Not the same parent %s:%s" % (parent, all_red_pj[all_red_cross_pj[pjj]]['parent']['name'])) + elif parent: + print("Not the same parent %s:None" % (parent)) + elif 'parent' in all_red_pj[all_red_cross_pj[pjj]]: + print("Not the same parent None:%s" % (all_red_pj[all_red_cross_pj[pjj]]['parent']['name'])) + + if 'repository' not in all_red_pj[all_red_cross_pj[pjj]]['enabled_modules']: + print("Repository is not activated for repo %s:%s" % (pjj, pj_ident)) + project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[all_red_cross_pj[pjj]]['id'], pj_ident, repository_url) + + elif len(all_red_pj[all_red_cross_pj[pjj]]['repositories']) == 0: + print("Repository URL is empty for repo %s:%s (%s)" % (pjj, pj_ident, repository_url)) + project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[all_red_cross_pj[pjj]]['id'], pj_ident, repository_url) + + elif os.path.join(basedir, pj) != all_red_pj[all_red_cross_pj[pjj]]['repositories'][0]['url']: + print("Repository URL is bad for repo %s:%s (%s <> %s)" + % (pjj, pj_ident, os.path.join(basedir, pj), all_red_pj[all_red_cross_pj[pjj]]['repositories'][0]['url'])) + + # if all_red_pj[pjj]['is_public']: + # reset verything to is_public false + project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id']) + project.is_public = True + project.inherit_members = False + project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}] + project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking', + 'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt'] + project.tracker_ids = [1, 2] + project.save() + + print("membership all_red_cross_pj id %s." % (all_red_pj[all_red_cross_pj[pjj]]['id'])) + + pj_wanted_membership = dict(wanted_membership) + pj_membership_del = [] + real_membership = redmine.project_membership.filter(project_id=all_red_pj[all_red_cross_pj[pjj]]['id']) + + for mb in real_membership: + if hasattr(mb, 'user'): + continue + ''' + print("------------") + print("membership") + print("mb.project: %s %s" % (mb.project.id, mb.project.name)) + print("mb.group: %s %s" % (mb.group.id, mb.group.name)) + print("mb.roles") + for rl in mb.roles: + print("%s %s" % (rl.id, rl.name)) + ''' + if mb.group.name in pj_wanted_membership: + for rl in mb.roles: + if pj_wanted_membership[mb.group.name] == rl.name: + del(pj_wanted_membership[mb.group.name]) + else: + for rl in mb.roles: + pj_membership_del.append(mb.id) + + else: + pj_membership_del.append(mb.id) + + pp.pprint(pj_wanted_membership) + for gr in pj_wanted_membership: + membership = redmine.project_membership.new() + membership.project_id = all_red_pj[all_red_cross_pj[pjj]]['id'] + # http://www.redmine.org/issues/17904 group is user... + membership.user_id = all_red_grp[gr]['id'] + membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']] + membership.save() + + pp.pprint(pj_membership_del) + for mb in pj_membership_del: + membership = redmine.project_membership.get(all_red_pj[all_red_cross_pj[pjj]]['id']) + membership.delete(mb) + + # break + + else: + print("The project '%s' need to be created." % (pj)) + print("hg:%s:%s" % (pj_ident, os.path.join(basedir, pj))) + + if parent and parent in all_red_pj: + print("Parent '%s' is found" % (parent)) + elif parent and parent in all_red_cross_pj: + print("Parent '%s' is found in the bad list" % (parent)) + + try: + print('id:%s' % (pj_ident)) + project = redmine.project.new() + project.name = pjj + project.identifier = pj_ident + project.description = pjj + project.homepage = None + project.is_public = True + project.inherit_members = False + project.parent_id = parent_id + # project.enabled_modules = ['repository'] Readonly attribute + # project.custom_fields = [{'id': 1, 'value': 'PE'}, {'id': 11, 'value': 'scm'}] + project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}] + # list(project) + project.save() + except Exception as e: + print('The creation of the ressources project "%s" did not suceed: %s' % (pjj, str(e))) + print(traceback.format_exc(5)) + break + + # try: + # project = redmine.project.get(pjj) + # except ResourceNotFoundError as e: + # print('The ressources is not found') + +sys.exit(0) diff --git a/bin/synchronize_redmine_users.py b/bin/synchronize_redmine_users.py new file mode 100755 index 0000000..e7e9d6c --- /dev/null +++ b/bin/synchronize_redmine_users.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, print_function + +import os +import sys + +import configparser as ConfigParser +import pprint +import inspect + +pp = pprint.PrettyPrinter(indent=4) + +PROGNAME = os.path.basename(sys.argv[0]).split(".")[0] +script = os.path.basename(__file__).split(".")[0] + +global_iniFile = '/opt/etc/ini/global.ini' +config_global = ConfigParser.RawConfigParser() +config_global.optionxform(str()) +config_global.optionxform = str +config_global.read(global_iniFile) +sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY')) + +from redminelib import Redmine + +if 'http_proxy' in os.environ: + del os.environ['http_proxy'] +if 'https_proxy' in os.environ: + del os.environ['https_proxy'] + + +CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem' +CA_bundle = '/etc/ssl/certs/ca-certificates.crt' + +def obj_dump(obj): + ''' + Object dumper + ''' + for attr in dir(obj): + if '_' in attr: + continue + try: + print("obj.%s = %s" % (attr, str(getattr(obj, attr)))) + except: + print("obj.%s = %s" % (attr, getattr(obj, attr))) + + for name, data in inspect.getmembers(obj): + if inspect.isclass(data): + print('name:%s' % (name)) + print(data) + +redmine_config_global = ConfigParser.RawConfigParser() +redmine_config_global.read(config_global.get('INI', 'Redmine')) + +# Parse config +REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST') +REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO') +REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey') + +redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle}) + +users = redmine.user.all(offset=0, limit=100) +for u in users: + # print(u) + # print '%s' % (u.id) + # print '%s' % (u.login) + # print '%s' % (u.firstname) + # print '%s' % (u.lastname) + # print '%s' % (u.mail) + # print '%s' % (u.auth_source_id) + # print '%s' % (u.mail_notification) + + print('%s %s %s <%s> (%s)' % (u.login, u.firstname, u.lastname, u.mail, u.id)) + obj_dump(u) + # obj_dump(u.contacts) + # obj_dump(u.deals) + obj_dump(u.groups) + obj_dump(u.memberships) + break -- GitLab