From 18bb3c64390b1eb564f9e4032bcc233cda4972d5 Mon Sep 17 00:00:00 2001 From: LingxianKong Date: Fri, 14 Aug 2015 11:48:51 +0800 Subject: [PATCH] Add service API support in client side $ mistral service-list +---------------+----------------+ | Name | Type | +---------------+----------------+ | mistral_29703 | engine_group | | mistral_29703 | api_group | | mistral_29703 | executor_group | +---------------+----------------+ Change-Id: I9be8c74c3fbab7782a9056a70075e7963e9b78f4 Implements: blueprint mistral-service-cli-support --- mistralclient/api/v2/client.py | 2 + mistralclient/api/v2/services.py | 26 ++++++++++++ mistralclient/commands/v2/services.py | 42 +++++++++++++++++++ mistralclient/shell.py | 4 +- mistralclient/tests/unit/v2/base.py | 1 + .../tests/unit/v2/test_cli_services.py | 38 +++++++++++++++++ mistralclient/tests/unit/v2/test_services.py | 42 +++++++++++++++++++ 7 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 mistralclient/api/v2/services.py create mode 100644 mistralclient/commands/v2/services.py create mode 100644 mistralclient/tests/unit/v2/test_cli_services.py create mode 100644 mistralclient/tests/unit/v2/test_services.py diff --git a/mistralclient/api/v2/client.py b/mistralclient/api/v2/client.py index 8f6fca5c..6e92c15f 100644 --- a/mistralclient/api/v2/client.py +++ b/mistralclient/api/v2/client.py @@ -21,6 +21,7 @@ from mistralclient.api.v2 import actions from mistralclient.api.v2 import cron_triggers from mistralclient.api.v2 import environments from mistralclient.api.v2 import executions +from mistralclient.api.v2 import services from mistralclient.api.v2 import tasks from mistralclient.api.v2 import workbooks from mistralclient.api.v2 import workflows @@ -58,6 +59,7 @@ class Client(object): self.cron_triggers = cron_triggers.CronTriggerManager(self) self.environments = environments.EnvironmentManager(self) self.action_executions = action_executions.ActionExecutionManager(self) + self.services = services.ServiceManager(self) def authenticate(self, mistral_url=None, username=None, api_key=None, project_name=None, auth_url=None, project_id=None, diff --git a/mistralclient/api/v2/services.py b/mistralclient/api/v2/services.py new file mode 100644 index 00000000..81125d71 --- /dev/null +++ b/mistralclient/api/v2/services.py @@ -0,0 +1,26 @@ +# Copyright 2015 Huawei Technologies Co., Ltd. +# +# 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 mistralclient.api import base + + +class Service(base.Resource): + resource_name = 'Service' + + +class ServiceManager(base.ResourceManager): + resource_class = Service + + def list(self): + return self._list('/services', response_key='services') diff --git a/mistralclient/commands/v2/services.py b/mistralclient/commands/v2/services.py new file mode 100644 index 00000000..48eb8fe4 --- /dev/null +++ b/mistralclient/commands/v2/services.py @@ -0,0 +1,42 @@ +# Copyright 2015 Huawei Technologies Co., Ltd. +# +# 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 logging + +from mistralclient.api.v2 import services +from mistralclient.commands.v2 import base + + +LOG = logging.getLogger(__name__) + + +def format_list(service=None): + columns = ('Name', 'Type') + + if service: + data = (service.name, service.type) + else: + data = (tuple('' for _ in range(len(columns))),) + + return columns, data + + +class List(base.MistralLister): + """List all services.""" + + def _get_format_function(self): + return format_list + + def _get_resources(self, parsed_args): + return services.ServiceManager(self.app.client).list() diff --git a/mistralclient/shell.py b/mistralclient/shell.py index ac8694f2..a760f3bd 100644 --- a/mistralclient/shell.py +++ b/mistralclient/shell.py @@ -25,6 +25,7 @@ import mistralclient.commands.v2.actions import mistralclient.commands.v2.cron_triggers import mistralclient.commands.v2.environments import mistralclient.commands.v2.executions +import mistralclient.commands.v2.services import mistralclient.commands.v2.tasks import mistralclient.commands.v2.workbooks import mistralclient.commands.v2.workflows @@ -364,7 +365,8 @@ class MistralShell(app.App): 'cron-trigger-create': mistralclient.commands.v2.cron_triggers.Create, 'cron-trigger-delete': - mistralclient.commands.v2.cron_triggers.Delete + mistralclient.commands.v2.cron_triggers.Delete, + 'service-list': mistralclient.commands.v2.services.List } diff --git a/mistralclient/tests/unit/v2/base.py b/mistralclient/tests/unit/v2/base.py index 1e36fe79..2eac15ba 100644 --- a/mistralclient/tests/unit/v2/base.py +++ b/mistralclient/tests/unit/v2/base.py @@ -29,3 +29,4 @@ class BaseClientV2Test(base.BaseClientTest): self.workflows = self._client.workflows self.environments = self._client.environments self.action_executions = self._client.action_executions + self.services = self._client.services diff --git a/mistralclient/tests/unit/v2/test_cli_services.py b/mistralclient/tests/unit/v2/test_cli_services.py new file mode 100644 index 00000000..1e3c4ad3 --- /dev/null +++ b/mistralclient/tests/unit/v2/test_cli_services.py @@ -0,0 +1,38 @@ +# Copyright 2015 Huawei Technologies Co., Ltd. +# +# 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 mistralclient.api.v2 import services +from mistralclient.commands.v2 import services as service_cmd +from mistralclient.tests.unit import base + + +SERVICE_DICT = { + 'name': 'service_name', + 'type': 'service_type', +} + +SERVICE = services.Service(mock, SERVICE_DICT) + + +class TestCLIServicesV2(base.BaseCommandTest): + @mock.patch('mistralclient.api.v2.services.ServiceManager.list') + def test_list(self, mock): + mock.return_value = (SERVICE,) + expected = (SERVICE_DICT['name'], SERVICE_DICT['type'],) + + result = self.call(service_cmd.List) + + self.assertListEqual([expected], result[1]) diff --git a/mistralclient/tests/unit/v2/test_services.py b/mistralclient/tests/unit/v2/test_services.py new file mode 100644 index 00000000..d37a3e8f --- /dev/null +++ b/mistralclient/tests/unit/v2/test_services.py @@ -0,0 +1,42 @@ +# Copyright 2015 Huawei Technologies Co., Ltd. +# +# 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 mistralclient.api.v2 import services +from mistralclient.tests.unit.v2 import base + + +SERVICE = { + 'name': 'service_name', + 'type': 'service_type', +} + +URL_TEMPLATE = '/services' + + +class TestServicesV2(base.BaseClientV2Test): + def test_list(self): + mock = self.mock_http_get(content={'services': [SERVICE]}) + + service_list = self.services.list() + + self.assertEqual(1, len(service_list)) + + srv = service_list[0] + + self.assertDictEqual( + services.Service(self.services, SERVICE).to_dict(), + srv.to_dict() + ) + + mock.assert_called_once_with(URL_TEMPLATE)