monasca-api/monasca_api/tests/test_alarms.py

784 lines
31 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
# Copyright 2015 Cray Inc.
# (C) Copyright 2015,2017 Hewlett Packard Enterprise Development LP
# Copyright 2016-2017 FUJITSU LIMITED
#
# 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 collections import OrderedDict
import copy
import json
import falcon.testing
import fixtures
import testtools.matchers as matchers
from mock import Mock
import oslo_config.fixture
from oslo_serialization import jsonutils
import six
from monasca_api.common.repositories.model import sub_alarm_definition
from monasca_api.tests import base
from monasca_api.v2.reference import alarm_definitions
from monasca_api.v2.reference import alarms
CONF = oslo_config.cfg.CONF
TENANT_ID = u"fedcba9876543210fedcba9876543210"
ALARM_HISTORY = OrderedDict((
# Only present in data returned from InfluxDB:
(u"time", u"2015-01-01T00:00:00.000Z"),
# Only present in data returned from API:
(u"timestamp", u"2015-01-01T00:00:00.000Z"),
(u"alarm_id", u"10000000-1000-1000-1000-10000000000"),
(u"metrics", [{
u"id": None,
u"name": u"test.metric",
u"dimensions": {u"dim1": u"dval1", u"dim2": u"dval2"}
}]),
(u"new_state", u"ALARM"),
(u"old_state", u"OK"),
(u"reason", u"Alarm reason"),
(u"reason_data", u"{}"),
(u"sub_alarms", [{
u"sub_alarm_expression": {
u"function": u"MAX",
# Only present in data returned from InfluxDB:
u"metric_definition": {
u"id": None,
u"name": u"test.metric",
u"dimensions": {u"dim1": u"dval1"},
},
# Only present in data returned from API:
u'metric_name': u'test.metric',
# Only present in data returned from API:
u'dimensions': {u'dim1': u'dval1'},
u"operator": u"GT",
u"threshold": 50.0,
u"period": 60,
u"periods": 1
},
u"sub_alarm_state": u"ALARM",
u"current_values": [50.1],
}]),
# Only present in data returned from InfluxDB:
(u"tenant_id", TENANT_ID),
# Only present in data returned from API:
(u"id", u"1420070400000"),
))
class InfluxClientAlarmHistoryResponseFixture(fixtures.MockPatch):
def _build_series(self, name, column_dict):
return {
"name": name,
"columns": column_dict.keys(),
"values": [column_dict.values(), ],
}
def _setUp(self):
super(InfluxClientAlarmHistoryResponseFixture, self)._setUp()
mock_data = copy.deepcopy(ALARM_HISTORY)
del mock_data[u"id"]
del mock_data[u"timestamp"]
del mock_data[u"sub_alarms"][0][u"sub_alarm_expression"][u"metric_name"]
del mock_data[u"sub_alarms"][0][u"sub_alarm_expression"][u"dimensions"]
mock_data[u"sub_alarms"] = json.dumps(mock_data[u"sub_alarms"])
mock_data[u"metrics"] = json.dumps(mock_data[u"metrics"])
self.mock.return_value.query.return_value.raw = {
"series": [self._build_series("alarm_state_history", mock_data)]
}
class RESTResponseEquals(object):
"""Match if the supplied data contains a single string containing a JSON
object which decodes to match expected_data, excluding the contents of
the 'links' key.
"""
def __init__(self, expected_data):
self.expected_data = expected_data
if u"links" in expected_data:
del expected_data[u"links"]
def __str__(self):
return 'RESTResponseEquals(%s)' % (self.expected,)
def match(self, actual):
if len(actual) != 1:
return matchers.Mismatch("Response contains <> 1 item: %r" % actual)
response_data = jsonutils.loads(actual[0])
if u"links" in response_data:
del response_data[u"links"]
return matchers.Equals(self.expected_data).match(response_data)
class AlarmTestBase(base.BaseApiTestCase):
def setUp(self):
super(AlarmTestBase, self).setUp()
self.useFixture(fixtures.MockPatch(
'monasca_api.common.messaging.kafka_publisher.KafkaPublisher'))
# [messaging]
self.conf_override(
driver='monasca_api.common.messaging.'
'kafka_publisher:KafkaPublisher',
group='messaging')
# [repositories]
self.conf_override(
alarms_driver='monasca_api.common.repositories.sqla.'
'alarms_repository:AlarmsRepository',
group='repositories')
self.conf_override(
alarm_definitions_driver='monasca_api.common.repositories.'
'alarm_definitions_repository:'
'AlarmDefinitionsRepository',
group='repositories')
self.conf_override(
metrics_driver='monasca_api.common.repositories.influxdb.'
'metrics_repository:MetricsRepository',
group='repositories')
class TestAlarmsStateHistory(AlarmTestBase):
def setUp(self):
super(TestAlarmsStateHistory, self).setUp()
self.useFixture(InfluxClientAlarmHistoryResponseFixture(
'monasca_api.common.repositories.influxdb.'
'metrics_repository.client.InfluxDBClient'))
self.useFixture(fixtures.MockPatch(
'monasca_api.common.repositories.sqla.'
'alarms_repository.AlarmsRepository'))
self.alarms_resource = alarms.AlarmsStateHistory()
self.api.add_route(
'/v2.0/alarms/{alarm_id}/state-history/', self.alarms_resource)
def test_alarm_state_history(self):
expected_elements = {u"elements": [dict(ALARM_HISTORY)]}
del expected_elements[u"elements"][0][u"time"]
del (expected_elements[u"elements"][0][u"sub_alarms"][0]
[u"sub_alarm_expression"][u"metric_definition"])
del expected_elements[u"elements"][0][u"tenant_id"]
response = self.simulate_request(
u'/v2.0/alarms/%s/state-history/' % ALARM_HISTORY[u"alarm_id"],
headers={
'X-Roles': CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID,
})
self.assertEqual(self.srmock.status, falcon.HTTP_200)
self.assertThat(response, RESTResponseEquals(expected_elements))
class TestAlarmDefinition(AlarmTestBase):
def setUp(self):
super(TestAlarmDefinition, self).setUp()
self.alarm_def_repo_mock = self.useFixture(fixtures.MockPatch(
'monasca_api.common.repositories.'
'alarm_definitions_repository.AlarmDefinitionsRepository'
)).mock
self.alarm_definition_resource = alarm_definitions.AlarmDefinitions()
self.alarm_definition_resource.send_event = Mock()
self._send_event = self.alarm_definition_resource.send_event
self.api.add_route("/v2.0/alarm-definitions/",
self.alarm_definition_resource)
self.api.add_route("/v2.0/alarm-definitions/{alarm_definition_id}",
self.alarm_definition_resource)
def test_alarm_definition_create(self):
return_value = self.alarm_def_repo_mock.return_value
return_value.get_alarm_definitions.return_value = []
return_value.create_alarm_definition.return_value = u"00000001-0001-0001-0001-000000000001"
alarm_def = {
"name": "Test Definition",
"expression": "test.metric > 10"
}
expected_data = {
u'alarm_actions': [],
u'ok_actions': [],
u'description': u'',
u'match_by': [],
u'name': u'Test Definition',
u'actions_enabled': True,
u'undetermined_actions': [],
u'expression': u'test.metric > 10',
u'deterministic': False,
u'id': u'00000001-0001-0001-0001-000000000001',
u'severity': u'LOW',
}
response = self.simulate_request("/v2.0/alarm-definitions/",
headers={'X-Roles':
CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="POST",
body=json.dumps(alarm_def))
self.assertEqual(self.srmock.status, falcon.HTTP_201)
self.assertThat(response, RESTResponseEquals(expected_data))
def test_alarm_definition_create_with_valid_expressions(self):
return_value = self.alarm_def_repo_mock.return_value
return_value.get_alarm_definitions.return_value = []
return_value.create_alarm_definition.return_value = u"00000001-0001-0001-0001-000000000001"
valid_expressions = [
u"max(-_.千幸福的笑脸{घोड़ा=馬, "
u"dn2=dv2,千幸福的笑脸घ=千幸福的笑脸घ}) gte 100 "
u"times 3 && "
u"(min(ເຮືອນ{dn3=dv3,家=дом}) < 10 or sum(biz{dn5=dv5}) >99 and "
u"count(fizzle) lt 0or count(baz) > 1)",
u"max(foo{hostname=mini-mon,千=千}, 120) > 100 and (max(bar)>100 "
u" or max(biz)>100)",
u"max(foo)>=100",
u"test_metric{this=that, that = this} < 1",
u"max ( 3test_metric5 { this = that }) lt 5 times 3",
u"3test_metric5 lt 3",
u"ntp.offset > 1 or ntp.offset < -5",
]
alarm_def = {
u'name': u'Test Definition',
u'expression': u'test.metric > 10'
}
expected_data = {
u'alarm_actions': [],
u'ok_actions': [],
u'description': u'',
u'match_by': [],
u'name': u'Test Definition',
u'actions_enabled': True,
u'undetermined_actions': [],
u'expression': u'test.metric > 10',
u'deterministic': False,
u'id': u'00000001-0001-0001-0001-000000000001',
u'severity': u'LOW',
}
for expression in valid_expressions:
alarm_def[u'expression'] = expression
expected_data[u'expression'] = expression
response = self.simulate_request("/v2.0/alarm-definitions/",
headers={'X-Roles':
CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="POST",
body=json.dumps(alarm_def))
self.assertEqual(self.srmock.status, falcon.HTTP_201,
u'Expression {} should have passed'.format(expression))
self.assertThat(response, RESTResponseEquals(expected_data))
def test_alarm_definition_create_with_invalid_expressions(self):
bad_expressions = [
"test=metric > 10",
"test.metric{dim=this=that} > 10",
"test_metric(5) > 2"
"test_metric > 10 and or alt_metric > 10"
]
alarm_def = {
u'name': 'Test Definition',
u'expression': 'test.metric > 10'
}
for expression in bad_expressions:
alarm_def[u'expression'] = expression
self.simulate_request("/v2.0/alarm-definitions/",
headers={'X-Roles': CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="POST",
body=json.dumps(alarm_def))
self.assertEqual(self.srmock.status, '422 Unprocessable Entity',
u'Expression {} should have failed'.format(expression))
def test_alarm_definition_update(self):
self.alarm_def_repo_mock.return_value.get_alarm_definitions.return_value = []
self.alarm_def_repo_mock.return_value.update_or_patch_alarm_definition.return_value = (
{u'alarm_actions': [],
u'ok_actions': [],
u'description': u'Non-ASCII character: \u2603',
u'match_by': u'hostname',
u'name': u'Test Alarm',
u'actions_enabled': True,
u'undetermined_actions': [],
u'is_deterministic': False,
u'expression': u'max(test.metric{hostname=host}) gte 1',
u'id': u'00000001-0001-0001-0001-000000000001',
u'severity': u'LOW'},
{'old': {'11111': sub_alarm_definition.SubAlarmDefinition(
row={'id': '11111',
'alarm_definition_id': u'00000001-0001-0001-0001-000000000001',
'function': 'max',
'metric_name': 'test.metric',
'dimensions': 'hostname=host',
'operator': 'gte',
'threshold': 1,
'period': 60,
'is_deterministic': False,
'periods': 1})},
'changed': {},
'new': {},
'unchanged': {'11111': sub_alarm_definition.SubAlarmDefinition(
row={'id': '11111',
'alarm_definition_id': u'00000001-0001-0001-0001-000000000001',
'function': 'max',
'metric_name': 'test.metric',
'dimensions': 'hostname=host',
'operator': 'gte',
'threshold': 1,
'period': 60,
'is_deterministic': False,
'periods': 1})}
}
)
expected_def = {
u'id': u'00000001-0001-0001-0001-000000000001',
u'alarm_actions': [],
u'ok_actions': [],
u'description': u'Non-ASCII character: \u2603',
u'links': [{u'href': u'http://falconframework.org/v2.0/alarm-definitions/'
u'00000001-0001-0001-0001-000000000001',
u'rel': u'self'}],
u'match_by': [u'hostname'],
u'name': u'Test Alarm',
u'actions_enabled': True,
u'undetermined_actions': [],
u'deterministic': False,
u'expression': u'max(test.metric{hostname=host}) gte 1',
u'severity': u'LOW',
}
alarm_def = {
u'alarm_actions': [],
u'ok_actions': [],
u'description': u'',
u'match_by': [u'hostname'],
u'name': u'Test Alarm',
u'actions_enabled': True,
u'undetermined_actions': [],
u'deterministic': False,
u'expression': u'max(test.metric{hostname=host}) gte 1',
u'severity': u'LOW',
}
result = self.simulate_request("/v2.0/alarm-definitions/%s" % expected_def[u'id'],
headers={'X-Roles':
CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="PUT",
body=json.dumps(alarm_def))
self.assertEqual(self.srmock.status, falcon.HTTP_200)
result_def = jsonutils.loads(result[0])
self.assertEqual(result_def, expected_def)
def test_alarm_definition_patch_no_id(self):
alarm_def = {
u'name': u'Test Alarm Definition Updated',
}
self.simulate_request(
"/v2.0/alarm-definitions/",
headers={
'X-Roles': CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="PATCH",
body=json.dumps(alarm_def))
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_alarm_definition_update_no_id(self):
alarm_def = {
u'name': u'Test Alarm Definition Updated',
}
self.simulate_request(
"/v2.0/alarm-definitions/",
headers={
'X-Roles': CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="PUT",
body=json.dumps(alarm_def))
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_alarm_definition_delete_no_id(self):
self.simulate_request(
"/v2.0/alarm-definitions/",
headers={
'X-Roles': CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="DELETE")
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_alarm_definition_patch(self):
self.alarm_def_repo_mock.return_value.get_alarm_definitions.return_value = []
description = u'Non-ASCII character: \u2603'
new_name = u'Test Alarm Updated'
actions_enabled = True
alarm_def_id = u'00000001-0001-0001-0001-000000000001'
alarm_expression = u'max(test.metric{hostname=host}) gte 1'
severity = u'LOW'
match_by = u'hostname'
self.alarm_def_repo_mock.return_value.update_or_patch_alarm_definition.return_value = (
{u'alarm_actions': [],
u'ok_actions': [],
u'description': description,
u'match_by': match_by,
u'name': new_name,
u'actions_enabled': actions_enabled,
u'undetermined_actions': [],
u'is_deterministic': False,
u'expression': alarm_expression,
u'id': alarm_def_id,
u'severity': severity},
{'old': {'11111': sub_alarm_definition.SubAlarmDefinition(
row={'id': '11111',
'alarm_definition_id': u'00000001-0001-0001-0001-000000000001',
'function': 'max',
'metric_name': 'test.metric',
'dimensions': 'hostname=host',
'operator': 'gte',
'threshold': 1,
'period': 60,
'is_deterministic': False,
'periods': 1})},
'changed': {},
'new': {},
'unchanged': {'11111': sub_alarm_definition.SubAlarmDefinition(
row={'id': '11111',
'alarm_definition_id': u'00000001-0001-0001-0001-000000000001',
'function': 'max',
'metric_name': 'test.metric',
'dimensions': 'hostname=host',
'operator': 'gte',
'threshold': 1,
'period': 60,
'is_deterministic': False,
'periods': 1})}
}
)
expected_def = {
u'id': alarm_def_id,
u'alarm_actions': [],
u'ok_actions': [],
u'description': description,
u'links': [{u'href': u'http://falconframework.org/v2.0/alarm-definitions/'
u'00000001-0001-0001-0001-000000000001',
u'rel': u'self'}],
u'match_by': [match_by],
u'name': new_name,
u'actions_enabled': actions_enabled,
u'undetermined_actions': [],
u'deterministic': False,
u'expression': alarm_expression,
u'severity': severity,
}
alarm_def = {
u'name': u'Test Alarm Updated',
}
result = self.simulate_request("/v2.0/alarm-definitions/%s" % expected_def[u'id'],
headers={'X-Roles':
CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="PATCH",
body=json.dumps(alarm_def))
self.assertEqual(self.srmock.status, falcon.HTTP_200)
result_def = jsonutils.loads(result[0])
self.assertEqual(result_def, expected_def)
# If the alarm-definition-updated event does not have all of the
# fields set, the Threshold Engine will get confused. For example,
# if alarmActionsEnabled is none, thresh will read that as false
# and pass that value onto the Notification Engine which will not
# create a notification even actions_enabled is True in the
# database. So, ensure all fields are set correctly
((_, event), _) = self._send_event.call_args
expr = u'max(test.metric{hostname=host}, 60) gte 1 times 1'
sub_expression = {'11111': {u'expression': expr,
u'function': 'max',
u'metricDefinition': {
u'dimensions': {'hostname': 'host'},
u'name': 'test.metric'},
u'operator': 'gte',
u'period': 60,
u'periods': 1,
u'threshold': 1}}
fields = {u'alarmActionsEnabled': actions_enabled,
u'alarmDefinitionId': alarm_def_id,
u'alarmDescription': description,
u'alarmExpression': alarm_expression,
u'alarmName': new_name,
u'changedSubExpressions': {},
u'matchBy': [match_by],
u'severity': severity,
u'tenantId': u'fedcba9876543210fedcba9876543210',
u'newAlarmSubExpressions': {},
u'oldAlarmSubExpressions': sub_expression,
u'unchangedSubExpressions': sub_expression}
reference = {u'alarm-definition-updated': fields}
self.assertEqual(reference, event)
def test_alarm_definition_update_missing_fields(self):
self.alarm_def_repo_mock.return_value.get_alarm_definitions.return_value = []
self.alarm_def_repo_mock.return_value.update_or_patch_alarm_definition.return_value = (
{u'alarm_actions': [],
u'ok_actions': [],
u'description': u'Non-ASCII character: \u2603',
u'match_by': u'hostname',
u'name': u'Test Alarm',
u'actions_enabled': True,
u'undetermined_actions': [],
u'expression': u'max(test.metric{hostname=host}) gte 1',
u'id': u'00000001-0001-0001-0001-000000000001',
u'is_deterministic': False,
u'severity': u'LOW'},
{'old': {'11111': sub_alarm_definition.SubAlarmDefinition(
row={'id': '11111',
'alarm_definition_id': u'00000001-0001-0001-0001-000000000001',
'function': 'max',
'metric_name': 'test.metric',
'dimensions': 'hostname=host',
'operator': 'gte',
'threshold': 1,
'period': 60,
'periods': 1,
'is_deterministic': False})},
'changed': {},
'new': {},
'unchanged': {'11111': sub_alarm_definition.SubAlarmDefinition(
row={'id': '11111',
'alarm_definition_id': u'00000001-0001-0001-0001-000000000001',
'function': 'max',
'metric_name': 'test.metric',
'dimensions': 'hostname=host',
'operator': 'gte',
'threshold': 1,
'period': 60,
'periods': 1,
'is_deterministic': False})}
}
)
expected_def = {
u'id': u'00000001-0001-0001-0001-000000000001',
u'alarm_actions': [],
u'ok_actions': [],
u'description': u'Non-ASCII character: \u2603',
u'links': [{u'href': u'http://falconframework.org/v2.0/alarm-definitions/'
u'00000001-0001-0001-0001-000000000001',
u'rel': u'self'}],
u'match_by': [u'hostname'],
u'name': u'Test Alarm',
u'actions_enabled': True,
u'undetermined_actions': [],
u'expression': u'max(test.metric{hostname=host}) gte 1',
u'severity': u'LOW',
u'deterministic': False
}
alarm_def = {
u'alarm_actions': [],
u'ok_actions': [],
u'description': u'',
u'match_by': [u'hostname'],
u'name': u'Test Alarm',
u'actions_enabled': True,
u'undetermined_actions': [],
u'expression': u'max(test.metric{hostname=host}) gte 1',
u'severity': u'LOW'
}
result = self.simulate_request("/v2.0/alarm-definitions/%s" % expected_def[u'id'],
headers={'X-Roles':
CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="PUT",
body=json.dumps(alarm_def))
self.assertEqual(self.srmock.status, falcon.HTTP_200)
result_def = jsonutils.loads(result[0])
self.assertEqual(result_def, expected_def)
for key, value in alarm_def.items():
del alarm_def[key]
self.simulate_request("/v2.0/alarm-definitions/%s" % expected_def[u'id'],
headers={'X-Roles':
CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID},
method="PUT",
body=json.dumps(alarm_def))
self.assertEqual(self.srmock.status, "422 Unprocessable Entity",
u"should have failed without key {}".format(key))
alarm_def[key] = value
def test_alarm_definition_get_specific_alarm(self):
self.alarm_def_repo_mock.return_value.get_alarm_definition.return_value = {
'alarm_actions': None,
'ok_actions': None,
# The description field was decoded to unicode when the
# alarm_definition was created.
'description': u'Non-ASCII character: \u2603',
'match_by': u'hostname',
'name': u'Test Alarm',
'actions_enabled': 1,
'undetermined_actions': None,
'deterministic': False,
'expression': u'max(test.metric{hostname=host}) gte 1',
'id': u'00000001-0001-0001-0001-000000000001',
'severity': u'LOW'
}
expected_data = {
u'alarm_actions': [],
u'ok_actions': [],
u'description': u'Non-ASCII character: \u2603',
u'match_by': [u'hostname'],
u'name': u'Test Alarm',
u'actions_enabled': True,
u'undetermined_actions': [],
u'deterministic': False,
u'expression': u'max(test.metric{hostname=host}) gte 1',
u'id': u'00000001-0001-0001-0001-000000000001',
u'severity': u'LOW',
}
response = self.simulate_request(
'/v2.0/alarm-definitions/%s' % (expected_data[u'id']),
headers={
'X-Roles': CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID,
})
self.assertEqual(self.srmock.status, falcon.HTTP_200)
self.assertThat(response, RESTResponseEquals(expected_data))
def test_alarm_definition_get_specific_alarm_description_none(self):
self.alarm_def_repo_mock.return_value.get_alarm_definition.return_value = {
'alarm_actions': None,
'ok_actions': None,
'description': None,
'match_by': u'hostname',
'name': u'Test Alarm',
'actions_enabled': 1,
'undetermined_actions': None,
'expression': u'max(test.metric{hostname=host}) gte 1',
'id': u'00000001-0001-0001-0001-000000000001',
'severity': u'LOW'
}
expected_data = {
u'alarm_actions': [],
u'ok_actions': [],
u'description': None,
u'match_by': [u'hostname'],
u'name': u'Test Alarm',
u'actions_enabled': True,
u'undetermined_actions': [],
u'deterministic': False,
u'expression': u'max(test.metric{hostname=host}) gte 1',
u'id': u'00000001-0001-0001-0001-000000000001',
u'severity': u'LOW',
}
response = self.simulate_request(
'/v2.0/alarm-definitions/%s' % (expected_data[u'id']),
headers={
'X-Roles': CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID,
})
self.assertEqual(self.srmock.status, falcon.HTTP_200)
self.assertThat(response, RESTResponseEquals(expected_data))
def test_get_alarm_definitions_with_multibyte_character(self):
def_name = '_'
if six.PY2:
def_name = def_name.decode('utf8')
expected_data = {
u'alarm_actions': [], u'ok_actions': [],
u'description': None, u'match_by': [u'hostname'],
u'actions_enabled': True, u'undetermined_actions': [],
u'deterministic': False,
u'expression': u'max(test.metric{hostname=host}) gte 1',
u'id': u'00000001-0001-0001-0001-000000000001',
u'severity': u'LOW', u'name': def_name
}
self.alarm_def_repo_mock.return_value.get_alarm_definition.return_value = {
'alarm_actions': None,
'ok_actions': None,
'description': None,
'match_by': u'hostname',
'name': def_name,
'actions_enabled': 1,
'undetermined_actions': None,
'expression': u'max(test.metric{hostname=host}) gte 1',
'id': u'00000001-0001-0001-0001-000000000001',
'severity': u'LOW'
}
response = self.simulate_request(
'/v2.0/alarm-definitions/%s' % (expected_data[u'id']),
headers={
'X-Roles': CONF.security.default_authorized_roles[0],
'X-Tenant-Id': TENANT_ID,
}
)
self.assertEqual(self.srmock.status, falcon.HTTP_200)
self.assertThat(response, RESTResponseEquals(expected_data))