vitrage evaluator - template validator
Change-Id: Iec95ee888dc4822f9bd478ce2434a89d1b00a2e1
This commit is contained in:
parent
641eaf6da2
commit
df74a75090
@ -19,3 +19,4 @@ Werkzeug>=0.7
|
|||||||
keystonemiddleware>=2.3.0
|
keystonemiddleware>=2.3.0
|
||||||
stevedore>=1.5.0 # Apache-2.0
|
stevedore>=1.5.0 # Apache-2.0
|
||||||
exrex>=0.9.4
|
exrex>=0.9.4
|
||||||
|
voluptuous>=0.8.8
|
||||||
|
@ -22,3 +22,4 @@ testscenarios>=0.4
|
|||||||
testtools>=1.4.0
|
testtools>=1.4.0
|
||||||
exrex>=0.9.4
|
exrex>=0.9.4
|
||||||
stevedore>=1.5.0 # Apache-2.0
|
stevedore>=1.5.0 # Apache-2.0
|
||||||
|
voluptuous>=0.8.8
|
||||||
|
@ -12,9 +12,13 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def load_files(dir_path, suffix=None):
|
def load_files(dir_path, suffix=None):
|
||||||
loaded_files = os.listdir(dir_path)
|
loaded_files = os.listdir(dir_path)
|
||||||
@ -25,15 +29,21 @@ def load_files(dir_path, suffix=None):
|
|||||||
return loaded_files
|
return loaded_files
|
||||||
|
|
||||||
|
|
||||||
def load_yaml_files(dir_path):
|
def load_yaml_files(dir_path, with_exception=False):
|
||||||
files = load_files(dir_path, '.yaml')
|
files = load_files(dir_path, '.yaml')
|
||||||
|
|
||||||
yaml_files = []
|
yaml_files = []
|
||||||
for file in files:
|
for file in files:
|
||||||
full_path = dir_path + '/' + file
|
full_path = dir_path + '/' + file
|
||||||
with open(full_path, 'r') as stream:
|
with open(full_path, 'r') as stream:
|
||||||
# TODO(alexey): check what to do if parse of one of the files fails
|
try:
|
||||||
config = yaml.load(stream)
|
config = yaml.load(stream, Loader=yaml.BaseLoader)
|
||||||
|
except Exception as e:
|
||||||
|
if with_exception:
|
||||||
|
raise e
|
||||||
|
else:
|
||||||
|
LOG.error('Fails to parse file: %s. %s' % full_path, e)
|
||||||
|
|
||||||
yaml_files.append(config)
|
yaml_files.append(config)
|
||||||
|
|
||||||
return yaml_files
|
return yaml_files
|
||||||
|
43
vitrage/evaluator/template_fields.py
Normal file
43
vitrage/evaluator/template_fields.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Copyright 2016 - 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.
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateFields(object):
|
||||||
|
|
||||||
|
METADATA = 'metadata'
|
||||||
|
DEFINITIONS = 'definitions'
|
||||||
|
SCENARIOS = 'scenarios'
|
||||||
|
|
||||||
|
ENTITIES = 'entities'
|
||||||
|
ENTITY = 'entity'
|
||||||
|
CATEGORY = 'category'
|
||||||
|
|
||||||
|
RELATIONSHIPS = 'relationships'
|
||||||
|
RELATIONSHIP = 'relationship'
|
||||||
|
RELATIONSHIP_TYPE = 'relationship_type'
|
||||||
|
|
||||||
|
SCENARIO = 'scenario'
|
||||||
|
CONDITION = 'condition'
|
||||||
|
ACTIONS = 'actions'
|
||||||
|
ACTION = 'action'
|
||||||
|
ACTION_TYPE = 'action_type'
|
||||||
|
PROPERTIES = 'properties'
|
||||||
|
ACTION_TARGET = 'action_target'
|
||||||
|
|
||||||
|
TEMPLATE_ID = 'template_id'
|
||||||
|
SOURCE = 'source'
|
||||||
|
TARGET = 'target'
|
||||||
|
TYPE = 'type'
|
||||||
|
|
||||||
|
ID = 'id'
|
@ -11,27 +11,17 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import yaml
|
|
||||||
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
|
||||||
from vitrage.common import file_utils
|
from vitrage.common import file_utils
|
||||||
|
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def load_templates_files(conf):
|
def load_templates_files(conf):
|
||||||
|
|
||||||
templates_dir_path = conf.evaluator.templates_dir
|
templates_dir_path = conf.evaluator.templates_dir
|
||||||
templates_files = file_utils.load_files(templates_dir_path, '.yaml')
|
template_files = file_utils.load_yaml_files(templates_dir_path)
|
||||||
|
|
||||||
templates_configs = []
|
for template_file in template_files:
|
||||||
for template_file in templates_files:
|
pass
|
||||||
|
|
||||||
full_path = templates_dir_path + '/' + template_file
|
|
||||||
with open(full_path, 'r') as stream:
|
|
||||||
config = yaml.load(stream)
|
|
||||||
templates_configs.append(config)
|
|
||||||
|
|
||||||
return templates_configs
|
|
||||||
|
278
vitrage/evaluator/template_validator.py
Normal file
278
vitrage/evaluator/template_validator.py
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
# Copyright 2015 - 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 oslo_log import log
|
||||||
|
from voluptuous import Any
|
||||||
|
from voluptuous import Error
|
||||||
|
from voluptuous import Required
|
||||||
|
from voluptuous import Schema
|
||||||
|
|
||||||
|
from vitrage.evaluator.template_fields import TemplateFields
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
MANDATORY_SECTIONS_ERROR = '"definitions", "metadata" and "scenarios are ' \
|
||||||
|
'mandatory sections in template file.'
|
||||||
|
TEMPLATE_VALIDATION_ERROR = 'Template validation failure.'
|
||||||
|
ELEMENTS_MIN_NUM_ERROR = 'At least one %s must be defined.'
|
||||||
|
DICT_STRUCTURE_SCHEMA_ERROR = '%s must refer to dictionary.'
|
||||||
|
SCHEMA_CONTENT_ERROR = '%s must contain %s Fields.'
|
||||||
|
|
||||||
|
|
||||||
|
def validate(template_conf):
|
||||||
|
|
||||||
|
is_valid = validate_template_sections(template_conf)
|
||||||
|
|
||||||
|
if is_valid:
|
||||||
|
is_metadata_valid = validate_metadata_section(
|
||||||
|
template_conf[TemplateFields.METADATA])
|
||||||
|
is_defs_valid = validate_definitions_section(
|
||||||
|
template_conf[TemplateFields.DEFINITIONS])
|
||||||
|
is_scenarios_valid = validate_scenarios_section(
|
||||||
|
template_conf[TemplateFields.SCENARIOS])
|
||||||
|
|
||||||
|
return is_metadata_valid and is_defs_valid and is_scenarios_valid
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def validate_template_sections(template_conf):
|
||||||
|
|
||||||
|
schema = Schema({
|
||||||
|
Required(TemplateFields.DEFINITIONS): dict,
|
||||||
|
Required(TemplateFields.METADATA): dict,
|
||||||
|
Required(TemplateFields.SCENARIOS): list
|
||||||
|
})
|
||||||
|
return _validate_dict_schema(
|
||||||
|
schema, template_conf, MANDATORY_SECTIONS_ERROR)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_metadata_section(metadata):
|
||||||
|
|
||||||
|
schema = Schema({
|
||||||
|
Required(TemplateFields.ID): Any(str, basestring)
|
||||||
|
})
|
||||||
|
|
||||||
|
error_msg = SCHEMA_CONTENT_ERROR % (
|
||||||
|
TemplateFields.METADATA, TemplateFields.ID)
|
||||||
|
return _validate_dict_schema(schema, metadata, error_msg)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_definitions_section(definitions):
|
||||||
|
|
||||||
|
schema = Schema({
|
||||||
|
Required(TemplateFields.ENTITIES): list,
|
||||||
|
TemplateFields.RELATIONSHIPS: list
|
||||||
|
})
|
||||||
|
|
||||||
|
error_msg = SCHEMA_CONTENT_ERROR % (
|
||||||
|
TemplateFields.DEFINITIONS,
|
||||||
|
'"%s"' % TemplateFields.ENTITIES
|
||||||
|
)
|
||||||
|
is_defs_valid = _validate_dict_schema(schema, definitions, error_msg)
|
||||||
|
|
||||||
|
if is_defs_valid:
|
||||||
|
is_entities_valid = validate_entities(
|
||||||
|
definitions[TemplateFields.ENTITIES]
|
||||||
|
)
|
||||||
|
|
||||||
|
relationships = definitions.get(TemplateFields.RELATIONSHIPS, None)
|
||||||
|
is_relationships_valid = True
|
||||||
|
if relationships:
|
||||||
|
is_relationships_valid = validate_relationships(relationships)
|
||||||
|
|
||||||
|
return is_relationships_valid and is_entities_valid
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def validate_entities(entities):
|
||||||
|
|
||||||
|
if len(entities) <= 0:
|
||||||
|
error_msg = ELEMENTS_MIN_NUM_ERROR % TemplateFields.ENTITY
|
||||||
|
LOG.error(_build_error_message(error_msg))
|
||||||
|
return False
|
||||||
|
|
||||||
|
for entity in entities:
|
||||||
|
|
||||||
|
try:
|
||||||
|
Schema({
|
||||||
|
Required(TemplateFields.ENTITY): dict,
|
||||||
|
})(entity)
|
||||||
|
except Error as e:
|
||||||
|
error_msg = DICT_STRUCTURE_SCHEMA_ERROR % TemplateFields.ENTITY
|
||||||
|
LOG.error(_build_error_message(error_msg, e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
return validate_entity(entity[TemplateFields.ENTITY])
|
||||||
|
|
||||||
|
|
||||||
|
def validate_entity(entity):
|
||||||
|
|
||||||
|
schema = Schema({
|
||||||
|
Required(TemplateFields.CATEGORY): Any(str, basestring),
|
||||||
|
TemplateFields.TYPE: Any(str, basestring),
|
||||||
|
Required(TemplateFields.TEMPLATE_ID): Any(str, basestring, int)
|
||||||
|
})
|
||||||
|
error_msg = SCHEMA_CONTENT_ERROR % (
|
||||||
|
TemplateFields.ENTITY,
|
||||||
|
'"%s" and "%s"' % (TemplateFields.CATEGORY, TemplateFields.TEMPLATE_ID)
|
||||||
|
)
|
||||||
|
return _validate_dict_schema(schema, entity, error_msg)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_relationships(relationships):
|
||||||
|
|
||||||
|
for relationship in relationships:
|
||||||
|
|
||||||
|
try:
|
||||||
|
Schema({
|
||||||
|
Required(TemplateFields.RELATIONSHIP): dict,
|
||||||
|
})(relationship)
|
||||||
|
except Error as e:
|
||||||
|
error_msg = DICT_STRUCTURE_SCHEMA_ERROR % (
|
||||||
|
TemplateFields.RELATIONSHIP
|
||||||
|
)
|
||||||
|
LOG.error(_build_error_message(error_msg, e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
return validate_relationship(relationship[TemplateFields.RELATIONSHIP])
|
||||||
|
|
||||||
|
|
||||||
|
def validate_relationship(relationship):
|
||||||
|
|
||||||
|
schema = Schema({
|
||||||
|
Required(TemplateFields.SOURCE): Any(str, basestring, int),
|
||||||
|
Required(TemplateFields.TARGET): Any(str, basestring, int),
|
||||||
|
TemplateFields.RELATIONSHIP_TYPE: Any(str, basestring),
|
||||||
|
Required(TemplateFields.TEMPLATE_ID): Any(str, basestring, int)
|
||||||
|
})
|
||||||
|
|
||||||
|
error_msg = SCHEMA_CONTENT_ERROR % (
|
||||||
|
TemplateFields.RELATIONSHIP, '"%s", "%s" and "%s"' % (
|
||||||
|
TemplateFields.SOURCE,
|
||||||
|
TemplateFields.TARGET,
|
||||||
|
TemplateFields.RELATIONSHIP_TYPE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return _validate_dict_schema(schema, relationship, error_msg)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_scenarios_section(scenarios):
|
||||||
|
|
||||||
|
if len(scenarios) <= 0:
|
||||||
|
error_msg = ELEMENTS_MIN_NUM_ERROR % TemplateFields.SCENARIOS
|
||||||
|
LOG.error(_build_error_message(error_msg))
|
||||||
|
return False
|
||||||
|
|
||||||
|
for scenario in scenarios:
|
||||||
|
|
||||||
|
try:
|
||||||
|
Schema({
|
||||||
|
Required(TemplateFields.SCENARIO): dict,
|
||||||
|
})(scenario)
|
||||||
|
except Error as e:
|
||||||
|
error_msg = DICT_STRUCTURE_SCHEMA_ERROR % TemplateFields.SCENARIO
|
||||||
|
LOG.error(_build_error_message(error_msg, e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
is_valid = validate_scenario(scenario[TemplateFields.SCENARIO])
|
||||||
|
if not is_valid:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def validate_scenario(scenario):
|
||||||
|
|
||||||
|
schema = Schema({
|
||||||
|
Required(TemplateFields.CONDITION): Any(str, basestring),
|
||||||
|
Required(TemplateFields.ACTIONS): list
|
||||||
|
})
|
||||||
|
|
||||||
|
error_msg = SCHEMA_CONTENT_ERROR % (
|
||||||
|
TemplateFields.SCENARIOS,
|
||||||
|
'"%s" and "%s"' % (TemplateFields.CONDITION, TemplateFields.ACTIONS)
|
||||||
|
)
|
||||||
|
is_scenario_valid = _validate_dict_schema(
|
||||||
|
schema, scenario, error_msg)
|
||||||
|
|
||||||
|
if is_scenario_valid:
|
||||||
|
return validate_actions_schema(scenario[TemplateFields.ACTIONS])
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def validate_actions_schema(actions):
|
||||||
|
|
||||||
|
if len(actions) <= 0:
|
||||||
|
error_message = ELEMENTS_MIN_NUM_ERROR % TemplateFields.ACTION
|
||||||
|
LOG.error(_build_error_message(error_message))
|
||||||
|
return False
|
||||||
|
|
||||||
|
for action in actions:
|
||||||
|
|
||||||
|
try:
|
||||||
|
Schema({
|
||||||
|
Required(TemplateFields.ACTION): dict,
|
||||||
|
})(action)
|
||||||
|
except Error as e:
|
||||||
|
msg = DICT_STRUCTURE_SCHEMA_ERROR % TemplateFields.ACTION
|
||||||
|
LOG.error(_build_error_message(msg, e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
is_action_valid = validate_action_schema(action[TemplateFields.ACTION])
|
||||||
|
if not is_action_valid:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def validate_action_schema(action):
|
||||||
|
|
||||||
|
schema = Schema({
|
||||||
|
Required(TemplateFields.ACTION_TYPE): Any(str, basestring),
|
||||||
|
TemplateFields.PROPERTIES: dict,
|
||||||
|
Required(TemplateFields.ACTION_TARGET): dict
|
||||||
|
})
|
||||||
|
|
||||||
|
error_msg = SCHEMA_CONTENT_ERROR % (
|
||||||
|
TemplateFields.ACTION,
|
||||||
|
'"%s" and "%s"' % (
|
||||||
|
TemplateFields.ACTION_TYPE,
|
||||||
|
TemplateFields.ACTION_TARGET
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return _validate_dict_schema(schema, action, error_msg)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_error_message(message, e=None):
|
||||||
|
|
||||||
|
if e:
|
||||||
|
return '%s %s %s' % (TEMPLATE_VALIDATION_ERROR, message, e)
|
||||||
|
else:
|
||||||
|
return '%s %s' % (TEMPLATE_VALIDATION_ERROR, message)
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_dict_schema(schema, value, error_message):
|
||||||
|
|
||||||
|
try:
|
||||||
|
schema(value)
|
||||||
|
except Error as e:
|
||||||
|
LOG.error(_build_error_message(error_message, e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
@ -1,36 +1,60 @@
|
|||||||
metadata:
|
metadata:
|
||||||
id=host_high_cpu_load_to_instance_cpu_suboptimal
|
id: host_high_cpu_load_to_instance_cpu_suboptimal
|
||||||
definitions:
|
definitions:
|
||||||
entities:
|
entities:
|
||||||
- entity:
|
- entity:
|
||||||
category: ALARM
|
category: ALARM
|
||||||
type: HOST_HIGH_CPU_LOAD
|
type: HOST_HIGH_CPU_LOAD
|
||||||
internal_id: 1
|
template_id: 1
|
||||||
- entity:
|
- entity:
|
||||||
category: ALARM
|
category: ALARM
|
||||||
type: VM_CPU_SUBOPTIMAL_PERFORMANCE
|
type: VM_CPU_SUBOPTIMAL_PERFORMANCE
|
||||||
internal_id: 2
|
template_id: 2
|
||||||
- entity:
|
- entity:
|
||||||
category: RESOURCE
|
category: RESOURCE
|
||||||
type: HOST
|
type: HOST
|
||||||
internal_id: 3
|
template_id: 3
|
||||||
- entity:
|
- entity:
|
||||||
category: RESOURCE
|
category: RESOURCE
|
||||||
type: INSTANCE
|
type: INSTANCE
|
||||||
internal_id: 4
|
template_id: 4
|
||||||
relationships:
|
relationships:
|
||||||
- relationship:
|
- relationship:
|
||||||
source: 1
|
source: 1
|
||||||
target: 3
|
target: 3
|
||||||
type: on
|
relationship_type: on
|
||||||
internal_id : alarm_on_host
|
template_id : alarm_on_host
|
||||||
- relationship:
|
- relationship:
|
||||||
source: 2
|
source: 2
|
||||||
target: 4
|
target: 4
|
||||||
type: on
|
relationship_type: on
|
||||||
internal_id : alarm_on_instance
|
template_id : alarm_on_instance
|
||||||
- relationship:
|
- relationship:
|
||||||
source: 3
|
source: 3
|
||||||
target: 4
|
target: 4
|
||||||
type: contains
|
relationship_type: contains
|
||||||
internal_id : host_contains_instance
|
template_id : host_contains_instance
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host and host_contains_instance
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: raise_alarm
|
||||||
|
properties:
|
||||||
|
alarm_type: VM_CPU_SUBOPTIMAL_PERFORMANCE
|
||||||
|
action_target:
|
||||||
|
target: 4
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
target: 4
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host and alarm_on_instance and host_contains_instance
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: add_causal_relationship
|
||||||
|
action_target:
|
||||||
|
source: 1
|
||||||
|
target: 2
|
||||||
|
@ -11,12 +11,10 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import os
|
|
||||||
|
|
||||||
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 vitrage.common import file_utils
|
||||||
from vitrage.evaluator import template_loader
|
|
||||||
from vitrage.tests import base
|
from vitrage.tests import base
|
||||||
from vitrage.tests.mocks import utils
|
from vitrage.tests.mocks import utils
|
||||||
|
|
||||||
@ -40,13 +38,9 @@ class TemplateLoaderTest(base.BaseTest):
|
|||||||
self.conf = cfg.ConfigOpts()
|
self.conf = cfg.ConfigOpts()
|
||||||
self.conf.register_opts(self.OPTS, group='evaluator')
|
self.conf.register_opts(self.OPTS, group='evaluator')
|
||||||
|
|
||||||
|
self.template_yamls = file_utils.load_yaml_files(
|
||||||
|
self.template_dir_path
|
||||||
|
)
|
||||||
|
|
||||||
def test_template_loader(self):
|
def test_template_loader(self):
|
||||||
|
pass
|
||||||
# Setup
|
|
||||||
total_templates = os.listdir(self.template_dir_path)
|
|
||||||
|
|
||||||
# Action
|
|
||||||
template_configs = template_loader.load_templates_files(self.conf)
|
|
||||||
|
|
||||||
# Test assertions
|
|
||||||
self.assertEqual(len(total_templates), len(template_configs))
|
|
||||||
|
153
vitrage/tests/unit/evaluator/test_template_validator.py
Normal file
153
vitrage/tests/unit/evaluator/test_template_validator.py
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
# Copyright 2016 - 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.
|
||||||
|
import copy
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from vitrage.common import file_utils
|
||||||
|
from vitrage.evaluator.template_fields import TemplateFields
|
||||||
|
from vitrage.evaluator import template_validator
|
||||||
|
from vitrage.tests import base
|
||||||
|
from vitrage.tests.mocks import utils
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyAttributeOutsideInit
|
||||||
|
class TemplateValidatorTest(base.BaseTest):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
|
||||||
|
template_dir_path = '%s/templates' % utils.get_resources_dir()
|
||||||
|
template_yamls = file_utils.load_yaml_files(template_dir_path)
|
||||||
|
cls.first_template = template_yamls[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def clone_template(self):
|
||||||
|
return copy.deepcopy(self.first_template)
|
||||||
|
|
||||||
|
def test_template_validator(self):
|
||||||
|
self.assertTrue(template_validator.validate(self.first_template))
|
||||||
|
|
||||||
|
def test_validate_template_without_metadata_section(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
template.pop(TemplateFields.METADATA)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_template_without_id_in_metadata_section(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
template[TemplateFields.METADATA].pop(TemplateFields.ID)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_template_without_definitions_section(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
template.pop(TemplateFields.DEFINITIONS)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_template_without_entities(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
template[TemplateFields.DEFINITIONS].pop(TemplateFields.ENTITIES)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_template_with_empty_entities(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
template[TemplateFields.DEFINITIONS][TemplateFields.ENTITIES] = []
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_entity_without_required_fields(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
definitions = template[TemplateFields.DEFINITIONS]
|
||||||
|
entity = definitions[TemplateFields.ENTITIES][0]
|
||||||
|
entity[TemplateFields.ENTITY].pop(TemplateFields.CATEGORY)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
definitions = template[TemplateFields.DEFINITIONS]
|
||||||
|
entity = definitions[TemplateFields.ENTITIES][0]
|
||||||
|
entity[TemplateFields.ENTITY].pop(TemplateFields.TEMPLATE_ID)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_relationships_without_required_fields(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
definitions = template[TemplateFields.DEFINITIONS]
|
||||||
|
relationship = definitions[TemplateFields.RELATIONSHIPS][0]
|
||||||
|
relationship[TemplateFields.RELATIONSHIP].pop(TemplateFields.SOURCE)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
definitions = template[TemplateFields.DEFINITIONS]
|
||||||
|
relationship = definitions[TemplateFields.RELATIONSHIPS][0]
|
||||||
|
relationship[TemplateFields.RELATIONSHIP].pop(TemplateFields.TARGET)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
definitions = template[TemplateFields.DEFINITIONS]
|
||||||
|
relationship = definitions[TemplateFields.RELATIONSHIPS][0]
|
||||||
|
relationship[TemplateFields.RELATIONSHIP].pop(
|
||||||
|
TemplateFields.TEMPLATE_ID
|
||||||
|
)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_template_without_scenarios(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
template.pop(TemplateFields.SCENARIOS)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_template_with_empty_scenarios(self):
|
||||||
|
template = self.clone_template
|
||||||
|
template[TemplateFields.SCENARIOS] = []
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_scenario_without_required_fields(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
scenario = template[TemplateFields.SCENARIOS][0]
|
||||||
|
scenario[TemplateFields.SCENARIO].pop(TemplateFields.CONDITION)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
scenario = template[TemplateFields.SCENARIOS][0]
|
||||||
|
scenario[TemplateFields.SCENARIO].pop(TemplateFields.ACTIONS)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_template_with_empty_actions(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
scenario = template[TemplateFields.SCENARIOS][0]
|
||||||
|
scenario[TemplateFields.SCENARIO][TemplateFields.ACTIONS] = []
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
def test_validate_action_without_required_fields(self):
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
scenario = template[TemplateFields.SCENARIOS][0]
|
||||||
|
action = scenario[TemplateFields.SCENARIO][TemplateFields.ACTIONS][0]
|
||||||
|
action[TemplateFields.ACTION].pop(TemplateFields.ACTION_TYPE)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
||||||
|
|
||||||
|
template = self.clone_template
|
||||||
|
scenario = template[TemplateFields.SCENARIOS][0]
|
||||||
|
action = scenario[TemplateFields.SCENARIO][TemplateFields.ACTIONS][0]
|
||||||
|
action[TemplateFields.ACTION].pop(TemplateFields.ACTION_TARGET)
|
||||||
|
self.assertFalse(template_validator.validate(template))
|
Loading…
Reference in New Issue
Block a user