Split @content decorator

Decorator content does too many different actions, so
let's split it into 3 decorators: @handle_errors,
@validate and @serialize. We can skip calling @serialize
in many places, because those methods just raise some
http error.

Also I've changed return value of all handlers from
serialized json (string) to python's structures, lists
and dicts. So It's become possible to implement different
serializers and I've added support for YAML output.

Change-Id: Ia3da3bd809bcca923d53666eca54def78c995f65
Closes-Bug: #1606211
This commit is contained in:
Dmitry Guryanov 2016-08-22 11:46:32 +03:00
parent 279a6160bd
commit 6e31938a0f
32 changed files with 581 additions and 288 deletions

View File

@ -19,7 +19,8 @@ Handlers dealing with nodes assignment
"""
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.assignment import NodeAssignmentValidator
from nailgun.api.v1.validators.assignment import NodeUnassignmentValidator
@ -31,7 +32,8 @@ class NodeAssignmentHandler(BaseHandler):
"""Node assignment handler"""
validator = NodeAssignmentValidator
@content
@handle_errors
@validate
def POST(self, cluster_id):
""":returns: Empty string
@ -62,7 +64,8 @@ class NodeUnassignmentHandler(BaseHandler):
"""Node assignment handler"""
validator = NodeUnassignmentValidator
@content
@handle_errors
@validate
def POST(self, cluster_id):
""":returns: Empty string

View File

@ -15,12 +15,13 @@
# under the License.
from datetime import datetime
from decorator import decorator
from oslo_serialization import jsonutils
import six
import traceback
import yaml
from decorator import decorator
from distutils.version import StrictVersion
from oslo_serialization import jsonutils
from sqlalchemy import exc as sa_exc
import web
@ -31,7 +32,6 @@ from nailgun.api.v1.validators.orchestrator_graph import \
from nailgun import consts
from nailgun.db import db
from nailgun import errors
from nailgun.errors.base import NailgunException
from nailgun.logger import logger
from nailgun import objects
from nailgun.objects.serializers.base import BasicSerializer
@ -271,40 +271,25 @@ class BaseHandler(object):
else:
return default
@staticmethod
def get_requested_mime():
accept = web.ctx.env.get("HTTP_ACCEPT", "application/json")
accept = accept.strip().split(',')[0]
accept = accept.split(';')[0]
return accept
def content_json(func, cls, *args, **kwargs):
json_resp = lambda data: (
jsonutils.dumps(data)
if isinstance(data, (dict, list)) or data is None else data
)
request_validate_needed = True
def json_resp(data):
if isinstance(data, (dict, list)) or data is None:
return jsonutils.dumps(data)
else:
return data
resource_type = "single"
if issubclass(
cls.__class__,
CollectionHandler
) and not func.func_name == "POST":
resource_type = "collection"
if (
func.func_name in ("GET", "DELETE") or
getattr(cls.__class__, 'validator', None) is None or
resource_type == "single" and not cls.validator.single_schema or
resource_type == "collection" and not cls.validator.collection_schema
):
request_validate_needed = False
@decorator
def handle_errors(func, cls, *args, **kwargs):
try:
if request_validate_needed:
BaseHandler.checked_data(
cls.validator.validate_request,
resource_type=resource_type
)
resp = func(cls, *args, **kwargs)
except web.notmodified:
raise
return func(cls, *args, **kwargs)
except web.HTTPError as http_error:
if http_error.status_code != 204:
web.header('Content-Type', 'application/json', unique=True)
@ -316,7 +301,7 @@ def content_json(func, cls, *args, **kwargs):
else:
http_error.data = json_resp(http_error.data)
raise
except NailgunException as exc:
except errors.NailgunException as exc:
logger.exception('NailgunException occured')
http_error = BaseHandler.http(400, exc.message)
web.header('Content-Type', 'text/plain')
@ -336,62 +321,66 @@ def content_json(func, cls, *args, **kwargs):
web.header('Content-Type', 'text/plain')
raise http_error
web.header('Content-Type', 'application/json', unique=True)
return json_resp(resp)
@decorator
def validate(func, cls, *args, **kwargs):
request_validation_needed = True
resource_type = "single"
if issubclass(
cls.__class__,
CollectionHandler
) and not func.func_name == "POST":
resource_type = "collection"
if (
func.func_name in ("GET", "DELETE") or
getattr(cls.__class__, 'validator', None) is None or
(resource_type == "single" and not cls.validator.single_schema) or
(resource_type == "collection" and not cls.validator.collection_schema)
):
request_validation_needed = False
if request_validation_needed:
BaseHandler.checked_data(
cls.validator.validate_request,
resource_type=resource_type
)
return func(cls, *args, **kwargs)
def content(*args, **kwargs):
"""Set context-type of response based on Accept header
@decorator
def serialize(func, cls, *args, **kwargs):
"""Set context-type of response based on Accept header.
This decorator checks Accept header received from client
and returns corresponding wrapper (only JSON is currently
supported). It can be used as is:
@content
def GET(self):
...
Default behavior may be overriden by passing list of
exact mimetypes to decorator:
@content(["text/plain"])
@handle_errors
@validate
@serialize
def GET(self):
...
"""
# TODO(ikutukov): this decorator is not coherent and doing more
# than just a response mimetype setting via type-specific content_json
# method that perform validation.
# Before you start to implement handler business logic ensure that
# @content decorator not already doing what you are planning to write.
# I think that validation routine and common http headers formation not
# depending on each other and should be decoupled. At least they should
# not be under one decorator with abstract name.
accepted_types = (
"application/json",
"application/x-yaml",
"*/*"
)
accept = cls.get_requested_mime()
if accept not in accepted_types:
raise BaseHandler.http(415)
exact_mimetypes = None
if len(args) >= 1 and isinstance(args[0], list):
exact_mimetypes = args[0]
@decorator
def wrapper(func, *args, **kwargs):
accept = web.ctx.env.get("HTTP_ACCEPT", "application/json")
accepted_types = [
"application/json",
"*/*"
]
if exact_mimetypes and isinstance(exact_mimetypes, list):
accepted_types = exact_mimetypes
if any(map(lambda m: m in accept, accepted_types)):
return content_json(func, *args, **kwargs)
else:
raise BaseHandler.http(415)
# case of @content without arguments, meaning arg[0] to be callable
# handler
if len(args) >= 1 and callable(args[0]):
return wrapper(args[0], *args[1:], **kwargs)
# case of @content(["mimetype"]) with explicit arguments
return wrapper
resp = func(cls, *args, **kwargs)
if accept == 'application/x-yaml':
web.header('Content-Type', 'application/x-yaml', unique=True)
return yaml.dump(resp, default_flow_style=False)
else:
# default is json
web.header('Content-Type', 'application/json', unique=True)
return jsonutils.dumps(resp)
class SingleHandler(BaseHandler):
@ -399,7 +388,9 @@ class SingleHandler(BaseHandler):
single = None
validator = BasicValidator
@content
@handle_errors
@validate
@serialize
def GET(self, obj_id):
""":returns: JSONized REST object.
@ -407,9 +398,11 @@ class SingleHandler(BaseHandler):
* 404 (object not found in db)
"""
obj = self.get_object_or_404(self.single, obj_id)
return self.single.to_json(obj)
return self.single.to_dict(obj)
@content
@handle_errors
@validate
@serialize
def PUT(self, obj_id):
""":returns: JSONized REST object.
@ -423,9 +416,10 @@ class SingleHandler(BaseHandler):
instance=obj
)
self.single.update(obj, data)
return self.single.to_json(obj)
return self.single.to_dict(obj)
@content
@handle_errors
@validate
def DELETE(self, obj_id):
""":returns: Empty string
@ -452,16 +446,19 @@ class CollectionHandler(BaseHandler):
validator = BasicValidator
eager = ()
@content
@handle_errors
@validate
@serialize
def GET(self):
""":returns: Collection of JSONized REST objects.
:http: * 200 (OK)
"""
q = self.collection.eager(None, self.eager)
return self.collection.to_json(q)
return self.collection.to_list(q)
@content
@handle_errors
@validate
def POST(self):
""":returns: JSONized REST object.
@ -495,7 +492,9 @@ class DBSingletonHandler(BaseHandler):
return instance
@content
@handle_errors
@validate
@serialize
def GET(self):
"""Get singleton object from DB
@ -504,9 +503,11 @@ class DBSingletonHandler(BaseHandler):
"""
instance = self.get_one_or_404()
return self.single.to_json(instance)
return self.single.to_dict(instance)
@content
@handle_errors
@validate
@serialize
def PUT(self):
"""Change object in DB
@ -520,9 +521,11 @@ class DBSingletonHandler(BaseHandler):
self.single.update(instance, data)
return self.single.to_json(instance)
return self.single.to_dict(instance)
@content
@handle_errors
@validate
@serialize
def PATCH(self):
"""Update object
@ -538,7 +541,7 @@ class DBSingletonHandler(BaseHandler):
self.single.serializer.serialize(instance), data
))
return self.single.to_json(instance)
return self.single.to_dict(instance)
# TODO(enchantner): rewrite more handlers to inherit from this
@ -557,7 +560,8 @@ class DeferredTaskHandler(BaseHandler):
def get_options(cls):
return {}
@content
@handle_errors
@validate
def PUT(self, cluster_id):
""":returns: JSONized Task object.
@ -618,7 +622,9 @@ class OrchestratorDeploymentTasksHandler(SingleHandler):
validator = GraphSolverTasksValidator
@content
@handle_errors
@validate
@serialize
def GET(self, obj_id):
""":returns: Deployment tasks
@ -654,7 +660,9 @@ class OrchestratorDeploymentTasksHandler(SingleHandler):
'name.'.format(e.task_name))
return tasks
@content
@handle_errors
@validate
@serialize
def PUT(self, obj_id):
""":returns: Deployment tasks

