diff options
author | Andrey Pavlov <apavlov@mirantis.com> | 2015-10-20 18:04:55 +0300 |
---|---|---|
committer | Andrey Pavlov <apavlov@mirantis.com> | 2015-10-20 18:04:55 +0300 |
commit | f007b70769cafc07e21787c3b72c7f765aa057ae (patch) | |
tree | b43d01fb6250729aa86ea6508652186a3c0f6381 | |
parent | c783dd593d508e739e0709b69d8f4552bcdf3bb2 (diff) | |
download | python-saharaclient-f007b70769cafc07e21787c3b72c7f765aa057ae.tar.gz |
Adding Job Types support to CLI
Adding Job Types commands to Sahara
OpenstackClient plugin:
$ dataprocessing job type list
$ dataprocessing job type configs get
Partially implements: blueprint cli-as-openstackclient-plugin
Change-Id: I259b006dc47da92952cdc2289ce0af8c200b39ef
-rw-r--r-- | saharaclient/osc/v1/job_types.py | 133 | ||||
-rw-r--r-- | saharaclient/tests/unit/osc/v1/test_job_types.py | 145 | ||||
-rw-r--r-- | setup.cfg | 3 |
3 files changed, 281 insertions, 0 deletions
diff --git a/saharaclient/osc/v1/job_types.py b/saharaclient/osc/v1/job_types.py new file mode 100644 index 0000000..ca483b8 --- /dev/null +++ b/saharaclient/osc/v1/job_types.py @@ -0,0 +1,133 @@ +# 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. + +from os import path + +from cliff import command +from cliff import lister +from openstackclient.common import exceptions +from openstackclient.common import utils as osc_utils +from oslo_log import log as logging +from oslo_serialization import jsonutils + +from saharaclient.osc.v1.job_templates import JOB_TYPES_CHOICES +from saharaclient.osc.v1 import utils + + +class ListJobTypes(lister.Lister): + """Lists job types supported by plugins""" + + log = logging.getLogger(__name__ + ".ListJobTypes") + + def get_parser(self, prog_name): + parser = super(ListJobTypes, self).get_parser(prog_name) + parser.add_argument( + '--type', + metavar="<type>", + choices=JOB_TYPES_CHOICES, + help="Get information about specific job type" + ) + parser.add_argument( + '--plugin', + metavar="<plugin>", + help="Get only job types supported by this plugin" + ) + parser.add_argument( + '--version', + metavar="<version>", + help="Get only job types supported by specific version of the " + "plugin. This parameter will be taken into account only if " + "plugin is provided" + ) + + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)" % parsed_args) + client = self.app.client_manager.data_processing + + search_opts = {} + if parsed_args.type: + search_opts['type'] = parsed_args.type + if parsed_args.plugin: + search_opts['plugin'] = parsed_args.plugin + if parsed_args.version: + search_opts['version'] = parsed_args.version + elif parsed_args.version: + raise exceptions.CommandError( + '--version argument should be specified with --plugin ' + 'argument') + + data = client.job_types.list(search_opts=search_opts) + for job in data: + plugins = [] + for plugin in job.plugins: + versions = ", ".join(sorted(plugin["versions"].keys())) + if versions: + versions = "(" + versions + ")" + plugins.append(plugin["name"] + versions) + job.plugins = ', '.join(plugins) + + columns = ('name', 'plugins') + column_headers = utils.prepare_column_headers(columns) + + return ( + column_headers, + (osc_utils.get_item_properties( + s, + columns + ) for s in data) + ) + + +class GetJobTypeConfigs(command.Command): + """Get job type configs""" + + log = logging.getLogger(__name__ + ".GetJobTypeConfigs") + + def get_parser(self, prog_name): + parser = super(GetJobTypeConfigs, self).get_parser(prog_name) + parser.add_argument( + "job_type", + metavar="<job-type>", + choices=JOB_TYPES_CHOICES, + help="Type of the job to provide config information about", + ) + parser.add_argument( + '--file', + metavar="<file>", + help='Destination file (defaults to job type)', + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)" % parsed_args) + client = self.app.client_manager.data_processing + + if not parsed_args.file: + parsed_args.file = parsed_args.job_type + + data = client.jobs.get_configs(parsed_args.job_type).to_dict() + + if path.exists(parsed_args.file): + self.log.error('File "%s" already exists. Choose another one with ' + '--file argument.' % parsed_args.file) + else: + with open(parsed_args.file, 'w') as f: + jsonutils.dump(data, f, indent=4) + self.log.info( + '"%(type)s" job configs were saved in "%(file)s"' + 'file' % {'type': parsed_args.job_type, + 'file': parsed_args.file}) diff --git a/saharaclient/tests/unit/osc/v1/test_job_types.py b/saharaclient/tests/unit/osc/v1/test_job_types.py new file mode 100644 index 0000000..ed2c1bb --- /dev/null +++ b/saharaclient/tests/unit/osc/v1/test_job_types.py @@ -0,0 +1,145 @@ +# 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 saharaclient.api import job_types as api_jt +from saharaclient.api import jobs as api_j +from saharaclient.osc.v1 import job_types as osc_jt + +from saharaclient.tests.unit.osc.v1 import fakes + +JOB_TYPE_INFO = { + "name": 'Pig', + "plugins": [ + { + 'versions': { + '0.1': {}, + '0.2': {} + }, + 'name': 'fake' + }, + { + 'versions': { + '6.2.2': {} + }, + 'name': 'wod' + } + ] +} + + +class TestJobTypes(fakes.TestDataProcessing): + def setUp(self): + super(TestJobTypes, self).setUp() + self.job_mock = self.app.client_manager.data_processing.jobs + self.jt_mock = self.app.client_manager.data_processing.job_types + self.jt_mock.reset_mock() + self.job_mock.reset_mock() + + +class TestListJobTemplates(TestJobTypes): + def setUp(self): + super(TestListJobTemplates, self).setUp() + self.jt_mock.list.return_value = [api_jt.JobType(None, JOB_TYPE_INFO)] + + # Command to test + self.cmd = osc_jt.ListJobTypes(self.app, None) + + def test_job_types_list_no_options(self): + arglist = [] + verifylist = [] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + # Check that columns are correct + expected_columns = ['Name', 'Plugins'] + self.assertEqual(expected_columns, columns) + + # Check that data is correct + expected_data = [('Pig', 'fake(0.1, 0.2), wod(6.2.2)')] + self.assertEqual(expected_data, list(data)) + + def test_job_types_list_extra_search_opts(self): + arglist = ['--type', 'Pig', '--plugin', 'fake', '--version', '0.1'] + verifylist = [('type', 'Pig'), ('plugin', 'fake'), ('version', '0.1')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + # Check that columns are correct + expected_columns = ['Name', 'Plugins'] + self.assertEqual(expected_columns, columns) + + # Check that data is correct + expected_data = [('Pig', 'fake(0.1, 0.2), wod(6.2.2)')] + self.assertEqual(expected_data, list(data)) + + +class TestGetJobTypeConfigs(TestJobTypes): + def setUp(self): + super(TestGetJobTypeConfigs, self).setUp() + self.job_mock.get_configs.return_value = ( + api_j.Job(None, JOB_TYPE_INFO)) + + # Command to test + self.cmd = osc_jt.GetJobTypeConfigs(self.app, None) + + @mock.patch('oslo_serialization.jsonutils.dump') + def test_get_job_type_configs_default_file(self, p_dump): + m_open = mock.mock_open() + with mock.patch('six.moves.builtins.open', m_open, create=True): + arglist = ['Pig'] + verifylist = [('job_type', 'Pig')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + + # Check that correct arguments was passed + self.job_mock.get_configs.assert_called_once_with( + 'Pig') + + args_to_dump = p_dump.call_args[0] + # Check that the right data will be saved + + self.assertEqual(JOB_TYPE_INFO, args_to_dump[0]) + # Check that data will be saved to the right file + self.assertEqual('Pig', m_open.call_args[0][0]) + + @mock.patch('oslo_serialization.jsonutils.dump') + def test_get_job_type_configs_specified_file(self, p_dump): + m_open = mock.mock_open() + with mock.patch('six.moves.builtins.open', m_open): + arglist = ['Pig', '--file', 'testfile'] + verifylist = [('job_type', 'Pig'), ('file', 'testfile')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + + # Check that correct arguments was passed + self.job_mock.get_configs.assert_called_once_with( + 'Pig') + + args_to_dump = p_dump.call_args[0] + # Check that the right data will be saved + + self.assertEqual(JOB_TYPE_INFO, args_to_dump[0]) + # Check that data will be saved to the right file + self.assertEqual('testfile', m_open.call_args[0][0]) @@ -79,6 +79,9 @@ openstack.data_processing.v1 = dataprocessing_job_template_update = saharaclient.osc.v1.job_templates:UpdateJobTemplate dataprocessing_job_template_delete = saharaclient.osc.v1.job_templates:DeleteJobTemplate + dataprocessing_job_type_list = saharaclient.osc.v1.job_types:ListJobTypes + dataprocessing_job_type_configs_get = saharaclient.osc.v1.job_types:GetJobTypeConfigs + [build_sphinx] all_files = 1 build-dir = doc/build |