Add check for restricted characters

Remove placeholder test
Adjust flake8 settings
Add new mock requirements to test-requirements.txt

Change-Id: I8f58341108710b1bc7431154cda096d6583d1ef3
This commit is contained in:
Ryan Brandt 2015-07-08 13:57:22 -06:00
parent 5377aa6cb0
commit 9607e1aabd
7 changed files with 145 additions and 32 deletions

View File

@ -1,21 +0,0 @@
# Copyright 2014 Hewlett-Packard
#
# 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 unittest
class Test_first(unittest.TestCase):
def test_first(self):
assert 1 == 1

View File

@ -0,0 +1,86 @@
# Copyright 2015 Hewlett-Packard
#
# 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 monasca_api.v2.common.validation as validation
import unittest
invalid_chars = "<>={}(),'\"\\;&"
class TestMetricNameValidation(unittest.TestCase):
def test_valid_name(self):
metric_name = "this.is_a.valid-name"
validation.metric_name(metric_name)
self.assertTrue(True)
def test_nonstring_name(self):
metric_name = 123456789
self.assertRaises(AssertionError, validation.metric_name, metric_name)
def test_long_name(self):
metric_name = ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz")
self.assertRaises(AssertionError, validation.metric_name, metric_name)
def test_invalid_chars(self):
for c in invalid_chars:
metric_name = "this{}that".format(c)
self.assertRaises(AssertionError, validation.metric_name, metric_name)
class TestDimensionValidation(unittest.TestCase):
def test_valid_key(self):
dim_key = "this.is_a.valid-key"
validation.dimension_key(dim_key)
self.assertTrue(True)
def test_nonstring_key(self):
dim_key = 123456
self.assertRaises(AssertionError, validation.dimension_key, dim_key)
def test_long_key(self):
dim_key = ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz")
self.assertRaises(AssertionError, validation.dimension_key, dim_key)
def test_invalid_chars_key(self):
for c in invalid_chars:
dim_key = "this{}that".format(c)
self.assertRaises(AssertionError, validation.dimension_key, dim_key)
def test_valid_value(self):
dim_value = "this.is_a.valid-value"
validation.dimension_value(dim_value)
self.assertTrue(True)
def test_nonstring_value(self):
dim_value = None
self.assertRaises(AssertionError, validation.dimension_value, dim_value)
def test_long_value(self):
dim_value = ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz")
self.assertRaises(AssertionError, validation.dimension_value, dim_value)
def test_invalid_chars_value(self):
for c in invalid_chars:
dim_value = "this{}that".format(c)
self.assertRaises(AssertionError, validation.dimension_value, dim_value)

View File

@ -0,0 +1,36 @@
# Copyright 2015 Hewlett-Packard
#
# 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 re
invalid_chars = "<>={}(),'\"\\\\;&"
restricted_chars = re.compile('[' + invalid_chars + ']')
def metric_name(name):
assert isinstance(name, (str, unicode)), "Metric name must be a string"
assert len(name) <= 255, "Metric name must be 255 characters or less"
assert not restricted_chars.search(name), "Invalid characters in metric name " + name
def dimension_key(dkey):
assert isinstance(dkey, (str, unicode)), "Dimension key must be a string"
assert len(dkey) <= 255, "Dimension key must be 255 characters or less"
assert not restricted_chars.search(dkey), "Invalid characters in dimension name " + dkey
def dimension_value(value):
assert isinstance(value, (str, unicode)), "Dimension value must be a string"
assert len(value) <= 255, "Dimension value must be 255 characters or less"
assert not restricted_chars.search(value), "Invalid characters in dimension value " + value

View File

@ -25,7 +25,7 @@ from monasca_api.common.repositories import exceptions
import monasca_api.expression_parser.alarm_expr_parser
from monasca_api.v2.common.schemas import (
alarm_definition_request_body_schema as schema_alarms)
from monasca_api.v2.common.schemas import exceptions as schemas_exceptions
from monasca_api.v2.common import validation
from monasca_api.v2.reference import alarming
from monasca_api.v2.reference import helpers
from monasca_api.v2.reference import resource
@ -316,7 +316,11 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API,
try:
schema_alarms.validate(alarm_definition)
except schemas_exceptions.ValidationException as ex:
if 'match_by' in alarm_definition:
for name in alarm_definition['match_by']:
validation.dimension_key(name)
except Exception as ex:
LOG.debug(ex)
raise falcon.HTTPBadRequest('Bad request', ex.message)

View File

@ -22,6 +22,7 @@ from monasca_api.common.messaging import (
exceptions as message_queue_exceptions)
from monasca_api.common.messaging.message_formats import (
metrics as metrics_message)
from monasca_api.v2.common import validation
from monasca_api.v2.reference import helpers
from monasca_api.v2.reference import resource
@ -80,16 +81,13 @@ class Metrics(metrics_api_v2.MetricsV2API):
raise falcon.HTTPBadRequest('Bad request', ex.message)
def _validate_single_metric(self, metric):
assert isinstance(metric['name'], (str, unicode))
assert len(metric['name']) <= 64
assert isinstance(metric['timestamp'], (int, float))
assert isinstance(metric['value'], (int, long, float, complex))
validation.metric_name(metric['name'])
assert isinstance(metric['timestamp'], (int, float)), "Timestamp must be a number"
assert isinstance(metric['value'], (int, long, float, complex)), "Value must be a number"
if "dimensions" in metric:
for d in metric['dimensions']:
assert isinstance(d, (str, unicode))
assert len(d) <= 255
assert isinstance(metric['dimensions'][d], (str, unicode))
assert len(metric['dimensions'][d]) <= 255
for dimension_key in metric['dimensions']:
validation.dimension_key(dimension_key)
validation.dimension_value(metric['dimensions'][dimension_key])
def _send_metrics(self, metrics):

View File

@ -8,6 +8,7 @@ flake8==2.1.0
pep8<=1.5.6
httplib2>=0.7.5
mock>=1.0
funcsigs
mox>=0.5.3
nose
# Docs Requirements

View File

@ -30,6 +30,15 @@ commands = python setup.py build_sphinx
commands = {posargs}
[flake8]
max-line-length = 120
# TODO: ignored checks should be enabled in the future
# H201 no 'except:' at least use 'except Exception:'
# H302 import only modules
# H305 imports not grouped correctly
# H307 like imports should be grouped together
# H405 multi line docstring summary not separated with an empty line
# H904 Wrap long lines in parentheses instead of a backslash
ignore = F821,H201,H302,H305,H307,H405,H904
builtins = _
exclude=.venv,.git,.tox,dist,doc,./monasca_api/openstack/common,*lib/python*,*egg,tools,build
show-source = True