View File

@ -26,7 +26,9 @@ import web
from nailgun import objects
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.task.manager import GenerateCapacityLogTaskManager
@ -78,14 +80,17 @@ class CapacityLogHandler(BaseHandler):
"report"
)
@content
@handle_errors
@validate
@serialize
def GET(self):
capacity_log = objects.CapacityLog.get_latest()
if not capacity_log:
raise self.http(404)
return self.render(capacity_log)
@content
@handle_errors
@validate
def PUT(self):
"""Starts capacity data generation.

View File

@ -23,10 +23,12 @@ import web
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import CollectionHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import DeferredTaskHandler
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import OrchestratorDeploymentTasksHandler
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import SingleHandler
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.handlers.deployment_graph import \
RelatedDeploymentGraphCollectionHandler
from nailgun.api.v1.handlers.deployment_graph import \
@ -55,7 +57,9 @@ class ClusterHandler(SingleHandler):
single = objects.Cluster
validator = ClusterValidator
@content
@handle_errors
@validate
@serialize
def PUT(self, obj_id):
""":returns: JSONized Cluster object.
@ -79,9 +83,10 @@ class ClusterHandler(SingleHandler):
except errors.NetworkTemplateCannotBeApplied as exc:
raise self.http(400, exc.message)
return self.single.to_json(obj)
return self.single.to_dict(obj)
@content
@handle_errors
@validate
def DELETE(self, obj_id):
""":returns: {}
@ -174,7 +179,9 @@ class ClusterAttributesHandler(BaseHandler):
validator = ClusterAttributesValidator
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized Cluster attributes.
@ -206,7 +213,9 @@ class ClusterAttributesHandler(BaseHandler):
# entity and PATCH method for changing its parts.
return self.PATCH(cluster_id)
@content
@handle_errors
@validate
@serialize
def PATCH(self, cluster_id):
""":returns: JSONized Cluster attributes.
@ -239,7 +248,9 @@ class ClusterAttributesDefaultsHandler(BaseHandler):
"editable",
)
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized default Cluster attributes.
@ -253,7 +264,9 @@ class ClusterAttributesDefaultsHandler(BaseHandler):
raise self.http(500, "No attributes found!")
return {"editable": attrs}
@content
@handle_errors
@validate
@serialize
def PUT(self, cluster_id):
""":returns: JSONized Cluster attributes.
@ -290,7 +303,9 @@ class ClusterAttributesDefaultsHandler(BaseHandler):
class ClusterAttributesDeployedHandler(BaseHandler):
"""Cluster deployed attributes handler"""
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized deployed Cluster editable attributes with plugins
@ -312,7 +327,9 @@ class ClusterAttributesDeployedHandler(BaseHandler):
class ClusterGeneratedData(BaseHandler):
"""Cluster generated data"""
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized cluster generated data
@ -333,7 +350,9 @@ class ClusterPluginsDeploymentTasksHandler(BaseHandler):
"""Handler for cluster plugins merged deployment tasks serialization."""
single = objects.Cluster
@content
@handle_errors
@validate
@serialize
def GET(self, obj_id):
""":returns: Deployment tasks
@ -351,7 +370,9 @@ class ClusterReleaseDeploymentTasksHandler(BaseHandler):
"""Handler for cluster release deployment tasks serialization."""
single = objects.Cluster
@content
@handle_errors
@validate
@serialize
def GET(self, obj_id):
""":returns: Deployment tasks
@ -374,7 +395,9 @@ class VmwareAttributesHandler(BaseHandler):
validator = VmwareAttributesValidator
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized Cluster vmware attributes.
@ -401,7 +424,9 @@ class VmwareAttributesHandler(BaseHandler):
return self.render(attributes)
@content
@handle_errors
@validate
@serialize
def PUT(self, cluster_id):
""":returns: JSONized Cluster vmware attributes.
@ -442,7 +467,9 @@ class VmwareAttributesHandler(BaseHandler):
class VmwareAttributesDefaultsHandler(BaseHandler):
"""Vmware default attributes handler"""
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized default Cluster vmware attributes.

