WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit a231689

Browse files
authored
Merge pull request #17 from cuebook/notebookTests
Refactoring notebook jobs services
2 parents 0a471d8 + c2721a3 commit a231689

File tree

6 files changed

+132
-215
lines changed

6 files changed

+132
-215
lines changed

api/genie/services/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
from .schemas import Schemas
33
from .connections import Connections
44
from .notebookTemplates import NotebookTemplateService
5-
from .kubernetes import KubernetesServices
5+
from .kubernetes import KubernetesServices
6+
from .schedules import ScheduleService

api/genie/services/notebookJobs.py

Lines changed: 1 addition & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from django.template import Template, Context
99
# from django_celery_beat.models import CrontabSchedule
1010
from genie.models import NOTEBOOK_STATUS_ABORT, NOTEBOOK_STATUS_QUEUED, NOTEBOOK_STATUS_RUNNING, NOTEBOOK_STATUS_ABORTING, NotebookObject, NotebookJob, RunStatus, Connection, NotebookTemplate, CustomSchedule as Schedule
11-
from genie.serializers import NotebookObjectSerializer, ScheduleSerializer, RunStatusSerializer
11+
from genie.serializers import NotebookObjectSerializer, RunStatusSerializer
1212
from workflows.models import Workflow, NotebookJob as WorkflowNotebookJob
1313
from utils.apiResponse import ApiResponse
1414
from utils.zeppelinAPI import Zeppelin
@@ -307,19 +307,6 @@ def addNotebookJob(notebookId: str, scheduleId: int):
307307
res.update(True, "NotebookJob added successfully", None)
308308
return res
309309

310-
@staticmethod
311-
def updateNotebookJob(notebookJobId: int, scheduleId: int):
312-
"""
313-
Service to update crontab of an existing NotebookJob
314-
:param notebookId: ID of the NotebookJob for which to update crontab
315-
:param scheduleId: ID of schedule
316-
"""
317-
res = ApiResponse()
318-
scheduleObj = Schedule.objects.get(crontabschedule_ptr_id=scheduleId)
319-
NotebookJob.objects.filter(id=notebookJobId).update(crontab=scheduleObj)
320-
res.update(True, "NotebookJob updated successfully", None)
321-
return res
322-
323310
@staticmethod
324311
def deleteNotebookJob(notebookId: int):
325312
"""
@@ -331,112 +318,6 @@ def deleteNotebookJob(notebookId: int):
331318
res.update(True, "NotebookJob deleted successfully", None)
332319
return res
333320

334-
@staticmethod
335-
def toggleNotebookJob(notebookId: int, enabled: bool):
336-
"""
337-
Service to update crontab of an existing NotebookJob
338-
:param notebookId: ID of the NotebookJob for which to update crontab
339-
:param scheduleId: ID of schedule
340-
"""
341-
res = ApiResponse()
342-
NotebookJob.objects.filter(notebookId=notebookId).update(enabled=enabled)
343-
res.update(True, "NotebookJob updated successfully", None)
344-
return res
345-
346-
@staticmethod
347-
def getSchedules():
348-
"""
349-
Service to get all schedule objects
350-
"""
351-
res = ApiResponse()
352-
schedules = Schedule.objects.exclude(id=1)
353-
data = ScheduleSerializer(schedules, many=True).data
354-
res.update(True, "Schedules fetched successfully", data)
355-
return res
356-
357-
@staticmethod
358-
def addSchedule(cron: str, timezone: str = None, name: str = ""):
359-
"""
360-
Service to add Schedule
361-
:param cron: Crontab in string format
362-
:param timezone: Timezone string for which to configure Schedule
363-
:param name: Name of schedule provided by user
364-
"""
365-
res = ApiResponse()
366-
cronElements = cron.split()
367-
if len(cronElements) != 5:
368-
res.update(False, "Crontab must contain five elements")
369-
return res
370-
timezone = timezone if timezone else "UTC"
371-
schedule = Schedule.objects.create(
372-
minute=cronElements[0],
373-
hour=cronElements[1],
374-
day_of_month=cronElements[2],
375-
month_of_year=cronElements[3],
376-
day_of_week=cronElements[4],
377-
timezone=timezone,
378-
name=name,
379-
)
380-
res.update(True, "Schedule added successfully", schedule.id)
381-
return res
382-
383-
@staticmethod
384-
def getSingleSchedule(scheduleId: int):
385-
"""
386-
Service to get singleSchedule
387-
:param scheduleId: int
388-
"""
389-
390-
res = ApiResponse()
391-
schedules = Schedule.objects.filter(crontabschedule_ptr_id=scheduleId)
392-
data = ScheduleSerializer(schedules, many=True).data
393-
res.update(True, "Schedules fetched successfully", data)
394-
return res
395-
396-
@staticmethod
397-
def updateSchedule(id, crontab, timezone, name):
398-
"""
399-
Service to update Schedule
400-
param id: int
401-
param cron: Crontab in string format
402-
param timezone: Timezone in string format
403-
param name: String
404-
"""
405-
res = ApiResponse()
406-
cronElements = crontab.split(" ")
407-
if len(cronElements) != 5:
408-
res.update(False, "Crontab must contain five elements")
409-
return res
410-
schedule = Schedule.objects.get(crontabschedule_ptr_id=id)
411-
schedule.minute=cronElements[0]
412-
schedule.hour=cronElements[1]
413-
schedule.day_of_month=cronElements[2]
414-
schedule.month_of_year=cronElements[3]
415-
schedule.day_of_week=cronElements[4]
416-
schedule.timezone = timezone
417-
schedule.name = name
418-
schedule.save()
419-
res.update(True, "Schedules updated successfully", [])
420-
return res
421-
422-
@staticmethod
423-
def deleteSchedule(scheduleId: int):
424-
""" Service to delete schedule of given scheduleId """
425-
res = ApiResponse()
426-
Schedule.objects.filter(id=scheduleId).delete()
427-
res.update(True, "Schedules deleted successfully", [])
428-
return res
429-
430-
@staticmethod
431-
def getTimezones():
432-
"""
433-
Service to fetch all pytz timezones
434-
"""
435-
res = ApiResponse()
436-
timezones = pytz.all_timezones
437-
res.update(True, "Timezones fetched successfully", timezones)
438-
return res
439-
440321
@staticmethod
441322
def runNotebookJob(notebookId: str):
442323
"""

