aboutsummaryrefslogtreecommitdiffstats
path: root/functest/api
diff options
context:
space:
mode:
Diffstat (limited to 'functest/api')
-rw-r--r--functest/api/__init__.py0
-rw-r--r--functest/api/base.py71
-rw-r--r--functest/api/common/__init__.py0
-rw-r--r--functest/api/common/api_utils.py101
-rw-r--r--functest/api/common/thread.py52
-rw-r--r--functest/api/database/__init__.py0
-rw-r--r--functest/api/database/db.py26
-rw-r--r--functest/api/database/v1/__init__.py0
-rw-r--r--functest/api/database/v1/handlers.py43
-rw-r--r--functest/api/database/v1/models.py33
-rw-r--r--functest/api/resources/__init__.py0
-rw-r--r--functest/api/resources/v1/__init__.py0
-rw-r--r--functest/api/resources/v1/creds.py80
-rw-r--r--functest/api/resources/v1/envs.py83
-rw-r--r--functest/api/resources/v1/tasks.py111
-rw-r--r--functest/api/resources/v1/testcases.py157
-rw-r--r--functest/api/resources/v1/tiers.py82
-rw-r--r--functest/api/server.py106
-rw-r--r--functest/api/swagger/creds.yaml36
-rw-r--r--functest/api/swagger/creds_action.yaml56
-rw-r--r--functest/api/swagger/envs.yaml27
-rw-r--r--functest/api/swagger/envs_action.yaml42
-rw-r--r--functest/api/swagger/task.yaml37
-rw-r--r--functest/api/swagger/task_log.yaml37
-rw-r--r--functest/api/swagger/testcase.yaml36
-rw-r--r--functest/api/swagger/testcase_run.yaml46
-rw-r--r--functest/api/swagger/testcases.yaml23
-rw-r--r--functest/api/swagger/testcases_in_tier.yaml30
-rw-r--r--functest/api/swagger/tier.yaml33
-rw-r--r--functest/api/swagger/tiers.yaml23
-rw-r--r--functest/api/urls.py70
31 files changed, 0 insertions, 1441 deletions
diff --git a/functest/api/__init__.py b/functest/api/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/functest/api/__init__.py
+++ /dev/null
diff --git a/functest/api/base.py b/functest/api/base.py
deleted file mode 100644
index 75f059b7..00000000
--- a/functest/api/base.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-The base class to dispatch request
-
-"""
-
-import logging
-
-from flask import request
-from flask_restful import Resource
-
-from functest.api.common import api_utils
-
-
-LOGGER = logging.getLogger(__name__)
-
-
-class ApiResource(Resource):
- """ API Resource class"""
-
- def __init__(self):
- super(ApiResource, self).__init__()
-
- def _post_args(self): # pylint: disable=no-self-use
- # pylint: disable=maybe-no-member
- """ Return action and args after parsing request """
-
- data = request.json if request.json else {}
- params = api_utils.change_to_str_in_dict(data)
- action = params.get('action', request.form.get('action', ''))
- args = params.get('args', {})
- try:
- args['file'] = request.files['file']
- except KeyError:
- pass
- LOGGER.debug('Input args are: action: %s, args: %s', action, args)
-
- return action, args
-
- def _get_args(self): # pylint: disable=no-self-use
- """ Convert the unicode to string for request.args """
- args = api_utils.change_to_str_in_dict(request.args)
- return args
-
- def _dispatch_post(self):
- """ Dispatch request """
- action, args = self._post_args()
- return self._dispatch(args, action)
-
- def _dispatch(self, args, action):
- """
- Dynamically load the classes with reflection and
- obtain corresponding methods
- """
- try:
- return getattr(self, action)(args)
- except AttributeError:
- api_utils.result_handler(status=1, data='No such action')
-
-
-# Import modules from package "functest.api.resources"
-# and append them into sys.modules
-api_utils.import_modules_from_package("functest.api.resources")
diff --git a/functest/api/common/__init__.py b/functest/api/common/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/functest/api/common/__init__.py
+++ /dev/null
diff --git a/functest/api/common/api_utils.py b/functest/api/common/api_utils.py
deleted file mode 100644
index d85acf92..00000000
--- a/functest/api/common/api_utils.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Utils for functest restapi
-
-"""
-
-import collections
-import logging
-import os
-import sys
-from oslo_utils import importutils
-
-from flask import jsonify
-import six
-
-import functest
-
-LOGGER = logging.getLogger(__name__)
-
-
-def change_to_str_in_dict(obj):
- """
- Return a dict with key and value both in string if they are in Unicode
- """
- if isinstance(obj, collections.Mapping):
- return {str(k): change_to_str_in_dict(v) for k, v in obj.items()}
- elif isinstance(obj, list):
- return [change_to_str_in_dict(ele) for ele in obj]
- elif isinstance(obj, six.text_type):
- return str(obj)
- return obj
-
-
-def itersubclasses(cls, _seen=None):
- """ Generator over all subclasses of a given class in depth first order """
-
- if not isinstance(cls, type):
- raise TypeError("itersubclasses must be called with "
- "new-style classes, not %.100r" % cls)
- _seen = _seen or set()
- try:
- subs = cls.__subclasses__()
- except TypeError: # fails only when cls is type
- subs = cls.__subclasses__(cls)
- for sub in subs:
- if sub not in _seen:
- _seen.add(sub)
- yield sub
- for itersub in itersubclasses(sub, _seen):
- yield itersub
-
-
-def import_modules_from_package(package):
- """
- Import modules from package and append into sys.modules
- :param: package - Full package name. For example: functest.api.resources
- """
- path = [os.path.dirname(functest.__file__), ".."] + package.split(".")
- path = os.path.join(*path)
- for root, _, files in os.walk(path):
- for filename in files:
- if filename.startswith("__") or not filename.endswith(".py"):
- continue
- new_package = ".".join(root.split(os.sep)).split("....")[1]
- module_name = "%s.%s" % (new_package, filename[:-3])
- try:
- try_append_module(module_name, sys.modules)
- except ImportError:
- LOGGER.exception("unable to import %s", module_name)
-
-
-def try_append_module(name, modules):
- """ Append the module into specified module system """
-
- if name not in modules:
- modules[name] = importutils.import_module(name)
-
-
-def change_obj_to_dict(obj):
- """ Transfer the object into dict """
- dic = {}
- for key, value in vars(obj).items():
- dic.update({key: value})
- return dic
-
-
-def result_handler(status, data):
- """ Return the json format of result in dict """
- result = {
- 'status': status,
- 'result': data
- }
- return jsonify(result)
diff --git a/functest/api/common/thread.py b/functest/api/common/thread.py
deleted file mode 100644
index fb60aaac..00000000
--- a/functest/api/common/thread.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Used to handle multi-thread tasks
-"""
-
-import logging
-import threading
-
-from oslo_serialization import jsonutils
-
-
-LOGGER = logging.getLogger(__name__)
-
-
-class TaskThread(threading.Thread):
- """ Task Thread Class """
-
- def __init__(self, target, args, handler):
- super(TaskThread, self).__init__(target=target, args=args)
- self.target = target
- self.args = args
- self.handler = handler
-
- def run(self):
- """ Override the function run: run testcase and update database """
- update_data = {'task_id': self.args.get('task_id'),
- 'status': 'IN PROGRESS'}
- self.handler.insert(update_data)
-
- LOGGER.info('Starting running test case')
-
- try:
- data = self.target(self.args)
- except Exception as err: # pylint: disable=broad-except
- LOGGER.exception('Task Failed')
- update_data = {'status': 'FAIL', 'error': str(err)}
- self.handler.update_attr(self.args.get('task_id'), update_data)
- else:
- LOGGER.info('Task Finished')
- LOGGER.debug('Result: %s', data)
- new_data = {'status': 'FINISHED',
- 'result': jsonutils.dumps(data.get('result', {}))}
-
- self.handler.update_attr(self.args.get('task_id'), new_data)
diff --git a/functest/api/database/__init__.py b/functest/api/database/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/functest/api/database/__init__.py
+++ /dev/null
diff --git a/functest/api/database/db.py b/functest/api/database/db.py
deleted file mode 100644
index ea861ddb..00000000
--- a/functest/api/database/db.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Create database to store task results using sqlalchemy
-"""
-
-from sqlalchemy import create_engine
-from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy.orm import scoped_session, sessionmaker
-
-
-SQLITE = 'sqlite:////tmp/functest.db'
-
-ENGINE = create_engine(SQLITE, convert_unicode=True)
-DB_SESSION = scoped_session(sessionmaker(autocommit=False,
- autoflush=False,
- bind=ENGINE))
-BASE = declarative_base()
-BASE.query = DB_SESSION.query_property()
diff --git a/functest/api/database/v1/__init__.py b/functest/api/database/v1/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/functest/api/database/v1/__init__.py
+++ /dev/null
diff --git a/functest/api/database/v1/handlers.py b/functest/api/database/v1/handlers.py
deleted file mode 100644
index 7bd286de..00000000
--- a/functest/api/database/v1/handlers.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Used to handle tasks: insert the task info into database and update it
-"""
-
-from functest.api.database.db import DB_SESSION
-from functest.api.database.v1.models import Tasks
-
-
-class TasksHandler(object):
- """ Tasks Handler Class """
-
- def insert(self, kwargs): # pylint: disable=no-self-use
- """ To insert the task info into database """
- task = Tasks(**kwargs)
- DB_SESSION.add(task) # pylint: disable=maybe-no-member
- DB_SESSION.commit() # pylint: disable=maybe-no-member
- return task
-
- def get_task_by_taskid(self, task_id): # pylint: disable=no-self-use
- """ Obtain the task by task id """
- # pylint: disable=maybe-no-member
- task = Tasks.query.filter_by(task_id=task_id).first()
- if not task:
- raise ValueError
-
- return task
-
- def update_attr(self, task_id, attr):
- """ Update the required attributes of the task """
- task = self.get_task_by_taskid(task_id)
-
- for key, value in attr.items():
- setattr(task, key, value)
- DB_SESSION.commit() # pylint: disable=maybe-no-member
diff --git a/functest/api/database/v1/models.py b/functest/api/database/v1/models.py
deleted file mode 100644
index c5de91bc..00000000
--- a/functest/api/database/v1/models.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Define tables for tasks
-"""
-
-from sqlalchemy import Column
-from sqlalchemy import Integer
-from sqlalchemy import String
-from sqlalchemy import Text
-
-from functest.api.database.db import BASE
-
-
-class Tasks(BASE): # pylint: disable=too-few-public-methods, no-init
- """ Create a table for tasks"""
-
- __tablename__ = 'tasks'
- id = Column(Integer, primary_key=True) # pylint: disable=invalid-name
- task_id = Column(String(50))
- status = Column(Integer)
- error = Column(String(120))
- result = Column(Text)
-
- def __repr__(self):
- return '<Task %r>' % Tasks.task_id
diff --git a/functest/api/resources/__init__.py b/functest/api/resources/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/functest/api/resources/__init__.py
+++ /dev/null
diff --git a/functest/api/resources/v1/__init__.py b/functest/api/resources/v1/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/functest/api/resources/v1/__init__.py
+++ /dev/null
diff --git a/functest/api/resources/v1/creds.py b/functest/api/resources/v1/creds.py
deleted file mode 100644
index 3eae1966..00000000
--- a/functest/api/resources/v1/creds.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Resources to handle openstack related requests
-"""
-
-import collections
-import logging
-import socket
-
-from flask import jsonify
-from flasgger.utils import swag_from
-import pkg_resources
-
-from functest.api.base import ApiResource
-from functest.api.common import api_utils
-from functest.ci import run_tests
-from functest.cli.commands.cli_os import OpenStack
-from functest.utils import constants
-
-LOGGER = logging.getLogger(__name__)
-
-ADDRESS = socket.gethostbyname(socket.gethostname())
-ENDPOINT_CREDS = ('http://{}:5000/api/v1/functest/openstack'.format(ADDRESS))
-
-
-class V1Creds(ApiResource):
- """ V1Creds Resource class"""
-
- @swag_from(
- pkg_resources.resource_filename('functest', 'api/swagger/creds.yaml'),
- endpoint='{0}/credentials'.format(ENDPOINT_CREDS))
- def get(self): # pylint: disable=no-self-use
- """ Get credentials """
- run_tests.Runner.source_envfile(constants.ENV_FILE)
- credentials_show = OpenStack.show_credentials()
- return jsonify(credentials_show)
-
- @swag_from(
- pkg_resources.resource_filename('functest',
- 'api/swagger/creds_action.yaml'),
- endpoint='{0}/action'.format(ENDPOINT_CREDS))
- def post(self):
- """ Used to handle post request """
- return self._dispatch_post()
-
- def update_openrc(self, args): # pylint: disable=no-self-use
- """ Used to update the OpenStack RC file """
- try:
- openrc_vars = args['openrc']
- except KeyError:
- return api_utils.result_handler(
- status=0, data='openrc must be provided')
- else:
- if not isinstance(openrc_vars, collections.Mapping):
- return api_utils.result_handler(
- status=0, data='args should be a dict')
-
- lines = ['export {}={}\n'.format(k, v) for k, v in openrc_vars.items()]
-
- rc_file = constants.ENV_FILE
- with open(rc_file, 'w') as creds_file:
- creds_file.writelines(lines)
-
- LOGGER.info("Sourcing the OpenStack RC file...")
- try:
- run_tests.Runner.source_envfile(rc_file)
- except Exception as err: # pylint: disable=broad-except
- LOGGER.exception('Failed to source the OpenStack RC file')
- return api_utils.result_handler(status=0, data=str(err))
-
- return api_utils.result_handler(
- status=0, data='Update openrc successfully')
diff --git a/functest/api/resources/v1/envs.py b/functest/api/resources/v1/envs.py
deleted file mode 100644
index 3e6f05ac..00000000
--- a/functest/api/resources/v1/envs.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Resources to handle environment related requests
-"""
-
-import pkg_resources
-import socket
-
-import IPy
-from flask import jsonify
-from flasgger.utils import swag_from
-
-from functest.api.base import ApiResource
-from functest.api.common import api_utils
-from functest.cli.commands.cli_env import Env
-
-ADDRESS = socket.gethostbyname(socket.gethostname())
-ENDPOINT_ENVS = ('http://{}:5000/api/v1/functest/envs'.format(ADDRESS))
-
-
-class V1Envs(ApiResource):
- """ V1Envs Resource class"""
-
- @swag_from(
- pkg_resources.resource_filename('functest', 'api/swagger/envs.yaml'),
- endpoint=ENDPOINT_ENVS)
- def get(self): # pylint: disable=no-self-use
- """ Get environment """
- environment_show = Env().show()
- return jsonify(environment_show)
-
- @swag_from(
- pkg_resources.resource_filename('functest',
- 'api/swagger/envs_action.yaml'),
- endpoint='{0}/action'.format(ENDPOINT_ENVS))
- def post(self):
- """ Used to handle post request """
- return self._dispatch_post()
-
- def update_hosts(self, hosts_info): # pylint: disable=no-self-use
- """ Update hosts info """
-
- if not isinstance(hosts_info, dict):
- return api_utils.result_handler(
- status=1, data='Error, args should be a dict')
-
- for key, value in hosts_info.items():
- if key:
- try:
- IPy.IP(value)
- except Exception: # pylint: disable=broad-except
- return api_utils.result_handler(
- status=1, data='The IP %s is invalid' % value)
- else:
- return api_utils.result_handler(
- status=1, data='Domain name is absent')
-
- try:
- functest_flag = "# SUT hosts info for Functest"
- hosts_list = ('\n{} {} {}'.format(ip, host_name, functest_flag)
- for host_name, ip in hosts_info.items())
-
- with open("/etc/hosts", 'r') as file_hosts:
- origin_lines = [line for line in file_hosts
- if functest_flag not in line]
-
- with open("/etc/hosts", 'w') as file_hosts:
- file_hosts.writelines(origin_lines)
- file_hosts.write(functest_flag)
- file_hosts.writelines(hosts_list)
- except Exception: # pylint: disable=broad-except
- return api_utils.result_handler(
- status=1, data='Error when updating hosts info')
- else:
- return api_utils.result_handler(
- status=0, data='Update hosts info successfully')
diff --git a/functest/api/resources/v1/tasks.py b/functest/api/resources/v1/tasks.py
deleted file mode 100644
index 30501adf..00000000
--- a/functest/api/resources/v1/tasks.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Resources to retrieve the task results
-"""
-
-import errno
-import json
-import logging
-import os
-import uuid
-
-from flask import jsonify
-from flasgger.utils import swag_from
-import pkg_resources
-
-from functest.api.base import ApiResource
-from functest.api.common import api_utils
-from functest.api.database.v1.handlers import TasksHandler
-from functest.utils import config
-
-
-LOGGER = logging.getLogger(__name__)
-
-
-class V1Task(ApiResource):
- """ V1Task Resource class"""
-
- @swag_from(pkg_resources.resource_filename(
- 'functest', 'api/swagger/task.yaml'))
- def get(self, task_id): # pylint: disable=no-self-use
- """ GET the result of the task id """
- try:
- uuid.UUID(task_id)
- except ValueError:
- return api_utils.result_handler(status=1, data='Invalid task id')
-
- task_handler = TasksHandler()
- try:
- task = task_handler.get_task_by_taskid(task_id)
- except ValueError:
- return api_utils.result_handler(status=1, data='No such task id')
-
- status = task.status
- LOGGER.debug('Task status is: %s', status)
-
- if status not in ['IN PROGRESS', 'FAIL', 'FINISHED']:
- return api_utils.result_handler(status=1,
- data='internal server error')
-
- switcher = {'IN PROGRESS': 0, 'FAIL': 1, 'FINISHED': 2}
- if status == 'IN PROGRESS':
- result = {'status': switcher.get(status), 'result': ''}
- elif status == 'FAIL':
- result = {'status': switcher.get(status), 'error': task.error}
- else:
- result = {'status': switcher.get(status),
- 'result': json.loads(task.result)}
-
- return jsonify(result)
-
-
-class V1TaskLog(ApiResource):
- """ V1TaskLog Resource class"""
-
- @swag_from(pkg_resources.resource_filename(
- 'functest', 'api/swagger/task_log.yaml'))
- def get(self, task_id): # pylint: disable=no-self-use
- """ GET the log of the task id """
- try:
- uuid.UUID(task_id)
- except ValueError:
- return api_utils.result_handler(status=1, data='Invalid task id')
-
- task_handler = TasksHandler()
- try:
- task = task_handler.get_task_by_taskid(task_id)
- except ValueError:
- return api_utils.result_handler(status=1, data='No such task id')
-
- task_log_dir = getattr(config.CONF, 'dir_results')
- # pylint: disable=maybe-no-member
- index = int(self._get_args().get('index', 0))
-
- try:
- with open(os.path.join(task_log_dir,
- '{}.log'.format(task_id)), 'r') as log_file:
- log_file.seek(index)
- data = log_file.readlines()
- index = log_file.tell()
- except OSError as err:
- if err.errno == errno.ENOENT:
- return api_utils.result_handler(
- status=1, data='Log file does not exist')
-
- return api_utils.result_handler(
- status=1, data='Error with log file')
-
- return_data = {'data': data, 'index': index}
-
- switcher = {'IN PROGRESS': 0, 'FAIL': 1, 'FINISHED': 2}
-
- return api_utils.result_handler(status=switcher.get(task.status),
- data=return_data)
diff --git a/functest/api/resources/v1/testcases.py b/functest/api/resources/v1/testcases.py
deleted file mode 100644
index 2dbf97e4..00000000
--- a/functest/api/resources/v1/testcases.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Resources to handle testcase related requests
-"""
-
-import ConfigParser
-import logging
-import os
-import re
-import socket
-import uuid
-
-from flask import jsonify
-from flasgger.utils import swag_from
-import pkg_resources
-
-from functest.api.base import ApiResource
-from functest.api.common import api_utils, thread
-from functest.cli.commands.cli_testcase import Testcase
-from functest.api.database.v1.handlers import TasksHandler
-from functest.utils import config
-from functest.utils import env
-import functest.utils.functest_utils as ft_utils
-
-LOGGER = logging.getLogger(__name__)
-
-ADDRESS = socket.gethostbyname(socket.gethostname())
-ENDPOINT_TESTCASES = ('http://{}:5000/api/v1/functest/testcases'
- .format(ADDRESS))
-
-
-class V1Testcases(ApiResource):
- """ V1Testcases Resource class"""
-
- @swag_from(pkg_resources.resource_filename(
- 'functest', 'api/swagger/testcases.yaml'))
- def get(self): # pylint: disable=no-self-use
- """ GET all testcases """
- testcases_list = Testcase().list()
- result = {'testcases': re.split(' |\n ', testcases_list)[1:]}
- return jsonify(result)
-
-
-class V1Testcase(ApiResource):
- """ V1Testcase Resource class"""
-
- @swag_from(
- pkg_resources.resource_filename('functest',
- 'api/swagger/testcase.yaml'),
- endpoint='{0}/<testcase_name>'.format(ENDPOINT_TESTCASES))
- def get(self, testcase_name): # pylint: disable=no-self-use
- """ GET the info of one testcase"""
- testcase = Testcase().show(testcase_name)
- if not testcase:
- return api_utils.result_handler(
- status=1,
- data="The test case '%s' does not exist or is not supported"
- % testcase_name)
-
- testcase_info = api_utils.change_obj_to_dict(testcase)
- dependency_dict = api_utils.change_obj_to_dict(
- testcase_info.get('dependency'))
- testcase_info.pop('name')
- testcase_info.pop('dependency')
- result = {'testcase': testcase_name}
- result.update(testcase_info)
- result.update({'dependency': dependency_dict})
- return jsonify(result)
-
- @swag_from(
- pkg_resources.resource_filename('functest',
- 'api/swagger/testcase_run.yaml'),
- endpoint='{0}/action'.format(ENDPOINT_TESTCASES))
- def post(self):
- """ Used to handle post request """
- return self._dispatch_post()
-
- def run_test_case(self, args):
- """ Run a testcase """
- try:
- case_name = args['testcase']
- except KeyError:
- return api_utils.result_handler(
- status=1, data='testcase name must be provided')
-
- testcase = Testcase().show(case_name)
- if not testcase:
- return api_utils.result_handler(
- status=1,
- data="The test case '%s' does not exist or is not supported"
- % case_name)
-
- task_id = str(uuid.uuid4())
-
- task_args = {'testcase': case_name, 'task_id': task_id}
-
- task_args.update(args.get('opts', {}))
-
- task_thread = thread.TaskThread(self._run, task_args, TasksHandler())
- task_thread.start()
-
- result = {'testcase': case_name, 'task_id': task_id}
- return jsonify({'result': result})
-
- def _run(self, args): # pylint: disable=no-self-use
- """ The built_in function to run a test case """
-
- case_name = args.get('testcase')
- self._update_logging_ini(args.get('task_id'))
-
- try:
- cmd = "run_tests -t {}".format(case_name)
- runner = ft_utils.execute_command(cmd)
- except Exception: # pylint: disable=broad-except
- result = 'FAIL'
- LOGGER.exception("Running test case %s failed!", case_name)
- if runner == os.EX_OK:
- result = 'PASS'
- else:
- result = 'FAIL'
-
- env_info = {
- 'installer': env.get('INSTALLER_TYPE'),
- 'scenario': env.get('DEPLOY_SCENARIO'),
- 'build_tag': env.get('BUILD_TAG'),
- 'ci_loop': env.get('CI_LOOP')
- }
- result = {
- 'task_id': args.get('task_id'),
- 'testcase': case_name,
- 'env_info': env_info,
- 'result': result
- }
-
- return {'result': result}
-
- def _update_logging_ini(self, task_id): # pylint: disable=no-self-use
- """ Update the log file for each task"""
- rconfig = ConfigParser.RawConfigParser()
- rconfig.read(
- pkg_resources.resource_filename('functest', 'ci/logging.ini'))
- log_path = os.path.join(getattr(config.CONF, 'dir_results'),
- '{}.log'.format(task_id))
- rconfig.set('handler_file', 'args', '("{}",)'.format(log_path))
-
- with open(
- pkg_resources.resource_filename(
- 'functest', 'ci/logging.ini'), 'wb') as configfile:
- rconfig.write(configfile)
diff --git a/functest/api/resources/v1/tiers.py b/functest/api/resources/v1/tiers.py
deleted file mode 100644
index 523df130..00000000
--- a/functest/api/resources/v1/tiers.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Resources to handle tier related requests
-"""
-
-import pkg_resources
-import re
-
-from flask import jsonify
-from flasgger.utils import swag_from
-
-from functest.api.base import ApiResource
-from functest.api.common import api_utils
-from functest.cli.commands.cli_tier import Tier
-
-
-class V1Tiers(ApiResource):
- """ V1Tiers Resource class """
-
- @swag_from(pkg_resources.resource_filename(
- 'functest', 'api/swagger/tiers.yaml'))
- def get(self):
- # pylint: disable=no-self-use
- """ GET all tiers """
- tiers_list = Tier().list()
- data = re.split("[\n\t]", tiers_list)
- data = [i.strip() for i in data if i != '']
- data_dict = dict()
- for i in range(len(data) / 2):
- one_data = {data[i * 2].lstrip('- ').rstrip(':'): data[i * 2 + 1]}
- if i == 0:
- data_dict = one_data
- else:
- data_dict.update(one_data)
- result = {'tiers': data_dict}
- return jsonify(result)
-
-
-class V1Tier(ApiResource):
- """ V1Tier Resource class """
-
- @swag_from(pkg_resources.resource_filename(
- 'functest', 'api/swagger/tier.yaml'))
- def get(self, tier_name): # pylint: disable=no-self-use
- """ GET the info of one tier """
- tier_info = Tier().show(tier_name)
- if not tier_info:
- return api_utils.result_handler(
- status=1,
- data="The tier with name '%s' does not exist." % tier_name)
- tier_info.__dict__.pop('name')
- tier_info.__dict__.pop('tests_array')
- tier_info.__dict__.pop('skipped_tests_array')
- testcases = Tier().gettests(tier_name)
- result = {'tier': tier_name, 'testcases': testcases}
- result.update(tier_info.__dict__)
- return jsonify(result)
-
-
-class V1TestcasesinTier(ApiResource):
- """ V1TestcasesinTier Resource class """
-
- @swag_from(pkg_resources.resource_filename(
- 'functest', 'api/swagger/testcases_in_tier.yaml'))
- def get(self, tier_name): # pylint: disable=no-self-use
- """ GET all testcases within given tier """
- tier_info = Tier().show(tier_name)
- if not tier_info:
- return api_utils.result_handler(
- status=1,
- data="The tier with name '%s' does not exist." % tier_name)
- testcases = Tier().gettests(tier_name)
- result = {'tier': tier_name, 'testcases': testcases}
- return jsonify(result)
diff --git a/functest/api/server.py b/functest/api/server.py
deleted file mode 100644
index 3200c1a2..00000000
--- a/functest/api/server.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Used to launch Functest RestApi
-
-"""
-
-import inspect
-import logging
-import socket
-from urlparse import urljoin
-import pkg_resources
-
-from flask import Flask
-from flask_restful import Api
-from flasgger import Swagger
-
-from functest.api.base import ApiResource
-from functest.api.common import api_utils
-from functest.api.database.db import BASE
-from functest.api.database.db import DB_SESSION
-from functest.api.database.db import ENGINE
-from functest.api.database.v1 import models
-from functest.api.urls import URLPATTERNS
-
-
-LOGGER = logging.getLogger(__name__)
-
-APP = Flask(__name__)
-API = Api(APP)
-Swagger(APP)
-
-
-@APP.teardown_request
-def shutdown_session(exception=None): # pylint: disable=unused-argument
- """
- To be called at the end of each request whether it is successful
- or an exception is raised
- """
- DB_SESSION.remove()
-
-
-def get_resource(resource_name):
- """ Obtain the required resource according to resource name """
- name = ''.join(resource_name.split('_'))
- return next((r for r in api_utils.itersubclasses(ApiResource)
- if r.__name__.lower() == name))
-
-
-def get_endpoint(url):
- """ Obtain the endpoint of url """
- address = socket.gethostbyname(socket.gethostname())
- return urljoin('http://{}:5000'.format(address), url)
-
-
-def api_add_resource():
- """
- The resource has multiple URLs and you can pass multiple URLs to the
- add_resource() method on the Api object. Each one will be routed to
- your Resource
- """
- for url_pattern in URLPATTERNS:
- try:
- API.add_resource(
- get_resource(url_pattern.target), url_pattern.url,
- endpoint=get_endpoint(url_pattern.url))
- except StopIteration:
- LOGGER.error('url resource not found: %s', url_pattern.url)
-
-
-def init_db():
- """
- Import all modules here that might define models so that
- they will be registered properly on the metadata, and then
- create a database
- """
- def func(subcls):
- """ To check the subclasses of BASE"""
- try:
- if issubclass(subcls[1], BASE):
- return True
- except TypeError:
- pass
- return False
- # pylint: disable=bad-builtin
- subclses = filter(func, inspect.getmembers(models, inspect.isclass))
- LOGGER.debug('Import models: %s', [subcls[1] for subcls in subclses])
- BASE.metadata.create_all(bind=ENGINE)
-
-
-def main():
- """Entry point"""
- logging.config.fileConfig(pkg_resources.resource_filename(
- 'functest', 'ci/logging.ini'))
- logging.captureWarnings(True)
- LOGGER.info('Starting Functest server')
- api_add_resource()
- init_db()
- APP.run(host='0.0.0.0')
diff --git a/functest/api/swagger/creds.yaml b/functest/api/swagger/creds.yaml
deleted file mode 100644
index eec7cb34..00000000
--- a/functest/api/swagger/creds.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
----
-Show credentials
-
-This api offers the interface to show credentials.
-The credentials dict will be returned.
----
-tags:
- - Creds
-definitions:
- Credentials:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Name'
- Name:
- type: dict
-responses:
- 200:
- description: Show credentials
- schema:
- $ref: '#/definitions/Credentials'
- examples:
- "OS_AUTH_URL": "https://192.16.1.222:5000/v3"
- "OS_AUTH_VERSION": "3"
- "OS_CACERT": "/home/opnfv/functest/conf/os_cacert"
- "OS_ENDPOINT_TYPE": "publicURL"
- "OS_IDENTITY_API_VERSION": "3"
- "OS_INTERFACE": "publicURL"
- "OS_NO_CACHE": "1"
- "OS_PASSWORD": "990232e0885da343ac805528522d"
- "OS_PROJECT_DOMAIN_NAME": "Default"
- "OS_PROJECT_NAME": "admin"
- "OS_REGION_NAME": "RegionOne"
- "OS_TENANT_NAME": "admin"
- "OS_USERNAME": "admin"
- "OS_USER_DOMAIN_NAME": "Default"
diff --git a/functest/api/swagger/creds_action.yaml b/functest/api/swagger/creds_action.yaml
deleted file mode 100644
index 7e7653bb..00000000
--- a/functest/api/swagger/creds_action.yaml
+++ /dev/null
@@ -1,56 +0,0 @@
----
-Update openrc
-
-This api offers the interface to Update openstack.creds.
----
-tags:
- - Creds
-parameters:
- - in: body
- name: body
- description: this is the input json dict
- schema:
- required:
- - action
- - args
- properties:
- action:
- type: string
- description: this is action for creds
- default: update_openrc
- args:
- schema:
- required:
- - openrc
- properties:
- openrc:
- type: string
- description: this is the test case name
- default:
- "OS_AUTH_URL": "http://192.16.1.222:5000/v3"
- "OS_ENDPOINT_TYPE": "publicURL"
- "OS_IDENTITY_API_VERSION": "3"
- "OS_INTERFACE": "publicURL"
- "OS_PASSWORD": "admn"
- "OS_PROJECT_DOMAIN_NAME": "Default"
- "OS_PROJECT_NAME": "admin"
- "OS_REGION_NAME": "RegionOne"
- "OS_TENANT_NAME": "admin"
- "OS_USERNAME": "admin"
- "OS_USER_DOMAIN_NAME": "Default"
-definitions:
- Credentials:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Name'
- Name:
- type: dict
-responses:
- 200:
- description: Update openrc
- schema:
- $ref: '#/definitions/Credentials'
- examples:
- 'status': 0
- 'result': 'Update openrc successfully'
diff --git a/functest/api/swagger/envs.yaml b/functest/api/swagger/envs.yaml
deleted file mode 100644
index 4ff50c86..00000000
--- a/functest/api/swagger/envs.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
----
-Show environment
-
-This api offers the interface to show environment.
-The environment dict will be returned.
----
-tags:
- - Envs
-definitions:
- Environment:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Name'
- Name:
- type: dict
-responses:
- 200:
- description: Show environment
- schema:
- $ref: '#/definitions/Environment'
- examples:
- "DEBUG FLAG": "false"
- "INSTALLER": "compass, 192.168.200.2"
- "POD": "unknown_pod"
- "SCENARIO": "os-nosdn-nofeature-noha"
- "STATUS": "ready"
diff --git a/functest/api/swagger/envs_action.yaml b/functest/api/swagger/envs_action.yaml
deleted file mode 100644
index 3ad6c880..00000000
--- a/functest/api/swagger/envs_action.yaml
+++ /dev/null
@@ -1,42 +0,0 @@
----
-Update hosts info
-
-This api offers the interface to update hosts info.
----
-tags:
- - Envs
-parameters:
- - in: body
- name: body
- description: this is the input json dict
- schema:
- required:
- - action
- - args
- properties:
- action:
- type: string
- description: this is action for envs
- default: update_hosts
- args:
- type: string
- description: Hosts info to be updated
- default:
- "identity.ac.dz.com": "8.20.11.22"
- "image.ac.dz.com": "8.20.11.22"
-definitions:
- Environment:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Name'
- Name:
- type: dict
-responses:
- 200:
- description: Update hosts info
- schema:
- $ref: '#/definitions/Environment'
- examples:
- 'status': 0
- 'result': 'Update hosts info successfully'
diff --git a/functest/api/swagger/task.yaml b/functest/api/swagger/task.yaml
deleted file mode 100644
index 3375b906..00000000
--- a/functest/api/swagger/task.yaml
+++ /dev/null
@@ -1,37 +0,0 @@
----
-Get the result of the specified task
-
-This api offers the interface to get the result of the specified task.
----
-tags:
- - Tasks
-parameters:
- - name: task_id
- description: task id
- in: path
- type: string
- required: true
-definitions:
- Task:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Result'
- Result:
- type: dict
-responses:
- 200:
- description: Get the result of the specified task
- schema:
- $ref: '#/definitions/Task'
- examples:
- "result": {
- "case_name": "vping_ssh",
- "env_info": {
- "build_tag": null,
- "ci_loop": "weekly",
- "installer": "compass",
- "scenario": "os-nosdn-nofeature-noha"},
- "result": "PASS",
- "task_id": "1a9f3c5d-ce0b-4354-862e-dd08b26fc484"}
- "status": 2
diff --git a/functest/api/swagger/task_log.yaml b/functest/api/swagger/task_log.yaml
deleted file mode 100644
index 120a8f6f..00000000
--- a/functest/api/swagger/task_log.yaml
+++ /dev/null
@@ -1,37 +0,0 @@
----
-Get the log of the specified task
-
-This api offers the interface to get the log of the specified task.
----
-tags:
- - Tasks
-parameters:
- - name: task_id
- description: task id
- in: path
- type: string
- required: true
-definitions:
- Task:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Result'
- Result:
- type: dict
-responses:
- 200:
- description: Get the log of the specified task
- schema:
- $ref: '#/definitions/Task'
- examples:
- "result": {
- "data": [
- "2017-09-14 06:46:26,106 - functest.ci.run_tests - DEBUG ",
- "- Sourcing the OpenStack RC file... ",
- "2017-09-14 06:46:26,107 - functest.ci.run_tests - DEBUG ",
- "- Test args: connection_check ",
- "2017-09-14 06:46:26,107 - functest.ci.run_tests - INFO ",
- "- Running test case 'connection_check'... ",
- "..."]}
- "status": 2
diff --git a/functest/api/swagger/testcase.yaml b/functest/api/swagger/testcase.yaml
deleted file mode 100644
index 34c13d21..00000000
--- a/functest/api/swagger/testcase.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
----
-Show the info of one testcase
-
-This api offers the interface to show the detailed info of one testcase.
-The info of one testcase will be returned.
----
-tags:
- - Testcases
-parameters:
- - name: testcase_name
- description: testcase name
- in: path
- type: string
- required: true
-definitions:
- Testcases:
- type: object
- properties:
- case_name:
- $ref: '#/definitions/Tests'
- Tests:
- type: dict
-responses:
- 200:
- description: Show the detailed info of one testcase
- schema:
- $ref: '#/definitions/Testcases'
- examples:
- "testcase": ""
- "blocking":
- "criteria":
- "dependency": {
- "installer": "",
- "scenario": ""}
- "description": ""
- "enabled":
diff --git a/functest/api/swagger/testcase_run.yaml b/functest/api/swagger/testcase_run.yaml
deleted file mode 100644
index 7b254c86..00000000
--- a/functest/api/swagger/testcase_run.yaml
+++ /dev/null
@@ -1,46 +0,0 @@
----
-Run a test case
-
-This api offers the interface to run a test case
----
-tags:
- - Testcases
-parameters:
- - in: body
- name: body
- description: this is the input json dict
- schema:
- required:
- - action
- - args
- properties:
- action:
- type: string
- description: this is action for creds
- default: run_test_case
- args:
- schema:
- required:
- - testcase
- properties:
- testcase:
- type: string
- description: this is the test case name
- default:
- vping_ssh
-definitions:
- Testcases:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Tests'
- Tests:
- type: dict
-responses:
- 200:
- description: Run a test case
- schema:
- $ref: '#/definitions/Testcases'
- examples:
- 'task_id': '94c8ec94-d873-466f-a205-bf592f31ff5b'
- 'testcase': 'vping_ssh'
diff --git a/functest/api/swagger/testcases.yaml b/functest/api/swagger/testcases.yaml
deleted file mode 100644
index 1dea2152..00000000
--- a/functest/api/swagger/testcases.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-List all test cases
-
-This api offers the interface to list all test cases
-The testcases list will be returned
----
-tags:
- - Testcases
-definitions:
- Testcases:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Tests'
- Tests:
- type: dict
-responses:
- 200:
- description: List all test cases
- schema:
- $ref: '#/definitions/Testcases'
- examples:
- "testcases": []
diff --git a/functest/api/swagger/testcases_in_tier.yaml b/functest/api/swagger/testcases_in_tier.yaml
deleted file mode 100644
index af195ceb..00000000
--- a/functest/api/swagger/testcases_in_tier.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
----
-List all testcases within given tier
-
-This api offers the interface to list all testcases within given tier.
-All testcases within given tier will be returned.
----
-tags:
- - Tiers
-parameters:
- - name: tier_name
- description: tier name
- in: path
- type: string
- required: true
-definitions:
- Testcases:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Tests'
- Tests:
- type: dict
-responses:
- 200:
- description: List all testcases within given tier
- schema:
- $ref: '#/definitions/Testcases'
- examples:
- "tier": ""
- "testcases": []
diff --git a/functest/api/swagger/tier.yaml b/functest/api/swagger/tier.yaml
deleted file mode 100644
index 250cddf7..00000000
--- a/functest/api/swagger/tier.yaml
+++ /dev/null
@@ -1,33 +0,0 @@
----
-Show the info of one tier
-
-This api offers the interface to show the detailed info of one tier.
-The info of one tier will be returned.
----
-tags:
- - Tiers
-parameters:
- - name: tier_name
- description: tier name
- in: path
- type: string
- required: true
-definitions:
- Tiers:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Name'
- Name:
- type: string
-responses:
- 200:
- description: Show the detailed info of one tier
- schema:
- $ref: '#/definitions/Tiers'
- examples:
- "tier": ""
- "ci_loop": ""
- "description": ""
- "order":
- "testcases": []
diff --git a/functest/api/swagger/tiers.yaml b/functest/api/swagger/tiers.yaml
deleted file mode 100644
index d42b2cd9..00000000
--- a/functest/api/swagger/tiers.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-List all tiers
-
-This api offers the interface to list all tiers.
-The tiers list will be returned.
----
-tags:
- - Tiers
-definitions:
- Tiers:
- type: object
- properties:
- creds_name:
- $ref: '#/definitions/Tier'
- Tier:
- type: dict
-responses:
- 200:
- description: List all tiers
- schema:
- $ref: '#/definitions/Tiers'
- examples:
- "tiers": ""
diff --git a/functest/api/urls.py b/functest/api/urls.py
deleted file mode 100644
index 10b7b293..00000000
--- a/functest/api/urls.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Define multiple URLs
-"""
-
-
-class Url(object): # pylint: disable=too-few-public-methods
- """ Url Class """
-
- def __init__(self, url, target):
- super(Url, self).__init__()
- self.url = url
- self.target = target
-
-
-URLPATTERNS = [
- # GET /api/v1/functest/envs => GET environment
- Url('/api/v1/functest/envs', 'v1_envs'),
-
- # POST /api/v1/functest/envs/action
- # {"action":"update_hosts", "args": {}} => Update hosts info
- Url('/api/v1/functest/envs/action', 'v1_envs'),
-
- # GET /api/v1/functest/openstack/credentials => GET credentials
- Url('/api/v1/functest/openstack/credentials', 'v1_creds'),
-
- # POST /api/v1/functest/openstack/action
- # {"action":"update_openrc", "args": {"openrc": {}}} => Update openrc
- Url('/api/v1/functest/openstack/action', 'v1_creds'),
-
- # GET /api/v1/functest/testcases => GET all testcases
- Url('/api/v1/functest/testcases', 'v1_test_cases'),
-
- # GET /api/v1/functest/testcases/<testcase_name>
- # => GET the info of one testcase
- Url('/api/v1/functest/testcases/<testcase_name>', 'v1_testcase'),
-
- # POST /api/v1/functest/testcases/action
- # {"action":"run_test_case", "args": {"opts": {}, "testcase": "vping_ssh"}}
- # => Run a testcase
- Url('/api/v1/functest/testcases/action', 'v1_testcase'),
-
- # GET /api/v1/functest/testcases => GET all tiers
- Url('/api/v1/functest/tiers', 'v1_tiers'),
-
- # GET /api/v1/functest/tiers/<tier_name>
- # => GET the info of one tier
- Url('/api/v1/functest/tiers/<tier_name>', 'v1_tier'),
-
- # GET /api/v1/functest/tiers/<tier_name>/testcases
- # => GET all testcases within given tier
- Url('/api/v1/functest/tiers/<tier_name>/testcases',
- 'v1_testcases_in_tier'),
-
- # GET /api/v1/functest/tasks/<task_id>
- # => GET the result of the task id
- Url('/api/v1/functest/tasks/<task_id>', 'v1_task'),
-
- # GET /api/v1/functest/tasks/<task_id>/log
- # => GET the log of the task
- Url('/api/v1/functest/tasks/<task_id>/log', 'v1_task_log')
-]