View File

@ -15,7 +15,9 @@
# under the License.
from nailgun.api.v1.handlers import base
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators import cluster_plugin_link
from nailgun import errors
from nailgun import objects
@ -26,6 +28,9 @@ class ClusterPluginLinkHandler(base.SingleHandler):
validator = cluster_plugin_link.ClusterPluginLinkValidator
single = objects.ClusterPluginLink
@handle_errors
@validate
@serialize
def GET(self, cluster_id, obj_id):
""":returns: JSONized REST object.
@ -35,9 +40,11 @@ class ClusterPluginLinkHandler(base.SingleHandler):
self.get_object_or_404(objects.Cluster, cluster_id)
obj = self.get_object_or_404(self.single, obj_id)
return self.single.to_json(obj)
return self.single.to_dict(obj)
@content
@handle_errors
@validate
@serialize
def PUT(self, cluster_id, obj_id):
""":returns: JSONized REST object.
@ -51,7 +58,7 @@ class ClusterPluginLinkHandler(base.SingleHandler):
instance=obj
)
self.single.update(obj, data)
return self.single.to_json(obj)
return self.single.to_dict(obj)
def PATCH(self, cluster_id, obj_id):
""":returns: JSONized REST object.
@ -62,7 +69,8 @@ class ClusterPluginLinkHandler(base.SingleHandler):
"""
return self.PUT(cluster_id, obj_id)
@content
@handle_errors
@validate
def DELETE(self, cluster_id, obj_id):
""":returns: JSONized REST object.
@ -79,7 +87,9 @@ class ClusterPluginLinkCollectionHandler(base.CollectionHandler):
collection = objects.ClusterPluginLinkCollection
validator = cluster_plugin_link.ClusterPluginLinkValidator
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: Collection of JSONized ClusterPluginLink objects.
@ -87,11 +97,12 @@ class ClusterPluginLinkCollectionHandler(base.CollectionHandler):
* 404 (cluster not found in db)
"""
self.get_object_or_404(objects.Cluster, cluster_id)
return self.collection.to_json(
return self.collection.to_list(
self.collection.get_by_cluster_id(cluster_id)
)
@content
@handle_errors
@validate
def POST(self, cluster_id):
""":returns: JSONized REST object.

View File

@ -14,15 +14,20 @@
# License for the specific language governing permissions and limitations
# under the License.
from nailgun.api.v1.handlers import base
from nailgun.api.v1.handlers.base import CollectionHandler
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.objects import Release
from nailgun.objects.serializers.release import ComponentSerializer
class ComponentCollectionHandler(base.CollectionHandler):
class ComponentCollectionHandler(CollectionHandler):
"""Component collection handler"""
@base.content
@handle_errors
@validate
@serialize
def GET(self, release_id):
""":returns: JSONized component data for release and releated plugins.

View File

@ -16,8 +16,10 @@
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import CollectionHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import SingleHandler
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators import deployment_graph as validators
from nailgun import errors
@ -35,7 +37,9 @@ class RelatedDeploymentGraphHandler(SingleHandler):
single = objects.DeploymentGraph
related = None # related should be substituted during handler inheritance
@content
@handle_errors
@validate
@serialize
def GET(self, obj_id, graph_type=None):
"""Get deployment graph.
@ -54,12 +58,14 @@ class RelatedDeploymentGraphHandler(SingleHandler):
obj = self.get_object_or_404(self.related, int(obj_id))
deployment_graph = self.single.get_for_model(obj, graph_type)
if deployment_graph:
return self.single.to_json(deployment_graph)
return self.single.to_dict(deployment_graph)
else:
raise self.http(404, "Graph with type: {0} is not defined".format(
graph_type))
@content
@handle_errors
@validate
@serialize
def POST(self, obj_id, graph_type=None):
"""Create deployment graph.
@ -85,9 +91,11 @@ class RelatedDeploymentGraphHandler(SingleHandler):
else:
deployment_graph = self.single.create_for_model(
data, obj, graph_type=graph_type)
return self.single.to_json(deployment_graph)
return self.single.to_dict(deployment_graph)
@content
@handle_errors
@validate
@serialize
def PUT(self, obj_id, graph_type=None):
"""Update deployment graph.
@ -109,12 +117,14 @@ class RelatedDeploymentGraphHandler(SingleHandler):
deployment_graph = self.single.get_for_model(obj, graph_type)
if deployment_graph:
self.single.update(deployment_graph, data)
return self.single.to_json(deployment_graph)
return self.single.to_dict(deployment_graph)
else:
raise self.http(404, "Graph with type: {0} is not defined".format(
graph_type))
@content
@handle_errors
@validate
@serialize
def PATCH(self, obj_id, graph_type=None):
"""Update deployment graph.
@ -132,6 +142,8 @@ class RelatedDeploymentGraphHandler(SingleHandler):
"""
return self.PUT(obj_id, graph_type)
@handle_errors
@validate
def DELETE(self, obj_id, graph_type=None):
"""Delete deployment graph.
@ -161,7 +173,9 @@ class RelatedDeploymentGraphCollectionHandler(CollectionHandler):
collection = objects.DeploymentGraphCollection
related = None # related should be substituted during handler inheritance
@content
@handle_errors
@validate
@serialize
def GET(self, obj_id):
"""Get deployment graphs list for given object.
@ -176,7 +190,7 @@ class RelatedDeploymentGraphCollectionHandler(CollectionHandler):
"""
related_model = self.get_object_or_404(self.related, int(obj_id))
graphs = self.collection.get_for_model(related_model)
return self.collection.to_json(graphs)
return self.collection.to_list(graphs)
class DeploymentGraphHandler(SingleHandler):
@ -185,7 +199,8 @@ class DeploymentGraphHandler(SingleHandler):
validator = validators.DeploymentGraphValidator
single = objects.DeploymentGraph
@content
@handle_errors
@validate
def DELETE(self, obj_id):
"""Delete deployment graph.
@ -196,7 +211,6 @@ class DeploymentGraphHandler(SingleHandler):
self.single.delete(d_e)
raise self.http(204)
@content
def PATCH(self, obj_id):
return self.PUT(obj_id)
@ -210,7 +224,8 @@ class GraphsExecutorHandler(BaseHandler):
validator = validators.GraphExecuteParamsValidator
@content
@handle_errors
@validate
def POST(self):
""":returns: JSONized Task object.

View File

@ -15,7 +15,9 @@
# under the License.
from nailgun.api.v1.handlers import base
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.deployment_history import \
DeploymentHistoryValidator
from nailgun import errors
@ -27,7 +29,9 @@ class DeploymentHistoryCollectionHandler(base.CollectionHandler):
collection = objects.DeploymentHistoryCollection
validator = DeploymentHistoryValidator
@content
@handle_errors
@validate
@serialize
def GET(self, transaction_id):
""":returns: Collection of JSONized DeploymentHistory records.

View File

@ -32,7 +32,9 @@ from nailgun import consts
from nailgun import objects
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.settings import settings
from nailgun.task.manager import DumpTaskManager
from nailgun.task.task import DumpTask
@ -195,7 +197,9 @@ def read_log(
class LogEntryCollectionHandler(BaseHandler):
"""Log entry collection handler"""
@content
@handle_errors
@validate
@serialize
def GET(self):
"""Receives following parameters:
@ -382,7 +386,8 @@ class LogEntryCollectionHandler(BaseHandler):
class LogPackageHandler(BaseHandler):
"""Log package handler"""
@content
@handle_errors
@validate
def PUT(self):
""":returns: JSONized Task object.
@ -404,7 +409,9 @@ class LogPackageHandler(BaseHandler):
class LogPackageDefaultConfig(BaseHandler):
@content
@handle_errors
@validate
@serialize
def GET(self):
"""Generates default config for snapshot
@ -416,7 +423,7 @@ class LogPackageDefaultConfig(BaseHandler):
class LogSourceCollectionHandler(BaseHandler):
"""Log source collection handler"""
@content
@serialize
def GET(self):
""":returns: Collection of log sources (from settings)
@ -443,7 +450,9 @@ class SnapshotDownloadHandler(BaseHandler):
class LogSourceByNodeCollectionHandler(BaseHandler):
"""Log source by node collection handler"""
@content
@handle_errors
@validate
@serialize
def GET(self, node_id):
""":returns: Collection of log sources by node (from settings)

View File

@ -14,8 +14,9 @@
from oslo_serialization import jsonutils
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import DBSingletonHandler
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.master_node_settings \
import MasterNodeSettingsValidator
from nailgun.logger import logger
@ -71,12 +72,14 @@ class MasterNodeSettingsHandler(DBSingletonHandler):
self._handle_stats_opt_in(settings_data=jsonutils.loads(result))
return result
@content
@handle_errors
@validate
def PUT(self):
return self._perform_update(
super(MasterNodeSettingsHandler, self).PUT)
@content
@handle_errors
@validate
def PATCH(self):
return self._perform_update(
super(MasterNodeSettingsHandler, self).PATCH)

View File

@ -24,8 +24,10 @@ import web
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import CollectionHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import SingleHandler
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators import node as node_validators
from nailgun import errors
@ -44,7 +46,9 @@ class NodeHandler(SingleHandler):
single = objects.Node
validator = node_validators.NodeValidator
@content
@handle_errors
@validate
@serialize
def PUT(self, obj_id):
""":returns: JSONized Node object.
@ -69,9 +73,10 @@ class NodeHandler(SingleHandler):
except errors.NetworkTemplateCannotBeApplied as exc:
raise self.http(400, exc.message)
return self.single.to_json(obj)
return self.single.to_dict(obj)
@content
@handle_errors
@validate
def DELETE(self, obj_id):
"""Deletes a node from DB and from Cobbler.
@ -100,7 +105,9 @@ class NodeCollectionHandler(CollectionHandler):
validator = node_validators.NodeValidator
collection = objects.NodeCollection
@content
@handle_errors
@validate
@serialize
def GET(self):
"""May receive cluster_id parameter to filter list of nodes
@ -115,9 +122,11 @@ class NodeCollectionHandler(CollectionHandler):
elif cluster_id:
nodes = nodes.filter_by(cluster_id=cluster_id)
return self.collection.to_json(nodes)
return self.collection.to_list(nodes)
@content
@handle_errors
@validate
@serialize
def PUT(self):
""":returns: Collection of JSONized Node objects.
@ -147,9 +156,10 @@ class NodeCollectionHandler(CollectionHandler):
self.collection.eager_nodes_handlers(None),
nodes_updated
)
return self.collection.to_json(nodes)
return self.collection.to_list(nodes)
@content
@handle_errors
@validate
def DELETE(self):
"""Deletes a batch of nodes.
@ -188,7 +198,9 @@ class NodeAgentHandler(BaseHandler):
collection = objects.NodeCollection
validator = node_validators.NodeValidator
@content
@handle_errors
@validate
@serialize
def PUT(self):
""":returns: node id.
@ -227,7 +239,9 @@ class NodeAgentHandler(BaseHandler):
class NodesAllocationStatsHandler(BaseHandler):
"""Node allocation stats handler"""
@content
@handle_errors
@validate
@serialize
def GET(self):
""":returns: Total and unallocated nodes count.
@ -245,7 +259,9 @@ class NodeAttributesHandler(BaseHandler):
validator = node_validators.NodeAttributesValidator
@content
@handle_errors
@validate
@serialize
def GET(self, node_id):
""":returns: JSONized Node attributes.
@ -256,7 +272,9 @@ class NodeAttributesHandler(BaseHandler):
return objects.Node.get_attributes(node)
@content
@handle_errors
@validate
@serialize
def PUT(self, node_id):
""":returns: JSONized Node attributes.

View File

@ -21,9 +21,10 @@ Handlers dealing with node groups
import web
from nailgun.api.v1.handlers.base import CollectionHandler
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import SingleHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.node_group import NodeGroupValidator
from nailgun import errors
@ -35,7 +36,8 @@ class NodeGroupHandler(SingleHandler):
single = objects.NodeGroup
validator = NodeGroupValidator
@content
@handle_errors
@validate
def DELETE(self, group_id):
""":returns: {}
@ -67,7 +69,9 @@ class NodeGroupCollectionHandler(CollectionHandler):
collection = objects.NodeGroupCollection
validator = NodeGroupValidator
@content
@handle_errors
@validate
@serialize
def GET(self):
"""May receive cluster_id parameter to filter list of groups
@ -78,10 +82,10 @@ class NodeGroupCollectionHandler(CollectionHandler):
user_data = web.input(cluster_id=None)
if user_data.cluster_id is not None:
return self.collection.to_json(
return self.collection.to_list(
self.collection.get_by_cluster_id(
user_data.cluster_id
)
)
else:
return self.collection.to_json()
return self.collection.to_list()

View File

@ -24,7 +24,9 @@ from nailgun.api.v1.handlers.base import SingleHandler
from nailgun import objects
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.notification import NotificationValidator
@ -40,7 +42,9 @@ class NotificationCollectionHandler(CollectionHandler):
collection = objects.NotificationCollection
validator = NotificationValidator
@content
@handle_errors
@validate
@serialize
def PUT(self):
""":returns: Collection of JSONized Notification objects.
@ -54,4 +58,4 @@ class NotificationCollectionHandler(CollectionHandler):
notif = self.collection.single.get_by_uid(nd["id"])
self.collection.single.update(notif, nd)
notifications_updated.append(notif)
return self.collection.to_json(notifications_updated)
return self.collection.to_list(notifications_updated)