api/genie/services/schedules.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import pytz
2+
import logging
3+
# from django_celery_beat.models import CrontabSchedule
4+
from genie.models import CustomSchedule as Schedule
5+
from genie.serializers import ScheduleSerializer
6+
from utils.apiResponse import ApiResponse
7+
8+
# Get an instance of a logger
9+
logger = logging.getLogger(__name__)
10+
11+
class ScheduleService:
12+
@staticmethod
13+
def getSchedules():
14+
"""
15+
Service to get all schedule objects
16+
"""
17+
res = ApiResponse()
18+
schedules = Schedule.objects.exclude(id=1)
19+
data = ScheduleSerializer(schedules, many=True).data
20+
res.update(True, "Schedules fetched successfully", data)
21+
return res
22+
23+
@staticmethod
24+
def addSchedule(cron: str, timezone: str = None, name: str = ""):
25+
"""
26+
Service to add Schedule
27+
:param cron: Crontab in string format
28+
:param timezone: Timezone string for which to configure Schedule
29+
:param name: Name of schedule provided by user
30+
"""
31+
res = ApiResponse()
32+
cronElements = cron.split()
33+
if len(cronElements) != 5:
34+
res.update(False, "Crontab must contain five elements")
35+
return res
36+
timezone = timezone if timezone else "UTC"
37+
schedule = Schedule.objects.create(
38+
minute=cronElements[0],
39+
hour=cronElements[1],
40+
day_of_month=cronElements[2],
41+
month_of_year=cronElements[3],
42+
day_of_week=cronElements[4],
43+
timezone=timezone,
44+
name=name,
45+
)
46+
res.update(True, "Schedule added successfully", schedule.id)
47+
return res
48+
49+
@staticmethod
50+
def getSingleSchedule(scheduleId: int):
51+
"""
52+
Service to get singleSchedule
53+
:param scheduleId: int
54+
"""
55+
56+
res = ApiResponse()
57+
schedules = Schedule.objects.filter(crontabschedule_ptr_id=scheduleId)
58+
data = ScheduleSerializer(schedules, many=True).data
59+
res.update(True, "Schedules fetched successfully", data)
60+
return res
61+
62+
@staticmethod
63+
def updateSchedule(id, crontab, timezone, name):
64+
"""
65+
Service to update Schedule
66+
param id: int
67+
param cron: Crontab in string format
68+
param timezone: Timezone in string format
69+
param name: String
70+
"""
71+
res = ApiResponse()
72+
cronElements = crontab.split(" ")
73+
if len(cronElements) != 5:
74+
res.update(False, "Crontab must contain five elements")
75+
return res
76+
schedule = Schedule.objects.get(crontabschedule_ptr_id=id)
77+
schedule.minute=cronElements[0]
78+
schedule.hour=cronElements[1]
79+
schedule.day_of_month=cronElements[2]
80+
schedule.month_of_year=cronElements[3]
81+
schedule.day_of_week=cronElements[4]
82+
schedule.timezone = timezone
83+
schedule.name = name
84+
schedule.save()
85+
res.update(True, "Schedules updated successfully", [])
86+
return res
87+
88+
@staticmethod
89+
def deleteSchedule(scheduleId: int):
90+
""" Service to delete schedule of given scheduleId """
91+
res = ApiResponse()
92+
Schedule.objects.filter(id=scheduleId).delete()
93+
res.update(True, "Schedules deleted successfully", [])
94+
return res
95+
96+
@staticmethod
97+
def getTimezones():
98+
"""
99+
Service to fetch all pytz timezones
100+
"""
101+
res = ApiResponse()
102+
timezones = pytz.all_timezones
103+
res.update(True, "Timezones fetched successfully", timezones)
104+
return res

