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
|
||||
stevedore>=1.5.0 # Apache-2.0
|
||||
exrex>=0.9.4
|
||||
voluptuous>=0.8.8
|
||||
|
@ -22,3 +22,4 @@ testscenarios>=0.4
|
||||
testtools>=1.4.0
|
||||
exrex>=0.9.4
|
||||
stevedore>=1.5.0 # Apache-2.0
|
||||
voluptuous>=0.8.8
|
||||
|
@ -12,9 +12,13 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import os
|
||||
|
||||
import yaml
|
||||
|
||||
from oslo_log import log
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
def load_files(dir_path, suffix=None):
|
||||
loaded_files = os.listdir(dir_path)
|
||||
@ -25,15 +29,21 @@ def load_files(dir_path, suffix=None):
|
||||
return loaded_files
|
||||
|
||||
|
||||
def load_yaml_files(dir_path):
|
||||
def load_yaml_files(dir_path, with_exception=False):
|
||||
files = load_files(dir_path, '.yaml')
|
||||
|
||||
yaml_files = []
|
||||
for file in files:
|
||||
full_path = dir_path + '/' + file
|
||||
with open(full_path, 'r') as stream:
|
||||
# TODO(alexey): check what to do if parse of one of the files fails
|
||||
config = yaml.load(stream)
|
||||
try:
|
||||
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)
|
||||
|
||||
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
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import yaml
|
||||
|
||||
from oslo_log import log
|
||||
|
||||
from vitrage.common import file_utils
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
def load_templates_files(conf):
|
||||
|
||||
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 templates_files:
|
||||
|
||||
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
|
||||
for template_file in template_files:
|
||||
pass
|
||||
|
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:
|
||||
id=host_high_cpu_load_to_instance_cpu_suboptimal
|
||||
id: host_high_cpu_load_to_instance_cpu_suboptimal
|
||||
definitions:
|
||||
entities:
|
||||
- entity:
|
||||
category: ALARM
|
||||
type: HOST_HIGH_CPU_LOAD
|
||||
internal_id: 1
|
||||
template_id: 1
|
||||
- entity:
|
||||
category: ALARM
|
||||
type: VM_CPU_SUBOPTIMAL_PERFORMANCE
|
||||
internal_id: 2
|
||||
template_id: 2
|
||||
- entity:
|
||||
category: RESOURCE
|
||||
type: HOST
|
||||
internal_id: 3
|
||||
template_id: 3
|
||||
- entity:
|
||||
category: RESOURCE
|
||||
type: INSTANCE
|
||||
internal_id: 4
|
||||
template_id: 4
|
||||
relationships:
|
||||
- relationship:
|
||||
source: 1
|
||||
target: 3
|
||||
type: on
|
||||
internal_id : alarm_on_host
|
||||
relationship_type: on
|
||||
template_id : alarm_on_host
|
||||
- relationship:
|
||||
source: 2
|
||||
target: 4
|
||||
type: on
|
||||
internal_id : alarm_on_instance
|
||||
relationship_type: on
|
||||
template_id : alarm_on_instance
|
||||
- relationship:
|
||||
source: 3
|
||||
target: 4
|
||||
type: contains
|
||||
internal_id : host_contains_instance
|
||||
relationship_type: contains
|
||||
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
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from vitrage.evaluator import template_loader
|
||||
from vitrage.common import file_utils
|
||||
from vitrage.tests import base
|
||||
from vitrage.tests.mocks import utils
|
||||
|
||||
@ -40,13 +38,9 @@ class TemplateLoaderTest(base.BaseTest):
|
||||
self.conf = cfg.ConfigOpts()
|
||||
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):
|
||||
|
||||
# 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))
|
||||
pass
|
||||
|
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