View File

@ -18,8 +18,10 @@ import six
import web
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import SingleHandler
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.openstack_config import OpenstackConfigValidator
from nailgun import errors
from nailgun.logger import logger
@ -31,7 +33,9 @@ class OpenstackConfigCollectionHandler(BaseHandler):
validator = OpenstackConfigValidator
@content
@handle_errors
@validate
@serialize
def GET(self):
"""Returns list of filtered config objects.
@ -48,7 +52,8 @@ class OpenstackConfigCollectionHandler(BaseHandler):
configs, 'node_id', node_ids)
return objects.OpenstackConfigCollection.to_list(configs)
@content
@handle_errors
@validate
def POST(self):
"""Creates new config object.
@ -72,7 +77,8 @@ class OpenstackConfigHandler(SingleHandler):
single = objects.OpenstackConfig
validator = OpenstackConfigValidator
@content
@handle_errors
@validate
def PUT(self, obj_id):
"""Update an existing configuration is not allowed
@ -80,7 +86,8 @@ class OpenstackConfigHandler(SingleHandler):
"""
raise self.http(405)
@content
@handle_errors
@validate
def DELETE(self, obj_id):
""":returns: Empty string
@ -111,7 +118,8 @@ class OpenstackConfigExecuteHandler(BaseHandler):
validator = OpenstackConfigValidator
task_manager = OpenstackConfigTaskManager
@content
@handle_errors
@validate
def PUT(self):
"""Executes update tasks for specified resources.

