Merge "Added a version to Vitrage templates"

This commit is contained in:
Zuul 2017-12-04 21:05:49 +00:00 committed by Gerrit Code Review
commit e8c4066881
12 changed files with 177 additions and 7 deletions

View File

@ -17,6 +17,7 @@ The template is written in YAML language, with the following structure:
::
metadata:
version: <template version>
name: <unique template identifier>
description: <what this template does>
definitions:
@ -38,7 +39,11 @@ The template is written in YAML language, with the following structure:
The template is divided into four main sections:
- *metadata:* Contains the template name, and brief description of what the template does (optional)
- *metadata:* Contains general information about the template.
- *version -* the version of the template format. The default is 1.
- *name -* the name of the template
- *description -* a brief description of what the template does (optional)
- *definitions:* This section is **mandatory** unless an include section is specified in the template (see below).
This section contains the atomic definitions referenced later on, for entities and relationships.

View File

@ -0,0 +1,5 @@
---
features:
- A ``version`` field was added to the metadata section of Vitrage templates,
to allow future changes that are not backward-compatible. The default
version is 1.

View File

@ -123,6 +123,7 @@ class TemplateTopologyFields(object):
METADATA = 'metadata'
DESCRIPTION = 'description'
NAME = 'name'
VERSION = 'version'
DEFINITIONS = 'definitions'

View File

@ -15,6 +15,10 @@
from vitrage.common.constants import TemplateTopologyFields
DEFAULT_VERSION = '1'
SUPPORTED_VERSIONS = ['1']
class TemplateFields(TemplateTopologyFields):
SCENARIOS = 'scenarios'

View File

@ -14,13 +14,18 @@
from oslo_log import log
from vitrage.evaluator.template_fields import DEFAULT_VERSION
from vitrage.evaluator.template_fields import SUPPORTED_VERSIONS
from vitrage.evaluator.template_fields import TemplateFields
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.content.definitions_validator \
import DefinitionsValidator as DefValidator
from vitrage.evaluator.template_validation.content.scenario_validator import \
ScenarioValidator
from vitrage.evaluator.template_validation.status_messages import status_msgs
LOG = log.getLogger(__name__)
@ -30,11 +35,12 @@ def content_validation(template, def_templates=None):
if def_templates is None:
def_templates = {}
result = get_content_correct_result()
result = _validate_version(template)
entities_index = {}
template_definitions = {}
if TemplateFields.DEFINITIONS in template:
if result.is_valid_config and TemplateFields.DEFINITIONS in template:
template_definitions = template[TemplateFields.DEFINITIONS]
if TemplateFields.ENTITIES in template_definitions:
@ -76,3 +82,18 @@ def content_validation(template, def_templates=None):
result = ScenarioValidator(definitions_index).validate(scenarios)
return result
def _validate_version(template):
metadata = template.get(TemplateFields.METADATA)
if metadata is None:
LOG.error('%s status code: %s' % (status_msgs[62], 62))
return get_content_fault_result(62)
version = metadata.get(TemplateFields.VERSION, DEFAULT_VERSION)
if version in SUPPORTED_VERSIONS:
return get_content_correct_result()
else:
LOG.error('%s status code: %s' % (status_msgs[63], 63))
return get_content_fault_result(63)

View File

