Skip to content

Commit f6eca44

Browse files
bsatoriubsatoriu
andauthored
Organizations & job queues management (#137)
* Organizations endpoint * Add role name to members endpoint * Members creation_date formatting bug fix * Add role_id to member put endpoint * Org tree response formatting updates * Use root org as default id * Use root org as default id * Add creation_date to org response payload * Add membership array to Org post/get endpoints * Add maintainer prop to org output * Add parent_org_id prop to org output * Add membership updates to Org put endpoint * Org put endpoint bug fix * Org delete endpoint updates * Org delete endpoint bug fix * Org delete endpoint err msg * Job queue admin endpoints * Job queue admin get bug fix * Job queue admin delete bug fix * Filter algorithm resources by user/public queues * Refactor orgs and job queues * Queue refactoring & error handling --------- Co-authored-by: bsatoriu <[email protected]>
1 parent 601b897 commit f6eca44

16 files changed

+992
-12
lines changed

api/endpoints/admin.py

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,115 @@
22
from flask_restx import Resource
33
from flask import request
44
from flask_api import status
5+
from api.models.job_queue import JobQueue
6+
from api.models.organization import Organization
7+
from api.models.organization_job_queue import OrganizationJobQueue
58
from api.models.role import Role
69
from api.restplus import api
710
from api.auth.security import login_required
811
from api.maap_database import db
912
from api.models.pre_approved import PreApproved
13+
from api.schemas.job_queue_schema import JobQueueSchema
1014
from api.schemas.pre_approved_schema import PreApprovedSchema
1115
from datetime import datetime
1216
import json
13-
17+
from api.utils import job_queue
1418
from api.utils.http_util import err_response
1519

1620
log = logging.getLogger(__name__)
1721
ns = api.namespace('admin', description='Operations related to the MAAP admin')
1822

23+
@ns.route('/job-queues')
24+
class JobQueuesCls(Resource):
25+
26+
@api.doc(security='ApiKeyAuth')
27+
@login_required(role=Role.ROLE_ADMIN)
28+
def get(self):
29+
"""
30+
Lists the job queues and associated organizations
31+
:return:
32+
"""
33+
all_queues = job_queue.get_all_queues()
34+
return all_queues
35+
36+
37+
@api.doc(security='ApiKeyAuth')
38+
@login_required(role=Role.ROLE_ADMIN)
39+
def post(self):
40+
41+
"""
42+
Create new job queue.
43+
"""
44+
45+
req_data = request.get_json()
46+
if not isinstance(req_data, dict):
47+
return err_response("Valid JSON body object required.")
48+
49+
queue_name = req_data.get("queue_name", "")
50+
if not isinstance(queue_name, str) or not queue_name:
51+
return err_response("Valid queue name is required.")
52+
53+
queue_description = req_data.get("queue_description", "")
54+
if not isinstance(queue_description, str) or not queue_description:
55+
return err_response("Valid queue description is required.")
56+
57+
guest_tier = req_data.get("guest_tier", False)
58+
orgs = req_data.get("orgs", [])
59+
60+
new_queue = job_queue.create_queue(queue_name, queue_description, guest_tier, orgs)
61+
return new_queue
62+
63+
64+
@ns.route('/job-queues/<int:queue_id>')
65+
class JobQueueCls(Resource):
66+
67+
@api.doc(security='ApiKeyAuth')
68+
@login_required()
69+
def put(self, queue_id):
70+
71+
"""
72+
Update job queue. Only supplied fields are updated.
73+
"""
74+
75+
if not queue_id:
76+
return err_response("Job queue id is required.")
77+
78+
req_data = request.get_json()
79+
if not isinstance(req_data, dict):
80+
return err_response("Valid JSON body object required.")
81+
82+
queue = db.session.query(JobQueue).filter_by(id=queue_id).first()
83+
84+
if queue is None:
85+
return err_response(msg="No job queue found with id " + queue_id)
86+
87+
queue.queue_name = req_data.get("queue_name", queue.queue_name)
88+
queue.queue_description = req_data.get("queue_description", queue.queue_description)
89+
queue.guest_tier = req_data.get("guest_tier", queue.guest_tier)
90+
orgs = req_data.get("orgs", [])
91+
92+
updated_queue = job_queue.update_queue(queue, orgs)
93+
return updated_queue
94+
95+
96+
@api.doc(security='ApiKeyAuth')
97+
@login_required(role=Role.ROLE_ADMIN)
98+
def delete(self, queue_id):
99+
"""
100+
Delete job queue
101+
"""
102+
103+
queue = db.session.query(JobQueue).filter_by(id=queue_id).first()
104+
queue_name = queue.queue_name
105+
106+
if queue is None:
107+
return err_response(msg="Job queue does not exist")
108+
109+
job_queue.delete_queue(queue_id)
110+
111+
return {"code": status.HTTP_200_OK, "message": "Successfully deleted {}.".format(queue_name)}
112+
113+
19114
@ns.route('/pre-approved')
20115
class PreApprovedEmails(Resource):
21116

api/endpoints/algorithm.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import logging
22
import os
3+
from collections import namedtuple
4+
5+
import sqlalchemy
36
from flask import request, Response
47
from flask_restx import Resource, reqparse
58
from flask_api import status
@@ -19,6 +22,8 @@
1922
from datetime import datetime
2023
import json
2124

25+
from api.utils import job_queue
26+
2227
log = logging.getLogger(__name__)
2328

2429
ns = api.namespace('mas', description='Operations to register an algorithm')
@@ -450,6 +455,9 @@ def delete(self, algo_id):
450455

451456
@ns.route('/algorithm/resource')
452457
class ResourceList(Resource):
458+
459+
@api.doc(security='ApiKeyAuth')
460+
@login_required()
453461
def get(self):
454462
"""
455463
This function would query DPS to see what resources (named based on memory space) are available for
@@ -458,7 +466,9 @@ def get(self):
458466
"""
459467
try:
460468
response_body = {"code": None, "message": None}
461-
queues = hysds.get_mozart_queues()
469+
user = get_authorized_user()
470+
queues = job_queue.get_user_queues(user.id)
471+
462472
response_body["code"] = status.HTTP_200_OK
463473
response_body["queues"] = queues
464474
response_body["message"] = "success"

api/endpoints/members.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from flask import request, jsonify, Response
55
from flask_api import status
66
from sqlalchemy.exc import SQLAlchemyError
7+
8+
from api.models.role import Role
79
from api.restplus import api
810
import api.settings as settings
911
from api.auth.security import get_authorized_user, login_required, valid_dps_request, edl_federated_request, \
@@ -42,18 +44,25 @@ class Member(Resource):
4244
@api.doc(security='ApiKeyAuth')
4345
@login_required()
4446
def get(self):
45-
members = db.session.query(
46-
Member_db.id,
47-
Member_db.username,
48-
Member_db.first_name,
49-
Member_db.last_name,
50-
Member_db.email,
51-
Member_db.status,
52-
Member_db.creation_date
47+
48+
member_query = db.session.query(
49+
Member_db, Role,
50+
).filter(
51+
Member_db.role_id == Role.id
5352
).order_by(Member_db.username).all()
5453

55-
member_schema = MemberSchema()
56-
result = [json.loads(member_schema.dumps(m)) for m in members]
54+
result = [{
55+
'id': m.Member.id,
56+
'username': m.Member.username,
57+
'first_name': m.Member.first_name,
58+
'last_name': m.Member.last_name,
59+
'email': m.Member.email,
60+
'role_id': m.Member.role_id,
61+
'role_name': m.Role.role_name,
62+
'status': m.Member.status,
63+
'creation_date': m.Member.creation_date.strftime('%m/%d/%Y'),
64+
} for m in member_query]
65+
5766
return result
5867

5968

@@ -263,6 +272,7 @@ def put(self, key):
263272
member.public_ssh_key_modified_date = datetime.utcnow()
264273
member.public_ssh_key = req_data.get("public_ssh_key", member.public_ssh_key)
265274
member.public_ssh_key_name = req_data.get("public_ssh_key_name", member.public_ssh_key_name)
275+
member.role_id = req_data.get("role_id", member.role_id)
266276
db.session.commit()
267277

268278
member_schema = MemberSchema()

0 commit comments

Comments
 (0)