View File

@ -20,7 +20,9 @@ import six
import web
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.cluster import ProvisionSelectedNodesValidator
from nailgun.api.v1.validators.node import DeploySelectedNodesValidator
from nailgun.api.v1.validators.node import NodeDeploymentValidator
@ -79,7 +81,9 @@ class DefaultOrchestratorInfo(NodesFilterMixin, BaseHandler):
Need to redefine serializer variable
"""
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized default data which will be passed to orchestrator
@ -110,7 +114,9 @@ class OrchestratorInfo(BaseHandler):
"""Method should override data which will be passed to orchestrator"""
raise NotImplementedError('Please Implement this method')
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized data which will be passed to orchestrator
@ -120,7 +126,9 @@ class OrchestratorInfo(BaseHandler):
cluster = self.get_object_or_404(objects.Cluster, cluster_id)
return self.get_orchestrator_info(cluster)
@content
@handle_errors
@validate
@serialize
def PUT(self, cluster_id):
""":returns: JSONized data which will be passed to orchestrator
@ -136,7 +144,8 @@ class OrchestratorInfo(BaseHandler):
.format(cluster_id))
return data
@content
@handle_errors
@validate
def DELETE(self, cluster_id):
""":returns: {}
@ -235,7 +244,8 @@ class SelectedNodesBase(NodesFilterMixin, BaseHandler):
self.raise_task(task)
@content
@handle_errors
@validate
def PUT(self, cluster_id):
""":returns: JSONized Task object.
@ -257,7 +267,8 @@ class ProvisionSelectedNodes(SelectedNodesBase):
def get_default_nodes(self, cluster):
return TaskHelper.nodes_to_provision(cluster)
@content
@handle_errors
@validate
def PUT(self, cluster_id):
""":returns: JSONized Task object.
@ -303,7 +314,8 @@ class BaseDeploySelectedNodes(SelectedNodesBase):
class DeploySelectedNodes(BaseDeploySelectedNodes, DryRunMixin):
"""Handler for deployment selected nodes."""
@content
@handle_errors
@validate
def PUT(self, cluster_id):
""":returns: JSONized Task object.
@ -324,7 +336,8 @@ class DeploySelectedNodesWithTasks(BaseDeploySelectedNodes, DryRunMixin):
validator = NodeDeploymentValidator
@content
@handle_errors
@validate
def PUT(self, cluster_id):
""":returns: JSONized Task object.
@ -353,6 +366,8 @@ class TaskDeployGraph(BaseHandler):
validator = GraphSolverVisualizationValidator
@handle_errors
@validate
def GET(self, cluster_id):
""":returns: DOT representation of deployment graph.
@ -407,7 +422,9 @@ class SerializedTasksHandler(NodesFilterMixin, BaseHandler):
return objects.Cluster.get_nodes_not_for_deletion(cluster).all()
return TaskHelper.nodes_to_deploy(cluster)
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: serialized tasks in json format

View File

@ -17,7 +17,8 @@
import six
from nailgun.api.v1.handlers import base
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.handlers.deployment_graph import \
RelatedDeploymentGraphCollectionHandler
from nailgun.api.v1.handlers.deployment_graph import \
@ -39,7 +40,8 @@ class PluginCollectionHandler(base.CollectionHandler):
collection = objects.PluginCollection
validator = plugin.PluginValidator
@content
@handle_errors
@validate
def POST(self):
""":returns: JSONized REST object.
@ -59,7 +61,8 @@ class PluginSyncHandler(base.BaseHandler):
validator = plugin.PluginSyncValidator
@content
@handle_errors
@validate
def POST(self):
""":returns: JSONized REST object.

View File

