From be44d29245b49975c5bf1ad079b490b15d3e622f Mon Sep 17 00:00:00 2001 From: Eyal Date: Mon, 10 Jun 2019 15:14:18 +0300 Subject: [PATCH] Add new api to list template versions supported Will print also the status which can be CURRENT, SUPPORTED or DEPRECATED At the moment we support all templates, we might deprecate the old ones in the future Change-Id: If072a77aa8f0aef2192598e267a48b19937e39f7 --- doc/source/contributor/vitrage-api.rst | 72 +++++++++++++++++++ ...dd_template_versions-5476a446705b43d2.yaml | 3 + vitrage/api/controllers/rest.py | 24 +------ vitrage/api/controllers/v1/template.py | 19 +++++ vitrage/api/controllers/v1/topology.py | 23 +++++- vitrage/api_handler/apis/template.py | 14 ++++ .../api/v1/test_template_versions.py | 49 +++++++++++++ 7 files changed, 180 insertions(+), 24 deletions(-) create mode 100644 releasenotes/notes/add_template_versions-5476a446705b43d2.yaml create mode 100644 vitrage/tests/functional/api/v1/test_template_versions.py diff --git a/doc/source/contributor/vitrage-api.rst b/doc/source/contributor/vitrage-api.rst index fbb1245a8..3ee2a547b 100644 --- a/doc/source/contributor/vitrage-api.rst +++ b/doc/source/contributor/vitrage-api.rst @@ -1930,3 +1930,75 @@ Response Examples "Name": "VitrageNotifierService worker(0)" } ] + +Template versions +^^^^^^^^^^^^^^^^^ + +Lists the vitrage template supported versions + +GET /v1/template/versions +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Headers +======= + +- X-Auth-Token (string, required) - Keystone auth token +- Accept (string) - application/json + +Path Parameters +=============== + +None. + +Query Parameters +================ + +None. + +Request Body +============ + +None. + +Request Examples +================ + +:: + + GET //v1/template/versions HTTP/1.1 + Host: 135.248.19.18:8999 + X-Auth-Token: 2b8882ba2ec44295bf300aecb2caa4f7 + Accept: application/json + + + +ResponseStatus code +=================== + +- 200 - OK +- 404 - Not Found + +Response Body +============= + +Returns a JSON object with a list of all template version supported. + +Response Examples +================= + +:: + + [ + { + "version": "v1", + "status": "SUPPORTED" + }, + { + "version": "v2", + "status": "SUPPORTED" + }, + { + "version": "v3", + "status": "CURRENT" + } + ] \ No newline at end of file diff --git a/releasenotes/notes/add_template_versions-5476a446705b43d2.yaml b/releasenotes/notes/add_template_versions-5476a446705b43d2.yaml new file mode 100644 index 000000000..3b734ecfb --- /dev/null +++ b/releasenotes/notes/add_template_versions-5476a446705b43d2.yaml @@ -0,0 +1,3 @@ +--- +features: + - Added a new API to list all vitrage template versions supported. \ No newline at end of file diff --git a/vitrage/api/controllers/rest.py b/vitrage/api/controllers/rest.py index c473e3a0a..72f364f6f 100644 --- a/vitrage/api/controllers/rest.py +++ b/vitrage/api/controllers/rest.py @@ -11,14 +11,11 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -import networkx as nx -from networkx.readwrite import json_graph + import oslo_messaging import pecan from pecan import rest -from vitrage.datasources import OPENSTACK_CLUSTER - class RootRestController(rest.RestController): @@ -41,22 +38,3 @@ class RootRestController(rest.RestController): pecan.abort(503, detail='vitrage-graph is not ready') except oslo_messaging.MessagingTimeout: pecan.abort(503, detail='vitrage-graph not available') - - @staticmethod - def as_tree(graph, root=OPENSTACK_CLUSTER, reverse=False): - if nx.__version__ >= '2.0': - linked_graph = json_graph.node_link_graph( - graph, attrs={'name': 'graph_index'}) - else: - linked_graph = json_graph.node_link_graph(graph) - if 0 == nx.number_of_nodes(linked_graph): - return {} - if reverse: - linked_graph = linked_graph.reverse() - if nx.__version__ >= '2.0': - return json_graph.tree_data( - linked_graph, - root=root, - attrs={'id': 'graph_index', 'children': 'children'}) - else: - return json_graph.tree_data(linked_graph, root=root) diff --git a/vitrage/api/controllers/v1/template.py b/vitrage/api/controllers/v1/template.py index 3021c94c2..0d7be7b34 100644 --- a/vitrage/api/controllers/v1/template.py +++ b/vitrage/api/controllers/v1/template.py @@ -34,10 +34,29 @@ LOG = log.getLogger(__name__) ONE_HOUR = int(timedelta(hours=1).total_seconds()) +class TemplateVersionsController(RootRestController): + @pecan.expose('json') + def index(self): + return self.get() + + @pecan.expose('json') + def get(self): + LOG.info('get template versions') + + try: + return pecan.request.client.call(pecan.request.context, + 'template_versions') + except Exception: + LOG.exception('Failed to get template versions') + abort(404, 'Failed to get template versions') + + @profiler.trace_cls("template controller", info={}, hide_args=False, trace_private=False) class TemplateController(RootRestController): + versions = TemplateVersionsController() + @pecan.expose('json') def get_all(self): diff --git a/vitrage/api/controllers/v1/topology.py b/vitrage/api/controllers/v1/topology.py index d3771942e..3a030b885 100644 --- a/vitrage/api/controllers/v1/topology.py +++ b/vitrage/api/controllers/v1/topology.py @@ -14,6 +14,7 @@ import json import networkx as nx +from networkx.readwrite import json_graph from oslo_log import log from oslo_utils.strutils import bool_from_string @@ -27,6 +28,7 @@ from vitrage.common.constants import VertexProperties as VProps # noinspection PyProtectedMember from vitrage.common.utils import decompress_obj +from vitrage.datasources import OPENSTACK_CLUSTER from vitrage.datasources.transformer_base import CLUSTER_ID @@ -95,12 +97,31 @@ class TopologyController(RootRestController): if node[VProps.VITRAGE_ID] == root: node_id = node[VProps.ID] break - return RootRestController.as_tree(graph, node_id) + return TopologyController.as_tree(graph, node_id) except Exception: LOG.exception('failed to get topology.') abort(404, 'Failed to get topology.') + @staticmethod + def as_tree(graph, root=OPENSTACK_CLUSTER, reverse=False): + if nx.__version__ >= '2.0': + linked_graph = json_graph.node_link_graph( + graph, attrs={'name': 'graph_index'}) + else: + linked_graph = json_graph.node_link_graph(graph) + if 0 == nx.number_of_nodes(linked_graph): + return {} + if reverse: + linked_graph = linked_graph.reverse() + if nx.__version__ >= '2.0': + return json_graph.tree_data( + linked_graph, + root=root, + attrs={'id': 'graph_index', 'children': 'children'}) + else: + return json_graph.tree_data(linked_graph, root=root) + @staticmethod def _check_input_para(graph_type, depth, query, root, all_tenants): if graph_type == 'graph' and depth is not None and root is None: diff --git a/vitrage/api_handler/apis/template.py b/vitrage/api_handler/apis/template.py index 4d315a022..7c6ebc943 100644 --- a/vitrage/api_handler/apis/template.py +++ b/vitrage/api_handler/apis/template.py @@ -15,8 +15,10 @@ import json from oslo_log import log from osprofiler import profiler + from vitrage.common.constants import TemplateStatus as TStatus from vitrage.evaluator.template_db import template_repository as template_repo +from vitrage.evaluator.template_schema_factory import TemplateSchemaFactory LOG = log.getLogger(__name__) @@ -44,6 +46,18 @@ class TemplateApis(object): results = [_to_result(r, p) for r, p in zip(results, paths)] return json.dumps({'results': results}) + def template_versions(self, ctx): + versions = sorted(TemplateSchemaFactory.supported_versions()) + # TODO(eyalb) at the moment all are supported + current = max(versions) + return [ + { + 'version': 'v%s' % version, + 'status': 'SUPPORTED' if version < current else 'CURRENT' + } + for version in versions + ] + def add_template(self, ctx, templates, template_type, params=None): """Signal the evaluator diff --git a/vitrage/tests/functional/api/v1/test_template_versions.py b/vitrage/tests/functional/api/v1/test_template_versions.py new file mode 100644 index 000000000..8782e81ec --- /dev/null +++ b/vitrage/tests/functional/api/v1/test_template_versions.py @@ -0,0 +1,49 @@ +# Copyright 2019 - Nokia Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import mock + +from vitrage.api_handler.apis.template import TemplateApis +from vitrage.evaluator import init_template_schemas +from vitrage.tests.functional.api.v1 import FunctionalTest + + +VERSIONS = [ + { + u'version': u'v1', + u'status': u'SUPPORTED' + }, + { + u'version': u'v2', + u'status': u'SUPPORTED' + }, + { + u'version': u'v3', + u'status': 'CURRENT' + } +] + + +class TemplateVersionsTest(FunctionalTest): + def __init__(self, *args, **kwds): + super(TemplateVersionsTest, self).__init__(*args, **kwds) + self.auth = 'noauth' + init_template_schemas() + + def test_get_versions(self): + with mock.patch('pecan.request') as request: + versions = TemplateApis().template_versions(mock.Mock()) + request.client.call.return_value = versions + resp = self.get_json('/template/versions/') + self.assert_list_equal(VERSIONS, resp)