Refactoring

This commit is contained in:
Tim Schubert 2018-03-28 17:20:30 +02:00
parent 3f82036c3d
commit 34b1bd617e
2 changed files with 117 additions and 129 deletions

View file

@ -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)

View file

@ -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