@ -15,7 +15,9 @@
# under the License.
from nailgun.api.v1.handlers import base
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators import plugin_link
from nailgun import errors
from nailgun import objects
@ -36,6 +38,9 @@ class PluginLinkHandler(base.SingleHandler):
"Plugin with id {0} not found".format(plugin_id)
)
@handle_errors
@validate
@serialize
def GET(self, plugin_id, obj_id):
""":returns: JSONized REST object.
@ -43,9 +48,11 @@ class PluginLinkHandler(base.SingleHandler):
* 404 (dashboard entry not found in db)
"""
obj = self._get_plugin_link_object(plugin_id, obj_id)
return self.single.to_json(obj)
return self.single.to_dict(obj)
@content
@handle_errors
@validate
@serialize
def PUT(self, plugin_id, obj_id):
""":returns: JSONized REST object.
@ -58,7 +65,7 @@ class PluginLinkHandler(base.SingleHandler):
self.validator.validate_update,
instance=obj)
self.single.update(obj, data)
return self.single.to_json(obj)
return self.single.to_dict(obj)
def PATCH(self, plugin_id, obj_id):
""":returns: JSONized REST object.
@ -69,7 +76,8 @@ class PluginLinkHandler(base.SingleHandler):
"""
return self.PUT(plugin_id, obj_id)
@content
@handle_errors
@validate
def DELETE(self, plugin_id, obj_id):
""":returns: JSONized REST object.
@ -86,7 +94,8 @@ class PluginLinkCollectionHandler(base.CollectionHandler):
collection = objects.PluginLinkCollection
validator = plugin_link.PluginLinkValidator
@content
@handle_errors
@validate
def GET(self, plugin_id):
""":returns: Collection of JSONized PluginLink objects.
@ -94,11 +103,12 @@ class PluginLinkCollectionHandler(base.CollectionHandler):
* 404 (plugin not found in db)
"""
self.get_object_or_404(objects.Plugin, plugin_id)
return self.collection.to_json(
return self.collection.to_list(
self.collection.get_by_plugin_id(plugin_id)
)
@content
@handle_errors
@validate
def POST(self, plugin_id):
""":returns: JSONized REST object.

View File

@ -19,9 +19,11 @@ Handlers dealing with releases
"""
from nailgun.api.v1.handlers.base import CollectionHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import OrchestratorDeploymentTasksHandler
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import SingleHandler
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.handlers.deployment_graph import \
RelatedDeploymentGraphCollectionHandler
from nailgun.api.v1.handlers.deployment_graph import \
@ -47,7 +49,9 @@ class ReleaseAttributesMetadataHandler(SingleHandler):
single = Release
validator = ReleaseAttributesMetadataValidator
@content
@handle_errors
@validate
@serialize
def GET(self, obj_id):
""":returns: JSONized Release attributes metadata.
@ -57,7 +61,9 @@ class ReleaseAttributesMetadataHandler(SingleHandler):
release = self.get_object_or_404(self.single, obj_id)
return release['attributes_metadata']
@content
@handle_errors
@validate
@serialize
def PUT(self, obj_id):
""":returns: JSONized Release attributes metadata.
@ -77,14 +83,16 @@ class ReleaseCollectionHandler(CollectionHandler):
validator = ReleaseValidator
collection = ReleaseCollection
@content
@handle_errors
@validate
@serialize
def GET(self):
""":returns: Sorted releases' collection in JSON format
:http: * 200 (OK)
"""
q = sorted(self.collection.all(), reverse=True)
return self.collection.to_json(q)
return self.collection.to_list(q)
class ReleaseNetworksHandler(SingleHandler):
@ -93,7 +101,9 @@ class ReleaseNetworksHandler(SingleHandler):
single = Release
validator = ReleaseNetworksValidator
@content
@handle_errors
@validate
@serialize
def GET(self, obj_id):
"""Read release networks metadata
@ -105,7 +115,9 @@ class ReleaseNetworksHandler(SingleHandler):
obj = self.get_object_or_404(self.single, obj_id)
return obj['networks_metadata']
@content
@handle_errors
@validate
@serialize
def PUT(self, obj_id):
"""Updates release networks metadata

View File

@ -17,7 +17,9 @@
Handlers for removed resources
"""
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
class BaseRemovedInHandler(BaseHandler):
@ -27,7 +29,9 @@ class BaseRemovedInHandler(BaseHandler):
def fuel_version(self):
raise NotImplementedError
@content
@handle_errors
@validate
@serialize
def GET(self):
"""A stub for the request. Always returns 410 with removed message.

View File

@ -17,7 +17,9 @@
import six
from nailgun.api.v1.handlers import base
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.role import RoleValidator
from nailgun import errors
from nailgun import objects
@ -37,7 +39,9 @@ class RoleHandler(base.SingleHandler):
release=release_id, name=role_name))
return role
@content
@handle_errors
@validate
@serialize
def GET(self, release_id, role_name):
"""Retrieve role
@ -48,7 +52,9 @@ class RoleHandler(base.SingleHandler):
release = self.get_object_or_404(objects.Release, release_id)
return RoleSerializer.serialize_from_release(release, role_name)
@content
@handle_errors
@validate
@serialize
def PUT(self, release_id, role_name):
"""Update role
@ -85,7 +91,8 @@ class RoleCollectionHandler(base.CollectionHandler):
validator = RoleValidator
@content
@handle_errors
@validate
def POST(self, release_id):
"""Create role for release
@ -110,7 +117,9 @@ class RoleCollectionHandler(base.CollectionHandler):
raise self.http(
201, RoleSerializer.serialize_from_release(release, role_name))
@content
@handle_errors
@validate
@serialize
def GET(self, release_id):
release = self.get_object_or_404(objects.Release, release_id)
role_names = six.iterkeys(release.roles_metadata)
@ -125,7 +134,9 @@ class ClusterRolesHandler(base.BaseHandler):
if role_name not in available_roles:
raise self.http(404, 'Role is not found for the cluster')
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id, role_name):
""":returns: JSON-ed metadata for the role
@ -140,7 +151,9 @@ class ClusterRolesHandler(base.BaseHandler):
class ClusterRolesCollectionHandler(base.BaseHandler):
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: collection of JSON-ed cluster roles metadata

View File

@ -18,7 +18,9 @@ import web
from nailgun.api.v1.handlers.base import CollectionHandler
from nailgun.api.v1.handlers.base import SingleHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.task import TaskValidator
from nailgun import errors
@ -38,7 +40,8 @@ class TaskHandler(SingleHandler):
single = objects.Task
validator = TaskValidator
@content
@handle_errors
@validate
def DELETE(self, obj_id):
""":returns: Empty string
@ -68,7 +71,9 @@ class TaskCollectionHandler(CollectionHandler):
collection = objects.TaskCollection
validator = TaskValidator
@content
@handle_errors
@validate
@serialize
def GET(self):
"""May receive cluster_id parameter to filter list of tasks
@ -79,8 +84,8 @@ class TaskCollectionHandler(CollectionHandler):
cluster_id = web.input(cluster_id=None).cluster_id
if cluster_id is not None:
return self.collection.to_json(
return self.collection.to_list(
self.collection.get_by_cluster_id(cluster_id)
)
else:
return self.collection.to_json(self.collection.all_not_deleted())
return self.collection.to_list(self.collection.all_not_deleted())

View File

@ -18,7 +18,9 @@ import web
from nailgun.api.v1.handlers.base import CollectionHandler
from nailgun.api.v1.handlers.tasks import TaskHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators.transaction import TransactionValidator
from nailgun import errors
@ -42,7 +44,9 @@ class TransactionCollectionHandler(CollectionHandler):
collection = objects.TransactionCollection
validator = TransactionValidator
@content
@handle_errors
@validate
@serialize
def GET(self):
"""May receive cluster_id parameter to filter list of tasks
@ -60,7 +64,7 @@ class TransactionCollectionHandler(CollectionHandler):
except errors.InvalidData as exc:
raise self.http(400, exc.message)
return self.collection.to_json(
return self.collection.to_list(
self.collection.get_transactions(
cluster_id=cluster_id,
statuses=statuses,
@ -72,7 +76,9 @@ class BaseTransactionDataHandler(TransactionHandler):
get_data = None
@content
@handle_errors
@validate
@serialize
def GET(self, transaction_id):
""":returns: Collection of JSONized DeploymentInfo objects.

View File

@ -19,14 +19,18 @@ Product info handlers
"""
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.settings import settings
class VersionHandler(BaseHandler):
"""Version info handler"""
@content
@handle_errors
@validate
@serialize
def GET(self):
""":returns: FUEL/FUELWeb commit SHA, release version.

View File

@ -20,7 +20,9 @@ import six
import web
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.api.v1.validators import node as validators
from nailgun.logger import logger
@ -72,7 +74,8 @@ class SpawnVmsHandler(BaseHandler):
else:
raise self.http(400, "No VMs to spawn")
@content
@handle_errors
@validate
def PUT(self, cluster_id):
""":returns: JSONized Task object.
@ -93,7 +96,9 @@ class NodeVMsHandler(BaseHandler):
validator = validators.NodeVMsValidator
@content
@handle_errors
@validate
@serialize
def GET(self, node_id):
""":returns: JSONized node vms_conf.
@ -104,7 +109,9 @@ class NodeVMsHandler(BaseHandler):
node_vms = node.vms_conf
return {"vms_conf": node_vms}
@content
@handle_errors
@validate
@serialize
def PUT(self, node_id):
""":returns: JSONized node vms_conf.

View File

@ -19,7 +19,9 @@ Handlers dealing with network configurations
"""
from ..task.manager import UpdateDnsmasqTaskManager
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.extensions.network_manager.objects.serializers.\
network_configuration import NeutronNetworkConfigurationSerializer
@ -71,7 +73,9 @@ class ProviderHandler(BaseHandler):
cluster=cluster, networks_required=False)
return cluster, data
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized network configuration for cluster.
@ -91,7 +95,9 @@ class ProviderHandler(BaseHandler):
logger.exception('Serialization failed')
raise
@content
@handle_errors
@validate
@serialize
def PUT(self, cluster_id):
""":returns: JSONized network configuration for cluster.
@ -153,7 +159,9 @@ class TemplateNetworkConfigurationHandler(BaseHandler):
raise self.http(403, "Network template cannot be changed "
"during deployment and after upgrade.")
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: network template for cluster (json format)
@ -163,7 +171,8 @@ class TemplateNetworkConfigurationHandler(BaseHandler):
cluster = self.get_object_or_404(objects.Cluster, cluster_id)
return cluster.network_config.configuration_template
@content
@handle_errors
@validate
def PUT(self, cluster_id):
""":returns: {}
@ -202,7 +211,8 @@ class NetworkConfigurationVerifyHandler(ProviderHandler):
validator = NetworkConfigurationValidator
@content
@handle_errors
@validate
def PUT(self, cluster_id):
""":IMPORTANT: this method should be rewritten to be more RESTful
@ -252,7 +262,9 @@ class NeutronNetworkConfigurationVerifyHandler(
class NetworkAttributesDeployedHandler(BaseHandler):
"""Cluster deployed network attributes handler"""
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
""":returns: JSONized deployed Cluster network configuration.

