From 50927b5c38c74b2639697de077a6850ab4e320dd Mon Sep 17 00:00:00 2001 From: chenying Date: Wed, 25 Oct 2017 14:47:47 +0800 Subject: [PATCH] Add OSC plugin for the verification API Change-Id: I2fbd064a058c7dcaff6e223a3e2c87bb16cdbaa0 Implements: blueprint support-verify-the-checkpoint-api --- karborclient/osc/v1/verifications.py | 182 ++++++++++++++++++ .../tests/unit/osc/v1/test_verifications.py | 129 +++++++++++++ setup.cfg | 3 + 3 files changed, 314 insertions(+) create mode 100644 karborclient/osc/v1/verifications.py create mode 100644 karborclient/tests/unit/osc/v1/test_verifications.py diff --git a/karborclient/osc/v1/verifications.py b/karborclient/osc/v1/verifications.py new file mode 100644 index 0000000..0023e3b --- /dev/null +++ b/karborclient/osc/v1/verifications.py @@ -0,0 +1,182 @@ +# 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. + +"""Data protection V1 verification action implementations""" + +import functools +import json + +from oslo_utils import uuidutils + +from osc_lib.command import command +from osc_lib import utils as osc_utils +from oslo_log import log as logging + +from karborclient.common.apiclient import exceptions +from karborclient.i18n import _ +from karborclient import utils + + +def format_verification(verification_info): + for key in ('parameters', 'resources_status', + 'resources_reason'): + if key not in verification_info: + continue + verification_info[key] = json.dumps(verification_info[key], + indent=2, sort_keys=True) + verification_info.pop("links", None) + + +class ListVerifications(command.Lister): + _description = _("List verifications.") + + log = logging.getLogger(__name__ + ".ListVerifications") + + def get_parser(self, prog_name): + parser = super(ListVerifications, self).get_parser(prog_name) + parser.add_argument( + '--all-projects', + action='store_true', + default=False, + help=_('Include all projects (admin only)'), + ) + parser.add_argument( + '--status', + metavar='', + help=_('Filter results by status'), + ) + parser.add_argument( + '--marker', + metavar='', + help=_('The last verification ID of the previous page'), + ) + parser.add_argument( + '--limit', + type=int, + metavar='', + help=_('Maximum number of verifications to display'), + ) + parser.add_argument( + '--sort', + metavar="[:]", + default=None, + help=_("Sort output by selected keys and directions(asc or desc), " + "multiple keys and directions can be " + "specified separated by comma"), + ) + parser.add_argument( + '--project', + metavar='', + help=_('Filter results by a project(admin only)') + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + data_protection_client = self.app.client_manager.data_protection + all_projects = bool(parsed_args.project) or parsed_args.all_projects + + search_opts = { + 'all_tenants': all_projects, + 'project_id': parsed_args.project, + 'status': parsed_args.status, + } + + data = data_protection_client.verifications.list( + search_opts=search_opts, marker=parsed_args.marker, + limit=parsed_args.limit, sort=parsed_args.sort) + + column_headers = ['Id', 'Project id', 'Provider id', 'Checkpoint id', + 'Parameters', 'Status'] + + json_dumps = functools.partial(json.dumps, indent=2, sort_keys=True) + formatters = { + "Parameters": json_dumps, + } + return (column_headers, + (osc_utils.get_item_properties( + s, column_headers, formatters=formatters, + ) for s in data)) + + +class ShowVerification(command.ShowOne): + _description = "Shows verification details" + + def get_parser(self, prog_name): + parser = super(ShowVerification, self).get_parser(prog_name) + parser.add_argument( + 'verification', + metavar="", + help=_('The UUID of the verification.') + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.data_protection + verification = osc_utils.find_resource(client.verifications, + parsed_args.verification) + + format_verification(verification._info) + return zip(*sorted(verification._info.items())) + + +class CreateVerification(command.ShowOne): + _description = "Creates a verification" + + def get_parser(self, prog_name): + parser = super(CreateVerification, self).get_parser(prog_name) + parser.add_argument( + 'provider_id', + metavar='', + help=_('The UUID of the provider.') + ) + parser.add_argument( + 'checkpoint_id', + metavar='', + help=_('The UUID of the checkpoint.') + ) + parser.add_argument( + '--parameters-json', + type=str, + dest='parameters_json', + metavar='', + default=None, + help=_('Verification parameters in json format.') + ) + parser.add_argument( + '--parameters', + action='append', + metavar='resource_type=[,resource_id=,key=val,...]', + default=[], + help=_("Verification parameters, may be specified multiple times. " + "resource_type: type of resource to apply parameters. " + "resource_id: limit the parameters to a specific resource. " + "Other keys and values: according to provider\'s " + "verification schema.") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.data_protection + if not uuidutils.is_uuid_like(parsed_args.provider_id): + raise exceptions.CommandError( + "Invalid provider id provided.") + if not uuidutils.is_uuid_like(parsed_args.checkpoint_id): + raise exceptions.CommandError( + "Invalid checkpoint id provided.") + + verification_parameters = utils.extract_parameters(parsed_args) + verification = client.verifications.create(parsed_args.provider_id, + parsed_args.checkpoint_id, + verification_parameters) + format_verification(verification._info) + return zip(*sorted(verification._info.items())) diff --git a/karborclient/tests/unit/osc/v1/test_verifications.py b/karborclient/tests/unit/osc/v1/test_verifications.py new file mode 100644 index 0000000..42b2688 --- /dev/null +++ b/karborclient/tests/unit/osc/v1/test_verifications.py @@ -0,0 +1,129 @@ +# 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 copy +import json + +from karborclient.osc.v1 import verifications as osc_verifications +from karborclient.tests.unit.osc.v1 import fakes +from karborclient.v1 import verifications + + +VERIFICATION_INFO = { + "id": "22b82aa7-9179-4c71-bba2-caf5c0e68db7", + "project_id": "e486a2f49695423ca9c47e589b948108", + "provider_id": "cf56bd3e-97a7-4078-b6d5-f36246333fd9", + "checkpoint_id": "dcb20606-ad71-40a3-80e4-ef0fafdad0c3", + "parameters": {}, + "resources_status": {}, + "resources_reason": {}, + "status": "success" +} + + +class TestVerifications(fakes.TestDataProtection): + def setUp(self): + super(TestVerifications, self).setUp() + self.verifications_mock = ( + self.app.client_manager.data_protection.verifications) + self.verifications_mock.reset_mock() + + +class TestListVerifications(TestVerifications): + def setUp(self): + super(TestListVerifications, self).setUp() + self.verifications_mock.list.return_value = ( + [verifications.Verification( + None, copy.deepcopy(VERIFICATION_INFO))]) + + # Command to test + self.cmd = osc_verifications.ListVerifications(self.app, None) + + def test_verifications_list(self): + arglist = ['--status', 'success'] + verifylist = [('status', 'success')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + expected_columns = ( + ['Id', 'Project id', 'Provider id', 'Checkpoint id', + 'Parameters', 'Status']) + self.assertEqual(expected_columns, columns) + + # Check that data is correct + expected_data = [("22b82aa7-9179-4c71-bba2-caf5c0e68db7", + "e486a2f49695423ca9c47e589b948108", + "cf56bd3e-97a7-4078-b6d5-f36246333fd9", + "dcb20606-ad71-40a3-80e4-ef0fafdad0c3", + json.dumps({}), + "success")] + self.assertEqual(expected_data, list(data)) + + +class TestCreateVerification(TestVerifications): + def setUp(self): + super(TestCreateVerification, self).setUp() + self.verifications_mock.create.return_value = ( + verifications.Verification( + None, copy.deepcopy(VERIFICATION_INFO))) + self.cmd = osc_verifications.CreateVerification(self.app, None) + + def test_verification_create(self): + arglist = ['cf56bd3e-97a7-4078-b6d5-f36246333fd9', + 'dcb20606-ad71-40a3-80e4-ef0fafdad0c3'] + verifylist = [('provider_id', 'cf56bd3e-97a7-4078-b6d5-f36246333fd9'), + ('checkpoint_id', + 'dcb20606-ad71-40a3-80e4-ef0fafdad0c3')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + + self.verifications_mock.create.assert_called_once_with( + 'cf56bd3e-97a7-4078-b6d5-f36246333fd9', + 'dcb20606-ad71-40a3-80e4-ef0fafdad0c3', {}) + + +class TestShowVerification(TestVerifications): + def setUp(self): + super(TestShowVerification, self).setUp() + self._verification_info = copy.deepcopy(VERIFICATION_INFO) + self.verifications_mock.get.return_value = ( + verifications.Verification(None, self._verification_info)) + + self.cmd = osc_verifications.ShowVerification(self.app, None) + + def test_verification_show(self): + arglist = ['22b82aa7-9179-4c71-bba2-caf5c0e68db7'] + verifylist = [('verification', '22b82aa7-9179-4c71-bba2-caf5c0e68db7')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + expected_columns = ( + 'checkpoint_id', 'id', 'parameters', 'project_id', + 'provider_id', 'resources_reason', 'resources_status', + 'status') + self.assertEqual(expected_columns, columns) + + self.assertEqual(self._verification_info['checkpoint_id'], data[0]) + self.assertEqual(self._verification_info['id'], data[1]) + self.assertEqual(self._verification_info['parameters'], data[2]) + self.assertEqual(self._verification_info['project_id'], data[3]) + self.assertEqual(self._verification_info['provider_id'], data[4]) + self.assertEqual(self._verification_info['resources_reason'], data[5]) + self.assertEqual(self._verification_info['resources_status'], data[6]) + self.assertEqual(self._verification_info['status'], data[7]) diff --git a/setup.cfg b/setup.cfg index 7497a50..d666742 100644 --- a/setup.cfg +++ b/setup.cfg @@ -63,6 +63,9 @@ openstack.data_protection.v1 = data_protection_scheduledoperation_delete = karborclient.osc.v1.scheduled_operations:DeleteScheduledOperation data_protection_operationlog_list = karborclient.osc.v1.operation_logs:ListOperationLogs data_protection_operationlog_show = karborclient.osc.v1.operation_logs:ShowOperationLog + data_protection_verification_list = karborclient.osc.v1.verifications:ListVerifications + data_protection_verification_show = karborclient.osc.v1.verifications:ShowVerification + data_protection_verification_create = karborclient.osc.v1.verifications:CreateVerification [compile_catalog] directory = karborclient/locale