add name for audit, changes for python-watcherclient

Change-Id: I9000018459913cd3107814e34977525eb3da10f4
Implements:blueprint add-name-for-audit
This commit is contained in:
suzhengwei
2017-06-19 18:45:15 +08:00
parent 0a29b296ae
commit f5b2e7e4f5
6 changed files with 94 additions and 52 deletions

View File

@@ -68,7 +68,7 @@ Once you have an watcher `Client`_, you can perform various tasks::
>>> watcher.action.list() # list of actions >>> watcher.action.list() # list of actions
>>> watcher.action_plan.list() # list of action_plan >>> watcher.action_plan.list() # list of action_plan
>>> watcher.audit.get(audit_uuid) # information about a particular audit >>> watcher.audit.get(audit_uuid_or_name) # information about a particular audit
When the `Client`_ needs to propagate an exception, it will usually When the `Client`_ needs to propagate an exception, it will usually
raise an instance subclassed from raise an instance subclassed from

View File

@@ -22,7 +22,7 @@ class AuditTests(base.TestCase):
"""Functional tests for audit.""" """Functional tests for audit."""
dummy_name = 'dummy' dummy_name = 'dummy'
list_fields = ['UUID', 'Audit Type', 'State', 'Goal', 'Strategy'] list_fields = ['UUID', 'Name', 'Audit Type', 'State', 'Goal', 'Strategy']
detailed_list_fields = list_fields + ['Created At', 'Updated At', detailed_list_fields = list_fields + ['Created At', 'Updated At',
'Deleted At', 'Parameters', 'Deleted At', 'Parameters',
'Interval', 'Audit Scope', 'Interval', 'Audit Scope',
@@ -71,7 +71,7 @@ class AuditTests(base.TestCase):
class AuditActiveTests(base.TestCase): class AuditActiveTests(base.TestCase):
list_fields = ['UUID', 'Audit Type', 'State', 'Goal', 'Strategy'] list_fields = ['UUID', 'Name', 'Audit Type', 'State', 'Goal', 'Strategy']
detailed_list_fields = list_fields + ['Created At', 'Updated At', detailed_list_fields = list_fields + ['Created At', 'Updated At',
'Deleted At', 'Parameters', 'Deleted At', 'Parameters',
'Interval', 'Audit Scope'] 'Interval', 'Audit Scope']

94
watcherclient/tests/unit/v1/test_audit_shell.py Normal file → Executable file
View File

@@ -17,7 +17,6 @@ import datetime
import mock import mock
import six import six
from watcherclient import exceptions
from watcherclient import shell from watcherclient import shell
from watcherclient.tests.unit.v1 import base from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource from watcherclient import v1 as resource
@@ -69,6 +68,7 @@ AUDIT_1 = {
'scope': '', 'scope': '',
'auto_trigger': False, 'auto_trigger': False,
'next_run_time': None, 'next_run_time': None,
'name': 'my_audit1',
} }
AUDIT_2 = { AUDIT_2 = {
@@ -87,6 +87,7 @@ AUDIT_2 = {
'scope': '', 'scope': '',
'auto_trigger': False, 'auto_trigger': False,
'next_run_time': None, 'next_run_time': None,
'name': 'my_audit2',
} }
AUDIT_3 = { AUDIT_3 = {
@@ -105,6 +106,7 @@ AUDIT_3 = {
'scope': '', 'scope': '',
'auto_trigger': True, 'auto_trigger': True,
'next_run_time': None, 'next_run_time': None,
'name': 'my_audit3',
} }
@@ -202,14 +204,19 @@ class AuditShellTest(base.CommandTestCase):
self.m_audit_mgr.get.assert_called_once_with( self.m_audit_mgr.get.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9') '5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_audit_show_by_not_uuid(self): def test_do_audit_show_by_name(self):
self.m_audit_mgr.get.side_effect = exceptions.HTTPNotFound audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.get.return_value = audit
exit_code, result = self.run_cmd( exit_code, result = self.run_cmd(
'audit show not_uuid', formatting=None) 'audit show my_audit')
self.assertEqual(1, exit_code) self.assertEqual(0, exit_code)
self.assertEqual('', result) self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.get.assert_called_once_with(
'my_audit')
def test_do_audit_delete(self): def test_do_audit_delete(self):
self.m_audit_mgr.delete.return_value = '' self.m_audit_mgr.delete.return_value = ''
@@ -223,6 +230,18 @@ class AuditShellTest(base.CommandTestCase):
self.m_audit_mgr.delete.assert_called_once_with( self.m_audit_mgr.delete.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9') '5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_audit_delete_by_name(self):
self.m_audit_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'audit delete my_audit',
formatting=None)
self.assertEqual(0, exit_code)
self.assertEqual('', result)
self.m_audit_mgr.delete.assert_called_once_with(
'my_audit')
def test_do_audit_delete_multiple(self): def test_do_audit_delete_multiple(self):
self.m_audit_mgr.delete.return_value = '' self.m_audit_mgr.delete.return_value = ''
@@ -238,16 +257,6 @@ class AuditShellTest(base.CommandTestCase):
self.m_audit_mgr.delete.assert_any_call( self.m_audit_mgr.delete.assert_any_call(
'5b157edd-5a7e-4aaa-b511-f7b33ec86e9f') '5b157edd-5a7e-4aaa-b511-f7b33ec86e9f')
def test_do_audit_delete_with_not_uuid(self):
self.m_audit_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'audit delete not_uuid',
formatting=None)
self.assertEqual(1, exit_code)
self.assertEqual('', result)
def test_do_audit_update(self): def test_do_audit_update(self):
audit = resource.Audit(mock.Mock(), AUDIT_1) audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.update.return_value = audit self.m_audit_mgr.update.return_value = audit
@@ -264,14 +273,20 @@ class AuditShellTest(base.CommandTestCase):
'5869da81-4876-4687-a1ed-12cd64cf53d9', '5869da81-4876-4687-a1ed-12cd64cf53d9',
[{'op': 'replace', 'path': '/state', 'value': 'PENDING'}]) [{'op': 'replace', 'path': '/state', 'value': 'PENDING'}])
def test_do_audit_update_with_not_uuid(self): def test_do_audit_update_by_name(self):
self.m_audit_mgr.update.return_value = '' audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.update.return_value = audit
exit_code, result = self.run_cmd( exit_code, result = self.run_cmd(
'audit update not_uuid replace state=PENDING', formatting=None) 'audit update my_audit replace state=PENDING')
self.assertEqual(1, exit_code) self.assertEqual(0, exit_code)
self.assertEqual('', result) self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.update.assert_called_once_with(
'my_audit',
[{'op': 'replace', 'path': '/state', 'value': 'PENDING'}])
def test_do_audit_create_with_audit_template_uuid(self): def test_do_audit_create_with_audit_template_uuid(self):
audit = resource.Audit(mock.Mock(), AUDIT_3) audit = resource.Audit(mock.Mock(), AUDIT_3)
@@ -288,7 +303,9 @@ class AuditShellTest(base.CommandTestCase):
result) result)
self.m_audit_mgr.create.assert_called_once_with( self.m_audit_mgr.create.assert_called_once_with(
audit_template_uuid='f8e47706-efcf-49a4-a5c4-af604eb492f2', audit_template_uuid='f8e47706-efcf-49a4-a5c4-af604eb492f2',
audit_type='ONESHOT', auto_trigger=False) audit_type='ONESHOT',
auto_trigger=False
)
def test_do_audit_create_with_audit_template_name(self): def test_do_audit_create_with_audit_template_name(self):
audit = resource.Audit(mock.Mock(), AUDIT_3) audit = resource.Audit(mock.Mock(), AUDIT_3)
@@ -305,7 +322,8 @@ class AuditShellTest(base.CommandTestCase):
self.m_audit_mgr.create.assert_called_once_with( self.m_audit_mgr.create.assert_called_once_with(
audit_template_uuid='f8e47706-efcf-49a4-a5c4-af604eb492f2', audit_template_uuid='f8e47706-efcf-49a4-a5c4-af604eb492f2',
auto_trigger=False, auto_trigger=False,
audit_type='ONESHOT') audit_type='ONESHOT'
)
def test_do_audit_create_with_goal(self): def test_do_audit_create_with_goal(self):
audit = resource.Audit(mock.Mock(), AUDIT_1) audit = resource.Audit(mock.Mock(), AUDIT_1)
@@ -356,7 +374,9 @@ class AuditShellTest(base.CommandTestCase):
result) result)
self.m_audit_mgr.create.assert_called_once_with( self.m_audit_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836', goal='fc087747-61be-4aad-8126-b701731ae836',
auto_trigger=False, audit_type='ONESHOT') auto_trigger=False,
audit_type='ONESHOT'
)
def test_do_audit_create_with_parameter(self): def test_do_audit_create_with_parameter(self):
audit = resource.Audit(mock.Mock(), AUDIT_1) audit = resource.Audit(mock.Mock(), AUDIT_1)
@@ -374,7 +394,8 @@ class AuditShellTest(base.CommandTestCase):
goal='fc087747-61be-4aad-8126-b701731ae836', goal='fc087747-61be-4aad-8126-b701731ae836',
audit_type='ONESHOT', audit_type='ONESHOT',
auto_trigger=False, auto_trigger=False,
parameters={'para1': 10, 'para2': 20}) parameters={'para1': 10, 'para2': 20}
)
def test_do_audit_create_with_type_continuous(self): def test_do_audit_create_with_type_continuous(self):
audit = resource.Audit(mock.Mock(), AUDIT_1) audit = resource.Audit(mock.Mock(), AUDIT_1)
@@ -392,4 +413,25 @@ class AuditShellTest(base.CommandTestCase):
goal='fc087747-61be-4aad-8126-b701731ae836', goal='fc087747-61be-4aad-8126-b701731ae836',
audit_type='CONTINUOUS', audit_type='CONTINUOUS',
auto_trigger=False, auto_trigger=False,
interval='3600') interval='3600'
)
def test_do_audit_create_with_name(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.create.return_value = audit
exit_code, result = self.run_cmd(
'audit create -g fc087747-61be-4aad-8126-b701731ae836 '
'-t CONTINUOUS -i 3600 --name my_audit')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
audit_type='CONTINUOUS',
auto_trigger=False,
interval='3600',
name='my_audit'
)

