From 24ff1c5e0ff4734f4cb1ce7f854dd4ba6cab2f25 Mon Sep 17 00:00:00 2001 From: Chris Bielow <chris.bielow@fu-berlin.de> Date: Tue, 23 Oct 2018 08:37:04 +0200 Subject: [PATCH] a version that works, if you are willing to accept some documented quirks --- main.py | 92 +++++++++++++++++++++++++++---------------- manageprojects.py | 48 +++++++++++++++-------- projectassign.py | 69 +++++++++++++++++++++------------ students.list | 99 +++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 229 insertions(+), 79 deletions(-) diff --git a/main.py b/main.py index 5ad26fb..1208182 100644 --- a/main.py +++ b/main.py @@ -2,66 +2,90 @@ import requests import json import manageprojects import projectassign +import os -token = "$GITLAB_ACCESS_TOKEN" +token = os.getenv('GITLABTOKEN', None) apilink = "https://git.imp.fu-berlin.de/api/v4/" group_name = None -def getgroupid(apilink, token, group_name): +def getgroupid(group_name): - rawdata = requests.get(apilink + "/groups?private_token=" + token, verify = False) + rawdata = requests.get(apilink + "/groups?private_token=" + token, verify = True) data = json.loads(rawdata.content) group_id = None - - for i in range(0,len(data)): - if(data[i]["name"] == group_name): - group_id = data[i]["id"] + #print(data); + #print (type(data), "\n") + + for d in data: + if ("name" in d and d["name"] == group_name): + group_id = d["id"] # int break - + if (group_id is None): + print("Could not find group. Response was: ", data) + else: + print("Found group id: '", group_id ,"'\n") return group_id def main(): print("Willkommen im GitLab Projektmanagement\n") - group_name = input("Welche Gruppe soll bearbeitet werden? ") - group_id = getgroupid(apilink, token, group_name) + if (not token): + raise Exception("Invalid authentication token: Set $GITLABTOKEN in your environment!") + group_id = None + group_name_default = "adp2018"; + while (group_id is None): + group_name = input("Welche Gruppe soll bearbeitet werden (Enter = " + group_name_default + ")? ") + if (not group_name): + group_name = group_name_default + group_id = getgroupid(group_name) while(True): - print("\ncr - Projekte erstellen") - print("rm - ein Projekt löschen") - print("as - Studenten zu Projekten hinzufügen\n") - - eingabe = input("Eingabe: ") - + print("\n") + print("ls - list projects") + print("cr - create projects") + print("rm - remove projects") + print("as - assign students to existing projects\n") + + + eingabe = input("choice: ") + + if (eingabe == "ls"): + proj_name_prefix = input("What is the project prefix? (Enter = all projects) ") + projects = manageprojects.getprojects(apilink, token, group_id, proj_name_prefix) + + if(eingabe == "cr"): - count = input("\nwie viele Projekte sollen erstellt werden?: ") - name = input("wie sollen die Projekte heißen?: ") - sf = input("\nSollen wirklich " + count + " Projekte mit dem Namen " + name + " erstellt werden? (y/n): ") + count = input("\nHow many projects do you need?: ") + name = input("What is the project prefix (e.g. 'group')?: ") + sf = input("\nDo you really want 1.." + count + " projects with prefix '" + name + "'(if the projects already exist, nothing will happen)? (y/n): ") if(sf == "y" or sf == "yes"): - for count in range(0, int(count)): - manageprojects.create(apilink, token, name , count, group_id) - print(count + " Projekte wurden erstellt") + for c in range(0, int(count)): + manageprojects.create(apilink, token, group_id, name, c) + print(str(count) + " projects created") if(eingabe == "rm"): - name = input("\nwelches Projekt soll gelöscht werden?: ") - - proj_id = manageprojects.getprojectid(apilink, group_id, name, token) - sf = input("Soll das Projekt " + name + " mit der ID " + str(proj_id) + " wirklich gelöscht werden? (y/n): ") + proj_name_prefix = input("What is the project prefix (e.g. 'group')? (Enter = all projects) ") + projects = manageprojects.getprojects(apilink, token, group_id, proj_name_prefix) + + sf = input("Do you really want to delete those? (y/n): ") if(sf == "y" or sf == "yes"): + for p in projects: + proj_id = manageprojects.getprojectid(apilink, token, group_id, p.name) manageprojects.remove(apilink, token, group_id, proj_id) - print("Das Projekt " + name + " wurde gelöscht") -_ + print("Project " + p.name + " removed\n") + if(eingabe == "as"): - projectnamespace = input("Wie heißen die Projekte?") - studentlist = input("Aus welcher Liste sollen Nutzer hinzugefügt werden?") - count = input("Wie viele Nutzer sollen pro Projekt verteilt werden?") - access_level = input("Access-Level?\n10 => Guest access\n20 => Reporter access\n30 => Developer access\n40 => Maintainer access") - group_id = str(getgroupid(apilink, token, group_name)) - projectassign.assign(projectnamespace, group_id, studentlist, count, access_level, apilink, token) + student_list = input("Aus welcher Liste sollen Nutzer hinzugefügt werden? (Enter = students.list)") + if (not student_list): + student_list = "students.list" + access_level = input("Access-Level?\n10 => Guest access\n20 => Reporter access\n30 => Developer access (no push to master)\n40 => Maintainer access (Enter = Maintainer)") + if (not access_level): + access_level = 40; + projectassign.assign(apilink, token, group_name, student_list, access_level) main() diff --git a/manageprojects.py b/manageprojects.py index 3936b46..a06b889 100644 --- a/manageprojects.py +++ b/manageprojects.py @@ -5,37 +5,51 @@ class project: id = 0 name = "" -def create(apilink, token, name, count, groupid): - - requests.post(apilink+"/projects?private_token="+token+"&name="+name+"_"+str(count+1)+"&namespace_id="+str(groupid),verify=False) - +def create(apilink, token, groupid, name, count): + fullname = name + str(count+1) + print ("create project: " + fullname + "\n") + requests.post(apilink + "/projects?private_token=" + token + + "&name=" + fullname + + "&namespace_id=" + str(groupid), + verify = True) + + def remove(apilink, token, groupid, projid): + requests.delete(apilink+"/projects/"+str(projid)+"?private_token="+token+"&namespace_id="+str(groupid), verify = True) - requests.delete(apilink+"/projects/"+str(projid)+"?private_token="+token+"&namespace_id="+str(groupid),verify=False) -def getprojects(projectnamespace, apilink, groupid, token): - rawdata = requests.get(apilink+"/groups/"+str(groupid)+"/projects?private_token="+token, verify = False) +def getprojects(apilink, token, groupid, proj_name_prefix): + print("warning: listing projects by Searching for a name prefix is broken in Gitlab, since the response will be incomplete for large answers. You might need to iterate (for deleting) or find a more specific prefix (which finds less hits)") + rawdata = requests.get(apilink+"/groups/"+str(groupid)+"/projects?private_token="+token, verify = True) data = json.loads(rawdata.content) projects = [] for i in range(0,len(data)): - tempname = data[i]["name"].split("_")[0] - if(tempname == projectnamespace): + if (data[i]["name"].startswith(proj_name_prefix)): prodata = project() prodata.id = data[i]["id"] prodata.name = data[i]["name"] projects.append(prodata) + print("Found projects: " + ", ".join([p.name for p in projects])) + return projects -def getprojectid(apilink, groupid, name, token): - rawdata = requests.get(apilink+"/groups/"+str(groupid)+"/projects?private_token="+token, verify = False) - data = json.loads(rawdata.content) +def getprojectid(apilink, token, group_name, proj_name): + # do NOT use the general query below, because it will prematurely stop after some records (some limitation/bug in the API) + # this is problematic if you have a dozen or so groups + #rawdata = requests.get(apilink+"/groups/" + str(groupid) + "/projects?private_token=" + token, verify = True) - for i in range(0,len(data)): - if(data[i]["name"] == name): - projid = data[i]["id"] - break + # query project directly using groupname/project (the / must be encoded as %2F) + rawdata = requests.get(apilink + "/projects/" + str(group_name) + "%2F" + proj_name + "?private_token=" + token, verify = True) + data = json.loads(rawdata.content) - return projid + proj_id = None + if ("name" in data and data["name"] == proj_name): + proj_id = data["id"] + print("Found project id: ", proj_id) + else: + print("Could not find project '" + proj_name + "'.") # Response was: ", data) + + return proj_id diff --git a/projectassign.py b/projectassign.py index e59a3d1..96ecff2 100644 --- a/projectassign.py +++ b/projectassign.py @@ -3,32 +3,53 @@ import json import manageprojects class member: - id = 0 - name = "" + gitlab_group = "" + zedat_name = "" -def readstudentlist(studentlist): - list = open(studentlist + ".txt") - students = list.read().splitlines() + + +def readStudentList(file_students): + list = open(file_students) + lines = list.read().splitlines() + students = [] + for l in lines: + itm = l.split('\t') + if len(itm)!=2: + raise Exception("Invalid student: '" + l + "'. Must have two items separated by tab!") + s = member() + s.zedat_name = itm[0] + s.gitlab_group = itm[1] + students.append(s) return students -def getstudentid(student, apilink, token): - rawdata = requests.get(apilink + "/users?private_token=" + token+ "&username=" + student, verify=False) +def getStudentID(apilink, token, zedat_name): + rawdata = requests.get(apilink + "/users?private_token=" + token + "&username=" + zedat_name, verify = True) data = json.loads(rawdata.content) - return data[0]["id"] + s_id = None + for d in data: + if ("id" in d): + s_id = d["id"] + break + if (s_id is None): + print("Could not find student '" + zedat_name + "'.") # Response was: ", data) + else: + print("Found student id: ", s_id ,"\n") + + return s_id -def assign(projectnamespace, groupid, studentlist, studentsamount, a_level, apilink, token): - students = readstudentlist(studentlist) - projects = manageprojects.getprojects(projectnamespace, apilink, groupid, token) - studentindex = 0 - print("im alive") - print(len(projects)) - for p in range(0,len(projects)): - print("project" + str(p)) - for s in range(0,int(studentsamount)): - if(studentindex == len(students)): - break - studentid = getstudentid(students[studentindex], apilink, token) - print(projects[p].id) - print(studentid) - requests.post(apilink + "/projects/" + str(projects[p].id) + "/members?private_token=" + token + "&user_id=" + str(studentid) + "&access_level=" + str(a_level), verify = False) - studentindex += 1 +def assign(apilink, token, group_name, file_students, access_level): + students = readStudentList(file_students) + for s in students: + print("\n-- Student " + s.zedat_name + " in " + s.gitlab_group) + proj_id = manageprojects.getprojectid(apilink, token, group_name, s.gitlab_group) + if (proj_id is None): + exit("Group is unknown. Please create it or correct its name") # this is a hard error -- groups are not created correctly + student_id = getStudentID(apilink, token, s.zedat_name) + if (student_id is None): + continue + # creates member (does nothing if already exists) + requests.post(apilink + "/projects/" + str(proj_id) + "/members?private_token=" + token + "&user_id=" + str(student_id) + "&access_level=" + str(access_level), verify = True) + # does an update (e.g. access rights, in case the student already exists) + link = apilink + "/projects/" + str(proj_id) + "/members/" + str(student_id) + "?private_token=" + token + "&access_level=" + str(access_level); + requests.put(link, verify = True) + print(" --> added") diff --git a/students.list b/students.list index 5e4978b..8db96dc 100644 --- a/students.list +++ b/students.list @@ -1,4 +1,95 @@ -student1 -student2 -student3 -student4 +farab95 group1 +sofyal97 group1 +felid99 group2 +mellej98 group2 +simonsasse97 group2 +armaj97 group3 +koehlek99 group3 +hannas24 group3 +bauman98 group4 +anthof95 group4 +glim99 group4 +oezgenug94 group5 +risa0 group5 +henris07 group5 +daboj85 group6 +tetak94 group6 +lapuj92 group6 +sarahjuf94 group7 +dennik99 group7 +ninao99 group7 +kruschwia32 group8 +grem16 group8 +anniepham group8 +chantak98 group9 +julikaw96 group9 +juliaz00 group9 +dilad97 group10 +hossnim96 group10 +adim99 group10 +miaa99 group11 +bannwid98 group11 +laraj98 group11 +finnjab97 group12 +emi41 group12 +tstrunk group12 +semiaj97 group13 +panc97 group13 +irfay03 group13 +hessea68 group14 +kolby19 group14 +transat group14 +warda06 group15 +helenabraun group15 +on3yhwh group15 +melim09 group16 +sielatchom00 group16 +schiris15 group16 +gtienle group17 +goekce group17 +sebastiann group17 +bieniam98 group18 +salomok98 group18 +sprangel99 group18 +tomlukas15 group19 +sebpaltzer group19 +ruyog96 group19 +ignaciocalvi group20 +koesed96 group20 +pipaj97 group20 +ashkag98 group21 +mustah98 group21 +trav97 group21 +misevio93 group22 +tumanova group22 +chex98 group22 +camilavib00 group23 +muehlhaup97 group23 +felir69 group23 +herbste93 group24 +jschmacht group24 +victorsi group24 +bodul99 group25 +lenaedelmann group25 +pohll95 group25 +aakan96 group26 +giacuop96 group26 +hendriz98 group26 +pikkin87 group27 +ammaa97 group28 +mmertins group28 +wangw98 group28 +namuub98 group29 +karadam96 group29 +koirap93 group29 +kriea97 group30 +ponzej97 group30 +ingat98 group30 +yunusek77 group31 +yusras98 group31 +dimit98 group31 +maximilian45 group32 +lenzo99 group33 +christiap20 group33 +tinop99 group33 +gachc96 group34 -- GitLab