Add name support for show, update and delete
Since the alarm name is limited to be unique for each project, add support for users to show, update and delete alarms using alarm name will be much more user friendly than using alarm_id. Partial-Bug: #1556809 Change-Id: I2d9316a24372f28b65c15a02aaefda8c0a1f748b
This commit is contained in:
@@ -47,6 +47,10 @@ class MutipleMeaningException(object):
|
||||
"""An mixin for exception that can be enhanced by reading the details"""
|
||||
|
||||
|
||||
class CommandError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BadRequest(ClientException):
|
||||
"""HTTP 400 - Bad request: you sent some malformed data."""
|
||||
http_status = 400
|
||||
@@ -110,6 +114,10 @@ class RateLimit(RetryAfterException):
|
||||
message = "Rate limit"
|
||||
|
||||
|
||||
class NoUniqueMatch(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class NotImplemented(ClientException):
|
||||
"""HTTP 501 - Not Implemented:
|
||||
|
||||
|
@@ -73,6 +73,21 @@ class AodhClientTest(base.ClientTestBase):
|
||||
self.assertEqual('ev_alarm1', alarm_show['name'])
|
||||
self.assertEqual('dummy', alarm_show['event_type'])
|
||||
|
||||
# GET BY NAME
|
||||
result = self.aodh(
|
||||
'alarm', params="show --alarm-name ev_alarm1")
|
||||
alarm_show = self.details_multiple(result)[0]
|
||||
self.assertEqual(ALARM_ID, alarm_show["alarm_id"])
|
||||
self.assertEqual(PROJECT_ID, alarm_show["project_id"])
|
||||
self.assertEqual('ev_alarm1', alarm_show['name'])
|
||||
self.assertEqual('dummy', alarm_show['event_type'])
|
||||
|
||||
# GET BY NAME AND ID ERROR
|
||||
self.assertRaises(exceptions.CommandFailed,
|
||||
self.aodh, u'alarm',
|
||||
params=(u"show %s --alarm-name ev_alarm1" %
|
||||
ALARM_ID))
|
||||
|
||||
# LIST
|
||||
result = self.aodh('alarm', params="list")
|
||||
self.assertIn(ALARM_ID,
|
||||
@@ -117,12 +132,12 @@ class AodhClientTest(base.ClientTestBase):
|
||||
|
||||
# CREATE
|
||||
result = self.aodh(u'alarm',
|
||||
params=(u"create --type threshold --name alarm1 "
|
||||
params=(u"create --type threshold --name alarm_th "
|
||||
"-m meter_name --threshold 5 "
|
||||
"--project-id %s" % PROJECT_ID))
|
||||
alarm = self.details_multiple(result)[0]
|
||||
ALARM_ID = alarm['alarm_id']
|
||||
self.assertEqual('alarm1', alarm['name'])
|
||||
self.assertEqual('alarm_th', alarm['name'])
|
||||
self.assertEqual('meter_name', alarm['meter_name'])
|
||||
self.assertEqual('5.0', alarm['threshold'])
|
||||
|
||||
@@ -144,17 +159,18 @@ class AodhClientTest(base.ClientTestBase):
|
||||
|
||||
# CREATE FAIL
|
||||
result = self.aodh(u'alarm',
|
||||
params=(u"create --type threshold --name alarm1 "
|
||||
params=(u"create --type threshold --name alarm_th "
|
||||
"-m meter_name --threshold 5 "
|
||||
"--project-id %s" % PROJECT_ID),
|
||||
fail_ok=True, merge_stderr=True)
|
||||
self.assertFirstLineStartsWith(
|
||||
result.split('\n'), "Alarm with name='alarm1' exists (HTTP 409)")
|
||||
result.split('\n'),
|
||||
"Alarm with name='alarm_th' exists (HTTP 409)")
|
||||
|
||||
# CREATE FAIL MISSING PARAM
|
||||
self.assertRaises(exceptions.CommandFailed,
|
||||
self.aodh, u'alarm',
|
||||
params=(u"create --type threshold --name alarm1 "
|
||||
params=(u"create --type threshold --name alarm_th "
|
||||
"--project-id %s" % PROJECT_ID))
|
||||
|
||||
# UPDATE
|
||||
@@ -172,10 +188,26 @@ class AodhClientTest(base.ClientTestBase):
|
||||
alarm_show = self.details_multiple(result)[0]
|
||||
self.assertEqual(ALARM_ID, alarm_show["alarm_id"])
|
||||
self.assertEqual(PROJECT_ID, alarm_show["project_id"])
|
||||
self.assertEqual('alarm1', alarm_show['name'])
|
||||
self.assertEqual('alarm_th', alarm_show['name'])
|
||||
self.assertEqual('meter_name', alarm_show['meter_name'])
|
||||
self.assertEqual('10.0', alarm_show['threshold'])
|
||||
|
||||
# GET BY NAME
|
||||
result = self.aodh(
|
||||
'alarm', params="show --alarm-name alarm_th")
|
||||
alarm_show = self.details_multiple(result)[0]
|
||||
self.assertEqual(ALARM_ID, alarm_show["alarm_id"])
|
||||
self.assertEqual(PROJECT_ID, alarm_show["project_id"])
|
||||
self.assertEqual('alarm_th', alarm_show['name'])
|
||||
self.assertEqual('meter_name', alarm_show['meter_name'])
|
||||
self.assertEqual('10.0', alarm_show['threshold'])
|
||||
|
||||
# GET BY NAME AND ID ERROR
|
||||
self.assertRaises(exceptions.CommandFailed,
|
||||
self.aodh, u'alarm',
|
||||
params=(u"show %s --alarm-name alarm_th" %
|
||||
ALARM_ID))
|
||||
|
||||
# LIST
|
||||
result = self.aodh('alarm', params="list")
|
||||
self.assertIn(ALARM_ID,
|
||||
@@ -185,14 +217,14 @@ class AodhClientTest(base.ClientTestBase):
|
||||
for alarm_list in self.parser.listing(result):
|
||||
self.assertEqual(sorted(output_colums), sorted(alarm_list.keys()))
|
||||
if alarm_list["alarm_id"] == ALARM_ID:
|
||||
self.assertEqual('alarm1', alarm_list['name'])
|
||||
self.assertEqual('alarm_th', alarm_list['name'])
|
||||
|
||||
# LIST WITH QUERY
|
||||
result = self.aodh('alarm',
|
||||
params=("list --query project_id=%s" % PROJECT_ID))
|
||||
alarm_list = self.parser.listing(result)[0]
|
||||
self.assertEqual(ALARM_ID, alarm_list["alarm_id"])
|
||||
self.assertEqual('alarm1', alarm_list['name'])
|
||||
self.assertEqual('alarm_th', alarm_list['name'])
|
||||
|
||||
# DELETE
|
||||
result = self.aodh('alarm', params="delete %s" % ALARM_ID)
|
||||
@@ -272,6 +304,20 @@ class AodhClientTest(base.ClientTestBase):
|
||||
self.assertEqual(project_id, alarm_show["project_id"])
|
||||
self.assertEqual('calarm1', alarm_show['name'])
|
||||
|
||||
# GET BY NAME
|
||||
result = self.aodh(
|
||||
'alarm', params="show --alarm-name calarm1")
|
||||
alarm_show = self.details_multiple(result)[0]
|
||||
self.assertEqual(alarm_id, alarm_show["alarm_id"])
|
||||
self.assertEqual(project_id, alarm_show["project_id"])
|
||||
self.assertEqual('calarm1', alarm_show['name'])
|
||||
|
||||
# GET BY NAME AND ID ERROR
|
||||
self.assertRaises(exceptions.CommandFailed,
|
||||
self.aodh, u'alarm',
|
||||
params=(u"show %s --alarm-name calarm1" %
|
||||
alarm_id))
|
||||
|
||||
# LIST
|
||||
result = self.aodh('alarm', params="list")
|
||||
self.assertIn(alarm_id,
|
||||
@@ -323,7 +369,7 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
|
||||
result = self.aodh(u'alarm',
|
||||
params=(u"create "
|
||||
"--type gnocchi_resources_threshold "
|
||||
"--name alarm1 --metric cpu_util "
|
||||
"--name alarm_gn1 --metric cpu_util "
|
||||
"--threshold 80 "
|
||||
"--resource-id %s --resource-type instance "
|
||||
"--aggregation-method last "
|
||||
@@ -331,7 +377,7 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
|
||||
% (RESOURCE_ID, PROJECT_ID)))
|
||||
alarm = self.details_multiple(result)[0]
|
||||
ALARM_ID = alarm['alarm_id']
|
||||
self.assertEqual('alarm1', alarm['name'])
|
||||
self.assertEqual('alarm_gn1', alarm['name'])
|
||||
self.assertEqual('cpu_util', alarm['metric'])
|
||||
self.assertEqual('80.0', alarm['threshold'])
|
||||
self.assertEqual('last', alarm['aggregation_method'])
|
||||
@@ -343,7 +389,7 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
|
||||
result = self.aodh(u'alarm',
|
||||
params=(u"create "
|
||||
"--type gnocchi_resources_threshold "
|
||||
"--name alarm1 --metric cpu_util "
|
||||
"--name alarm_gn1 --metric cpu_util "
|
||||
"--threshold 80 "
|
||||
"--resource-id %s --resource-type instance "
|
||||
"--aggregation-method last "
|
||||
@@ -351,7 +397,8 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
|
||||
% (RESOURCE_ID, PROJECT_ID)),
|
||||
fail_ok=True, merge_stderr=True)
|
||||
self.assertFirstLineStartsWith(
|
||||
result.split('\n'), "Alarm with name='alarm1' exists (HTTP 409)")
|
||||
result.split('\n'),
|
||||
"Alarm with name='alarm_gn1' exists (HTTP 409)")
|
||||
|
||||
# CREATE FAIL MISSING PARAM
|
||||
self.assertRaises(exceptions.CommandFailed,
|
||||
@@ -379,13 +426,31 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
|
||||
alarm_show = self.details_multiple(result)[0]
|
||||
self.assertEqual(ALARM_ID, alarm_show["alarm_id"])
|
||||
self.assertEqual(PROJECT_ID, alarm_show["project_id"])
|
||||
self.assertEqual('alarm1', alarm_show['name'])
|
||||
self.assertEqual('alarm_gn1', alarm_show['name'])
|
||||
self.assertEqual('cpu_util', alarm_show['metric'])
|
||||
self.assertEqual('90.0', alarm_show['threshold'])
|
||||
self.assertEqual('critical', alarm_show['severity'])
|
||||
self.assertEqual('last', alarm_show['aggregation_method'])
|
||||
self.assertEqual('instance', alarm_show['resource_type'])
|
||||
|
||||
# GET BY NAME
|
||||
result = self.aodh(
|
||||
'alarm', params="show --alarm-name alarm_gn1")
|
||||
self.assertEqual(ALARM_ID, alarm_show["alarm_id"])
|
||||
self.assertEqual(PROJECT_ID, alarm_show["project_id"])
|
||||
self.assertEqual('alarm_gn1', alarm_show['name'])
|
||||
self.assertEqual('cpu_util', alarm_show['metric'])
|
||||
self.assertEqual('90.0', alarm_show['threshold'])
|
||||
self.assertEqual('critical', alarm_show['severity'])
|
||||
self.assertEqual('last', alarm_show['aggregation_method'])
|
||||
self.assertEqual('instance', alarm_show['resource_type'])
|
||||
|
||||
# GET BY NAME AND ID ERROR
|
||||
self.assertRaises(exceptions.CommandFailed,
|
||||
self.aodh, u'alarm',
|
||||
params=(u"show %s --alarm-name alarm_gn1" %
|
||||
ALARM_ID))
|
||||
|
||||
# LIST
|
||||
result = self.aodh('alarm', params="list")
|
||||
self.assertIn(ALARM_ID,
|
||||
@@ -395,14 +460,14 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
|
||||
for alarm_list in self.parser.listing(result):
|
||||
self.assertEqual(sorted(output_colums), sorted(alarm_list.keys()))
|
||||
if alarm_list["alarm_id"] == ALARM_ID:
|
||||
self.assertEqual('alarm1', alarm_list['name'])
|
||||
self.assertEqual('alarm_gn1', alarm_list['name'])
|
||||
|
||||
# LIST WITH QUERY
|
||||
result = self.aodh('alarm',
|
||||
params=("list --query project_id=%s" % PROJECT_ID))
|
||||
alarm_list = self.parser.listing(result)[0]
|
||||
self.assertEqual(ALARM_ID, alarm_list["alarm_id"])
|
||||
self.assertEqual('alarm1', alarm_list['name'])
|
||||
self.assertEqual('alarm_gn1', alarm_list['name'])
|
||||
|
||||
# DELETE
|
||||
result = self.aodh('alarm', params="delete %s" % ALARM_ID)
|
||||
|
@@ -19,6 +19,8 @@ from cliff import show
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import strutils
|
||||
|
||||
from aodhclient import exceptions
|
||||
from aodhclient.i18n import _
|
||||
from aodhclient import utils
|
||||
|
||||
ALARM_TYPES = ['threshold', 'event', 'composite',
|
||||
@@ -65,16 +67,56 @@ def _format_alarm(alarm):
|
||||
return alarm
|
||||
|
||||
|
||||
def _find_alarm_by_name(client, name, return_id=False):
|
||||
# then try to get entity as name
|
||||
query = jsonutils.dumps({"=": {"name": name}})
|
||||
alarms = client.list(query)
|
||||
if len(alarms) > 1:
|
||||
msg = (_("Multiple alarms matches found for '%s', "
|
||||
"use an ID to be more specific.") % name)
|
||||
raise exceptions.NoUniqueMatch(msg)
|
||||
elif not alarms:
|
||||
msg = (_("Alarm %s not found") % name)
|
||||
raise exceptions.NotFound(404, msg)
|
||||
else:
|
||||
if return_id:
|
||||
return alarms[0]['alarm_id']
|
||||
return alarms[0]
|
||||
|
||||
|
||||
def _check_name_and_id(parsed_args, action):
|
||||
if parsed_args.id and parsed_args.alarm_name:
|
||||
raise exceptions.CommandError(
|
||||
"You should provide only one of "
|
||||
"alarm ID and alarm name(--alarm-name) "
|
||||
"to %s an alarm." % action)
|
||||
if not parsed_args.id and not parsed_args.alarm_name:
|
||||
msg = (_("You need to specify one of "
|
||||
"alarm ID and alarm name(--alarm-name) "
|
||||
"to %s an alarm.") % action)
|
||||
raise exceptions.CommandError(msg)
|
||||
|
||||
|
||||
class CliAlarmShow(show.ShowOne):
|
||||
"""Show an alarm"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliAlarmShow, self).get_parser(prog_name)
|
||||
parser.add_argument("alarm_id", help="ID of an alarm")
|
||||
parser.add_argument("id", nargs='?',
|
||||
metavar='<ALARM ID>',
|
||||
help="ID of an alarm")
|
||||
parser.add_argument("--alarm-name", dest='alarm_name',
|
||||
metavar='<ALARM NAME>',
|
||||
help="name of an alarm")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
alarm = self.app.client.alarm.get(alarm_id=parsed_args.alarm_id)
|
||||
_check_name_and_id(parsed_args, 'query')
|
||||
if parsed_args.id:
|
||||
alarm = self.app.client.alarm.get(alarm_id=parsed_args.id)
|
||||
else:
|
||||
alarm = _find_alarm_by_name(self.app.client.alarm,
|
||||
parsed_args.alarm_name)
|
||||
return self.dict2columns(_format_alarm(alarm))
|
||||
|
||||
|
||||
@@ -323,13 +365,26 @@ class CliAlarmUpdate(CliAlarmCreate):
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliAlarmUpdate, self).get_parser(prog_name)
|
||||
parser.add_argument("alarm_id", help="ID of the alarm")
|
||||
parser.add_argument("id", nargs='?',
|
||||
metavar='<ALARM ID>',
|
||||
help="ID of an alarm")
|
||||
parser.add_argument("--alarm-name", dest='alarm_name',
|
||||
metavar='<ALARM NAME>',
|
||||
help="name of an alarm")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
_check_name_and_id(parsed_args, 'update')
|
||||
attributes = self._alarm_from_args(parsed_args)
|
||||
updated_alarm = self.app.client.alarm.update(
|
||||
alarm_id=parsed_args.alarm_id, alarm_update=attributes)
|
||||
if parsed_args.id:
|
||||
updated_alarm = self.app.client.alarm.update(
|
||||
alarm_id=parsed_args.id, alarm_update=attributes)
|
||||
else:
|
||||
alarm_id = _find_alarm_by_name(self.app.client.alarm,
|
||||
parsed_args.alarm_name,
|
||||
return_id=True)
|
||||
updated_alarm = self.app.client.alarm.update(
|
||||
alarm_id=alarm_id, alarm_update=attributes)
|
||||
return self.dict2columns(_format_alarm(updated_alarm))
|
||||
|
||||
|
||||
@@ -338,8 +393,20 @@ class CliAlarmDelete(command.Command):
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliAlarmDelete, self).get_parser(prog_name)
|
||||
parser.add_argument("alarm_id", help="ID of the alarm")
|
||||
parser.add_argument("id", nargs='?',
|
||||
metavar='<ALARM ID>',
|
||||
help="ID of an alarm")
|
||||
parser.add_argument("--alarm-name", dest='alarm_name',
|
||||
metavar='<ALARM NAME>',
|
||||
help="name of an alarm")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.client.alarm.delete(parsed_args.alarm_id)
|
||||
_check_name_and_id(parsed_args, 'delete')
|
||||
if parsed_args.id:
|
||||
self.app.client.alarm.delete(parsed_args.id)
|
||||
else:
|
||||
alarm_id = _find_alarm_by_name(self.app.client.alarm,
|
||||
parsed_args.alarm_name,
|
||||
return_id=True)
|
||||
self.app.client.alarm.delete(alarm_id)
|
||||
|
Reference in New Issue
Block a user