View File

@@ -19,7 +19,8 @@ from watcherclient import exceptions as exc
CREATION_ATTRIBUTES = ['audit_template_uuid', 'audit_type', 'interval', CREATION_ATTRIBUTES = ['audit_template_uuid', 'audit_type', 'interval',
'parameters', 'goal', 'strategy', 'auto_trigger'] 'parameters', 'goal', 'strategy', 'auto_trigger',
'name']
class Audit(base.Resource): class Audit(base.Resource):
@@ -38,8 +39,7 @@ class AuditManager(base.Manager):
sort_dir=None, detail=False, goal=None, strategy=None): sort_dir=None, detail=False, goal=None, strategy=None):
"""Retrieve a list of audit. """Retrieve a list of audit.
:param audit_template: Name of the audit :param audit_template: Name of the audit template
:param name: Name of the audit
:param limit: The maximum number of results to return per :param limit: The maximum number of results to return per
request, if: request, if:
@@ -92,14 +92,14 @@ class AuditManager(base.Manager):
raise exc.InvalidAttribute() raise exc.InvalidAttribute()
return self._create(self._path(), new) return self._create(self._path(), new)
def get(self, audit_id): def get(self, audit):
try: try:
return self._list(self._path(audit_id))[0] return self._list(self._path(audit))[0]
except IndexError: except IndexError:
return None return None
def delete(self, audit_id): def delete(self, audit):
return self._delete(self._path(audit_id)) return self._delete(self._path(audit))
def update(self, audit_id, patch): def update(self, audit, patch):
return self._update(self._path(audit_id), patch) return self._update(self._path(audit), patch)

