Skip to content

Commit

Permalink
Merge pull request #38 from diggyk/master
Browse files Browse the repository at this point in the history
Adding quest status page
  • Loading branch information
gmjosack committed Sep 14, 2015
2 parents cb5adf6 + f7213ae commit ad96519
Show file tree
Hide file tree
Showing 19 changed files with 678 additions and 397 deletions.
1 change: 1 addition & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"angular-animate": "~1.4.5",
"angular-route": "~1.4.5",
"bootstrap": "~3.3.5",
"d3": "~3.5.6",
"raphael": "raphael.js#~2.1.4"
}
}
128 changes: 112 additions & 16 deletions hermes/handlers/api.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from __future__ import division

import json
import logging
import random
import re
import sqlalchemy
from sqlalchemy import desc, or_
from sqlalchemy import desc, or_, and_
from sqlalchemy.exc import IntegrityError
import string
import time
Expand Down Expand Up @@ -1937,7 +1940,7 @@ def get(self):
.. sourcecode:: http
GET /api/v1/quests HTTP/1.1
GET /api/v1/quests?progressInfo=true HTTP/1.1
Host: localhost
**Example response:**
Expand All @@ -1961,20 +1964,25 @@ def get(self):
"targetTime": timestamp,
"completionTime": timestamp,
"description": "This is a quest almighty",
"totalLabors": 20,
"openLabors": 10,
"percentComplete": 50,
"labors": [],
},
...
],
}
:query boolean filterClosed: if true, filter out completed Quests
:query boolean progressInfo: if true, include progress information
:query int limit: (*optional*) Limit result to N resources.
:query int offset: (*optional*) Skip the first N resources.
:statuscode 200: The request was successful.
:statuscode 401: The request was made without being logged in.
"""
filter_closed = self.get_argument("filterClosed", None)
progress_info = self.get_argument("progressInfo", None)

quests = self.session.query(Quest).order_by(desc(Quest.embark_time))

Expand All @@ -1989,11 +1997,49 @@ def get(self):
quests_json = []
for quest in quests.all():
quest_json = quest.to_dict(self.href_prefix)
if progress_info:
labor_count = self.session.query(Labor).filter(
Labor.quest_id == quest.id
).count()
open_labors_count = self.session.query(Labor).filter(
and_(
Labor.quest_id == quest.id,
Labor.completion_time == None
)
).count()

percent_complete = round(
(labor_count - open_labors_count) / labor_count * 100,
2
)
quest_json['totalLabors'] = labor_count
quest_json['openLabors'] = open_labors_count
quest_json['percentComplete'] = percent_complete
if "labors" in expand:
quest_json["labors"] = [
labor.to_dict(self.href_prefix)
for labor in quest.labors
]
quest_json["labors"] = []
for labor in quest.labors:
labor_json = labor.to_dict(self.href_prefix)
if "hosts" in expand:
labor_json["host"] = labor.host.to_dict(self.href_prefix)
if "events" in expand:
labor_json["creationEvent"] = (
labor.creation_event.to_dict(self.href_prefix)
)
if "eventtypes" in expand:
labor_json["creationEvent"]["eventType"] = (
labor.creation_event.event_type.to_dict(self.href_prefix)
)
if labor.completion_event:
labor_json["completionEvent"] = (
labor.completion_event.to_dict(self.href_prefix)
)
labor_json["completionEvent"]["eventType"] = (
labor.completion_event
.event_type.to_dict(self.href_prefix)
)
else:
labor_json["completionEvent"] = None
quest_json["labors"].append(labor_json)
quests_json.append(quest_json)

json = {
Expand Down Expand Up @@ -2040,23 +2086,54 @@ def get(self, id):
:type id: int
:query string expand: (*optional*) supports labors, hosts, events, eventtypes
:query boolean progressInfo: (*optional*) if true, include progress information
:query boolean onlyOpenLabors: (*optional*) if true, only return open labors
:statuscode 200: The request was successful.
:statuscode 401: The request was made without being logged in.
:statuscode 404: The EventType was not found.
"""
offset, limit, expand = self.get_pagination_values()