View File

@ -15,8 +15,10 @@
# under the License.
from nailgun.api.v1.handlers.base import CollectionHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import SingleHandler
from nailgun.api.v1.handlers.base import validate
from nailgun.extensions.network_manager.validators.network import \
NetworkGroupValidator
@ -38,7 +40,9 @@ class NetworkGroupHandler(SingleHandler):
validator = NetworkGroupValidator
single = objects.NetworkGroup
@content
@handle_errors
@validate
@serialize
def PUT(self, group_id):
""":returns: JSONized Network Group object.
@ -57,9 +61,10 @@ class NetworkGroupHandler(SingleHandler):
)
self.single.update(ng, data)
return self.single.to_json(ng)
return self.single.to_dict(ng)
@content
@handle_errors
@validate
def DELETE(self, group_id):
"""Remove Network Group
@ -87,7 +92,8 @@ class NetworkGroupCollectionHandler(CollectionHandler):
collection = objects.NetworkGroupCollection
validator = NetworkGroupValidator
@content
@handle_errors
@validate
def POST(self):
""":returns: JSONized Network Group object.

View File

@ -21,7 +21,9 @@ Handlers dealing with nodes
import web
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.extensions.network_manager.validators.network import \
NetAssignmentValidator
@ -42,7 +44,9 @@ class NodeNICsHandler(BaseHandler):
validator = NetAssignmentValidator
serializer = NodeInterfacesSerializer
@content
@handle_errors
@validate
@serialize
def GET(self, node_id):
""":returns: Collection of JSONized Node interfaces.
@ -52,7 +56,9 @@ class NodeNICsHandler(BaseHandler):
node = self.get_object_or_404(objects.Node, node_id)
return map(self.render, node.interfaces)
@content
@handle_errors
@validate
@serialize
def PUT(self, node_id):
""":returns: Collection of JSONized Node objects.
@ -79,7 +85,9 @@ class NodeCollectionNICsHandler(BaseHandler):
validator = NetAssignmentValidator
serializer = NodeInterfacesSerializer
@content
@handle_errors
@validate
@serialize
def PUT(self):
""":returns: Collection of JSONized Node objects.
@ -107,7 +115,9 @@ class NodeCollectionNICsHandler(BaseHandler):
class NodeNICsDefaultHandler(BaseHandler):
"""Node default network interfaces handler"""
@content
@handle_errors
@validate
@serialize
def GET(self, node_id):
""":returns: Collection of default JSONized interfaces for node.
@ -129,7 +139,9 @@ class NodeCollectionNICsDefaultHandler(NodeNICsDefaultHandler):
validator = NetAssignmentValidator
@content
@handle_errors
@validate
@serialize
def GET(self):
"""May receive cluster_id parameter to filter list of nodes

View File