View File

@@ -31,7 +31,7 @@ class ShowAudit(command.ShowOne):
parser.add_argument( parser.add_argument(
'audit', 'audit',
metavar='<audit>', metavar='<audit>',
help=_('UUID of the audit'), help=_('UUID or name of the audit'),
) )
return parser return parser
@@ -175,13 +175,19 @@ class CreateAudit(command.ShowOne):
default=False, default=False,
help=_('Trigger automatically action plan ' help=_('Trigger automatically action plan '
'once audit is succeeded.')) 'once audit is succeeded.'))
parser.add_argument(
'--name',
dest='name',
metavar='<name>',
help=_('Name for this audit.'))
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim") client = getattr(self.app.client_manager, "infra-optim")
field_list = ['audit_template_uuid', 'audit_type', 'parameters', field_list = ['audit_template_uuid', 'audit_type', 'parameters',
'interval', 'goal', 'strategy', 'auto_trigger'] 'interval', 'goal', 'strategy', 'auto_trigger', 'name']
fields = dict((k, v) for (k, v) in vars(parsed_args).items() fields = dict((k, v) for (k, v) in vars(parsed_args).items()
if k in field_list and v is not None) if k in field_list and v is not None)
@@ -219,7 +225,7 @@ class UpdateAudit(command.ShowOne):
parser.add_argument( parser.add_argument(
'audit', 'audit',
metavar='<audit>', metavar='<audit>',
help=_("UUID of the audit.")) help=_("UUID or name of the audit."))
parser.add_argument( parser.add_argument(
'op', 'op',
metavar='<op>', metavar='<op>',
@@ -239,9 +245,6 @@ class UpdateAudit(command.ShowOne):
def take_action(self, parsed_args): def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim") client = getattr(self.app.client_manager, "infra-optim")
if not uuidutils.is_uuid_like(parsed_args.audit):
raise exceptions.ValidationError()
patch = common_utils.args_array_to_patch( patch = common_utils.args_array_to_patch(
parsed_args.op, parsed_args.attributes[0], parsed_args.op, parsed_args.attributes[0],
exclude_fields=['/interval']) exclude_fields=['/interval'])
@@ -263,7 +266,7 @@ class DeleteAudit(command.Command):
'audits', 'audits',
metavar='<audit>', metavar='<audit>',
nargs='+', nargs='+',
help=_('UUID of the audit'), help=_('UUID or name of the audit'),
) )
return parser return parser
@@ -271,7 +274,4 @@ class DeleteAudit(command.Command):
client = getattr(self.app.client_manager, "infra-optim") client = getattr(self.app.client_manager, "infra-optim")
for audit in parsed_args.audits: for audit in parsed_args.audits:
if not uuidutils.is_uuid_like(audit):
raise exceptions.ValidationError()
client.audit.delete(audit) client.audit.delete(audit)

