From 00ac17932463faeaad3f5fd817eb3dc28f11c8dc Mon Sep 17 00:00:00 2001 From: Stan Lagun Date: Mon, 27 Jun 2016 13:35:39 -0700 Subject: [PATCH] Support for Schemas API was added Partially-Implements blueprint: muranopl-forms Depends-On: I43ccd2d9d94f9f89db1855932280539f69f2f8d8 Change-Id: I00dbe9edfa532d078b2715aed1ddb778c043809c --- muranoclient/osc/v1/schema.py | 52 ++++++++++++++++ muranoclient/tests/unit/osc/v1/test_schema.py | 59 +++++++++++++++++++ muranoclient/tests/unit/test_shell.py | 43 ++++++++++++++ muranoclient/v1/client.py | 2 + muranoclient/v1/schemas.py | 51 ++++++++++++++++ muranoclient/v1/shell.py | 14 +++++ ...dded-schemas-support-e4a6e44c7bac2751.yaml | 7 +++ setup.cfg | 1 + 8 files changed, 229 insertions(+) create mode 100644 muranoclient/osc/v1/schema.py create mode 100644 muranoclient/tests/unit/osc/v1/test_schema.py create mode 100644 muranoclient/v1/schemas.py create mode 100644 releasenotes/notes/added-schemas-support-e4a6e44c7bac2751.yaml diff --git a/muranoclient/osc/v1/schema.py b/muranoclient/osc/v1/schema.py new file mode 100644 index 00000000..8dc4c127 --- /dev/null +++ b/muranoclient/osc/v1/schema.py @@ -0,0 +1,52 @@ +# 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. + +"""Application-catalog v1 class-schema action implementation""" + +from osc_lib.command import command +from oslo_log import log as logging + +LOG = logging.getLogger(__name__) + + +class ShowSchema(command.ShowOne): + """Show class schema.""" + + def get_parser(self, prog_name): + parser = super(ShowSchema, self).get_parser(prog_name) + parser.add_argument( + "class_name", metavar="", help="Class FQN") + parser.add_argument( + "method_names", metavar="", + help="Method name", nargs='*') + parser.add_argument( + "--package-name", default=None, + help="FQN of the package where the class is located") + parser.add_argument( + "--class-version", default='=0', + help="Class version or version range (version spec)") + + return parser + + def take_action(self, parsed_args): + LOG.debug("take_action({0})".format(parsed_args)) + client = self.app.client_manager.application_catalog + schema = client.schemas.get( + parsed_args.class_name, parsed_args.method_names, + class_version=parsed_args.class_version, + package_name=parsed_args.package_name) + + return self.dict2columns(schema.data) + + @property + def formatter_default(self): + return 'json' diff --git a/muranoclient/tests/unit/osc/v1/test_schema.py b/muranoclient/tests/unit/osc/v1/test_schema.py new file mode 100644 index 00000000..657ecb3c --- /dev/null +++ b/muranoclient/tests/unit/osc/v1/test_schema.py @@ -0,0 +1,59 @@ +# 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 muranoclient.osc.v1 import schema as osc_schema +from muranoclient.tests.unit.osc.v1 import fakes +from muranoclient.v1 import schemas as api_schemas + +SAMPLE_CLASS_SCHEMA = { + '': { + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": {} + }, + 'modelBuilder': { + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": {} + } +} + + +class TestSchema(fakes.TestApplicationCatalog): + def setUp(self): + super(TestSchema, self).setUp() + self.schemas_mock = \ + self.app.client_manager.application_catalog.schemas + self.schemas_mock.get.return_value = api_schemas.Schema( + None, SAMPLE_CLASS_SCHEMA) + self.cmd = osc_schema.ShowSchema(self.app, None) + + @mock.patch('osc_lib.utils.get_item_properties') + def test_query_class_schema(self, mock_util): + mock_util.return_value = 'result' + + arglist = ['class.name', 'methodName1', + '--package-name', 'package.name', + '--class-version', '>1'] + verifylist = [('class_name', 'class.name'), + ('method_names', ['methodName1']), + ('package_name', 'package.name'), + ('class_version', '>1')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + expected_columns = ['', 'modelBuilder'] + self.assertItemsEqual(expected_columns, columns) + self.assertItemsEqual(tuple(SAMPLE_CLASS_SCHEMA.values()), data) diff --git a/muranoclient/tests/unit/test_shell.py b/muranoclient/tests/unit/test_shell.py index 6d4d5e2c..bd3d5884 100644 --- a/muranoclient/tests/unit/test_shell.py +++ b/muranoclient/tests/unit/test_shell.py @@ -611,6 +611,49 @@ class ShellCommandTest(ShellTest): } }) + @mock.patch('muranoclient.v1.schemas.SchemaManager') + @requests_mock.mock() + def test_class_schema(self, mock_manager, m_requests): + self.client.schemas = mock_manager() + self.make_env() + self.register_keystone_discovery_fixture(m_requests) + self.register_keystone_token_fixture(m_requests) + self.shell('class-schema class.name') + self.client.schemas.get.assert_called_once_with( + 'class.name', [], + package_name=None, + class_version='=0' + ) + + @mock.patch('muranoclient.v1.schemas.SchemaManager') + @requests_mock.mock() + def test_class_schema_with_methods(self, mock_manager, m_requests): + self.client.schemas = mock_manager() + self.make_env() + self.register_keystone_discovery_fixture(m_requests) + self.register_keystone_token_fixture(m_requests) + self.shell('class-schema class.name method1 method2') + self.client.schemas.get.assert_called_once_with( + 'class.name', ['method1', 'method2'], + package_name=None, + class_version='=0' + ) + + @mock.patch('muranoclient.v1.schemas.SchemaManager') + @requests_mock.mock() + def test_class_schema_full(self, mock_manager, m_requests): + self.client.schemas = mock_manager() + self.make_env() + self.register_keystone_discovery_fixture(m_requests) + self.register_keystone_token_fixture(m_requests) + self.shell('class-schema class.name method1 method2 ' + '--class-version >1.2.3 --package-name foo.bar') + self.client.schemas.get.assert_called_once_with( + 'class.name', ['method1', 'method2'], + package_name='foo.bar', + class_version='>1.2.3' + ) + @mock.patch('muranoclient.v1.templates.EnvTemplateManager') @requests_mock.mock() def test_env_template_delete(self, mock_manager, m_requests): diff --git a/muranoclient/v1/client.py b/muranoclient/v1/client.py index 36eb06c7..80aa0c2c 100644 --- a/muranoclient/v1/client.py +++ b/muranoclient/v1/client.py @@ -21,6 +21,7 @@ from muranoclient.v1 import environments from muranoclient.v1 import instance_statistics from muranoclient.v1 import packages from muranoclient.v1 import request_statistics +from muranoclient.v1 import schemas from muranoclient.v1 import services from muranoclient.v1 import sessions from muranoclient.v1 import static_actions @@ -47,6 +48,7 @@ class Client(object): self.sessions = sessions.SessionManager(self.http_client) self.services = services.ServiceManager(self.http_client) self.deployments = deployments.DeploymentManager(self.http_client) + self.schemas = schemas.SchemaManager(self.http_client) self.request_statistics = \ request_statistics.RequestStatisticsManager(self.http_client) self.instance_statistics = \ diff --git a/muranoclient/v1/schemas.py b/muranoclient/v1/schemas.py new file mode 100644 index 00000000..b8edadfc --- /dev/null +++ b/muranoclient/v1/schemas.py @@ -0,0 +1,51 @@ +# Copyright (c) 2016 Mirantis, Inc. +# +# 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. + +from six.moves import urllib + +from muranoclient.common import base + + +class Schema(base.Resource): + def __repr__(self): + return "" % self._info + + @property + def data(self): + return self._info + + +class SchemaManager(base.Manager): + resource_class = Schema + + def get(self, class_name, method_names=None, + class_version=None, package_name=None): + """Get JSON-schema for class or method""" + + if isinstance(method_names, (list, tuple)): + method_names = ','.join(method_names) + + base_url = '/v1/schemas/' + '/'.join( + t for t in (class_name, method_names) if t) + + params = { + key: value for key, value in ( + ('classVersion', class_version), + ('packageName', package_name)) if value + } + + if len(params): + base_url += '?' + urllib.parse.urlencode(params, True) + + return self._get(base_url) diff --git a/muranoclient/v1/shell.py b/muranoclient/v1/shell.py index c8edc4a2..77141ee7 100644 --- a/muranoclient/v1/shell.py +++ b/muranoclient/v1/shell.py @@ -1163,3 +1163,17 @@ def do_category_delete(mc, args): raise exceptions.CommandError("Unable to find and delete any of the " "specified categories.") do_category_list(mc) + + +@utils.arg("class_name", metavar="", help="Class FQN") +@utils.arg("method_names", metavar="", help="Method name", nargs='*') +@utils.arg("--package-name", default=None, + help="FQN of the package where the class is located") +@utils.arg("--class-version", default='=0', + help="Class version or version range (version spec)") +def do_class_schema(mc, args): + """Display class schema""" + schema = mc.schemas.get(args.class_name, args.method_names, + class_version=args.class_version, + package_name=args.package_name) + print(utils.json_formatter(schema.data)) diff --git a/releasenotes/notes/added-schemas-support-e4a6e44c7bac2751.yaml b/releasenotes/notes/added-schemas-support-e4a6e44c7bac2751.yaml new file mode 100644 index 00000000..aebdd579 --- /dev/null +++ b/releasenotes/notes/added-schemas-support-e4a6e44c7bac2751.yaml @@ -0,0 +1,7 @@ +--- +features: + - Support for class/method JSON-schema API was added + - New murano CLI command ``murano class-schema [--package-name PACKAGE_NAME] + [--class-version PACKAGE_VERSION] [ [ ...]]`` + - New OSC command ``openstack class-schema [--package-name PACKAGE_NAME] + [--class-version PACKAGE_VERSION] [ [ ...]]`` diff --git a/setup.cfg b/setup.cfg index 51668ebe..b23c253f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -51,6 +51,7 @@ openstack.application_catalog.v1 = deployment_list = muranoclient.osc.v1.deployment:ListDeployment static-action_call = muranoclient.osc.v1.action:StaticActionCall + class-schema = muranoclient.osc.v1.schema:ShowSchema [global] setup-hooks =