Fpb, do not fail validation if 'attributes' is not set

* Fixed validation for environment_config.yaml file, "attributes"
  field is optional
* Improved validation for, added required fields for attributes

Change-Id: I6a8a5b3864fd0bfb760d4f852fb95a9208a4c1d3
Closes-bug: #1396491
This commit is contained in:
Evgeniy L 2014-12-02 20:40:33 +04:00
parent 52f59b8e62
commit 11dcdf2684
5 changed files with 125 additions and 25 deletions

View File

@ -2,9 +2,15 @@
## 1.0.2 (UNRELEASED)
- Show correct message, if 'timeout' field is not specified for task in tasks.yaml
- Show correct message, if 'timeout' field is not specified for
task in tasks.yaml
https://bugs.launchpad.net/fuel/+bug/1396234
- Print error messages to stderr instead of stdout
- Fixed validation for environment_config.yaml file, "attributes"
field is optional
https://bugs.launchpad.net/fuel/+bug/1396491
- Improved validation for environment_config.yaml file, added
required fields for attributes
## 1.0.1 (2014-11-20)

View File

@ -39,8 +39,9 @@ class TestValidatorV1(BaseTestCase):
check_schemas_mock.assert_called_once_with()
check_paths_mock.assert_called_once_with()
@mock.patch.object(ValidatorV1, 'check_env_config_attrs')
@mock.patch.object(ValidatorV1, 'validate_file_by_schema')
def test_check_schemas(self, validator_mock):
def test_check_schemas(self, validator_mock, check_env_conf_mock):
self.validator.check_schemas()
self.assertEqual(
[mock.call(
@ -48,11 +49,9 @@ class TestValidatorV1(BaseTestCase):
self.validator.meta_path),
mock.call(
v1.TASKS_SCHEMA,
self.validator.tasks_path),
mock.call(
v1.ENV_CONFIG_SCHEMA,
self.validator.env_conf_path)],
self.validator.tasks_path)],
validator_mock.call_args_list)
check_env_conf_mock.assert_called_once_with()
@mock.patch.object(ValidatorV1, 'validate_schema')
@mock.patch('fuel_plugin_builder.validators.validator_v1.utils')
@ -99,3 +98,45 @@ class TestValidatorV1(BaseTestCase):
'Cannot find directories /tmp/deployment_scripts_path'
', /tmp/repository_path for release "'):
self.validator.check_releases_paths()
@mock.patch('fuel_plugin_builder.validators.validator_v1.utils.parse_yaml')
def test_check_env_config_attrs_do_not_fail_if_empty(
self, parse_yaml_mock):
parse_yaml_mock.return_value = None
self.validator.check_env_config_attrs()
@mock.patch('fuel_plugin_builder.validators.validator_v1.utils.parse_yaml')
def test_check_env_config_attrs_fail_if_none(self, parse_yaml_mock):
parse_yaml_mock.return_value = {'attributes': None}
with self.assertRaisesRegexp(
errors.ValidationError,
"File '/tmp/plugin_path/environment_config.yaml', None "
"is not of type 'object', value path 'attributes'"):
self.validator.check_env_config_attrs()
@mock.patch('fuel_plugin_builder.validators.validator_v1.utils.parse_yaml')
def test_check_env_config_attrs_checks_metadata(self, parse_yaml_mock):
parse_yaml_mock.return_value = {
'attributes': {'metadata': []}}
with self.assertRaisesRegexp(
errors.ValidationError,
"File '/tmp/plugin_path/environment_config.yaml', \[\] is "
"not of type 'object', value path 'attributes -> metadata'"):
self.validator.check_env_config_attrs()
@mock.patch('fuel_plugin_builder.validators.validator_v1.utils.parse_yaml')
def test_check_env_config_attrs_checks_attrs(self, parse_yaml_mock):
parse_yaml_mock.return_value = {
'attributes': {
'key1': {
'type': True,
'label': 'text',
'value': 'text',
'weight': 1}}}
with self.assertRaisesRegexp(
errors.ValidationError,
"File '/tmp/plugin_path/environment_config.yaml', True is not "
"of type 'string', value path 'attributes -> key1 -> type'"):
self.validator.check_env_config_attrs()

