Check unspecified parameters create audit
Currently, create audit with unspecified parameters will success. This is not reasonable, we shoud return a FAILED status to notify the admin user. Change-Id: Ifbcb3b8d9e736607b05b1eb408ec0f41bdf58a2f Closes-Bug: #1599879
This commit is contained in:
@@ -519,7 +519,7 @@ class AuditsController(rest.RestController):
|
|||||||
if schema:
|
if schema:
|
||||||
# validate input parameter with default value feedback
|
# validate input parameter with default value feedback
|
||||||
no_schema = False
|
no_schema = False
|
||||||
utils.DefaultValidatingDraft4Validator(schema).validate(
|
utils.StrictDefaultValidatingDraft4Validator(schema).validate(
|
||||||
audit.parameters)
|
audit.parameters)
|
||||||
|
|
||||||
if no_schema and audit.parameters:
|
if no_schema and audit.parameters:
|
||||||
|
|||||||
@@ -214,6 +214,10 @@ class AuditTypeNotFound(Invalid):
|
|||||||
msg_fmt = _("Audit type %(audit_type)s could not be found")
|
msg_fmt = _("Audit type %(audit_type)s could not be found")
|
||||||
|
|
||||||
|
|
||||||
|
class AuditParameterNotAllowed(Invalid):
|
||||||
|
msg_fmt = _("Audit parameter %(parameter)s are not allowed")
|
||||||
|
|
||||||
|
|
||||||
class AuditNotFound(ResourceNotFound):
|
class AuditNotFound(ResourceNotFound):
|
||||||
msg_fmt = _("Audit %(audit)s could not be found")
|
msg_fmt = _("Audit %(audit)s could not be found")
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
from jsonschema import validators
|
from jsonschema import validators
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from watcher.common import exception
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import six
|
import six
|
||||||
@@ -142,13 +143,29 @@ def extend_with_default(validator_class):
|
|||||||
instance.setdefault(prop, subschema["default"])
|
instance.setdefault(prop, subschema["default"])
|
||||||
|
|
||||||
for error in validate_properties(
|
for error in validate_properties(
|
||||||
validator, properties, instance, schema,
|
validator, properties, instance, schema
|
||||||
):
|
):
|
||||||
yield error
|
yield error
|
||||||
|
|
||||||
return validators.extend(
|
return validators.extend(validator_class,
|
||||||
validator_class, {"properties": set_defaults},
|
{"properties": set_defaults})
|
||||||
)
|
|
||||||
|
|
||||||
DefaultValidatingDraft4Validator = extend_with_default(
|
|
||||||
validators.Draft4Validator)
|
# Parameter strict check extension as jsonschema doesn't support it
|
||||||
|
def extend_with_strict_schema(validator_class):
|
||||||
|
validate_properties = validator_class.VALIDATORS["properties"]
|
||||||
|
|
||||||
|
def strict_schema(validator, properties, instance, schema):
|
||||||
|
for para in instance.keys():
|
||||||
|
if para not in properties.keys():
|
||||||
|
raise exception.AuditParameterNotAllowed(parameter=para)
|
||||||
|
|
||||||
|
for error in validate_properties(
|
||||||
|
validator, properties, instance, schema
|
||||||
|
):
|
||||||
|
yield error
|
||||||
|
|
||||||
|
return validators.extend(validator_class, {"properties": strict_schema})
|
||||||
|
|
||||||
|
StrictDefaultValidatingDraft4Validator = extend_with_default(
|
||||||
|
extend_with_strict_schema(validators.Draft4Validator))
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class DefaultStrategyContext(base.BaseStrategyContext):
|
|||||||
schema = selected_strategy.get_schema()
|
schema = selected_strategy.get_schema()
|
||||||
if not audit.parameters and schema:
|
if not audit.parameters and schema:
|
||||||
# Default value feedback if no predefined strategy
|
# Default value feedback if no predefined strategy
|
||||||
utils.DefaultValidatingDraft4Validator(schema).validate(
|
utils.StrictDefaultValidatingDraft4Validator(schema).validate(
|
||||||
audit.parameters)
|
audit.parameters)
|
||||||
|
|
||||||
selected_strategy.input_parameters.update({
|
selected_strategy.input_parameters.update({
|
||||||
|
|||||||
@@ -567,6 +567,62 @@ class TestPost(api_base.FunctionalTest):
|
|||||||
self.assertIn(expected_error_msg, response.json['error_message'])
|
self.assertIn(expected_error_msg, response.json['error_message'])
|
||||||
assert not mock_trigger_audit.called
|
assert not mock_trigger_audit.called
|
||||||
|
|
||||||
|
@mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit')
|
||||||
|
def test_create_audit_with_parameter_not_allowed(
|
||||||
|
self, mock_trigger_audit):
|
||||||
|
mock_trigger_audit.return_value = mock.ANY
|
||||||
|
audit_template = self.prepare_audit_template_strategy_with_parameter()
|
||||||
|
|
||||||
|
audit_dict = api_utils.audit_post_data(
|
||||||
|
parameters={'fake1': 1, 'fake2': "hello"})
|
||||||
|
|
||||||
|
audit_dict['audit_template_uuid'] = audit_template['uuid']
|
||||||
|
del_keys = ['uuid', 'goal_id', 'strategy_id', 'state', 'interval']
|
||||||
|
for k in del_keys:
|
||||||
|
del audit_dict[k]
|
||||||
|
|
||||||
|
response = self.post_json('/audits', audit_dict, expect_errors=True)
|
||||||
|
self.assertEqual(400, response.status_int)
|
||||||
|
self.assertEqual("application/json", response.content_type)
|
||||||
|
expected_error_msg = 'Audit parameter fake2 are not allowed'
|
||||||
|
self.assertTrue(response.json['error_message'])
|
||||||
|
self.assertIn(expected_error_msg, response.json['error_message'])
|
||||||
|
assert not mock_trigger_audit.called
|
||||||
|
|
||||||
|
def prepare_audit_template_strategy_with_parameter(self):
|
||||||
|
fake_spec = {
|
||||||
|
"properties": {
|
||||||
|
"fake1": {
|
||||||
|
"description": "number parameter example",
|
||||||
|
"type": "number",
|
||||||
|
"default": 3.2,
|
||||||
|
"minimum": 1.0,
|
||||||
|
"maximum": 10.2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template_uuid = 'e74c40e0-d825-11e2-a28f-0800200c9a67'
|
||||||
|
strategy_uuid = 'e74c40e0-d825-11e2-a28f-0800200c9a68'
|
||||||
|
template_name = 'my template'
|
||||||
|
strategy_name = 'my strategy'
|
||||||
|
strategy_id = 3
|
||||||
|
strategy = db_utils.get_test_strategy(parameters_spec=fake_spec,
|
||||||
|
id=strategy_id,
|
||||||
|
uuid=strategy_uuid,
|
||||||
|
name=strategy_name)
|
||||||
|
obj_utils.create_test_strategy(self.context,
|
||||||
|
parameters_spec=fake_spec,
|
||||||
|
id=strategy_id,
|
||||||
|
uuid=strategy_uuid,
|
||||||
|
name=strategy_name)
|
||||||
|
obj_utils.create_test_audit_template(self.context,
|
||||||
|
strategy_id=strategy_id,
|
||||||
|
uuid=template_uuid,
|
||||||
|
name='name')
|
||||||
|
audit_template = db_utils.get_test_audit_template(
|
||||||
|
strategy_id=strategy['id'], uuid=template_uuid, name=template_name)
|
||||||
|
return audit_template
|
||||||
|
|
||||||
|
|
||||||
# class TestDelete(api_base.FunctionalTest):
|
# class TestDelete(api_base.FunctionalTest):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user