summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Rodrigue Koffi <koffirodrigue@gmail.com>2015-10-01 10:56:55 +0200
committerGuy Rodrigue Koffi <koffirodrigue@gmail.com>2015-10-08 11:53:34 +0200
commit8afb6df913ce350090b8374b652ac9ca07c0d077 (patch)
treee0258011a85b7823bd82cf701423ac5803bc7530
parentce7c448901f386b935a0f03d5f17ca6e541b9a49 (diff)
Updates for result_collection_api
- pod identification : RELENG-33 - add filters on results : RELENG-32 / RELENG-31 - fix bugs on db connection Change-Id: Ie720bb8028e5bfabd914c57df323b81d40c47fcd Signed-off-by: Guy Rodrigue Koffi <koffirodrigue@gmail.com>
-rw-r--r--utils/test/result_collection_api/common/config.py6
-rw-r--r--utils/test/result_collection_api/config.ini8
-rw-r--r--utils/test/result_collection_api/resources/handlers.py120
-rw-r--r--utils/test/result_collection_api/resources/models.py32
-rw-r--r--utils/test/result_collection_api/result_collection_api.py7
5 files changed, 143 insertions, 30 deletions
diff --git a/utils/test/result_collection_api/common/config.py b/utils/test/result_collection_api/common/config.py
index a0d0757a5..a62e80593 100644
--- a/utils/test/result_collection_api/common/config.py
+++ b/utils/test/result_collection_api/common/config.py
@@ -47,6 +47,7 @@ class APIConfig:
def __init__(self):
self._default_config_location = "config.ini"
self.mongo_url = None
+ self.mongo_dbname = None
self.api_port = None
self.api_debug_on = None
self._parser = None
@@ -87,13 +88,18 @@ class APIConfig:
# Linking attributes to keys from file with their sections
obj.mongo_url = obj._get_parameter("mongo", "url")
+ obj.mongo_dbname = obj._get_parameter("mongo", "dbname")
+
obj.api_port = obj._get_int_parameter("api", "port")
obj.api_debug_on = obj._get_bool_parameter("api", "debug")
+
return obj
def __str__(self):
return "mongo_url = %s \n" \
+ "mongo_dbname = %s \n" \
"api_port = %s \n" \
"api_debug_on = %s \n" % (self.mongo_url,
+ self.mongo_dbname,
self.api_port,
self.api_debug_on)
diff --git a/utils/test/result_collection_api/config.ini b/utils/test/result_collection_api/config.ini
index e00b56c5f..f703cc6c4 100644
--- a/utils/test/result_collection_api/config.ini
+++ b/utils/test/result_collection_api/config.ini
@@ -1,10 +1,12 @@
+# to add a new parameter in the config file,
+# the CONF object in config.ini must be updated
[mongo]
# URL of the mongo DB
# Mongo auth url => mongodb://user1:pwd1@host1/?authSource=db1
-url = mongodb://127.0.0.1:27017/test_results_collection
-
+url = mongodb://127.0.0.1:27017/
+dbname = test_results_collection
[api]
# Listening port
-port = 80
+port = 8000
# With debug_on set to true, error traces will be shown in HTTP responses
debug = True \ No newline at end of file
diff --git a/utils/test/result_collection_api/resources/handlers.py b/utils/test/result_collection_api/resources/handlers.py
index 3faba5aeb..f8b26d090 100644
--- a/utils/test/result_collection_api/resources/handlers.py
+++ b/utils/test/result_collection_api/resources/handlers.py
@@ -11,7 +11,7 @@ import json
from tornado.web import RequestHandler, asynchronous, HTTPError
from tornado import gen
-from datetime import datetime
+from datetime import datetime, timedelta
from models import Pod, TestProject, TestCase, TestResult
from common.constants import DEFAULT_REPRESENTATION, HTTP_BAD_REQUEST, \
@@ -60,6 +60,8 @@ class PodHandler(GenericApiHandler):
""" Handle the requests about the POD Platforms
HTTP Methdods :
- GET : Get PODS
+ - POST : Create a pod
+ - DELETE : DELETE POD
"""
def initialize(self):
@@ -68,19 +70,15 @@ class PodHandler(GenericApiHandler):
@asynchronous
@gen.coroutine
- def get(self, pod_id=None):
+ def get(self, pod_name=None):
"""
Get all pods or a single pod
:param pod_id:
"""
-
- if pod_id is None:
- pod_id = ""
-
get_request = dict()
- if len(pod_id) > 0:
- get_request["_id"] = int(pod_id)
+ if pod_name is not None:
+ get_request["name"] = pod_name
res = []
cursor = self.db.pod.find(get_request)
@@ -98,6 +96,69 @@ class PodHandler(GenericApiHandler):
self.finish_request(answer)
+ @asynchronous
+ @gen.coroutine
+ def post(self):
+ """ Create a POD"""
+
+ if self.json_args is None:
+ raise HTTPError(HTTP_BAD_REQUEST)
+
+ query = {"name": self.json_args.get("name")}
+
+ # check for existing name in db
+ mongo_dict = yield self.db.pod.find_one(query)
+ if mongo_dict is not None:
+ raise HTTPError(HTTP_FORBIDDEN,
+ "{} already exists as a pod".format(
+ self.json_args.get("name")))
+
+ pod = Pod.pod_from_dict(self.json_args)
+ pod.creation_date = datetime.now()
+
+ future = self.db.pod.insert(pod.format())
+ result = yield future
+ pod._id = result
+
+ meta = dict()
+ meta["success"] = True
+ meta["uri"] = "/pods/{}".format(pod.name)
+
+ answer = dict()
+ answer["pod"] = pod.format_http()
+ answer["meta"] = meta
+
+ self.finish_request(answer)
+
+ @asynchronous
+ @gen.coroutine
+ def delete(self, pod_name):
+ """ Remove a POD
+
+ # check for an existing pod to be deleted
+ mongo_dict = yield self.db.pod.find_one(
+ {'name': pod_name})
+ pod = TestProject.pod(mongo_dict)
+ if pod is None:
+ raise HTTPError(HTTP_NOT_FOUND,
+ "{} could not be found as a pod to be deleted"
+ .format(pod_name))
+
+ # just delete it, or maybe save it elsewhere in a future
+ res = yield self.db.test_projects.remove(
+ {'name': pod_name})
+
+ meta = dict()
+ meta["success"] = True
+ meta["deletion-data"] = res
+
+ answer = dict()
+ answer["meta"] = meta
+
+ self.finish_request(answer)
+ """
+ pass
+
class TestProjectHandler(GenericApiHandler):
"""
@@ -440,18 +501,26 @@ class TestResultsHandler(GenericApiHandler):
Available filters for this request are :
- project : project name
- case : case name
- - pod : pod ID
+ - pod : pod name
+ - version : platform version (Arno-R1, ...)
+ - installer (fuel, ...)
+ - period : x (x last days)
+
:param result_id: Get a result by ID
:raise HTTPError
- GET /results/project=functest&case=keystone.catalog&pod=1
+ GET /results/project=functest&case=vPing&version=Arno-R1 \
+ &pod=pod_name&period=15
=> get results with optional filters
"""
project_arg = self.get_query_argument("project", None)
case_arg = self.get_query_argument("case", None)
pod_arg = self.get_query_argument("pod", None)
+ version_arg = self.get_query_argument("version", None)
+ installer_arg = self.get_query_argument("installer", None)
+ period_arg = self.get_query_argument("period", None)
# prepare request
get_request = dict()
@@ -463,15 +532,34 @@ class TestResultsHandler(GenericApiHandler):
get_request["case_name"] = case_arg
if pod_arg is not None:
- get_request["pod_id"] = int(pod_arg)
+ get_request["pod_name"] = pod_arg
+
+ if version_arg is not None:
+ get_request["version"] = version_arg
+
+ if installer_arg is not None:
+ get_request["installer"] = installer_arg
+
+ if period_arg is not None:
+ try:
+ period_arg = int(period_arg)
+ except:
+ raise HTTPError(HTTP_BAD_REQUEST)
+
+ if period_arg > 0:
+ period = datetime.now() - timedelta(days=period_arg)
+ obj = {"$gte": period}
+ get_request["creation_date"] = obj
else:
get_request["_id"] = result_id
+ print get_request
res = []
# fetching results
cursor = self.db.test_results.find(get_request)
while (yield cursor.fetch_next):
- test_result = TestResult.test_result_from_dict(cursor.next_object())
+ test_result = TestResult.test_result_from_dict(
+ cursor.next_object())
res.append(test_result.format_http())
# building meta object
@@ -502,7 +590,9 @@ class TestResultsHandler(GenericApiHandler):
raise HTTPError(HTTP_BAD_REQUEST)
if self.json_args.get("case_name") is None:
raise HTTPError(HTTP_BAD_REQUEST)
- if self.json_args.get("pod_id") is None:
+ # check for pod_name instead of id,
+ # keeping id for current implementations
+ if self.json_args.get("pod_name") is None:
raise HTTPError(HTTP_BAD_REQUEST)
# TODO : replace checks with jsonschema
@@ -524,11 +614,11 @@ class TestResultsHandler(GenericApiHandler):
# check for pod
mongo_dict = yield self.db.pod.find_one(
- {"_id": self.json_args.get("pod_id")})
+ {"name": self.json_args.get("pod_name")})
if mongo_dict is None:
raise HTTPError(HTTP_NOT_FOUND,
"Could not find POD [{}] "
- .format(self.json_args.get("pod_id")))
+ .format(self.json_args.get("pod_name")))
# convert payload to object
test_result = TestResult.test_result_from_dict(self.json_args)
diff --git a/utils/test/result_collection_api/resources/models.py b/utils/test/result_collection_api/resources/models.py
index 82c17fda3..3b4d843f3 100644
--- a/utils/test/result_collection_api/resources/models.py
+++ b/utils/test/result_collection_api/resources/models.py
@@ -22,13 +22,19 @@ class Pod:
p = Pod()
p._id = pod_dict.get('_id')
- p.creation_date = pod_dict.get('creation_date')
+ p.creation_date = str(pod_dict.get('creation_date'))
p.name = pod_dict.get('name')
return p
def format(self):
return {
- "_id": self._id,
+ "name": self.name,
+ "creation_date": str(self.creation_date),
+ }
+
+ def format_http(self):
+ return {
+ "_id": str(self._id),
"name": self.name,
"creation_date": str(self.creation_date),
}
@@ -82,6 +88,7 @@ class TestCase:
self.name = None
self.project_name = None
self.description = None
+ self.url = None
self.creation_date = None
@staticmethod
@@ -96,6 +103,7 @@ class TestCase:
t.creation_date = testcase_dict.get('creation_date')
t.name = testcase_dict.get('name')
t.description = testcase_dict.get('description')
+ t.url = testcase_dict.get('url')
return t
@@ -104,7 +112,8 @@ class TestCase:
"name": self.name,
"description": self.description,
"project_name": self.project_name,
- "creation_date": str(self.creation_date)
+ "creation_date": str(self.creation_date),
+ "url": self.url
}
def format_http(self, test_project=None):
@@ -113,6 +122,7 @@ class TestCase:
"name": self.name,
"description": self.description,
"creation_date": str(self.creation_date),
+ "url": self.url,
}
if test_project is not None:
res["test_project"] = test_project
@@ -127,9 +137,9 @@ class TestResult:
self._id = None
self.case_name = None
self.project_name = None
- self.pod_id = None
+ self.pod_name = None
self.installer = None
- self.platform_version = None
+ self.version = None
self.description = None
self.creation_date = None
self.details = None
@@ -143,11 +153,13 @@ class TestResult:
t = TestResult()
t._id = test_result_dict.get('_id')
t.case_name = test_result_dict.get('case_name')
+ t.pod_name = test_result_dict.get('pod_name')
t.project_name = test_result_dict.get('project_name')
- t.pod_id = test_result_dict.get('pod_id')
t.description = test_result_dict.get('description')
t.creation_date = str(test_result_dict.get('creation_date'))
t.details = test_result_dict.get('details')
+ t.version = test_result_dict.get('version')
+ t.installer = test_result_dict.get('installer')
return t
@@ -155,9 +167,11 @@ class TestResult:
return {
"case_name": self.case_name,
"project_name": self.project_name,
- "pod_id": self.pod_id,
+ "pod_name": self.pod_name,
"description": self.description,
"creation_date": str(self.creation_date),
+ "version": self.version,
+ "installer": self.installer,
"details": self.details,
}
@@ -166,8 +180,10 @@ class TestResult:
"_id": str(self._id),
"case_name": self.case_name,
"project_name": self.project_name,
- "pod_id": self.pod_id,
+ "pod_name": self.pod_name,
"description": self.description,
"creation_date": str(self.creation_date),
+ "version": self.version,
+ "installer": self.installer,
"details": self.details,
}
diff --git a/utils/test/result_collection_api/result_collection_api.py b/utils/test/result_collection_api/result_collection_api.py
index c04e0343b..49695772d 100644
--- a/utils/test/result_collection_api/result_collection_api.py
+++ b/utils/test/result_collection_api/result_collection_api.py
@@ -15,14 +15,12 @@ Pre-requisites:
We can launch the API with this file
TODOs :
- - use POD name instead of id
- logging
- json args validation with schemes
- POST/PUT/DELETE for PODs
- POST/PUT/GET/DELETE for installers, platforms (enrich results info)
- count cases for GET on test_projects
- count results for GET on cases
- - provide filtering on requests
- include objects
- swagger documentation
- setup file
@@ -48,7 +46,8 @@ args = parser.parse_args()
CONF = APIConfig().parse(args.config_file)
# connecting to MongoDB server, and choosing database
-db = motor.MotorClient(CONF.mongo_url)
+client = motor.MotorClient(CONF.mongo_url)
+db = client[CONF.mongo_dbname]
def make_app():
@@ -61,7 +60,7 @@ def make_app():
# GET /pods => Get all pods
# GET /pods/1 => Get details on POD 1
(r"/pods", PodHandler),
- (r"/pods/(\d*)", PodHandler),
+ (r"/pods/([^/]+)", PodHandler),
# few examples:
# GET /test_projects