progress_info = self.get_argument("progressInfo", False)
only_open_labors = self.get_argument("onlyOpenLabors", False)

quest = self.session.query(Quest).filter_by(id=id).scalar()

if not quest:
raise exc.NotFound("No such Quest {} found".format(id))

json = quest.to_dict(self.href_prefix)
if progress_info:
labor_count = self.session.query(Labor).filter(
Labor.quest_id == quest.id
).count()
open_labors_count = self.session.query(Labor).filter(
and_(
Labor.quest_id == quest.id,
Labor.completion_time == None
)
).count()

percent_complete = round(
(labor_count - open_labors_count) / labor_count * 100,
2
)
json['totalLabors'] = labor_count
json['openLabors'] = open_labors_count
json['percentComplete'] = percent_complete
if only_open_labors:
labors = self.session.query(Labor).filter(
and_(
Labor.quest_id == quest.id,
Labor.completion_event_id == None
)
).all()
else:
labors = quest.labors
if "labors" in expand:
json["labors"] = []
for labor in quest.labors:
for labor in labors:
labor_json = labor.to_dict(self.href_prefix)
if "hosts" in expand:
labor_json["host"] = labor.host.to_dict(self.href_prefix)
Expand All @@ -2081,7 +2158,7 @@ def get(self, id):
json["labors"].append(labor_json)
else:
json["labors"] = []
for labor in quest.labors:
for labor in labors:
json["labors"].append({
"id": labor.id,
"href": labor.href(self.href_prefix)
Expand Down Expand Up @@ -2195,7 +2272,7 @@ def get(self):
.. sourcecode:: http
GET /api/v1/query?hostQuery=server HTTP/1.1
GET /api/v1/query?query=server HTTP/1.1
Host: localhost
**Example response:**
Expand All @@ -2217,22 +2294,41 @@ def get(self):
]
}
:query string hostQuery: the query to send to the plugin to come up with the list of hostnames
:statuscode 200: The request was successful.
:statuscode 401: The request was made without being logged in.
"""
host_query = self.get_argument("hostQuery", None)

response = PluginHelper.request_get(params={"query": host_query})
response = PluginHelper.request_get(params=self.request.arguments)
if (
response.status_code == 200
and response.json()["status"] == "ok"
):
json = {
result_json = {
"results": response.json()["results"],
}
else:
raise exc.BadRequest("Bad host query: {}".format(host_query))
raise exc.BadRequest("Bad host query: {}".format(
self.request.arguments
))

self.success(json)
self.success(result_json)

def post(self):
"""
Pass through post to the external query handler
"""
json_data = json.loads(self.request.body)
response = PluginHelper.request_post(json_body=json_data)
if (
response.status_code == 200
and response.json()["status"] == "ok"
):
result_json = {
"results": response.json()["results"],
}
else:
raise exc.BadRequest("Bad host query: {}".format(
self.request.body
))

self.success(result_json)
18 changes: 18 additions & 0 deletions hermes/handlers/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,31 @@ def request_get(cls, path="", params={}):
Args:
path: the full path to the resource
params: the query parameters to send
Returns:
the http response
"""
response = requests.get(settings.query_server + path, params=params)

return response

@classmethod
def request_post(cls, path="", params={}, json_body={}):
"""Make an HTTP POST request for the given path
Args:
path: the full path to the resource
params: the query params to send
json_body: the body of the message in JSON format
Returns:
the http response
"""
response = requests.post(
settings.query_server + path, params=params, json=json_body
)

return response


class BaseHandler(RequestHandler):
def initialize(self):
Expand Down
2 changes: 1 addition & 1 deletion hermes/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

# Frontend Handlers
(
r"/((?:css|js|vendor|templates)/.*)",
r"/((?:css|img|js|vendor|templates)/.*)",
web.StaticFileHandler,
dict(
path=os.path.join(os.path.dirname(__file__), "webapp/build")
Expand Down

0 comments on commit ad96519

Please sign in to comment.