View File

@ -45,8 +45,11 @@ class BaseValidator(object):
def _make_error_message(self, exc, file_path, value_path):
error_msg = "File '{0}', {1}".format(file_path, exc.message)
if value_path is None and exc.absolute_path:
value_path = exc.absolute_path
if value_path is None:
value_path = []
if exc.absolute_path:
value_path.extend(exc.absolute_path)
if value_path:
value_path = ' -> '.join(map(six.text_type, value_path))

View File

@ -97,16 +97,37 @@ TASKS_SCHEMA = {
'items': TASK_SCHEMA}
ENV_CONFIG_SCHEMA = {
ATTR_ELEMENT_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'type': 'object',
'required': ['type', 'label', 'weight', 'value'],
'properties': {
'type': {'type': 'string'},
'weight': {'type': 'integer'},
'value': {'type': ['string', 'boolean']},
'label': {'type': 'string'},
'values': {'type': 'array', 'items':
{'type': 'object',
'required': ['data', 'label'],
'properties': {
'data': {'type': 'string'},
'label': {'type': 'string'}}}}}}
ATTR_META_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'type': 'object',
'properties': {
'attributes': {
'type': 'object',
'additionalProperties': {
'type': 'object',
'properties': {
'type': {'type': 'string'},
'weight': {'type': 'integer'},
'value': {'type': ['string', 'boolean']},
'label': {'type': 'string'}}}}}}
'label': {'type': 'string'},
'weight': {'type': 'integer'},
'toggleable': {'type': 'boolean'},
'enabled': {'type': 'boolean'},
'restrictions': {
'type': 'array', 'items': {'type': ['string', 'object']}}}}
ATTR_ROOT_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'type': 'object',
'properties': {
'attributes': {'type': 'object'}}}

View File

@ -18,6 +18,8 @@ import logging
from os.path import join as join_path
import six
from fuel_plugin_builder import errors
from fuel_plugin_builder import utils
from fuel_plugin_builder.validators.base import BaseValidator
@ -44,7 +46,35 @@ class ValidatorV1(BaseValidator):
logger.debug('Start schema checking "%s"', self.plugin_path)
self.validate_file_by_schema(v1.METADATA_SCHEMA, self.meta_path)
self.validate_file_by_schema(v1.TASKS_SCHEMA, self.tasks_path)
self.validate_file_by_schema(v1.ENV_CONFIG_SCHEMA, self.env_conf_path)
self.check_env_config_attrs()
def check_env_config_attrs(self):
"""Check attributes in environment config file.
'attributes' is not required field, but if it's
present it should contain UI elements OR metadata
structure.
"""
config = utils.parse_yaml(self.env_conf_path)
if not config:
return
self.validate_schema(config, v1.ATTR_ROOT_SCHEMA, self.env_conf_path)
attrs = config.get('attributes', {})
for attr_id, attr in six.iteritems(attrs):
schema = v1.ATTR_ELEMENT_SCHEMA
# Metadata object is totally different
# from the others, we have to set different
# validator for it
if attr_id == 'metadata':
schema = v1.ATTR_META_SCHEMA
self.validate_schema(
attr,
schema,
self.env_conf_path,
value_path=['attributes', attr_id])
def check_tasks(self):
"""Json schema doesn't have any conditions, so we have
@ -54,15 +84,14 @@ class ValidatorV1(BaseValidator):
logger.debug('Start tasks checking "%s"', self.tasks_path)
tasks = utils.parse_yaml(self.tasks_path)
for idx, task in enumerate(tasks):
if task['type'] == 'puppet':
schema = v1.PUPPET_PARAMETERS
elif task['type'] == 'shell':
schema = v1.SHELL_PARAMETERS
schemas = {
'puppet': v1.PUPPET_PARAMETERS,
'shell': v1.SHELL_PARAMETERS}
for idx, task in enumerate(tasks):
self.validate_schema(
task['parameters'],
schema,
schemas[task['type']],
self.tasks_path,
value_path=[idx, 'parameters'])