api/genie/tests/test_views_notebookJobs.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -99,26 +99,6 @@ def test_notebookJob(client, populate_seed_data, mocker):
9999
assert response.status_code == 200
100100
assert response.data['success'] == True
101101

102-
# TODO Test and fix update notebook job
103-
# Test Update Notebook Schedule
104-
# mixer.blend("genie.customSchedule", id=2)
105-
# data = {"notebookId": "BX976MDDE", "scheduleId": 2}
106-
# response = client.put(path, data=data, content_type="application/json")
107-
# assert response.status_code == 200
108-
# assert response.data['success'] == True
109-
110-
# Test disable notebook job
111-
data = {"notebookId": "BX976MDDE", "enabled": False}
112-
response = client.put(path, data=data, content_type="application/json")
113-
assert response.status_code == 200
114-
assert response.data['success'] == True
115-
116-
# Test enabled notebook job
117-
data = {"notebookId": "BX976MDDE", "enabled": True}
118-
response = client.put(path, data=data, content_type="application/json")
119-
assert response.status_code == 200
120-
assert response.data['success'] == True
121-
122102
# Test delete notebook job
123103
response = client.delete(path, data=data, content_type="application/json")
124104
assert response.status_code == 200

api/genie/views.py

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import json
33
from rest_framework.views import APIView
44
from rest_framework.response import Response
5-
from genie.services import NotebookJobServices, Connections, NotebookTemplateService, KubernetesServices, Schemas
5+
from genie.services import NotebookJobServices, Connections, NotebookTemplateService, KubernetesServices, Schemas, ScheduleService
66
from rest_framework.decorators import api_view
77

88
class NotebookOperationsView(APIView):
@@ -99,16 +99,6 @@ def post(self, request):
9999
scheduleId = request.data["scheduleId"]
100100
res = NotebookJobServices.addNotebookJob(notebookId=notebookId, scheduleId=scheduleId)
101101
return Response(res.json())
102-
103-
def put(self, request):
104-
notebookId = request.data["notebookId"]
105-
if "scheduleId" in request.data:
106-
scheduleId = request.data["scheduleId"]
107-
res = NotebookJobServices.updateNotebookJob(notebookId=notebookId, scheduleId=scheduleId)
108-
elif "enabled" in request.data:
109-
enabled = request.data["enabled"]
110-
res = NotebookJobServices.toggleNotebookJob(notebookId=notebookId, enabled=enabled)
111-
return Response(res.json())
112102

113103
def delete(self, request, notebookId=None):
114104
res = NotebookJobServices.deleteNotebookJob(notebookId=notebookId)
@@ -119,22 +109,22 @@ class ScheduleView(APIView):
119109
Class to get and add available crontab schedules
120110
"""
121111
def get(self, request):
122-
res = NotebookJobServices.getSchedules()
112+
res = ScheduleService.getSchedules()
123113
return Response(res.json())
124114

125115
def post(self, request):
126116
name = request.data["name"]
127117
cron = request.data["crontab"]
128118
timezone = request.data["timezone"]
129-
res = NotebookJobServices.addSchedule(cron=cron, timezone=timezone, name=name)
119+
res = ScheduleService.addSchedule(cron=cron, timezone=timezone, name=name)
130120
return Response(res.json())
131121

132122
def put(self,request):
133123
id = request.data["id"]
134124
name = request.data["name"]
135125
crontab = request.data["crontab"]
136126
timezone = request.data["timezone"]
137-
res = NotebookJobServices.updateSchedule(id=id, crontab=crontab, timezone=timezone, name=name)
127+
res = ScheduleService.updateSchedule(id=id, crontab=crontab, timezone=timezone, name=name)
138128
return Response(res.json())
139129

140130
@api_view(["GET", "PUT", "DELETE"])
@@ -145,10 +135,10 @@ def schedule(request: HttpRequest, scheduleId: int) -> Response:
145135
:param connection_id: Connection Id
146136
"""
147137
if request.method == "GET":
148-
res = NotebookJobServices.getSingleSchedule(scheduleId)
138+
res = ScheduleService.getSingleSchedule(scheduleId)
149139
return Response(res.json())
150140
if request.method == "DELETE":
151-
res = NotebookJobServices.deleteSchedule(scheduleId)
141+
res = ScheduleService.deleteSchedule(scheduleId)
152142
return Response(res.json())
153143

154144

@@ -157,7 +147,7 @@ class TimzoneView(APIView):
157147
Class to get standard pytz timezones
158148
"""
159149
def get(self, request):
160-
res = NotebookJobServices.getTimezones()
150+
res = ScheduleService.getTimezones()
161151
return Response(res.json())
162152

163153

0 commit comments

Comments
 (0)