View File

@@ -30,20 +30,20 @@ AUDIT_TEMPLATE_SHORT_LIST_FIELDS = [
AUDIT_TEMPLATE_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Goal', 'Strategy'] AUDIT_TEMPLATE_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Goal', 'Strategy']
# Audit # Audit
AUDIT_FIELDS = ['uuid', 'created_at', 'updated_at', 'deleted_at', AUDIT_FIELDS = ['uuid', 'name', 'created_at', 'updated_at', 'deleted_at',
'state', 'audit_type', 'parameters', 'interval', 'goal_name', 'state', 'audit_type', 'parameters', 'interval', 'goal_name',
'strategy_name', 'scope', 'auto_trigger', 'next_run_time'] 'strategy_name', 'scope', 'auto_trigger', 'next_run_time']
AUDIT_FIELD_LABELS = ['UUID', 'Created At', 'Updated At', 'Deleted At', AUDIT_FIELD_LABELS = ['UUID', 'Name', 'Created At', 'Updated At', 'Deleted At',
'State', 'Audit Type', 'Parameters', 'Interval', 'Goal', 'State', 'Audit Type', 'Parameters', 'Interval', 'Goal',
'Strategy', 'Audit Scope', 'Auto Trigger', 'Strategy', 'Audit Scope', 'Auto Trigger',
'Next Run Time'] 'Next Run Time']
AUDIT_SHORT_LIST_FIELDS = ['uuid', 'audit_type', AUDIT_SHORT_LIST_FIELDS = ['uuid', 'name', 'audit_type',
'state', 'goal_name', 'strategy_name', 'state', 'goal_name', 'strategy_name',
'auto_trigger'] 'auto_trigger']
AUDIT_SHORT_LIST_FIELD_LABELS = ['UUID', 'Audit Type', 'State', 'Goal', AUDIT_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Audit Type', 'State', 'Goal',
'Strategy', 'Auto Trigger'] 'Strategy', 'Auto Trigger']
# Action Plan # Action Plan