@ -14,6 +14,7 @@
from vitrage.common.constants import EdgeLabel
from vitrage.common.constants import EntityCategory
from vitrage.evaluator.actions.base import action_types
from vitrage.evaluator.template_fields import SUPPORTED_VERSIONS
status_msgs = {
@ -41,6 +42,8 @@ status_msgs = {
# metadata section status messages 60-79
60: 'metadata section must contain id field.',
62: 'metadata is a mandatory section.',
63: 'Unsupported version. Version must be one of: {versions}'
.format(versions=SUPPORTED_VERSIONS),
# scenarios section status messages 80-99
80: 'scenarios is a mandatory section.',

View File

@ -115,6 +115,7 @@ def _validate_metadata_section(metadata):
any_str = Any(str, six.text_type)
schema = Schema({
TemplateFields.VERSION: any_str,
Required(TemplateFields.NAME, msg=60): any_str,
TemplateFields.DESCRIPTION: any_str
})

View File

@ -0,0 +1,30 @@
metadata:
version: 999
name: invalid_version
description: template with an invalid version
definitions:
entities:
- entity:
category: ALARM
name: compute.host.down
template_id: host_down_alarm
- entity:
category: RESOURCE
type: nova.host
template_id: host
relationships:
- relationship:
source: host_down_alarm
relationship_type: on
target: host
template_id : host_down_alarm_on_host
scenarios:
- scenario:
condition: host_down_alarm_on_host
actions:
- action:
action_type: set_state
properties:
state: ERROR
action_target:
target: host

View File

@ -0,0 +1,29 @@
metadata:
name: no_version
description: template without version
definitions:
entities:
- entity:
category: ALARM
name: compute.host.down
template_id: host_down_alarm
- entity:
category: RESOURCE
type: nova.host
template_id: host
relationships:
- relationship:
source: host_down_alarm
relationship_type: on
target: host
template_id : host_down_alarm_on_host
scenarios:
- scenario:
condition: host_down_alarm_on_host
actions:
- action:
action_type: set_state
properties:
state: ERROR
action_target:
target: host

View File

@ -0,0 +1,30 @@
metadata:
version: 1
name: version_1
description: template with version 1
definitions:
entities:
- entity:
category: ALARM
name: compute.host.down
template_id: host_down_alarm
- entity:
category: RESOURCE
type: nova.host
template_id: host
relationships:
- relationship:
source: host_down_alarm
relationship_type: on
target: host
template_id : host_down_alarm_on_host
scenarios:
- scenario:
condition: host_down_alarm_on_host
actions:
- action:
action_type: set_state
properties:
state: ERROR
action_target:
target: host

View File

@ -25,6 +25,7 @@ from vitrage.utils import file as file_utils
CONDITION_TEMPLATES_DIR = '%s/templates/evaluator/conditions/%s'
REGEX_TEMPLATE_DIR = '%s/templates/regex/%s'
VERSION_TEMPLATE_DIR = '%s/templates/version/%s'
class TemplateContentValidatorTest(ValidatorTest):
@ -277,6 +278,27 @@ class TemplateContentValidatorTest(ValidatorTest):
self._execute_and_assert_with_correct_result(
basic_regex_template)
def test_validate_template_with_no_version(self):
invalid_version_path = \
VERSION_TEMPLATE_DIR % (utils.get_resources_dir(),
"no_version.yaml")
template = file_utils.load_yaml_file(invalid_version_path)
self._execute_and_assert_with_correct_result(template)
def test_validate_template_with_version_1(self):
invalid_version_path = \
VERSION_TEMPLATE_DIR % (utils.get_resources_dir(),
"version1.yaml")
template = file_utils.load_yaml_file(invalid_version_path)
self._execute_and_assert_with_correct_result(template)
def test_validate_template_with_invalid_version(self):
invalid_version_path = \
VERSION_TEMPLATE_DIR % (utils.get_resources_dir(),
"invalid_version.yaml")
template = file_utils.load_yaml_file(invalid_version_path)
self._execute_and_assert_with_fault_result(template, 63)
def _execute_condition_template_with_correct_result(self, template_name):
template_path = CONDITION_TEMPLATES_DIR % (utils.get_resources_dir(),
template_name)

View File

@ -36,6 +36,8 @@ class TemplateSyntaxValidatorTest(base.BaseTest):
cls.def_template_dir_path = utils.get_resources_dir() + \
'/templates/def_template_tests'
template_dir_path = '%s/templates/general' % utils.get_resources_dir()
cls.version_dir_path = '%s/templates/version/' \
% utils.get_resources_dir()
cls.template_yamls = file_utils.load_yaml_files(template_dir_path)
cls.bad_template = \
ScenarioRepository._load_template_file(template_dir_path
@ -219,6 +221,23 @@ class TemplateSyntaxValidatorTest(base.BaseTest):
template = file_utils.load_yaml_file(template_path)
self._test_execution_with_correct_result(template)
def test_template_with_no_version(self):
template_path = self.version_dir_path + 'no_version.yaml'
template = file_utils.load_yaml_file(template_path)
self._test_execution_with_correct_result(template)
def test_template_with_valid_version(self):
template_path = self.version_dir_path + 'version1.yaml'
template = file_utils.load_yaml_file(template_path)
self._test_execution_with_correct_result(template)
def test_template_with_invalid_version(self):
# Invalid version number is checked by the content validator, not by
# the syntax validator
template_path = self.version_dir_path + 'invalid_version.yaml'
template = file_utils.load_yaml_file(template_path)
self._test_execution_with_correct_result(template)
def _test_validate_action_without_required_fields(self):
self._test_validate_action_without_required_field(