summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Pavlov <apavlov@mirantis.com>2015-10-20 18:04:55 +0300
committerAndrey Pavlov <apavlov@mirantis.com>2015-10-20 18:04:55 +0300
commitf007b70769cafc07e21787c3b72c7f765aa057ae (patch)
treeb43d01fb6250729aa86ea6508652186a3c0f6381
parentc783dd593d508e739e0709b69d8f4552bcdf3bb2 (diff)
downloadpython-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.py133
-rw-r--r--saharaclient/tests/unit/osc/v1/test_job_types.py145
-rw-r--r--setup.cfg3
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])
diff --git a/setup.cfg b/setup.cfg
index 7710e02..2862ad1 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -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