Refactoring
This commit is contained in:
parent
3f82036c3d
commit
34b1bd617e
2 changed files with 117 additions and 129 deletions
185
abgabesystem.py
185
abgabesystem.py
|
@ -19,9 +19,8 @@ class Deadline(yaml.YAMLObject):
|
||||||
self.time = time
|
self.time = time
|
||||||
self.ref = ref
|
self.ref = ref
|
||||||
|
|
||||||
def tag(self, project):
|
def trigger(self, project):
|
||||||
"""Create protected tag on ref for all deadlines that have been
|
"""Create protected tag on ref"""
|
||||||
reached"""
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
project.tags.create({
|
project.tags.create({
|
||||||
|
@ -31,42 +30,28 @@ class Deadline(yaml.YAMLObject):
|
||||||
except gitlab.exceptions.GitlabHttpError as e:
|
except gitlab.exceptions.GitlabHttpError as e:
|
||||||
log.warn(e)
|
log.warn(e)
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
return self.time <= datetime.datetime.now()
|
||||||
|
|
||||||
|
|
||||||
class Course(yaml.YAMLObject):
|
class Course(yaml.YAMLObject):
|
||||||
"""A course"""
|
"""A course"""
|
||||||
|
|
||||||
yaml_tag = 'Course'
|
yaml_tag = 'Course'
|
||||||
|
|
||||||
def setup_gitlab_group(self, groups):
|
def __init__(self, name, base, ldap, deadlines):
|
||||||
try:
|
self.name = name
|
||||||
found = groups.list(search=self.name)
|
self.base = base
|
||||||
return found[0]
|
self.ldap = ldap
|
||||||
except gitlab.exceptions.GitlabHttpError as e:
|
self.deadlines = deadlines
|
||||||
log.info(e)
|
|
||||||
if e.response_code == 404:
|
def create_group(self, gl):
|
||||||
gl.groups.create({})
|
|
||||||
path = self.name.replace(' ', '_').lower()
|
path = self.name.replace(' ', '_').lower()
|
||||||
group = gl.groups.create({
|
self.group = gl.groups.create({
|
||||||
'name': self.name,
|
'name': self.name,
|
||||||
'path': path
|
'path': path
|
||||||
})
|
})
|
||||||
for repo in self.repos:
|
return self.group
|
||||||
group.repos.create({
|
|
||||||
'name': repo,
|
|
||||||
'namespace_id': group.path,
|
|
||||||
'visibility': 'internal'
|
|
||||||
})
|
|
||||||
return group
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
def __init__(self, name, deadlines, repos):
|
|
||||||
self.name = name
|
|
||||||
self.repos = repos
|
|
||||||
self.deadlines = deadlines
|
|
||||||
|
|
||||||
def projects(self, groups):
|
|
||||||
return groups.list(search=self.name)[0].projects.list()
|
|
||||||
|
|
||||||
|
|
||||||
class Student():
|
class Student():
|
||||||
|
@ -78,83 +63,87 @@ class Student():
|
||||||
self.name = name
|
self.name = name
|
||||||
self.group = group
|
self.group = group
|
||||||
|
|
||||||
def setup_project(self, base, course):
|
def from_csv(csvfile):
|
||||||
|
reader = csv.DictReader(csvfile, delimiter=';', quotechar='"')
|
||||||
|
|
||||||
|
for line in reader:
|
||||||
|
yield Student(line['Nutzernamen'], line['E-Mail'], line['Vorname']
|
||||||
|
+ ' ' + line['Nachname'], line['Gruppe'])
|
||||||
|
|
||||||
|
def create_user(self, gl, ldap):
|
||||||
|
"""Creates a dummy user for users that do not exist in gitlab
|
||||||
|
but in LDAP and have not logged in yet"""
|
||||||
|
|
||||||
|
return gl.users.create({
|
||||||
|
'email': self.email,
|
||||||
|
'username': self.name,
|
||||||
|
'name': self.user,
|
||||||
|
'provider': ldap['provider'],
|
||||||
|
'skip_confirmation': True,
|
||||||
|
'extern_uid': 'uid=%s,%s' % (self.user, ldap['basedn']),
|
||||||
|
'password': secrets.token_urlsafe(nbytes=32)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def fork_project(gl, group, base, user):
|
||||||
"""Create user projects as forks from course/solutions in namespace of
|
"""Create user projects as forks from course/solutions in namespace of
|
||||||
course and add user as developer (NOT master) user should not be able
|
course and add user as developer (NOT master) user should not be able
|
||||||
to modify protected TAG or force-push on protected branch users can
|
to modify protected TAG or force-push on protected branch users can
|
||||||
later invite other users into their projects"""
|
later invite other users into their projects"""
|
||||||
|
|
||||||
fork = course.group.projects.list(name=self.user)
|
# fork course base project (e.g. solutions)
|
||||||
if len(fork) == 0:
|
|
||||||
fork = base.forks.create({
|
fork = base.forks.create({
|
||||||
'name': self.user,
|
'name': user['name'],
|
||||||
'namespace': base.namspace,
|
'namespace': group.namspace,
|
||||||
'visibility': 'private'
|
'visibility': 'private'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# add student as member of project
|
||||||
fork.members.create({
|
fork.members.create({
|
||||||
'user_id': self.user,
|
'user_id': user,
|
||||||
'access_level': gitlab.DEVELOPER_ACCESS
|
'access_level': gitlab.DEVELOPER_ACCESS
|
||||||
})
|
})
|
||||||
|
|
||||||
return fork
|
return fork
|
||||||
|
|
||||||
def setup_ldap_dummy(self, users, provider, basedn):
|
|
||||||
# TODO call from creation of student object()
|
|
||||||
|
|
||||||
"""Creates a dummy user for users that do not exist in gitlab
|
def create_project(group, name):
|
||||||
but in LDAP and have not logged in yet"""
|
return group.projects.create({
|
||||||
|
'name': name,
|
||||||
users = users.list(search=self.user)
|
'namespace_id': group.path,
|
||||||
|
'visibility': 'internal'
|
||||||
if len(users) == 0:
|
|
||||||
dummy = users.create({
|
|
||||||
'email': self.email,
|
|
||||||
'username': self.name,
|
|
||||||
'name': self.user,
|
|
||||||
'provider': provider,
|
|
||||||
'skip_confirmation': True,
|
|
||||||
'extern_uid': 'uid=%s,%s' % (self.user, basedn),
|
|
||||||
'password': secrets.token_urlsafe(nbytes=32)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return dummy
|
|
||||||
else:
|
|
||||||
return users[0]
|
|
||||||
|
|
||||||
def from_csv(csvfile):
|
def deadlines(gl, course, args):
|
||||||
reader = csv.DictReader(csvfile, delimiter=';', quotechar='"')
|
"""Checks deadlines for course and triggers deadline if it is reached"""
|
||||||
|
|
||||||
for line in reader:
|
|
||||||
student = Student(line['Nutzernamen'],
|
|
||||||
line['E-Mail'],
|
|
||||||
line['Vorname'] + ' ' + line['Nachname'],
|
|
||||||
line['Gruppe'])
|
|
||||||
yield student
|
|
||||||
|
|
||||||
|
|
||||||
def create_students(gl, conf, args):
|
|
||||||
with open(args.students[0], 'r') as csvfile:
|
|
||||||
for student in Student.from_csv(csvfile):
|
|
||||||
student.setup_ldap_dummy(gl.users, conf['ldap']['provider'], conf['ldap']['basedn'])
|
|
||||||
student.setup_project('solutions', args['course'][0]) #TODO
|
|
||||||
print(student)
|
|
||||||
|
|
||||||
|
|
||||||
def create_courses(gl, conf, args):
|
|
||||||
for course in conf['courses']:
|
|
||||||
course.setup_gitlab_group(gl.groups)
|
|
||||||
print(course)
|
|
||||||
|
|
||||||
|
|
||||||
def create_deadlines(gl, conf, args):
|
|
||||||
for course in conf['courses']:
|
|
||||||
for deadline in course.deadlines:
|
for deadline in course.deadlines:
|
||||||
pass
|
if deadline.test():
|
||||||
#if deadline.time <= datetime.datetime.now():
|
deadline.trigger(course)
|
||||||
# deadline has approached
|
|
||||||
# TODO setup cronjob?
|
|
||||||
# deadline.tag(project)
|
def sync(gl, courses, args):
|
||||||
|
"""Sync groups and students from Stud.IP to Gitlab and create student
|
||||||
|
projects
|
||||||
|
|
||||||
|
one-way sync!!!
|
||||||
|
"""
|
||||||
|
|
||||||
|
for course in courses:
|
||||||
|
course.create_group(gl)
|
||||||
|
create_project(course.group)
|
||||||
|
|
||||||
|
with open(args.students[0]) as csvfile:
|
||||||
|
for student in Student.from_csv(csvfile):
|
||||||
|
student.create_user(gl, course.ldap)
|
||||||
|
|
||||||
|
|
||||||
|
def parseconf(conf):
|
||||||
|
"""Reads courses from config file"""
|
||||||
|
|
||||||
|
with open(args.config, 'r') as conf:
|
||||||
|
return yaml.safe_load(conf)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -163,21 +152,23 @@ if __name__ == '__main__':
|
||||||
gl.auth()
|
gl.auth()
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--config', type=str, nargs=1, help='path to config file', default='config.yml')
|
parser.add_argument(
|
||||||
|
'--config', type=str, nargs=1, help='path to config file',
|
||||||
|
default='config.yml')
|
||||||
|
subparsers = parser.add_subparsers(title='subcommands')
|
||||||
|
|
||||||
course_parser = parser.add_subparsers('courses')
|
sync_parser = subparsers.add_parser(
|
||||||
course_parser.set_defaults(func=create_courses)
|
'sync',
|
||||||
|
description='students and courses from Stud.IP and LDAP')
|
||||||
|
sync_parser.set_defaults(func=sync)
|
||||||
|
sync_parser.add_argument('--students', nargs=1,
|
||||||
|
description='Students CSV file')
|
||||||
|
|
||||||
student_parser = parser.add_subparsers('students')
|
deadline_parser = subparsers.add_parser('deadlines',
|
||||||
student_parser.add_argument('students', desc='Exported CSV file from Stud.IP', nargs=1, type=str)
|
description='trigger deadlines')
|
||||||
student_parser.add_argument('course', desc='Course for CSV file', nargs=1, type=str)
|
deadline_parser.set_defaults(func=deadlines)
|
||||||
student_parser.set_defaults(func=create_students)
|
|
||||||
|
|
||||||
deadline_parser = parser.add_subparsers('deadlines')
|
|
||||||
deadline_parser.set_defaults(func=create_deadlines)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
conf = parseconf(args.conf)
|
||||||
|
|
||||||
with open(args.config, 'r') as conf:
|
|
||||||
conf = yaml.safe_load(conf)
|
|
||||||
args.func(gl, conf, args)
|
args.func(gl, conf, args)
|
||||||
|
|
19
config.yml
19
config.yml
|
@ -1,23 +1,20 @@
|
||||||
|
---
|
||||||
|
!!Course
|
||||||
|
name: Programmieren 1
|
||||||
|
base: solutions
|
||||||
ldap:
|
ldap:
|
||||||
basedn: "ou=people,dc=tu-bs,dc=de"
|
basedn: "ou=people,dc=tu-bs,dc=de"
|
||||||
dummy_user:
|
|
||||||
provider: main
|
provider: main
|
||||||
skip_confirmation: true
|
deadlines:
|
||||||
|
|
||||||
courses:
|
|
||||||
-
|
-
|
||||||
--- !Course
|
!!Deadline
|
||||||
name: Programmieren 1
|
|
||||||
repos: [solutions, exercises]
|
|
||||||
deadlines:
|
|
||||||
-
|
|
||||||
--- !Deadline
|
|
||||||
tag: Exercise 1
|
tag: Exercise 1
|
||||||
time: 2018-04-01t00:00.00
|
time: 2018-04-01t00:00.00
|
||||||
ref: master
|
ref: master
|
||||||
|
|
||||||
-
|
-
|
||||||
--- !Deadline
|
!!Deadline
|
||||||
tag: Exercise 2
|
tag: Exercise 2
|
||||||
time: 2018-04-15t15:00.00
|
time: 2018-04-15t15:00.00
|
||||||
ref: master
|
ref: master
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue