Support templates with parameters in v3.
Change-Id: I5ddd4fb27694bfb4efe33753c85f4e3c58edb89a Story: 2004056 Task: 29445 Depends-On: https://review.openstack.org/#/c/638096/
This commit is contained in:
parent
fb84a1f9c7
commit
72ce36b415
|
@ -17,65 +17,49 @@ from oslo_log import log
|
|||
import re
|
||||
import six
|
||||
|
||||
from vitrage.evaluator.template_validation.content.base import \
|
||||
get_content_correct_result
|
||||
from vitrage.evaluator.template_validation.content.base import \
|
||||
get_content_fault_result
|
||||
from vitrage.evaluator.template_validation.status_messages import status_msgs
|
||||
from vitrage.evaluator.template_validation.base import ValidationError
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
FuncInfo = namedtuple('FuncInfo', ['name', 'func', 'error_code'])
|
||||
|
||||
|
||||
class FunctionResolver(object):
|
||||
@classmethod
|
||||
def resolve_function(cls, func_info, template, **kwargs):
|
||||
return cls._traverse_function(func_info, template, True, **kwargs)
|
||||
def resolve_function(func_info, template, **kwargs):
|
||||
return _traverse_function(func_info, template, resolve=True, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def validate_function(cls, func_info, template, **kwargs):
|
||||
return cls._traverse_function(func_info, template, False, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def _traverse_function(cls, func_info, template, resolve, **kwargs):
|
||||
return cls._recursive_resolve_function(
|
||||
func_info, template, template, resolve, **kwargs)
|
||||
def validate_function(func_info, template, **kwargs):
|
||||
return _traverse_function(func_info, template, resolve=False, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def _recursive_resolve_function(cls, func_info, template, template_block,
|
||||
resolve, **kwargs):
|
||||
result = get_content_correct_result()
|
||||
|
||||
for key, value in template_block.items():
|
||||
if result.is_valid_config:
|
||||
if isinstance(value, six.string_types) and \
|
||||
_is_wanted_function(value, func_info.name):
|
||||
def _traverse_function(func_info, template, resolve, **kwargs):
|
||||
return _recursive_resolve_function(
|
||||
func_info, template, template, resolve, **kwargs)
|
||||
|
||||
func = func_info.func
|
||||
if not func:
|
||||
status = func_info.error_code
|
||||
LOG.error('%s status code: %s' %
|
||||
(status_msgs[status], status))
|
||||
return get_content_fault_result(status)
|
||||
|
||||
result, resolved_value = func(value, template, **kwargs)
|
||||
if result.is_valid_config and resolve:
|
||||
template_block[key] = resolved_value
|
||||
LOG.debug('Replaced %s with %s', value,
|
||||
resolved_value)
|
||||
def _recursive_resolve_function(func_info, template, template_block,
|
||||
resolve, **kwargs):
|
||||
|
||||
elif isinstance(value, dict):
|
||||
result = cls._recursive_resolve_function(
|
||||
func_info, template, value, resolve, **kwargs)
|
||||
for key, value in template_block.items():
|
||||
if isinstance(value, six.string_types) and \
|
||||
_is_wanted_function(value, func_info.name):
|
||||
|
||||
elif isinstance(value, list):
|
||||
for item in value:
|
||||
if result.is_valid_config:
|
||||
result = cls._recursive_resolve_function(
|
||||
func_info, template, item, resolve, **kwargs)
|
||||
if not func_info.func:
|
||||
raise ValidationError(func_info.error_code, value)
|
||||
|
||||
return result
|
||||
resolved_value = func_info.func(value, template, **kwargs)
|
||||
if resolve:
|
||||
template_block[key] = resolved_value
|
||||
LOG.debug('Replaced %s with %s', value, resolved_value)
|
||||
|
||||
elif isinstance(value, dict):
|
||||
_recursive_resolve_function(
|
||||
func_info, template, value, resolve, **kwargs)
|
||||
|
||||
elif isinstance(value, list):
|
||||
for item in value:
|
||||
_recursive_resolve_function(
|
||||
func_info, template, item, resolve, **kwargs)
|
||||
|
||||
|
||||
def is_function(str):
|
||||
|
|
|
@ -13,11 +13,10 @@
|
|||
# under the License.
|
||||
from oslo_log import log
|
||||
|
||||
from vitrage.evaluator.template_functions.function_resolver import \
|
||||
FuncInfo
|
||||
from vitrage.evaluator.template_functions.function_resolver import \
|
||||
FunctionResolver
|
||||
from vitrage.evaluator.template_functions import function_resolver
|
||||
from vitrage.evaluator.template_functions import GET_PARAM
|
||||
from vitrage.evaluator.template_validation.base import get_custom_fault_result
|
||||
from vitrage.evaluator.template_validation.base import ValidationError
|
||||
from vitrage.evaluator.template_validation.content.base import \
|
||||
get_content_correct_result
|
||||
from vitrage.evaluator.template_validation.content.base import \
|
||||
|
@ -37,7 +36,13 @@ def resolve_parameters(template_def, params=None):
|
|||
|
||||
get_param = template_schema.functions.get(GET_PARAM)
|
||||
|
||||
return FunctionResolver().resolve_function(
|
||||
func_info=FuncInfo(name=GET_PARAM, func=get_param, error_code=160),
|
||||
template=template_def,
|
||||
actual_params=params)
|
||||
try:
|
||||
function_resolver.resolve_function(
|
||||
func_info=function_resolver.FuncInfo(
|
||||
name=GET_PARAM, func=get_param, error_code=0),
|
||||
template=template_def,
|
||||
actual_params=params)
|
||||
except ValidationError as e:
|
||||
return get_custom_fault_result(e.code, e.details)
|
||||
|
||||
return get_content_correct_result()
|
||||
|
|
|
@ -15,11 +15,7 @@ from oslo_log import log
|
|||
|
||||
from vitrage.evaluator.template_fields import TemplateFields
|
||||
from vitrage.evaluator.template_functions import GET_PARAM
|
||||
from vitrage.evaluator.template_validation.content.base import \
|
||||
get_content_correct_result
|
||||
from vitrage.evaluator.template_validation.content.base import \
|
||||
get_content_fault_result
|
||||
from vitrage.evaluator.template_validation.status_messages import status_msgs
|
||||
from vitrage.evaluator.template_validation.base import ValidationError
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
@ -112,42 +108,39 @@ def get_param(param_name, template, **kwargs):
|
|||
:param kwargs: Additional arguments.
|
||||
The expected argument is actual_params, a dict with key=value pairs of
|
||||
parameter values.
|
||||
:return: A tuple of (Result, param value)
|
||||
The parameter value is taken from the actual_params, if given, or from the
|
||||
default value that is defined in the template parameters section.
|
||||
If none exists, a fault result is returned.
|
||||
:return: The parameter value is taken from the actual_params, if given, or
|
||||
from the default value that is defined in the template parameters section.
|
||||
If none exists, or param_name does not contains a valid function call
|
||||
a ValidationError is raised.
|
||||
:raises: ValidationError
|
||||
"""
|
||||
param_defs = template.get(TemplateFields.PARAMETERS)
|
||||
actual_params = kwargs.get('actual_params')
|
||||
|
||||
if not param_defs:
|
||||
LOG.error('%s status code: %s' % (status_msgs[161], 161))
|
||||
return get_content_fault_result(161), None
|
||||
raise ValidationError(161)
|
||||
|
||||
if param_name.startswith(GET_PARAM):
|
||||
if not param_name.startswith(GET_PARAM + '(') or \
|
||||
not param_name.endswith(')') or \
|
||||
len(param_name) < len(GET_PARAM) + 3:
|
||||
LOG.error('%s status code: %s' % (status_msgs[162], 162))
|
||||
return get_content_fault_result(162), None
|
||||
raise ValidationError(162, param_name)
|
||||
|
||||
param_name = extract_param_name(param_name)
|
||||
if not param_name:
|
||||
LOG.error('%s status code: %s' % (status_msgs[162], 162))
|
||||
return get_content_fault_result(162), None
|
||||
extracted_param_name = extract_param_name(param_name)
|
||||
if not extracted_param_name:
|
||||
raise ValidationError(162, param_name)
|
||||
|
||||
# Make sure the parameter is defined in the parameters section
|
||||
found_param_def = None
|
||||
for param_key, param_value in param_defs.items():
|
||||
if param_name == param_key:
|
||||
if extracted_param_name == param_key:
|
||||
found_param_def = param_key, param_value
|
||||
|
||||
if not found_param_def:
|
||||
LOG.error('%s status code: %s' % (status_msgs[161], 161))
|
||||
return get_content_fault_result(161), None
|
||||
raise ValidationError(161, extracted_param_name)
|
||||
|
||||
# Check if an actual value was assigned to this parameter
|
||||
param_value = get_actual_value(param_name, actual_params)
|
||||
param_value = get_actual_value(extracted_param_name, actual_params)
|
||||
if not param_value:
|
||||
found_param_value = found_param_def[1]
|
||||
default = found_param_value.get(TemplateFields.DEFAULT) \
|
||||
|
@ -155,9 +148,9 @@ def get_param(param_name, template, **kwargs):
|
|||
if default:
|
||||
param_value = default
|
||||
else:
|
||||
return get_content_fault_result(163), None
|
||||
raise ValidationError(163, extracted_param_name)
|
||||
|
||||
return get_content_correct_result(), param_value
|
||||
return param_value
|
||||
|
||||
|
||||
def extract_param_name(param):
|
||||
|
|
|
@ -127,7 +127,10 @@ class TemplateSchema3(object):
|
|||
ActionType.SET_STATE: V3ActionLoader(),
|
||||
}
|
||||
|
||||
self.functions = {GET_ATTR: get_attr}
|
||||
self.functions = {
|
||||
GET_ATTR: get_attr,
|
||||
GET_PARAM: get_param
|
||||
}
|
||||
|
||||
def version(self):
|
||||
return '3'
|
||||
|
|
|
@ -40,7 +40,7 @@ def validate_template(template, def_templates, params=None):
|
|||
|
||||
try:
|
||||
template_schema.validators[SYNTAX].validate(template)
|
||||
template_schema.validators[CONTENT].validate(template)
|
||||
template_schema.validators[CONTENT].validate(template, params)
|
||||
except base.ValidationError as e:
|
||||
return base.get_custom_fault_result(e.code, e.details)
|
||||
except VoluptuousError as e:
|
||||
|
|
|
@ -43,7 +43,7 @@ def get_fault_result(description, code, msg=None):
|
|||
|
||||
def get_custom_fault_result(code, msg):
|
||||
return Result('Template validation', False, code,
|
||||
status_msgs[code] + ' ' + msg)
|
||||
status_msgs[code] + ' - ' + msg)
|
||||
|
||||
|
||||
def get_status_code(voluptuous_error):
|
||||
|
|
|
@ -104,6 +104,5 @@ def content_validation(template, def_templates=None, params=None):
|
|||
|
||||
|
||||
def parameters_validation(template_schema, template, actual_params):
|
||||
params_validator = \
|
||||
template_schema.validators.get(GET_PARAM) if template_schema else None
|
||||
params_validator = template_schema.validators[GET_PARAM]
|
||||
return params_validator.validate(template, actual_params)
|
||||
|
|
|
@ -21,6 +21,9 @@ from vitrage.evaluator.base import get_template_schema
|
|||
from vitrage.evaluator import condition as dnf
|
||||
|
||||
from vitrage.evaluator.template_fields import TemplateFields
|
||||
from vitrage.evaluator.template_functions import function_resolver
|
||||
from vitrage.evaluator.template_functions import GET_PARAM
|
||||
from vitrage.evaluator.template_functions.v2.functions import get_param
|
||||
from vitrage.evaluator.template_loading.template_loader_v3 import \
|
||||
TemplateLoader as V3TemplateLoader
|
||||
from vitrage.evaluator.template_validation.base import ValidationError
|
||||
|
@ -33,9 +36,10 @@ RELATION = 'relationship'
|
|||
class ContentValidator(object):
|
||||
|
||||
@staticmethod
|
||||
def validate(template):
|
||||
def validate(template, actual_params):
|
||||
_validate_entities_regex(template)
|
||||
_validate_conditions(template)
|
||||
_validate_parameters(template, actual_params)
|
||||
|
||||
# As part of validation, when it is finished,
|
||||
# we try to load the template, as some validations can only be
|
||||
|
@ -69,6 +73,14 @@ def _validate_conditions(template):
|
|||
_validate_not_condition(condition)
|
||||
|
||||
|
||||
def _validate_parameters(template, actual_params):
|
||||
function_resolver.validate_function(
|
||||
func_info=function_resolver.FuncInfo(
|
||||
name=GET_PARAM, func=get_param, error_code=160),
|
||||
template=template,
|
||||
actual_params=actual_params)
|
||||
|
||||
|
||||
def _validate_condition_entity_ids(template, condition):
|
||||
curr_str = ' ' + condition + ' '
|
||||
|
||||
|
|
|
@ -12,11 +12,12 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from vitrage.evaluator.template_functions.function_resolver import \
|
||||
FuncInfo
|
||||
from vitrage.evaluator.template_functions.function_resolver import \
|
||||
FunctionResolver
|
||||
from vitrage.evaluator.template_functions import function_resolver
|
||||
from vitrage.evaluator.template_functions import GET_PARAM
|
||||
from vitrage.evaluator.template_validation.base import get_custom_fault_result
|
||||
from vitrage.evaluator.template_validation.base import ValidationError
|
||||
from vitrage.evaluator.template_validation.content.base import \
|
||||
get_content_correct_result
|
||||
|
||||
|
||||
class GetParamValidator(object):
|
||||
|
@ -25,7 +26,12 @@ class GetParamValidator(object):
|
|||
def validate(cls, template, actual_params):
|
||||
# if there is a get_param in the template, an error message will be
|
||||
# returned since func is None
|
||||
return FunctionResolver().validate_function(
|
||||
func_info=FuncInfo(name=GET_PARAM, func=None, error_code=160),
|
||||
template=template,
|
||||
actual_params=actual_params)
|
||||
try:
|
||||
function_resolver.validate_function(
|
||||
func_info=function_resolver.FuncInfo(
|
||||
name=GET_PARAM, func=None, error_code=160),
|
||||
template=template,
|
||||
actual_params=actual_params)
|
||||
except ValidationError as e:
|
||||
return get_custom_fault_result(e.code, e.details)
|
||||
return get_content_correct_result()
|
||||
|
|
|
@ -12,19 +12,25 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from vitrage.evaluator.template_functions.function_resolver import \
|
||||
FuncInfo
|
||||
from vitrage.evaluator.template_functions.function_resolver import \
|
||||
FunctionResolver
|
||||
from vitrage.evaluator.template_functions import function_resolver
|
||||
from vitrage.evaluator.template_functions import GET_PARAM
|
||||
from vitrage.evaluator.template_functions.v2.functions import get_param
|
||||
from vitrage.evaluator.template_validation.base import get_custom_fault_result
|
||||
from vitrage.evaluator.template_validation.base import ValidationError
|
||||
from vitrage.evaluator.template_validation.content.base import \
|
||||
get_content_correct_result
|
||||
|
||||
|
||||
class GetParamValidator(object):
|
||||
|
||||
@classmethod
|
||||
def validate(cls, template, actual_params):
|
||||
return FunctionResolver().validate_function(
|
||||
func_info=FuncInfo(name=GET_PARAM, func=get_param, error_code=160),
|
||||
template=template,
|
||||
actual_params=actual_params)
|
||||
try:
|
||||
function_resolver.validate_function(
|
||||
function_resolver.FuncInfo(
|
||||
name=GET_PARAM, func=get_param, error_code=0),
|
||||
template,
|
||||
actual_params=actual_params)
|
||||
except ValidationError as e:
|
||||
return get_custom_fault_result(e.code, e.details)
|
||||
return get_content_correct_result()
|
||||
|
|
|
@ -44,6 +44,7 @@ class SyntaxValidator(object):
|
|||
Required(TF.ENTITIES, msg=10000): _entities_schema(),
|
||||
Required(TF.METADATA, msg=62): _metadata_schema(),
|
||||
Required(TF.SCENARIOS, msg=80): _scenarios_schema(template),
|
||||
Optional(TF.PARAMETERS): _parameters_schema(),
|
||||
})(template)
|
||||
|
||||
|
||||
|
@ -79,6 +80,15 @@ def _scenarios_schema(template):
|
|||
})])
|
||||
|
||||
|
||||
def _parameters_schema():
|
||||
return Schema({
|
||||
any_str: Any(any_str, Schema({
|
||||
Optional(TF.DESCRIPTION): any_str,
|
||||
Optional(TF.DEFAULT): any_str,
|
||||
})),
|
||||
})
|
||||
|
||||
|
||||
def _raise_alarm_schema(template):
|
||||
return Schema({
|
||||
Optional(ActionType.RAISE_ALARM): Schema({
|
||||
|
|
|
@ -19,6 +19,8 @@ from oslo_utils import timeutils
|
|||
# noinspection PyPackageRequirements
|
||||
from oslotest import base
|
||||
import sys
|
||||
|
||||
from testtools import matchers
|
||||
from testtools.matchers import HasLength
|
||||
|
||||
|
||||
|
@ -91,6 +93,10 @@ class BaseTest(base.BaseTestCase):
|
|||
dict(g2_edges.get(e_source_id)),
|
||||
"Edges of each graph are not equal")
|
||||
|
||||
def assert_starts_with(self, expected_prefix, observed_str, msg=None):
|
||||
self.assertThat(observed_str,
|
||||
matchers.StartsWith(expected_prefix), msg)
|
||||
|
||||
@staticmethod
|
||||
def path_get(project_file=None):
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
|
|
|
@ -23,10 +23,7 @@ from vitrage.tests.unit.entity_graph.base import TestEntityGraphUnitBase
|
|||
|
||||
|
||||
class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
||||
TEMPLATE_WITH_PARAMS = 'with_params.yaml'
|
||||
TEMPLATE_WITH_EXTRA_PARAM_DEF = 'with_extra_param_def.yaml'
|
||||
TEMPLATE_WITH_MISSING_PARAM_DEF = 'with_missing_param_def.yaml'
|
||||
TEMPLATE_WITHOUT_PARAMS = 'without_params.yaml'
|
||||
|
||||
VALIDATION_FAILED = 'validation failed'
|
||||
VALIDATION_OK = 'validation OK'
|
||||
|
||||
|
@ -46,13 +43,14 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
super(TestTemplates, self).tearDown()
|
||||
self._delete_templates()
|
||||
|
||||
def test_validate_template_with_no_params(self):
|
||||
# Setup
|
||||
def _load_template_content(self, template_filename):
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
template_filename)
|
||||
return [(template_path, self._load_yaml_file(template_path))]
|
||||
|
||||
def _validate_template_with_no_params(self, template_filename):
|
||||
files_content = self._load_template_content(template_filename)
|
||||
# Action
|
||||
results = self.apis.validate_template(
|
||||
ctx=None, templates=files_content, template_type=None, params=None)
|
||||
|
@ -62,14 +60,11 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self.VALIDATION_FAILED, 163,
|
||||
'Failed to resolve parameter', results)
|
||||
|
||||
def test_validate_template_with_missing_param(self):
|
||||
def _validate_template_with_missing_param(self, template_filename):
|
||||
# Setup
|
||||
apis = TemplateApis(notifier=self.MockNotifier(), db=self._db)
|
||||
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'template_name': 'template_with_params_1',
|
||||
'alarm_name': 'My alarm', 'new_state': 'SUBOPTIMAL'}
|
||||
|
||||
|
@ -82,14 +77,10 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self.VALIDATION_FAILED, 163,
|
||||
'Failed to resolve parameter', results)
|
||||
|
||||
def test_validate_template_with_actual_params(self):
|
||||
def _validate_template_with_actual_params(self, template_filename):
|
||||
# Setup
|
||||
apis = TemplateApis(notifier=self.MockNotifier(), db=self._db)
|
||||
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'template_name': 'template_with_params_2',
|
||||
'alarm_type': 'zabbix', 'alarm_name': 'My alarm',
|
||||
'new_state': 'SUBOPTIMAL'}
|
||||
|
@ -102,14 +93,10 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self._assert_validate_template_result(
|
||||
self.VALIDATION_OK, 0, 'Template validation is OK', results)
|
||||
|
||||
def test_validate_template_with_missing_param_def(self):
|
||||
def _validate_template_with_missing_param_def(self, template_filename):
|
||||
# Setup
|
||||
apis = TemplateApis(notifier=self.MockNotifier(), db=self._db)
|
||||
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_MISSING_PARAM_DEF)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'alarm_type': 'zabbix', 'alarm_name': 'My alarm',
|
||||
'new_state': 'SUBOPTIMAL'}
|
||||
|
||||
|
@ -122,14 +109,10 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self.VALIDATION_FAILED, 161, 'get_param called for a parameter '
|
||||
'that is not defined in the \'parameters\' block', results)
|
||||
|
||||
def test_validate_template_without_params(self):
|
||||
def _validate_template_without_params(self, template_filename):
|
||||
# Setup
|
||||
apis = TemplateApis(notifier=self.MockNotifier(), db=self._db)
|
||||
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITHOUT_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
|
||||
# Action
|
||||
results = apis.validate_template(ctx=None, templates=files_content,
|
||||
|
@ -139,14 +122,10 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self._assert_validate_template_result(
|
||||
self.VALIDATION_OK, 0, 'Template validation is OK', results)
|
||||
|
||||
def test_validate_template_with_extra_actual_param(self):
|
||||
def _validate_template_with_extra_actual_param(self, template_filename):
|
||||
# Setup
|
||||
apis = TemplateApis(notifier=self.MockNotifier(), db=self._db)
|
||||
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'template_name': 'template_with_params_2',
|
||||
'alarm_type': 'zabbix', 'alarm_name': 'My alarm',
|
||||
'new_state': 'SUBOPTIMAL',
|
||||
|
@ -160,14 +139,10 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self._assert_validate_template_result(
|
||||
self.VALIDATION_OK, 0, 'Template validation is OK', results)
|
||||
|
||||
def test_validate_template_with_extra_param_def(self):
|
||||
def _validate_template_with_extra_param_def(self, template_filename):
|
||||
# Setup
|
||||
apis = TemplateApis(notifier=self.MockNotifier(), db=self._db)
|
||||
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_EXTRA_PARAM_DEF)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'template_name': 'template_with_params_2',
|
||||
'alarm_type': 'zabbix', 'alarm_name': 'My alarm',
|
||||
'new_state': 'SUBOPTIMAL'}
|
||||
|
@ -180,12 +155,9 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self._assert_validate_template_result(
|
||||
self.VALIDATION_OK, 0, 'Template validation is OK', results)
|
||||
|
||||
def test_add_template_with_no_params(self):
|
||||
def _add_template_with_no_params(self, template_filename):
|
||||
# Setup
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
|
||||
# Action.
|
||||
added_templates = \
|
||||
|
@ -196,15 +168,12 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
# Test assertions
|
||||
self.assertThat(added_templates, matchers.HasLength(1))
|
||||
self.assertEqual('ERROR', added_templates[0]['status'])
|
||||
self.assertEqual('Failed to resolve parameter',
|
||||
added_templates[0]['status details'])
|
||||
self.assert_starts_with('Failed to resolve parameter',
|
||||
added_templates[0]['status details'])
|
||||
|
||||
def test_add_template_with_missing_param(self):
|
||||
def _add_template_with_missing_param(self, template_filename):
|
||||
# Setup
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'template_name': 'template_with_params_3',
|
||||
'alarm_name': 'My alarm', 'new_state': 'SUBOPTIMAL'}
|
||||
|
||||
|
@ -217,15 +186,12 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
# Test assertions
|
||||
self.assertThat(added_templates, matchers.HasLength(1))
|
||||
self.assertEqual('ERROR', added_templates[0]['status'])
|
||||
self.assertEqual('Failed to resolve parameter',
|
||||
added_templates[0]['status details'])
|
||||
self.assert_starts_with('Failed to resolve parameter',
|
||||
added_templates[0]['status details'])
|
||||
|
||||
def test_add_template_with_actual_params(self):
|
||||
def _add_template_with_actual_params(self, template_filename):
|
||||
# Setup
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'template_name': 'template_with_params_4',
|
||||
'alarm_type': 'zabbix', 'alarm_name': 'My alarm',
|
||||
'new_state': 'SUBOPTIMAL'}
|
||||
|
@ -240,12 +206,9 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self.assertThat(added_templates, matchers.HasLength(1))
|
||||
self.assertEqual('LOADING', added_templates[0]['status'])
|
||||
|
||||
def test_add_template_with_missing_param_def(self):
|
||||
def _add_template_with_missing_param_def(self, template_filename):
|
||||
# Setup
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_MISSING_PARAM_DEF)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'alarm_type': 'zabbix', 'alarm_name': 'My alarm',
|
||||
'new_state': 'SUBOPTIMAL'}
|
||||
|
||||
|
@ -257,16 +220,13 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
|
||||
# Test assertions
|
||||
self.assertEqual('ERROR', added_templates[0]['status'])
|
||||
self.assertEqual('get_param called for a parameter that is not '
|
||||
'defined in the \'parameters\' block',
|
||||
added_templates[0]['status details'])
|
||||
self.assert_starts_with('get_param called for a parameter that is not '
|
||||
'defined in the \'parameters\' block',
|
||||
added_templates[0]['status details'])
|
||||
|
||||
def test_add_template_without_params(self):
|
||||
def _add_template_without_params(self, template_filename):
|
||||
# Setup
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITHOUT_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
|
||||
# Action
|
||||
added_templates = \
|
||||
|
@ -278,12 +238,9 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self.assertThat(added_templates, matchers.HasLength(1))
|
||||
self.assertEqual('LOADING', added_templates[0]['status'])
|
||||
|
||||
def test_add_template_with_extra_actual_param(self):
|
||||
def _add_template_with_extra_actual_param(self, template_filename):
|
||||
# Setup
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_PARAMS)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'template_name': 'template_with_extra_actual_param',
|
||||
'alarm_type': 'zabbix', 'alarm_name': 'My alarm',
|
||||
'new_state': 'SUBOPTIMAL',
|
||||
|
@ -299,12 +256,9 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self.assertThat(added_templates, matchers.HasLength(1))
|
||||
self.assertEqual('LOADING', added_templates[0]['status'])
|
||||
|
||||
def test_add_template_with_extra_param_def(self):
|
||||
def _add_template_with_extra_param_def(self, template_filename):
|
||||
# Setup
|
||||
template_path = '%s/templates/parameters/%s' % (
|
||||
utils.get_resources_dir(),
|
||||
self.TEMPLATE_WITH_EXTRA_PARAM_DEF)
|
||||
files_content = [(template_path, self._load_yaml_file(template_path))]
|
||||
files_content = self._load_template_content(template_filename)
|
||||
params = {'template_name': 'template_with_extra_param_def',
|
||||
'alarm_type': 'zabbix', 'alarm_name': 'My alarm',
|
||||
'new_state': 'SUBOPTIMAL'}
|
||||
|
@ -329,7 +283,7 @@ class TestTemplates(TestEntityGraphUnitBase, TestConfiguration):
|
|||
self.assertThat(results, matchers.HasLength(1))
|
||||
self.assertEqual(expected_status, results[0]['status'])
|
||||
self.assertEqual(expected_status_code, results[0]['status code'])
|
||||
self.assertEqual(expected_message, results[0]['message'])
|
||||
self.assert_starts_with(expected_message, results[0]['message'])
|
||||
|
||||
def _delete_templates(self):
|
||||
if self.added_template:
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
# Copyright 2019 - Nokia
|
||||
#
|
||||
# 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 vitrage.tests.functional.api_handler.test_templates import TestTemplates
|
||||
|
||||
TEMPLATE_WITH_PARAMS = 'v2_with_params.yaml'
|
||||
TEMPLATE_WITH_EXTRA_PARAM_DEF = 'v2_with_extra_param_def.yaml'
|
||||
TEMPLATE_WITH_MISSING_PARAM_DEF = 'v2_with_missing_param_def.yaml'
|
||||
TEMPLATE_WITHOUT_PARAMS = 'v2_without_params.yaml'
|
||||
|
||||
|
||||
class TestTemplatesV2(TestTemplates):
|
||||
|
||||
def test_validate_template_with_no_params(self):
|
||||
self._validate_template_with_no_params(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_validate_template_with_missing_param(self):
|
||||
self._validate_template_with_missing_param(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_validate_template_with_actual_params(self):
|
||||
self._validate_template_with_actual_params(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_validate_template_with_missing_param_def(self):
|
||||
self._validate_template_with_missing_param_def(
|
||||
TEMPLATE_WITH_MISSING_PARAM_DEF)
|
||||
|
||||
def test_validate_template_without_params(self):
|
||||
self._validate_template_without_params(TEMPLATE_WITHOUT_PARAMS)
|
||||
|
||||
def test_validate_template_with_extra_actual_param(self):
|
||||
self._validate_template_with_extra_actual_param(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_validate_template_with_extra_param_def(self):
|
||||
self._validate_template_with_extra_param_def(
|
||||
TEMPLATE_WITH_EXTRA_PARAM_DEF)
|
||||
|
||||
def test_add_template_with_no_params(self):
|
||||
self._add_template_with_no_params(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_add_template_with_missing_param(self):
|
||||
self._add_template_with_missing_param(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_add_template_with_actual_params(self):
|
||||
self._add_template_with_actual_params(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_add_template_with_missing_param_def(self):
|
||||
self._add_template_with_missing_param_def(
|
||||
TEMPLATE_WITH_MISSING_PARAM_DEF)
|
||||
|
||||
def test_add_template_without_params(self):
|
||||
self._add_template_without_params(TEMPLATE_WITHOUT_PARAMS)
|
||||
|
||||
def test_add_template_with_extra_actual_param(self):
|
||||
self._add_template_with_extra_actual_param(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_add_template_with_extra_param_def(self):
|
||||
self._add_template_with_extra_param_def(TEMPLATE_WITH_EXTRA_PARAM_DEF)
|
|
@ -0,0 +1,60 @@
|
|||
# Copyright 2019 - Nokia
|
||||
#
|
||||
# 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 vitrage.tests.functional.api_handler.test_templates import TestTemplates
|
||||
|
||||
TEMPLATE_WITH_PARAMS = 'v3_with_params.yaml'
|
||||
TEMPLATE_WITH_EXTRA_PARAM_DEF = 'v3_with_extra_param_def.yaml'
|
||||
TEMPLATE_WITH_MISSING_PARAM_DEF = 'v3_with_missing_param_def.yaml'
|
||||
|
||||
|
||||
class TestTemplatesV3(TestTemplates):
|
||||
|
||||
def test_validate_template_with_no_params(self):
|
||||
self._validate_template_with_no_params(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_validate_template_with_missing_param(self):
|
||||
self._validate_template_with_missing_param(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_validate_template_with_actual_params(self):
|
||||
self._validate_template_with_actual_params(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_validate_template_with_missing_param_def(self):
|
||||
self._validate_template_with_missing_param_def(
|
||||
TEMPLATE_WITH_MISSING_PARAM_DEF)
|
||||
|
||||
def test_validate_template_with_extra_actual_param(self):
|
||||
self._validate_template_with_extra_actual_param(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_validate_template_with_extra_param_def(self):
|
||||
self._validate_template_with_extra_param_def(
|
||||
TEMPLATE_WITH_EXTRA_PARAM_DEF)
|
||||
|
||||
def test_add_template_with_no_params(self):
|
||||
self._add_template_with_no_params(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_add_template_with_missing_param(self):
|
||||
self._add_template_with_missing_param(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_add_template_with_actual_params(self):
|
||||
self._add_template_with_actual_params(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_add_template_with_missing_param_def(self):
|
||||
self._add_template_with_missing_param_def(
|
||||
TEMPLATE_WITH_MISSING_PARAM_DEF)
|
||||
|
||||
def test_add_template_with_extra_actual_param(self):
|
||||
self._add_template_with_extra_actual_param(TEMPLATE_WITH_PARAMS)
|
||||
|
||||
def test_add_template_with_extra_param_def(self):
|
||||
self._add_template_with_extra_param_def(TEMPLATE_WITH_EXTRA_PARAM_DEF)
|
|
@ -0,0 +1,30 @@
|
|||
metadata:
|
||||
version: 3
|
||||
type: standard
|
||||
name: get_param(template_name)
|
||||
description: template with extra parameter def (extra_param is unused)
|
||||
parameters:
|
||||
template_name:
|
||||
description: the name of the template
|
||||
default: template_with_params
|
||||
alarm_type:
|
||||
description: the type of the alarm
|
||||
alarm_name:
|
||||
new_state:
|
||||
default: ERROR
|
||||
extra_param:
|
||||
description: a parameter definition that is unused in the template
|
||||
entities:
|
||||
alarm:
|
||||
category: ALARM
|
||||
type: get_param(alarm_type)
|
||||
name: get_param(alarm_name)
|
||||
host:
|
||||
category: RESOURCE
|
||||
type: nova.host
|
||||
scenarios:
|
||||
- condition: alarm [on] host
|
||||
actions:
|
||||
- set_state:
|
||||
state: get_param(new_state)
|
||||
target: host
|
|
@ -0,0 +1,24 @@
|
|||
metadata:
|
||||
version: 3
|
||||
type: standard
|
||||
name: template_with_missing_param_def
|
||||
description: INVALID template with missing parameter def for alarm_name
|
||||
parameters:
|
||||
alarm_type:
|
||||
description: the type of the alarm
|
||||
new_state:
|
||||
default: ERROR
|
||||
entities:
|
||||
alarm:
|
||||
category: ALARM
|
||||
type: get_param(alarm_type)
|
||||
name: get_param(alarm_name)
|
||||
host:
|
||||
category: RESOURCE
|
||||
type: nova.host
|
||||
scenarios:
|
||||
- condition: alarm [on] host
|
||||
actions:
|
||||
- set_state:
|
||||
state: get_param(new_state)
|
||||
target: host
|
|
@ -0,0 +1,28 @@
|
|||
metadata:
|
||||
version: 3
|
||||
type: standard
|
||||
name: get_param(template_name)
|
||||
description: template with parameters
|
||||
parameters:
|
||||
template_name:
|
||||
description: the name of the template
|
||||
default: template_with_params
|
||||
alarm_type:
|
||||
description: the type of the alarm
|
||||
alarm_name:
|
||||
new_state:
|
||||
default: ERROR
|
||||
entities:
|
||||
alarm:
|
||||
category: ALARM
|
||||
type: get_param(alarm_type)
|
||||
name: get_param(alarm_name)
|
||||
host:
|
||||
category: RESOURCE
|
||||
type: nova.host
|
||||
scenarios:
|
||||
- condition: alarm [on] host
|
||||
actions:
|
||||
- set_state:
|
||||
state: get_param(new_state)
|
||||
target: host
|
|
@ -26,11 +26,13 @@ class ParametersValidatorTest(ValidatorTest):
|
|||
"""
|
||||
|
||||
def test_validate_no_parameters(self):
|
||||
result = GetParamValidator.validate(template={}, actual_params=None)
|
||||
result = GetParamValidator.validate(
|
||||
template={'alarm_name': "Don't add a comment"}, actual_params=None)
|
||||
self._assert_correct_result(result)
|
||||
|
||||
def test_validate_empty_parameters(self):
|
||||
result = GetParamValidator.validate(template={}, actual_params={})
|
||||
result = GetParamValidator.validate(
|
||||
template={'alarm_name': '+2 for everybody'}, actual_params={})
|
||||
self._assert_correct_result(result)
|
||||
|
||||
def test_validate_with_parameter(self):
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
from vitrage.evaluator.template_fields import TemplateFields
|
||||
from vitrage.evaluator.template_functions.v2.functions import get_param
|
||||
from vitrage.evaluator.template_validation.base import ValidationError
|
||||
from vitrage.evaluator.template_validation.content.v2.get_param_validator \
|
||||
import GetParamValidator
|
||||
from vitrage.tests.unit.evaluator.template_validation.content.base import \
|
||||
|
@ -70,13 +71,15 @@ class ParametersValidatorTest(ValidatorTest):
|
|||
|
||||
def test_validate_get_param_with_no_parameters(self):
|
||||
template = {'alarm_name': 'get_param(param1)'}
|
||||
result, _ = get_param('get_param(param1)', template)
|
||||
self._assert_fault_result(result, 161)
|
||||
self.assert_get_param_result('get_param(param1)',
|
||||
template,
|
||||
expected_error_code=161)
|
||||
|
||||
def test_validate_get_param_with_empty_parameters(self):
|
||||
template = {}
|
||||
result, _ = get_param('get_param(param1)', template)
|
||||
self._assert_fault_result(result, 161)
|
||||
self.assert_get_param_result('get_param(param1)',
|
||||
template,
|
||||
expected_error_code=161)
|
||||
|
||||
def test_validate_get_param_with_undefined_parameter(self):
|
||||
template = {
|
||||
|
@ -90,8 +93,9 @@ class ParametersValidatorTest(ValidatorTest):
|
|||
},
|
||||
}
|
||||
}
|
||||
result, _ = get_param('get_param(undefined)', template)
|
||||
self._assert_fault_result(result, 161)
|
||||
self.assert_get_param_result('get_param(undefined)',
|
||||
template,
|
||||
expected_error_code=161)
|
||||
|
||||
def test_validate_get_param_with_valid_parameter(self):
|
||||
template = {
|
||||
|
@ -105,8 +109,9 @@ class ParametersValidatorTest(ValidatorTest):
|
|||
},
|
||||
}
|
||||
}
|
||||
result, result_value = get_param('get_param(param1)', template)
|
||||
self._assert_correct_result(result)
|
||||
self.assert_get_param_result('get_param(param1)',
|
||||
template,
|
||||
expected_error_code=0)
|
||||
|
||||
def test_validate_get_param_with_malformed_parameter(self):
|
||||
template = {
|
||||
|
@ -121,23 +126,23 @@ class ParametersValidatorTest(ValidatorTest):
|
|||
}
|
||||
}
|
||||
|
||||
result, _ = get_param('get_param(param1', template)
|
||||
self._assert_fault_result(result, 162)
|
||||
self.assert_get_param_result(
|
||||
'get_param(param1', template, expected_error_code=162)
|
||||
|
||||
result, _ = get_param('get_paramparam1)', template)
|
||||
self._assert_fault_result(result, 162)
|
||||
self.assert_get_param_result(
|
||||
'get_paramparam1)', template, expected_error_code=162)
|
||||
|
||||
result, _ = get_param('get_paramparam1', template)
|
||||
self._assert_fault_result(result, 162)
|
||||
self.assert_get_param_result(
|
||||
'get_paramparam1', template, expected_error_code=162)
|
||||
|
||||
result, _ = get_param('get_param', template)
|
||||
self._assert_fault_result(result, 162)
|
||||
self.assert_get_param_result(
|
||||
'get_param', template, expected_error_code=162)
|
||||
|
||||
result, _ = get_param('get_param()', template)
|
||||
self._assert_fault_result(result, 162)
|
||||
self.assert_get_param_result(
|
||||
'get_param()', template, expected_error_code=162)
|
||||
|
||||
result, _ = get_param('get_param)param1(', template)
|
||||
self._assert_fault_result(result, 162)
|
||||
self.assert_get_param_result(
|
||||
'get_param)param1(', template, expected_error_code=162)
|
||||
|
||||
def test_validate_get_param_with_actual_parameter(self):
|
||||
template = {
|
||||
|
@ -155,10 +160,10 @@ class ParametersValidatorTest(ValidatorTest):
|
|||
'param1': 'value1',
|
||||
'param2': 'value2'
|
||||
}
|
||||
result, result_value = get_param('get_param(param2)', template,
|
||||
actual_params=actual_params)
|
||||
self._assert_correct_result(result)
|
||||
self.assertEqual('value2', result_value)
|
||||
self.assert_get_param_result('get_param(param2)',
|
||||
template,
|
||||
actual_params,
|
||||
expected_result='value2')
|
||||
|
||||
def test_validate_get_param_with_missing_actual_parameter(self):
|
||||
template = {
|
||||
|
@ -175,9 +180,9 @@ class ParametersValidatorTest(ValidatorTest):
|
|||
actual_params = {
|
||||
'param1': 'value1',
|
||||
}
|
||||
result, _ = get_param('get_param(param2)', template,
|
||||
actual_params=actual_params)
|
||||
self._assert_fault_result(result, 163)
|
||||
self.assert_get_param_result('get_param(param2)',
|
||||
template, actual_params,
|
||||
expected_error_code=163)
|
||||
|
||||
def test_validate_get_param_with_default_actual_parameter(self):
|
||||
template = {
|
||||
|
@ -194,7 +199,27 @@ class ParametersValidatorTest(ValidatorTest):
|
|||
actual_params = {
|
||||
'param2': 'value2',
|
||||
}
|
||||
result, result_value = get_param('get_param(param1)', template,
|
||||
actual_params=actual_params)
|
||||
self._assert_correct_result(result)
|
||||
self.assertEqual('this is my default', result_value)
|
||||
self.assert_get_param_result('get_param(param1)',
|
||||
template,
|
||||
actual_params,
|
||||
expected_result='this is my default')
|
||||
|
||||
def assert_get_param_result(self,
|
||||
func_str,
|
||||
template,
|
||||
actual_params=None,
|
||||
expected_result=None,
|
||||
expected_error_code=None):
|
||||
error = None
|
||||
try:
|
||||
result = get_param(func_str, template, actual_params=actual_params)
|
||||
except ValidationError as e:
|
||||
error = e
|
||||
|
||||
if expected_error_code:
|
||||
self.assertIsNotNone(error)
|
||||
self.assertEqual(error.code, expected_error_code)
|
||||
else:
|
||||
self.assertIsNone(error)
|
||||
if expected_result:
|
||||
self.assertEqual(expected_result, result)
|
||||
|
|
Loading…
Reference in New Issue