Implemented the notification subcommands masakari CLI
This patch adds sub commands of notification. Change-Id: I8f756ebad2f7d470e5c229b2416d59a5d9943810 Implements: bp implement-masakari-cli
This commit is contained in:
parent
8b222138a9
commit
1257f0985c
@ -30,7 +30,9 @@ def add_global_args(parser, version):
|
||||
help=_('Version number for Masakari API to use, Default to "1".'))
|
||||
|
||||
parser.add_argument(
|
||||
'--debug', default=False, action='store_true',
|
||||
'-d', '--debug',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_('Print debugging output.'))
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from oslo_utils import encodeutils
|
||||
@ -26,6 +27,7 @@ from masakariclient.common.i18n import _
|
||||
from masakariclient.common import utils
|
||||
|
||||
USER_AGENT = 'python-masakariclient'
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MasakariShell(object):
|
||||
@ -113,6 +115,16 @@ class MasakariShell(object):
|
||||
|
||||
return masakari_client.Client(api_ver, user_agent=USER_AGENT, **kwargs)
|
||||
|
||||
def _setup_logging(self, debug):
|
||||
if debug:
|
||||
log_level = logging.DEBUG
|
||||
else:
|
||||
log_level = logging.WARNING
|
||||
log_format = "%(levelname)s (%(module)s) %(message)s"
|
||||
logging.basicConfig(format=log_format, level=log_level)
|
||||
logging.getLogger('iso8601').setLevel(logging.WARNING)
|
||||
logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING)
|
||||
|
||||
def main(self, argv):
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
@ -129,6 +141,8 @@ class MasakariShell(object):
|
||||
# parse main arguments
|
||||
(options, args) = parser.parse_known_args(argv)
|
||||
|
||||
self._setup_logging(options.debug)
|
||||
|
||||
base_parser = parser
|
||||
api_ver = options.masakari_api_version
|
||||
|
||||
@ -177,7 +191,7 @@ def main(args=None):
|
||||
print(_("KeyboardInterrupt masakari client"), sys.stderr)
|
||||
return 130
|
||||
except Exception as e:
|
||||
if '--debug' in args:
|
||||
if '--debug' in args or '-d' in args:
|
||||
raise
|
||||
else:
|
||||
print(encodeutils.safe_encode(six.text_type(e)), sys.stderr)
|
||||
|
0
masakariclient/tests/unit/__init__.py
Normal file
0
masakariclient/tests/unit/__init__.py
Normal file
29
masakariclient/tests/unit/test_cliargs.py
Normal file
29
masakariclient/tests/unit/test_cliargs.py
Normal file
@ -0,0 +1,29 @@
|
||||
# Copyright(c) 2016 Nippon Telegraph and Telephone Corporation
|
||||
#
|
||||
# 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
|
||||
import testtools
|
||||
|
||||
from masakariclient import cliargs
|
||||
|
||||
|
||||
class TestCliArgs(testtools.TestCase):
|
||||
|
||||
def test_add_global_identity_args(self):
|
||||
parser = mock.Mock()
|
||||
cliargs.add_global_identity_args(parser)
|
||||
|
||||
def test_add_global_args(self):
|
||||
parser = mock.Mock()
|
||||
cliargs.add_global_args(parser, '1')
|
@ -1,3 +1,5 @@
|
||||
# Copyright(c) 2016 Nippon Telegraph and Telephone Corporation
|
||||
#
|
||||
# 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
|
||||
@ -16,11 +18,30 @@ test_masakariclient
|
||||
|
||||
Tests for `masakariclient` module.
|
||||
"""
|
||||
import mock
|
||||
|
||||
from masakariclient import client as mc
|
||||
from masakariclient.common import utils
|
||||
from masakariclient.tests import base
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
|
||||
def __init__(self, session):
|
||||
super(FakeClient, self).__init__()
|
||||
self.session = session
|
||||
|
||||
|
||||
class TestMasakariclient(base.TestCase):
|
||||
|
||||
def test_something(self):
|
||||
pass
|
||||
@mock.patch.object(utils, 'import_versioned_module')
|
||||
def test_client_init(self, mock_import):
|
||||
the_module = mock.Mock()
|
||||
the_module.Client = FakeClient
|
||||
mock_import.return_value = the_module
|
||||
session = mock.Mock()
|
||||
|
||||
res = mc.Client('FAKE_VER', session)
|
||||
|
||||
mock_import.assert_called_once_with('FAKE_VER', 'client')
|
||||
self.assertIsInstance(res, FakeClient)
|
128
masakariclient/tests/unit/test_shell.py
Normal file
128
masakariclient/tests/unit/test_shell.py
Normal file
@ -0,0 +1,128 @@
|
||||
# Copyright(c) 2016 Nippon Telegraph and Telephone Corporation
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
test_shell
|
||||
----------------------------------
|
||||
|
||||
Tests for `masakariclient` module.
|
||||
"""
|
||||
import logging
|
||||
import mock
|
||||
import six
|
||||
import sys
|
||||
import testtools
|
||||
|
||||
from masakariclient import shell
|
||||
from masakariclient.tests import base
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
|
||||
def __init__(self):
|
||||
super(FakeClient, self).__init__()
|
||||
self.service = FakeService()
|
||||
return self.service
|
||||
|
||||
|
||||
class FakeService(object):
|
||||
|
||||
def __init__(self):
|
||||
super(FakeService, self).__init__()
|
||||
|
||||
def do_notification_list(self):
|
||||
pass
|
||||
|
||||
|
||||
class HelpFormatterTest(testtools.TestCase):
|
||||
|
||||
def test_start_section(self):
|
||||
formatter = shell.HelpFormatter('masakari')
|
||||
res = formatter.start_section(('dummyheading', 'dummy', 'dummy'))
|
||||
self.assertIsNone(res)
|
||||
heading = formatter._current_section.heading
|
||||
self.assertEqual("DUMMYHEADING('dummy', 'dummy')", heading)
|
||||
|
||||
|
||||
class TestMasakariShell(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestMasakariShell, self).setUp()
|
||||
|
||||
def _shell(self, func, *args, **kwargs):
|
||||
orig_out = sys.stdout
|
||||
sys.stdout = six.StringIO()
|
||||
func(*args, **kwargs)
|
||||
output = sys.stdout.getvalue()
|
||||
sys.stdout.close()
|
||||
sys.stdout = orig_out
|
||||
|
||||
return output
|
||||
|
||||
def test_do_bash_completion(self):
|
||||
sh = shell.MasakariShell()
|
||||
sc1 = mock.Mock()
|
||||
sc2 = mock.Mock()
|
||||
sc1._optionals._option_string_actions = ('A1', 'A2', 'C')
|
||||
sc2._optionals._option_string_actions = ('B1', 'B2', 'C')
|
||||
sh.subcommands = {
|
||||
'command-foo': sc1,
|
||||
'command-bar': sc2,
|
||||
'bash-completion': None,
|
||||
'bash_completion': None,
|
||||
}
|
||||
|
||||
output = self._shell(sh.do_bash_completion, None)
|
||||
|
||||
output = output.split('\n')[0]
|
||||
output_list = output.split(' ')
|
||||
for option in ('A1', 'A2', 'C', 'B1', 'B2',
|
||||
'command-foo', 'command-bar'):
|
||||
self.assertIn(option, output_list)
|
||||
|
||||
@mock.patch.object(logging, 'basicConfig')
|
||||
@mock.patch.object(logging, 'getLogger')
|
||||
def test_setup_logging_debug_true(self, moc_getLogger,
|
||||
moc_basicConfig):
|
||||
sh = shell.MasakariShell()
|
||||
sh._setup_logging(True)
|
||||
|
||||
moc_basicConfig.assert_called_once_with(
|
||||
format="%(levelname)s (%(module)s) %(message)s",
|
||||
level=logging.DEBUG)
|
||||
mock_calls = [
|
||||
mock.call('iso8601'),
|
||||
mock.call().setLevel(logging.WARNING),
|
||||
mock.call('urllib3.connectionpool'),
|
||||
mock.call().setLevel(logging.WARNING),
|
||||
]
|
||||
moc_getLogger.assert_has_calls(mock_calls)
|
||||
|
||||
@mock.patch.object(logging, 'basicConfig')
|
||||
@mock.patch.object(logging, 'getLogger')
|
||||
def test_setup_logging_debug_false(self,
|
||||
moc_getLogger,
|
||||
moc_basicConfig):
|
||||
sh = shell.MasakariShell()
|
||||
sh._setup_logging(False)
|
||||
|
||||
moc_basicConfig.assert_called_once_with(
|
||||
format="%(levelname)s (%(module)s) %(message)s",
|
||||
level=logging.WARNING)
|
||||
mock_calls = [
|
||||
mock.call('iso8601'),
|
||||
mock.call().setLevel(logging.WARNING),
|
||||
mock.call('urllib3.connectionpool'),
|
||||
mock.call().setLevel(logging.WARNING),
|
||||
]
|
||||
moc_getLogger.assert_has_calls(mock_calls)
|
0
masakariclient/tests/unit/v1/__init__.py
Normal file
0
masakariclient/tests/unit/v1/__init__.py
Normal file
50
masakariclient/tests/unit/v1/test_client.py
Normal file
50
masakariclient/tests/unit/v1/test_client.py
Normal file
@ -0,0 +1,50 @@
|
||||
# Copyright(c) 2016 Nippon Telegraph and Telephone Corporation
|
||||
#
|
||||
# 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.
|
||||
"""
|
||||
test_masakariclient
|
||||
----------------------------------
|
||||
|
||||
Tests for `masakariclient` module.
|
||||
"""
|
||||
import mock
|
||||
|
||||
from masakariclient.sdk.ha import connection
|
||||
from masakariclient.tests import base
|
||||
import masakariclient.v1.client as mc
|
||||
|
||||
|
||||
class FakeConnection(object):
|
||||
|
||||
def __init__(self, prof=None, user_agent=None, **kwargs):
|
||||
super(FakeConnection, self).__init__()
|
||||
self.vmha = None
|
||||
|
||||
|
||||
class TestV1Client(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestV1Client, self).setUp()
|
||||
self.conn = mock.Mock()
|
||||
self.service = mock.Mock()
|
||||
self.conn.vmha = self.service
|
||||
|
||||
def test_client_init(self):
|
||||
with mock.patch.object(connection,
|
||||
'create_connection') as mock_connection:
|
||||
mock_connection.return_value = self.conn
|
||||
|
||||
res = mc.Client()
|
||||
|
||||
self.assertEqual(self.conn.ha, res.service)
|
||||
mock_connection.assert_called_once_with(prof=None, user_agent=None)
|
57
masakariclient/tests/unit/v1/test_shell.py
Normal file
57
masakariclient/tests/unit/v1/test_shell.py
Normal file
@ -0,0 +1,57 @@
|
||||
# Copyright(c) 2016 Nippon Telegraph and Telephone Corporation
|
||||
#
|
||||
# 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.
|
||||
"""
|
||||
test_masakariclient
|
||||
----------------------------------
|
||||
|
||||
Tests for `masakariclient` module.
|
||||
"""
|
||||
import mock
|
||||
|
||||
from masakariclient.common import utils
|
||||
from masakariclient.tests import base
|
||||
import masakariclient.v1.shell as ms
|
||||
|
||||
|
||||
class TestV1Shell(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestV1Shell, self).setUp()
|
||||
self.vals = {
|
||||
'notification_uuid': 'b3bf75d7-c2e9-4023-a10b-e5b464b9b539',
|
||||
'source_host_uuid': '68fa7386-983e-4497-b5c4-3780f774d302',
|
||||
'created_at': '2016-11-15T12:24:39.000000',
|
||||
'updated_at': None,
|
||||
'payload': {'event': 'STOPPED'},
|
||||
'generated_time': '2016-10-10T10:00:00.000000',
|
||||
'type': 'VM',
|
||||
'id': '27'}
|
||||
|
||||
@mock.patch.object(utils, 'print_list')
|
||||
def test_do_notification_list(self, mock_print_list):
|
||||
service = mock.Mock()
|
||||
service.notifications.return_value = self.vals
|
||||
args = mock.Mock()
|
||||
columns = [
|
||||
'notification_uuid',
|
||||
'generated_time',
|
||||
'status',
|
||||
'source_host_uuid',
|
||||
'type']
|
||||
|
||||
ms.do_notification_list(service, args)
|
||||
|
||||
mock_print_list.assert_called_once_with(
|
||||
self.vals,
|
||||
columns)
|
@ -12,4 +12,61 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Implement sub commands in this file after that."""
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from masakariclient.common import utils
|
||||
|
||||
|
||||
def do_notification_list(service, args):
|
||||
"""List notifications.
|
||||
|
||||
:param service: service object.
|
||||
:param args: API args.
|
||||
"""
|
||||
try:
|
||||
notifications = service.notifications()
|
||||
columns = [
|
||||
'notification_uuid', 'generated_time', 'status',
|
||||
'source_host_uuid', 'type']
|
||||
utils.print_list(notifications, columns)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
@utils.arg('--id', metavar='<NOTIFICATION_ID>', required=True,
|
||||
help='Notification to display (name or ID)')
|
||||
def do_notification_show(service, args):
|
||||
"""Show a notification details."""
|
||||
try:
|
||||
notification = service.get_notification(args.id)
|
||||
utils.print_dict(notification.to_dict())
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
@utils.arg('--type', metavar='<TYPE>', required=True,
|
||||
help='Type of failure.')
|
||||
@utils.arg('--hostname', metavar='<HOSTNAME>', required=True,
|
||||
help='Hostname of notification.')
|
||||
@utils.arg('--generated-time', metavar='<GENERATED_TIME>', required=True,
|
||||
help='Timestamp for notification. e.g. 2016-01-01T01:00:00.000')
|
||||
@utils.arg('--payload', metavar='<PAYLOAD>', required=True,
|
||||
help='JSON string about failure event.')
|
||||
def do_notification_create(service, args):
|
||||
"""Create a notification."""
|
||||
try:
|
||||
payload = jsonutils.loads(args.payload)
|
||||
attrs = {
|
||||
'type': args.type,
|
||||
'hostname': args.hostname,
|
||||
'generated_time': args.generated_time,
|
||||
'payload': payload,
|
||||
}
|
||||
notification = service.create_notification(**attrs)
|
||||
utils.print_dict(notification.to_dict())
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
Loading…
Reference in New Issue
Block a user