api: update for WSME 0.5b6 compliance
This makes use of the mandatory option of WSME, that now works, to remove some of our custom validation code. This is needed for new versions of WSME that do more validation on their own. Fixes-Bug: #1240741 Change-Id: Icb66d17066b515bebf3f3a326d84e18cbfce01ef Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
c0b7e4984a
commit
e4a1a4fcef
@ -524,19 +524,19 @@ class Sample(_Base):
|
||||
source = wtypes.text
|
||||
"The ID of the source that identifies where the sample comes from"
|
||||
|
||||
counter_name = wtypes.text
|
||||
counter_name = wsme.wsattr(wtypes.text, mandatory=True)
|
||||
"The name of the meter"
|
||||
# FIXME(dhellmann): Make this meter_name?
|
||||
|
||||
counter_type = wtypes.text
|
||||
counter_type = wsme.wsattr(wtypes.text, mandatory=True)
|
||||
"The type of the meter (see :ref:`measurements`)"
|
||||
# FIXME(dhellmann): Make this meter_type?
|
||||
|
||||
counter_unit = wtypes.text
|
||||
counter_unit = wsme.wsattr(wtypes.text, mandatory=True)
|
||||
"The unit of measure for the value in counter_volume"
|
||||
# FIXME(dhellmann): Make this meter_unit?
|
||||
|
||||
counter_volume = float
|
||||
counter_volume = wsme.wsattr(float, mandatory=True)
|
||||
"The actual measured value"
|
||||
|
||||
user_id = wtypes.text
|
||||
@ -545,7 +545,7 @@ class Sample(_Base):
|
||||
project_id = wtypes.text
|
||||
"The ID of the project or tenant that owns the resource"
|
||||
|
||||
resource_id = wtypes.text
|
||||
resource_id = wsme.wsattr(wtypes.text, mandatory=True)
|
||||
"The ID of the :class:`Resource` for which the measurements are taken"
|
||||
|
||||
timestamp = datetime.datetime
|
||||
@ -569,11 +569,6 @@ class Sample(_Base):
|
||||
super(Sample, self).__init__(counter_volume=counter_volume,
|
||||
resource_metadata=resource_metadata,
|
||||
timestamp=timestamp, **kwds)
|
||||
# Seems the mandatory option doesn't work so do it manually
|
||||
for m in ('counter_volume', 'counter_unit',
|
||||
'counter_name', 'counter_type', 'resource_id'):
|
||||
if getattr(self, m) in (wsme.Unset, None):
|
||||
raise wsme.exc.MissingArgument(m)
|
||||
|
||||
if self.resource_metadata in (wtypes.Unset, None):
|
||||
self.resource_metadata = {}
|
||||
@ -717,20 +712,12 @@ class MeterController(rest.RestController):
|
||||
for e in pecan.request.storage_conn.get_samples(f, limit=limit)
|
||||
]
|
||||
|
||||
@wsme.validate([Sample])
|
||||
@wsme_pecan.wsexpose([Sample], body=[Sample])
|
||||
def post(self, body):
|
||||
def post(self, samples):
|
||||
"""Post a list of new Samples to Ceilometer.
|
||||
|
||||
:param body: a list of samples within the request body.
|
||||
:param samples: a list of samples within the request body.
|
||||
"""
|
||||
# Note:
|
||||
# 1) the above validate decorator seems to do nothing. LP#1220678
|
||||
# 2) the mandatory options seems to also do nothing. LP#1227004
|
||||
# 3) the body should already be in a list of Sample's LP#1233219
|
||||
|
||||
samples = [Sample(**b) for b in body]
|
||||
|
||||
now = timeutils.utcnow()
|
||||
auth_project = acl.get_limited_to_project(pecan.request.headers)
|
||||
def_source = pecan.request.cfg.sample_source
|
||||
@ -1010,14 +997,6 @@ class AlarmThresholdRule(_Base):
|
||||
|
||||
@staticmethod
|
||||
def validate(threshold_rule):
|
||||
#note(sileht): wsme mandatory doesn't work as expected
|
||||
#workaround for https://bugs.launchpad.net/wsme/+bug/1227004
|
||||
for field in ['meter_name', 'threshold']:
|
||||
if not getattr(threshold_rule, field):
|
||||
error = _("threshold_rule/%s is mandatory") % field
|
||||
pecan.response.translatable_error = error
|
||||
raise wsme.exc.ClientSideError(unicode(error))
|
||||
|
||||
#note(sileht): wsme default doesn't work in some case
|
||||
#workaround for https://bugs.launchpad.net/wsme/+bug/1227039
|
||||
if not threshold_rule.query:
|
||||
@ -1082,17 +1061,6 @@ class AlarmCombinationRule(_Base):
|
||||
alarm_ids=['739e99cb-c2ec-4718-b900-332502355f38',
|
||||
'153462d0-a9b8-4b5b-8175-9e4b05e9b856'])
|
||||
|
||||
@staticmethod
|
||||
def validate(combination_rule):
|
||||
#note(sileht): wsme mandatory doesn't works as expected
|
||||
#workaround for https://bugs.launchpad.net/wsme/+bug/1227004
|
||||
if not combination_rule.alarm_ids:
|
||||
error = _("combination_rule/alarm_ids is mandatory")
|
||||
pecan.response.translatable_error = error
|
||||
raise wsme.exc.ClientSideError(unicode(error))
|
||||
|
||||
return combination_rule
|
||||
|
||||
|
||||
class Alarm(_Base):
|
||||
"""Representation of an alarm.
|
||||
@ -1173,13 +1141,18 @@ class Alarm(_Base):
|
||||
|
||||
@staticmethod
|
||||
def validate(alarm):
|
||||
#note(sileht): wsme mandatory doesn't work as expected
|
||||
#workaround for https://bugs.launchpad.net/wsme/+bug/1227004
|
||||
for field in ['name', 'type']:
|
||||
if not getattr(alarm, field):
|
||||
error = _("%s is mandatory") % field
|
||||
pecan.response.translatable_error = error
|
||||
raise wsme.exc.ClientSideError(unicode(error))
|
||||
if (alarm.threshold_rule == wtypes.Unset
|
||||
and alarm.combination_rule == wtypes.Unset):
|
||||
error = _("either threshold_rule or combination_rule "
|
||||
"must be set")
|
||||
pecan.response.translatable_error = error
|
||||
raise wsme.exc.ClientSideError(unicode(error))
|
||||
|
||||
if alarm.threshold_rule and alarm.combination_rule:
|
||||
error = _("threshold_rule and combination_rule "
|
||||
"cannot be set at the same time")
|
||||
pecan.response.translatable_error = error
|
||||
raise wsme.exc.ClientSideError(unicode(error))
|
||||
|
||||
if alarm.threshold_rule:
|
||||
# ensure an implicit constraint on project_id is added to
|
||||
@ -1190,20 +1163,17 @@ class Alarm(_Base):
|
||||
on_behalf_of=alarm.project_id
|
||||
)
|
||||
elif alarm.combination_rule:
|
||||
auth_project = _get_auth_project(alarm.project_id)
|
||||
project = _get_auth_project(alarm.project_id
|
||||
if alarm.project_id != wtypes.Unset
|
||||
else None)
|
||||
for id in alarm.combination_rule.alarm_ids:
|
||||
alarms = list(pecan.request.storage_conn.get_alarms(
|
||||
alarm_id=id, project=auth_project))
|
||||
alarm_id=id, project=project))
|
||||
if not alarms:
|
||||
error = _("Alarm %s doesn't exist") % id
|
||||
pecan.response.translatable_error = error
|
||||
raise wsme.exc.ClientSideError(unicode(error))
|
||||
|
||||
if alarm.threshold_rule and alarm.combination_rule:
|
||||
error = _("threshold_rule and combination_rule "
|
||||
"cannot be set at the same time")
|
||||
pecan.response.translatable_error = error
|
||||
raise wsme.exc.ClientSideError(unicode(error))
|
||||
return alarm
|
||||
|
||||
@classmethod
|
||||
@ -1333,7 +1303,6 @@ class AlarmController(rest.RestController):
|
||||
"""Return this alarm."""
|
||||
return Alarm.from_db_model(self._alarm())
|
||||
|
||||
@wsme.validate(Alarm)
|
||||
@wsme_pecan.wsexpose(Alarm, wtypes.text, body=Alarm)
|
||||
def put(self, data):
|
||||
"""Modify this alarm."""
|
||||
@ -1344,18 +1313,20 @@ class AlarmController(rest.RestController):
|
||||
|
||||
data.alarm_id = self._id
|
||||
user, project = acl.get_limited_to(pecan.request.headers)
|
||||
data.user_id = user or data.user_id or alarm_in.user_id
|
||||
data.project_id = project or data.project_id or alarm_in.project_id
|
||||
if user:
|
||||
data.user_id = user
|
||||
elif data.user_id == wtypes.Unset:
|
||||
data.user_id = alarm_in.user_id
|
||||
if project:
|
||||
data.project_id = project
|
||||
elif data.project_id == wtypes.Unset:
|
||||
data.project_id = alarm_in.project_id
|
||||
data.timestamp = now
|
||||
if alarm_in.state != data.state:
|
||||
data.state_timestamp = now
|
||||
else:
|
||||
data.state_timestamp = alarm_in.state_timestamp
|
||||
|
||||
#note(sileht): workaround for
|
||||
#https://bugs.launchpad.net/wsme/+bug/1220678
|
||||
Alarm.validate(data)
|
||||
|
||||
old_alarm = Alarm.from_db_model(alarm_in).as_dict(storage.models.Alarm)
|
||||
updated_alarm = data.as_dict(storage.models.Alarm)
|
||||
try:
|
||||
@ -1462,7 +1433,6 @@ class AlarmsController(rest.RestController):
|
||||
payload['detail'] = scrubbed_data
|
||||
_send_notification(type, payload)
|
||||
|
||||
@wsme.validate(Alarm)
|
||||
@wsme_pecan.wsexpose(Alarm, body=Alarm, status_code=201)
|
||||
def post(self, data):
|
||||
"""Create a new alarm."""
|
||||
@ -1471,17 +1441,17 @@ class AlarmsController(rest.RestController):
|
||||
|
||||
data.alarm_id = str(uuid.uuid4())
|
||||
user, project = acl.get_limited_to(pecan.request.headers)
|
||||
data.user_id = (user or data.user_id or
|
||||
pecan.request.headers.get('X-User-Id'))
|
||||
data.project_id = (project or data.project_id or
|
||||
pecan.request.headers.get('X-Project-Id'))
|
||||
if user:
|
||||
data.user_id = user
|
||||
elif data.user_id == wtypes.Unset:
|
||||
data.user_id = pecan.request.headers.get('X-User-Id')
|
||||
if project:
|
||||
data.project_id = project
|
||||
elif data.project_id == wtypes.Unset:
|
||||
data.project_id = pecan.request.headers.get('X-Project-Id')
|
||||
data.timestamp = now
|
||||
data.state_timestamp = now
|
||||
|
||||
#note(sileht): workaround for
|
||||
#https://bugs.launchpad.net/wsme/+bug/1220678
|
||||
Alarm.validate(data)
|
||||
|
||||
change = data.as_dict(storage.models.Alarm)
|
||||
|
||||
# make sure alarms are unique by name per project.
|
||||
|
@ -104,6 +104,9 @@ class FunctionalTest(db_test_base.TestBase):
|
||||
'template_path': '%s/ceilometer/api/templates' % root_dir,
|
||||
'enable_acl': enable_acl,
|
||||
},
|
||||
'wsme': {
|
||||
'debug': True,
|
||||
},
|
||||
}
|
||||
|
||||
return pecan.testing.load_test_app(self.config)
|
||||
|
@ -279,7 +279,9 @@ class TestAlarms(FunctionalTest,
|
||||
status=400, headers=self.auth_headers)
|
||||
self.assertEqual(
|
||||
resp.json['error_message']['faultstring'],
|
||||
'%s is mandatory' % field)
|
||||
"Invalid input for field/attribute %s."
|
||||
" Value: \'None\'. Mandatory field missing."
|
||||
% field.split('/', 1)[-1])
|
||||
alarms = list(self.conn.get_alarms())
|
||||
self.assertEqual(4, len(alarms))
|
||||
|
||||
|
@ -134,7 +134,8 @@ class TestApiMiddleware(FunctionalTest):
|
||||
# Ensure translated messages get placed properly into json faults
|
||||
self.stubs.Set(gettextutils, 'get_localized_message',
|
||||
self._fake_get_localized_message)
|
||||
response = self.post_json('/alarms', params={},
|
||||
response = self.post_json('/alarms', params={'name': 'foobar',
|
||||
'type': 'threshold'},
|
||||
expect_errors=True,
|
||||
headers={"Accept":
|
||||
"application/json"}
|
||||
@ -169,7 +170,8 @@ class TestApiMiddleware(FunctionalTest):
|
||||
self.stubs.Set(gettextutils, 'get_localized_message',
|
||||
self._fake_get_localized_message)
|
||||
|
||||
response = self.post_json('/alarms', params={},
|
||||
response = self.post_json('/alarms', params={'name': 'foobar',
|
||||
'type': 'threshold'},
|
||||
expect_errors=True,
|
||||
headers={"Accept":
|
||||
"application/xml,*/*"}
|
||||
@ -186,7 +188,8 @@ class TestApiMiddleware(FunctionalTest):
|
||||
self.stubs.Set(gettextutils, 'get_localized_message',
|
||||
self._fake_get_localized_message)
|
||||
|
||||
response = self.post_json('/alarms', params={},
|
||||
response = self.post_json('/alarms', params={'name': 'foobar',
|
||||
'type': 'threshold'},
|
||||
expect_errors=True,
|
||||
headers={"Accept":
|
||||
"application/xml,*/*",
|
||||
|
@ -198,7 +198,7 @@ class TestPostSamples(FunctionalTest,
|
||||
s_broke = copy.copy(s1)
|
||||
del s_broke[0][m]
|
||||
print('posting without %s' % m)
|
||||
data = self.post_json('/meters/my_counter_name/', s_broke,
|
||||
data = self.post_json('/meters/my_counter_name', s_broke,
|
||||
expect_errors=True)
|
||||
self.assertEqual(data.status_int, 400)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user