@ -18,7 +18,9 @@
import web
from nailgun.api.v1.handlers import base
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.extensions.network_manager.validators import ip_addr
from nailgun import objects
@ -51,7 +53,9 @@ class ClusterVIPHandler(base.SingleHandler):
else:
return obj
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id, ip_addr_id):
"""Get VIP record.
@ -68,9 +72,11 @@ class ClusterVIPHandler(base.SingleHandler):
"""
obj = self._get_vip_from_cluster_or_http_error(
int(cluster_id), int(ip_addr_id))
return self.single.to_json(obj)
return self.single.to_dict(obj)
@content
@handle_errors
@validate
@serialize
def PUT(self, cluster_id, ip_addr_id):
"""Update VIP record.
@ -94,7 +100,7 @@ class ClusterVIPHandler(base.SingleHandler):
existing_obj=obj
)
self.single.update(obj, data)
return self.single.to_json(obj)
return self.single.to_dict(obj)
def PATCH(self, cluster_id, ip_addr_id):
"""Update VIP record.
@ -126,7 +132,9 @@ class ClusterVIPCollectionHandler(base.CollectionHandler):
collection = objects.IPAddrCollection
validator = ip_addr.IPAddrValidator
@content
@handle_errors
@validate
@serialize
def GET(self, cluster_id):
"""Get VIPs collection optionally filtered by network or network role.
@ -141,7 +149,7 @@ class ClusterVIPCollectionHandler(base.CollectionHandler):
network_role = web.input(network_role=None).network_role
self.get_object_or_404(objects.Cluster, int(cluster_id))
return self.collection.to_json(
return self.collection.to_list(
self.collection.get_vips_by_cluster_id(
int(cluster_id),
network_id,
@ -149,7 +157,8 @@ class ClusterVIPCollectionHandler(base.CollectionHandler):
)
)
@content
@handle_errors
@validate
def POST(self, cluster_id):
"""Create (allocate) VIP
@ -174,7 +183,9 @@ class ClusterVIPCollectionHandler(base.CollectionHandler):
raise self.http(200, self.collection.single.to_json(vip))
@content
@handle_errors
@validate
@serialize
def PUT(self, cluster_id):
"""Update VIPs collection.
@ -191,7 +202,7 @@ class ClusterVIPCollectionHandler(base.CollectionHandler):
cluster_id=int(cluster_id)
)
return self.collection.to_json(
return self.collection.to_list(
self.collection.update_vips(update_data)
)

View File

@ -22,7 +22,9 @@ from ..manager import DisksFormatConvertor
from ..manager import VolumeManager
from ..validators.disks import NodeDisksValidator
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun import objects
@ -30,7 +32,9 @@ class NodeDisksHandler(BaseHandler):
validator = NodeDisksValidator
@content
@handle_errors
@validate
@serialize
def GET(self, node_id):
""":returns: JSONized node disks.
@ -43,7 +47,9 @@ class NodeDisksHandler(BaseHandler):
node_volumes = VolumeObject.get_volumes(node)
return DisksFormatConvertor.format_disks_to_simple(node_volumes)
@content
@handle_errors
@validate
@serialize
def PUT(self, node_id):
""":returns: JSONized node disks.
@ -75,7 +81,9 @@ class NodeDisksHandler(BaseHandler):
class NodeDefaultsDisksHandler(BaseHandler):
@content
@handle_errors
@validate
@serialize
def GET(self, node_id):
""":returns: JSONized node disks.
@ -92,7 +100,9 @@ class NodeDefaultsDisksHandler(BaseHandler):
class NodeVolumesInformationHandler(BaseHandler):
@content
@handle_errors
@validate
@serialize
def GET(self, node_id):
""":returns: JSONized volumes info for node.

View File

@ -15,7 +15,9 @@
# under the License.
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.api.v1.handlers.base import validate
from nailgun.fake_keystone import generate_token
from nailgun.fake_keystone import validate_password_credentials
from nailgun.fake_keystone import validate_token
@ -24,7 +26,9 @@ from nailgun.settings import settings
class TokensHandler(BaseHandler):
@content
@handle_errors
@validate
@serialize
def POST(self):
data = self.checked_data()
try:
@ -73,7 +77,9 @@ class TokensHandler(BaseHandler):
class VersionHandler(BaseHandler):
@content
@handle_errors
@validate
@serialize
def GET(self):
keystone_href = 'http://{ip_addr}:{port}/keystone/v2.0/'.format(
ip_addr=settings.LISTEN_ADDRESS, port=settings.LISTEN_PORT)
@ -107,7 +113,9 @@ class VersionHandler(BaseHandler):
class ServicesHandler(BaseHandler):
@content
@handle_errors
@validate
@serialize
def GET(self):
return {
'OS-KSADM:services': [{'type': 'ostf', 'enabled': True,
@ -127,7 +135,9 @@ class ServicesHandler(BaseHandler):
class EndpointsHandler(BaseHandler):
@content
@handle_errors
@validate
@serialize
def GET(self):
keystone_href = 'http://{ip_addr}:{port}/keystone/v2.0'.format(
ip_addr=settings.AUTH['auth_host'], port=settings.LISTEN_PORT)

View File

@ -636,6 +636,8 @@ class TestStartEndTaskPassedCorrectly(BaseGraphTasksTests):
def assert_passed_correctly(self, url, **kwargs):
with mock.patch.object(GraphSolver,
'find_subgraph') as mfind_subgraph:
mfind_subgraph.return_value.node.values.return_value = {}
resp = self.app.get(
url,
params=kwargs,

View File

@ -19,10 +19,9 @@ import urllib
import web
from mock import patch
from nailgun.api.v1.handlers.base import BaseHandler
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.handlers.base import handle_errors
from nailgun.api.v1.handlers.base import serialize
from nailgun.test.base import BaseIntegrationTest
from nailgun.utils import reverse
@ -97,15 +96,15 @@ class TestHandlers(BaseIntegrationTest):
def test_content_decorator(self):
class FakeHandler(object):
class FakeHandler(BaseHandler):
@content
@serialize
def GET(self):
return {}
@content(["text/plain"])
@serialize
def POST(self):
return "Plain Text"
return {}
web.ctx.headers = []
web.ctx.env = {"HTTP_ACCEPT": "text/html"}
@ -116,18 +115,7 @@ class TestHandlers(BaseIntegrationTest):
fake_handler.GET
)
web.ctx.env = {"HTTP_ACCEPT": "application/json"}
with patch("nailgun.api.v1.handlers.base.content_json") as cj:
fake_handler.GET()
self.assertEqual(cj.call_count, 1)
web.ctx.env = {"HTTP_ACCEPT": "*/*"}
with patch("nailgun.api.v1.handlers.base.content_json") as cj:
fake_handler.GET()
self.assertEqual(cj.call_count, 1)
web.ctx.headers = []
fake_handler.GET()
self.assertIn(
@ -136,7 +124,7 @@ class TestHandlers(BaseIntegrationTest):
)
web.ctx.headers = []
web.ctx.env = {"HTTP_ACCEPT": "text/plain"}
web.ctx.env = {"HTTP_ACCEPT": "application/json"}
fake_handler.POST()
self.assertIn(
# we don't have plain/text serializer right now
@ -144,6 +132,20 @@ class TestHandlers(BaseIntegrationTest):
web.ctx.headers
)
def test_invalid_handler_output(self):
class FakeHandler(object):
@handle_errors
@serialize
def GET(self):
return {set([1, 2, 3])}
fake_handler = FakeHandler()
web.ctx.env = {"HTTP_ACCEPT": "*/*"}
web.ctx.headers = []
self.assertRaises(web.HTTPError, fake_handler.GET)
def test_get_param_as_set(self):
urls = ("/hello", "hello")
@ -160,3 +162,26 @@ class TestHandlers(BaseIntegrationTest):
self.assertEqual(set(json.loads(resp.data)),
set(['1', '4', '777', 'x']))
def check_get_requested_mime(self, headers, expected_mime):
urls = ("/hello", "hello")
class hello(object):
def GET(self_inner):
web.header('Content-Type', 'text/plain')
return BaseHandler.get_requested_mime()
app = web.application(urls, {'hello': hello})
resp = app.request('/hello', headers=headers)
self.assertEqual(resp.data, expected_mime)
def test_get_requested_mime1(self):
self.check_get_requested_mime({'ACCEPT': 'text/html'}, 'text/html')
def test_get_requested_mime2(self):
self.check_get_requested_mime(
{'ACCEPT': 'text/plain;q=0.7, text/html;level=1,'}, 'text/plain')
def test_get_requested_default(self):
self.check_get_requested_mime({}, 'application/json')