diff --git a/karborclient/osc/__init__.py b/karborclient/osc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/karborclient/osc/plugin.py b/karborclient/osc/plugin.py new file mode 100644 index 0000000..e24c9dc --- /dev/null +++ b/karborclient/osc/plugin.py @@ -0,0 +1,56 @@ +# 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 osc_lib import utils + +LOG = logging.getLogger(__name__) + +DEFAULT_DATA_PROTECTION_API_VERSION = '1' +API_VERSION_OPTION = 'os_data_protection_api_version' +API_NAME = 'data_protection' +API_VERSIONS = { + '1': 'karborclient.v1.client.Client', +} + + +def make_client(instance): + """Returns a data protection service client""" + data_protection_client = utils.get_client_class( + API_NAME, + instance._api_version[API_NAME], + API_VERSIONS) + LOG.debug('Instantiating data protection client: %s', + data_protection_client) + client = data_protection_client( + auth=instance.auth, + session=instance.session, + service_type="data-protect" + ) + + return client + + +def build_option_parser(parser): + """Hook to add global options""" + parser.add_argument( + '--os-data-protection-api-version', + metavar='', + default=utils.env( + 'OS_DATA_PROTECTION_API_VERSION', + default=DEFAULT_DATA_PROTECTION_API_VERSION), + help='Data protection API version, default=' + + DEFAULT_DATA_PROTECTION_API_VERSION + + ' (Env: OS_DATA_PROTECTION_API_VERSION)') + return parser diff --git a/karborclient/osc/v1/__init__.py b/karborclient/osc/v1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/karborclient/osc/v1/plans.py b/karborclient/osc/v1/plans.py new file mode 100644 index 0000000..afd3c85 --- /dev/null +++ b/karborclient/osc/v1/plans.py @@ -0,0 +1,98 @@ +# 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 plan action implementations""" + +from osc_lib.command import command +from osc_lib import utils +from oslo_log import log as logging + +from karborclient.i18n import _ + + +class ListPlans(command.Lister): + _description = _("List plans.") + + log = logging.getLogger(__name__ + ".ListPlans") + + def get_parser(self, prog_name): + parser = super(ListPlans, self).get_parser(prog_name) + parser.add_argument( + '--all-projects', + action='store_true', + default=False, + help=_('Include all projects (admin only)'), + ) + parser.add_argument( + '--name', + metavar='', + help=_('Filter results by plan name'), + ) + parser.add_argument( + '--description', + metavar='', + help=_('Filter results by plan description'), + ) + parser.add_argument( + '--status', + metavar='', + help=_('Filter results by status'), + ) + parser.add_argument( + '--marker', + metavar='', + help=_('The last plan ID of the previous page'), + ) + parser.add_argument( + '--limit', + type=int, + metavar='', + help=_('Maximum number of plans to display'), + ) + parser.add_argument( + '--sort', + metavar="[:]", + default=None, + help=_("Sort output by selected keys and directions(asc or desc) " + "(default: name:asc), multiple keys and directions can be " + "specified separated by comma"), + ) + parser.add_argument( + '--tenant', + metavar='', + help=_('Filter results by a tenant(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.tenant) or parsed_args.all_projects + + search_opts = { + 'all_tenants': all_projects, + 'project_id': parsed_args.tenant, + 'name': parsed_args.name, + 'description': parsed_args.description, + 'status': parsed_args.status, + } + + data = data_protection_client.plans.list( + search_opts=search_opts, marker=parsed_args.marker, + limit=parsed_args.limit, sort=parsed_args.sort) + + column_headers = ['Id', 'Name', 'Description', 'Provider id', 'Status'] + + return (column_headers, + (utils.get_item_properties( + s, column_headers + ) for s in data)) diff --git a/karborclient/tests/unit/osc/__init__.py b/karborclient/tests/unit/osc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/karborclient/tests/unit/osc/v1/__init__.py b/karborclient/tests/unit/osc/v1/__init__.py new file mode 100644 index 0000000..df84054 --- /dev/null +++ b/karborclient/tests/unit/osc/v1/__init__.py @@ -0,0 +1 @@ +__author__ = 'c00179918' diff --git a/karborclient/tests/unit/osc/v1/fakes.py b/karborclient/tests/unit/osc/v1/fakes.py new file mode 100644 index 0000000..4c11a2a --- /dev/null +++ b/karborclient/tests/unit/osc/v1/fakes.py @@ -0,0 +1,29 @@ +# Copyright (c) 2015 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. + + +import mock +from osc_lib.tests import utils + + +class TestDataProtection(utils.TestCommand): + + def setUp(self): + super(TestDataProtection, self).setUp() + + self.app.client_manager.data_protection = mock.Mock() + self.app.client_manager.network = mock.Mock() + self.app.client_manager.compute = mock.Mock() + self.app.client_manager.volume = mock.Mock() diff --git a/karborclient/tests/unit/osc/v1/test_plans.py b/karborclient/tests/unit/osc/v1/test_plans.py new file mode 100644 index 0000000..4e7cdf2 --- /dev/null +++ b/karborclient/tests/unit/osc/v1/test_plans.py @@ -0,0 +1,65 @@ +# 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 karborclient.osc.v1 import plans as osc_plans +from karborclient.tests.unit.osc.v1 import fakes +from karborclient.v1 import plans + + +PLAN_INFO = { + "status": "suspended", + "provider_id": "cf56bd3e-97a7-4078-b6d5-f36246333fd9", + "description": "", + "parameters": {}, + "id": "204c825e-eb2f-4609-95ab-70b3caa43ac8", + "resources": [], + "name": "OS Volume protection plan." +} + + +class TestPlans(fakes.TestDataProtection): + def setUp(self): + super(TestPlans, self).setUp() + self.plans_mock = self.app.client_manager.data_protection.plans + self.plans_mock.reset_mock() + + +class TestListPlans(TestPlans): + def setUp(self): + super(TestListPlans, self).setUp() + self.plans_mock.list.return_value = [plans.Plan( + None, PLAN_INFO)] + + # Command to test + self.cmd = osc_plans.ListPlans(self.app, None) + + def test_plans_list(self): + arglist = ['--status', 'suspended'] + verifylist = [('status', 'suspended')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + # Check that columns are correct + expected_columns = ( + ['Id', 'Name', 'Description', 'Provider id', 'Status']) + self.assertEqual(expected_columns, columns) + + # Check that data is correct + expected_data = [("204c825e-eb2f-4609-95ab-70b3caa43ac8", + "OS Volume protection plan.", + "", + "cf56bd3e-97a7-4078-b6d5-f36246333fd9", + "suspended")] + self.assertEqual(expected_data, list(data)) diff --git a/requirements.txt b/requirements.txt index 9195759..85647e0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,7 @@ requests!=2.12.2,!=2.13.0,>=2.10.0 # Apache-2.0 simplejson>=2.2.0 # MIT Babel!=2.4.0,>=2.3.4 # BSD six>=1.9.0 # MIT +osc-lib>=1.5.1 # Apache-2.0 oslo.utils>=3.20.0 # Apache-2.0 oslo.log>=3.22.0 # Apache-2.0 oslo.i18n>=2.1.0 # Apache-2.0 diff --git a/setup.cfg b/setup.cfg index 4811047..4012942 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,6 +30,12 @@ packages = console_scripts = karbor = karborclient.shell:main +openstack.cli.extension = + data_protection = karborclient.osc.plugin + +openstack.data_protection.v1 = + dataprotection_plan_list = karborclient.osc.v1.plans:ListPlans + [build_sphinx] source-dir = doc/source build-dir = doc/build diff --git a/test-requirements.txt b/test-requirements.txt index 0f8d8d9..613667f 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -10,6 +10,8 @@ docutils>=0.11 # OSI-Approved Open Source, Public Domain sphinx!=1.6.1,>=1.5.1 # BSD oslosphinx>=4.7.0 # Apache-2.0 oslotest>=1.10.0 # Apache-2.0 +python-openstackclient!=3.10.0,>=3.3.0 # Apache-2.0 +requests-mock>=1.1 # Apache-2.0 testrepository>=0.0.18 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD testtools>=1.4.0 # MIT