tasks.yaml, network_roles.yaml are optional files for V3
For V3: - tasks.yaml and network_roles.yaml are not mandatory, - validation is skipped if optional file is not exists, - unit test class TestValidatorV3 added, - tests for validators V1, V2 extracted to separate files. Added error messages for empty and not exist files. Fixed error for task without parameters for V1, V2. Change-Id: I3eaf12a7a22a35067bae04b6bb5cc81a6835cfd5 Closes-Bug: #1477128
This commit is contained in:
parent
9237356b18
commit
d6017cc5c2
|
@ -33,6 +33,20 @@ class ValidationError(FuelPluginException):
|
|||
pass
|
||||
|
||||
|
||||
class FileIsEmpty(ValidationError):
|
||||
def __init__(self, file_path):
|
||||
super(FileIsEmpty, self).__init__(
|
||||
"File '{0}' is empty".format(file_path)
|
||||
)
|
||||
|
||||
|
||||
class FileDoesNotExist(ValidationError):
|
||||
def __init__(self, file_path):
|
||||
super(FileDoesNotExist, self).__init__(
|
||||
"File '{0}' does not exist".format(file_path)
|
||||
)
|
||||
|
||||
|
||||
class WrongPackageVersionError(FuelPluginException):
|
||||
pass
|
||||
|
||||
|
|
|
@ -21,9 +21,10 @@ except ImportError:
|
|||
from unittest2.case import TestCase
|
||||
|
||||
import mock
|
||||
|
||||
from StringIO import StringIO
|
||||
|
||||
from fuel_plugin_builder import errors
|
||||
|
||||
|
||||
class FakeFile(StringIO):
|
||||
"""It's a fake file which returns StringIO
|
||||
|
@ -81,3 +82,140 @@ class BaseTestCase(TestCase):
|
|||
"""
|
||||
for method in methods:
|
||||
setattr(obj, method, mock.MagicMock())
|
||||
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
class BaseValidator(BaseTestCase):
|
||||
|
||||
__test__ = False
|
||||
validator_class = None
|
||||
schema_class = None
|
||||
|
||||
def setUp(self):
|
||||
self.plugin_path = '/tmp/plugin_path'
|
||||
self.validator = self.validator_class(self.plugin_path)
|
||||
|
||||
def test_validate(self, _):
|
||||
mocked_methods = [
|
||||
'check_schemas',
|
||||
'check_tasks',
|
||||
'check_releases_paths',
|
||||
'check_compatibility',
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
self.validator.validate()
|
||||
|
||||
self.validator.check_tasks.assert_called_once_with()
|
||||
self.validator.check_schemas.assert_called_once_with()
|
||||
self.validator.check_releases_paths.assert_called_once_with()
|
||||
self.validator.check_compatibility.assert_called_once_with()
|
||||
|
||||
def test_check_schemas(self, _):
|
||||
mocked_methods = [
|
||||
'check_env_config_attrs',
|
||||
'validate_file_by_schema'
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
self.validator.check_schemas()
|
||||
|
||||
self.assertEqual(
|
||||
[mock.call(
|
||||
self.schema_class().metadata_schema,
|
||||
self.validator.meta_path),
|
||||
mock.call(
|
||||
self.schema_class().tasks_schema,
|
||||
self.validator.tasks_path)],
|
||||
self.validator.validate_file_by_schema.call_args_list)
|
||||
self.validator.check_env_config_attrs.assert_called_once_with()
|
||||
|
||||
def test_check_releases_paths(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'releases': [{
|
||||
'deployment_scripts_path': '/tmp/deployment_scripts_path',
|
||||
'repository_path': '/tmp/repository_path'}]}
|
||||
|
||||
utils_mock.exists.return_value = True
|
||||
self.validator.check_releases_paths()
|
||||
self.assertEqual(
|
||||
utils_mock.exists.call_args_list,
|
||||
[mock.call('/tmp/deployment_scripts_path'),
|
||||
mock.call('/tmp/repository_path')])
|
||||
|
||||
def test_check_releases_paths_error(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'releases': [{
|
||||
'deployment_scripts_path': '/tmp/deployment_scripts_path',
|
||||
'repository_path': '/tmp/repository_path'}]}
|
||||
|
||||
utils_mock.exists.return_value = False
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ReleasesDirectoriesError,
|
||||
'Cannot find directories /tmp/deployment_scripts_path'
|
||||
', /tmp/repository_path for release '):
|
||||
self.validator.check_releases_paths()
|
||||
|
||||
def test_check_env_config_attrs_do_not_fail_if_empty(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = None
|
||||
self.validator.check_env_config_attrs()
|
||||
|
||||
def test_check_env_config_attrs_fail_if_none(self, utils_mock):
|
||||
utils_mock.parse_yaml.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()
|
||||
|
||||
def test_check_env_config_attrs_checks_metadata(self, utils_mock):
|
||||
utils_mock.parse_yaml.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()
|
||||
|
||||
def test_check_env_config_attrs_checks_attrs(self, utils_mock):
|
||||
utils_mock.parse_yaml.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()
|
||||
|
||||
def test_check_env_config_attrs_restriction_fails(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'attributes': {
|
||||
'key1': {
|
||||
'type': 'text',
|
||||
'label': 'test',
|
||||
'value': 'test',
|
||||
'weight': 1,
|
||||
'restrictions': [
|
||||
{
|
||||
'condition': 'false',
|
||||
'action': 'disable'
|
||||
},
|
||||
{
|
||||
'condition': True,
|
||||
'action': 'hide'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ValidationError,
|
||||
"File '/tmp/plugin_path/environment_config.yaml', True is not "
|
||||
"of type 'string', value path "
|
||||
"'attributes -> key1 -> restrictions -> 1 -> condition"):
|
||||
self.validator.check_env_config_attrs()
|
||||
|
|
|
@ -89,6 +89,16 @@ class TestBaseValidator(BaseTestCase):
|
|||
self.validator.validate_schema(
|
||||
data, schema, 'file_path', value_path=[0, 'path2'])
|
||||
|
||||
@mock.patch(
|
||||
'fuel_plugin_builder.validators.base.BaseValidator.validate_schema')
|
||||
def test_validate_file_by_schema_failed(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = self.data
|
||||
with self.assertRaisesRegexp(
|
||||
errors.FileDoesNotExist,
|
||||
"File '/tmp/plugin_path' does not exist"):
|
||||
self.validator.validate_file_by_schema(
|
||||
self.schema, self.plugin_path)
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
@mock.patch(
|
||||
'fuel_plugin_builder.validators.base.BaseValidator.validate_schema')
|
||||
|
@ -98,6 +108,17 @@ class TestBaseValidator(BaseTestCase):
|
|||
utils_mock.parse_yaml.assert_called_once_with(self.plugin_path)
|
||||
validate_mock(self.data, self.schema, self.plugin_path)
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils.exists')
|
||||
def test_error_message_on_empty_file(self, exists_mock, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = None
|
||||
exists_mock.return_value = True
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ValidationError,
|
||||
"File '/tmp/plugin_path' is empty"):
|
||||
self.validator.validate_file_by_schema(
|
||||
self.schema, self.plugin_path)
|
||||
|
||||
def test_validate_schema_with_subschemas(self):
|
||||
schema_object = {
|
||||
'key': {
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Mirantis, Inc.
|
||||
#
|
||||
# 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 mock
|
||||
|
||||
from fuel_plugin_builder import errors
|
||||
from fuel_plugin_builder.tests.base import BaseTestCase
|
||||
from fuel_plugin_builder.validators import ValidatorV1
|
||||
from fuel_plugin_builder.validators import ValidatorV2
|
||||
|
||||
from fuel_plugin_builder.validators.schemas.v1 import SchemaV1
|
||||
from fuel_plugin_builder.validators.schemas.v2 import SchemaV2
|
||||
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
class BaseValidator(BaseTestCase):
|
||||
|
||||
__test__ = False
|
||||
validator_class = None
|
||||
schema_class = None
|
||||
|
||||
def setUp(self):
|
||||
self.plugin_path = '/tmp/plugin_path'
|
||||
self.validator = self.validator_class(self.plugin_path)
|
||||
|
||||
def test_validate(self, _):
|
||||
mocked_methods = [
|
||||
'check_schemas',
|
||||
'check_tasks',
|
||||
'check_releases_paths',
|
||||
'check_compatibility',
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
self.validator.validate()
|
||||
|
||||
self.validator.check_tasks.assert_called_once_with()
|
||||
self.validator.check_schemas.assert_called_once_with()
|
||||
self.validator.check_releases_paths.assert_called_once_with()
|
||||
self.validator.check_compatibility.assert_called_once_with()
|
||||
|
||||
def test_check_schemas(self, _):
|
||||
mocked_methods = [
|
||||
'check_env_config_attrs',
|
||||
'validate_file_by_schema'
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
self.validator.check_schemas()
|
||||
|
||||
self.assertEqual(
|
||||
[mock.call(
|
||||
self.schema_class().metadata_schema,
|
||||
self.validator.meta_path),
|
||||
mock.call(
|
||||
self.schema_class().tasks_schema,
|
||||
self.validator.tasks_path)],
|
||||
self.validator.validate_file_by_schema.call_args_list)
|
||||
self.validator.check_env_config_attrs.assert_called_once_with()
|
||||
|
||||
def test_check_releases_paths(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'releases': [{
|
||||
'deployment_scripts_path': '/tmp/deployment_scripts_path',
|
||||
'repository_path': '/tmp/repository_path'}]}
|
||||
|
||||
utils_mock.exists.return_value = True
|
||||
self.validator.check_releases_paths()
|
||||
self.assertEqual(
|
||||
utils_mock.exists.call_args_list,
|
||||
[mock.call('/tmp/deployment_scripts_path'),
|
||||
mock.call('/tmp/repository_path')])
|
||||
|
||||
def test_check_releases_paths_error(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'releases': [{
|
||||
'deployment_scripts_path': '/tmp/deployment_scripts_path',
|
||||
'repository_path': '/tmp/repository_path'}]}
|
||||
|
||||
utils_mock.exists.return_value = False
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ReleasesDirectoriesError,
|
||||
'Cannot find directories /tmp/deployment_scripts_path'
|
||||
', /tmp/repository_path for release '):
|
||||
self.validator.check_releases_paths()
|
||||
|
||||
def test_check_env_config_attrs_do_not_fail_if_empty(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = None
|
||||
self.validator.check_env_config_attrs()
|
||||
|
||||
def test_check_env_config_attrs_fail_if_none(self, utils_mock):
|
||||
utils_mock.parse_yaml.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()
|
||||
|
||||
def test_check_env_config_attrs_checks_metadata(self, utils_mock):
|
||||
utils_mock.parse_yaml.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()
|
||||
|
||||
def test_check_env_config_attrs_checks_attrs(self, utils_mock):
|
||||
utils_mock.parse_yaml.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()
|
||||
|
||||
def test_check_env_config_attrs_restriction_fails(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'attributes': {
|
||||
'key1': {
|
||||
'type': 'text',
|
||||
'label': 'test',
|
||||
'value': 'test',
|
||||
'weight': 1,
|
||||
'restrictions': [
|
||||
{
|
||||
'condition': 'false',
|
||||
'action': 'disable'
|
||||
},
|
||||
{
|
||||
'condition': True,
|
||||
'action': 'hide'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ValidationError,
|
||||
"File '/tmp/plugin_path/environment_config.yaml', True is not "
|
||||
"of type 'string', value path "
|
||||
"'attributes -> key1 -> restrictions -> 1 -> condition"):
|
||||
self.validator.check_env_config_attrs()
|
||||
|
||||
|
||||
class TestValidatorV1(BaseValidator):
|
||||
|
||||
__test__ = True
|
||||
validator_class = ValidatorV1
|
||||
schema_class = SchemaV1
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.validator_v1.utils')
|
||||
def test_check_tasks(self, utils_mock):
|
||||
mocked_methods = [
|
||||
'validate_schema'
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
utils_mock.parse_yaml.return_value = [
|
||||
{'type': 'puppet', 'parameters': 'param1'},
|
||||
{'type': 'shell', 'parameters': 'param2'}]
|
||||
|
||||
self.validator.check_tasks()
|
||||
|
||||
self.assertEqual(
|
||||
[mock.call('param1', self.schema_class().puppet_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[0, 'parameters']),
|
||||
mock.call('param2', self.schema_class().shell_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[1, 'parameters'])],
|
||||
self.validator.validate_schema.call_args_list)
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
def test_check_compatibility(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'fuel_version': ['5.1', '6.0', '6.1'],
|
||||
'package_version': '1.0.0'}
|
||||
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ValidationError,
|
||||
'Current plugin format 1.0.0 is not compatible with 5.1 Fuel'
|
||||
' release. Fuel version must be 6.0 or higher.'
|
||||
' Please remove 5.1 version from metadata.yaml file or'
|
||||
' downgrade package_version.'):
|
||||
self.validator.check_compatibility()
|
||||
|
||||
|
||||
class TestValidatorV2(BaseValidator):
|
||||
|
||||
__test__ = True
|
||||
validator_class = ValidatorV2
|
||||
schema_class = SchemaV2
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.validator_v2.utils')
|
||||
def test_check_tasks(self, utils_mock):
|
||||
mocked_methods = [
|
||||
'validate_schema'
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
utils_mock.parse_yaml.return_value = [
|
||||
{'type': 'puppet', 'parameters': 'param1'},
|
||||
{'type': 'shell', 'parameters': 'param2'},
|
||||
{'type': 'reboot', 'parameters': 'param3'}]
|
||||
|
||||
self.validator.check_tasks()
|
||||
|
||||
self.assertEqual(
|
||||
[mock.call('param1', self.schema_class().puppet_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[0, 'parameters']),
|
||||
mock.call('param2', self.schema_class().shell_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[1, 'parameters']),
|
||||
mock.call('param3', self.schema_class().reboot_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[2, 'parameters'])],
|
||||
self.validator.validate_schema.call_args_list)
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
def test_check_compatibility(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'fuel_version': ['6.0', '6.1'],
|
||||
'package_version': '2.0.0'}
|
||||
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ValidationError,
|
||||
'Current plugin format 2.0.0 is not compatible with 6.0 Fuel'
|
||||
' release. Fuel version must be 6.1 or higher.'
|
||||
' Please remove 6.0 version from metadata.yaml file or'
|
||||
' downgrade package_version.'):
|
||||
self.validator.check_compatibility()
|
|
@ -0,0 +1,82 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Mirantis, Inc.
|
||||
#
|
||||
# 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 mock
|
||||
|
||||
from fuel_plugin_builder import errors
|
||||
from fuel_plugin_builder.tests.base import BaseValidator
|
||||
from fuel_plugin_builder.validators.schemas.v1 import SchemaV1
|
||||
from fuel_plugin_builder.validators.validator_v1 import ValidatorV1
|
||||
|
||||
|
||||
class TestValidatorV1(BaseValidator):
|
||||
|
||||
__test__ = True
|
||||
validator_class = ValidatorV1
|
||||
schema_class = SchemaV1
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.validator_v1.utils')
|
||||
def test_check_tasks(self, utils_mock):
|
||||
mocked_methods = [
|
||||
'validate_schema'
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
utils_mock.parse_yaml.return_value = [
|
||||
{'type': 'puppet', 'parameters': 'param1'},
|
||||
{'type': 'shell', 'parameters': 'param2'}]
|
||||
|
||||
self.validator.check_tasks()
|
||||
|
||||
self.assertEqual(
|
||||
[mock.call('param1', self.schema_class().puppet_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[0, 'parameters']),
|
||||
mock.call('param2', self.schema_class().shell_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[1, 'parameters'])],
|
||||
self.validator.validate_schema.call_args_list)
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.validator_v1.utils')
|
||||
def test_check_tasks_no_parameters_not_failed(self, utils_mock):
|
||||
mocked_methods = [
|
||||
'validate_schema'
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
utils_mock.parse_yaml.return_value = [
|
||||
{'type': 'puppet'},
|
||||
]
|
||||
|
||||
self.validator.check_tasks()
|
||||
|
||||
self.assertEqual(
|
||||
[mock.call(None, self.schema_class().puppet_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[0, 'parameters'])],
|
||||
self.validator.validate_schema.call_args_list)
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
def test_check_compatibility(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'fuel_version': ['5.1', '6.0', '6.1'],
|
||||
'package_version': '1.0.0'}
|
||||
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ValidationError,
|
||||
'Current plugin format 1.0.0 is not compatible with 5.1 Fuel'
|
||||
' release. Fuel version must be 6.0 or higher.'
|
||||
' Please remove 5.1 version from metadata.yaml file or'
|
||||
' downgrade package_version.'):
|
||||
self.validator.check_compatibility()
|
|
@ -0,0 +1,86 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Mirantis, Inc.
|
||||
#
|
||||
# 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 mock
|
||||
|
||||
from fuel_plugin_builder import errors
|
||||
from fuel_plugin_builder.tests.base import BaseValidator
|
||||
from fuel_plugin_builder.validators.schemas.v2 import SchemaV2
|
||||
from fuel_plugin_builder.validators.validator_v2 import ValidatorV2
|
||||
|
||||
|
||||
class TestValidatorV2(BaseValidator):
|
||||
|
||||
__test__ = True
|
||||
validator_class = ValidatorV2
|
||||
schema_class = SchemaV2
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.validator_v2.utils')
|
||||
def test_check_tasks(self, utils_mock):
|
||||
mocked_methods = [
|
||||
'validate_schema'
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
utils_mock.parse_yaml.return_value = [
|
||||
{'type': 'puppet', 'parameters': 'param1'},
|
||||
{'type': 'shell', 'parameters': 'param2'},
|
||||
{'type': 'reboot', 'parameters': 'param3'}]
|
||||
|
||||
self.validator.check_tasks()
|
||||
|
||||
self.assertEqual(
|
||||
[mock.call('param1', self.schema_class().puppet_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[0, 'parameters']),
|
||||
mock.call('param2', self.schema_class().shell_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[1, 'parameters']),
|
||||
mock.call('param3', self.schema_class().reboot_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[2, 'parameters'])],
|
||||
self.validator.validate_schema.call_args_list)
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
def test_check_compatibility(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'fuel_version': ['6.0', '6.1'],
|
||||
'package_version': '2.0.0'}
|
||||
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ValidationError,
|
||||
'Current plugin format 2.0.0 is not compatible with 6.0 Fuel'
|
||||
' release. Fuel version must be 6.1 or higher.'
|
||||
' Please remove 6.0 version from metadata.yaml file or'
|
||||
' downgrade package_version.'):
|
||||
self.validator.check_compatibility()
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.validator_v2.utils')
|
||||
def test_check_tasks_no_parameters_not_failed(self, utils_mock):
|
||||
mocked_methods = [
|
||||
'validate_schema'
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
utils_mock.parse_yaml.return_value = [
|
||||
{'type': 'puppet'},
|
||||
]
|
||||
|
||||
self.validator.check_tasks()
|
||||
|
||||
self.assertEqual(
|
||||
[mock.call(None, self.schema_class().puppet_parameters,
|
||||
self.validator.tasks_path,
|
||||
value_path=[0, 'parameters'])],
|
||||
self.validator.validate_schema.call_args_list)
|
|
@ -0,0 +1,222 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Mirantis, Inc.
|
||||
#
|
||||
# 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 mock
|
||||
|
||||
from fuel_plugin_builder import errors
|
||||
from fuel_plugin_builder.tests.base import BaseValidator
|
||||
from fuel_plugin_builder.validators.schemas.v3 import SchemaV3
|
||||
from fuel_plugin_builder.validators.validator_v3 import ValidatorV3
|
||||
|
||||
|
||||
class TestValidatorV3(BaseValidator):
|
||||
|
||||
__test__ = True
|
||||
validator_class = ValidatorV3
|
||||
schema_class = SchemaV3
|
||||
|
||||
def test_check_tasks_schema_validation_failed(self):
|
||||
data_sets = [
|
||||
{
|
||||
'type': 'shell',
|
||||
'parameters': {
|
||||
'timeout': 3
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
},
|
||||
{
|
||||
'type': 'puppet',
|
||||
'parameters': {
|
||||
'timeout': 3
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
},
|
||||
{
|
||||
'type': 'puppet',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
'cmd': 'xx'
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
},
|
||||
{
|
||||
'type': 'shell',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
'puppet_manifest': 'xx',
|
||||
'puppet_modules': 'yy',
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
}
|
||||
]
|
||||
|
||||
with mock.patch.object(self.validator, '_parse_tasks') as \
|
||||
parse_tasks_mock:
|
||||
for data in data_sets:
|
||||
parse_tasks_mock.return_value = [data]
|
||||
self.assertRaises(errors.ValidationError,
|
||||
self.validator.check_tasks)
|
||||
|
||||
def test_check_tasks_schema_validation_passed(self):
|
||||
data_sets = [
|
||||
[
|
||||
{
|
||||
'type': 'shell',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
'cmd': 'xx'
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'shell',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
'cmd': 'xx'
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
},
|
||||
{
|
||||
'type': 'puppet',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
'puppet_manifest': 'xx',
|
||||
'puppet_modules': 'xxx'
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'reboot',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
},
|
||||
{
|
||||
'type': 'shell',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
'cmd': 'xx'
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
},
|
||||
{
|
||||
'type': 'puppet',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
'puppet_manifest': 'xx',
|
||||
'puppet_modules': 'xxx'
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'reboot',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
'cmd': 'xx'
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
},
|
||||
{
|
||||
'type': 'reboot',
|
||||
'parameters': {
|
||||
'timeout': 3,
|
||||
'puppet_manifest': 'xx',
|
||||
'puppet_modules': 'yy',
|
||||
},
|
||||
'stage': 'post_deployment',
|
||||
'role': '*'
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
with mock.patch.object(self.validator, '_parse_tasks') as \
|
||||
parse_tasks_mock:
|
||||
for data in data_sets:
|
||||
parse_tasks_mock.return_value = data
|
||||
self.validator.check_tasks()
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils.exists')
|
||||
def test_check_tasks_no_file(self, exists_mock):
|
||||
mocked_methods = ['validate_schema']
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
exists_mock.return_value = False
|
||||
self.validator.check_tasks()
|
||||
self.assertFalse(self.validator.validate_schema.called)
|
||||
|
||||
def test_check_schemas(self):
|
||||
mocked_methods = [
|
||||
'check_env_config_attrs',
|
||||
'validate_file_by_schema'
|
||||
]
|
||||
self.mock_methods(self.validator, mocked_methods)
|
||||
self.validator.check_schemas()
|
||||
|
||||
self.assertEqual(
|
||||
[mock.call(self.schema_class().metadata_schema,
|
||||
self.validator.meta_path),
|
||||
mock.call(self.schema_class().tasks_schema,
|
||||
self.validator.tasks_path, check_file_exists=False),
|
||||
mock.call(self.schema_class().network_roles_schema,
|
||||
self.validator.network_roles_path,
|
||||
check_file_exists=False)],
|
||||
self.validator.validate_file_by_schema.call_args_list)
|
||||
self.validator.check_env_config_attrs.assert_called_once_with()
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
def test_check_compatibility_failed(self, utils_mock):
|
||||
fuel_version_checks = (
|
||||
(['6.0', '6.1', '7.0']),
|
||||
(['6.1', '7.0']),
|
||||
)
|
||||
|
||||
for fuel_version in fuel_version_checks:
|
||||
version_in_msg = fuel_version[0]
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'fuel_version': fuel_version,
|
||||
'package_version': '3.0.0'}
|
||||
|
||||
with self.assertRaisesRegexp(
|
||||
errors.ValidationError,
|
||||
'Current plugin format 3.0.0 is not compatible with {0}'
|
||||
' Fuel release. Fuel version must be 7.0 or higher.'
|
||||
' Please remove {0} version from metadata.yaml file or'
|
||||
' downgrade package_version.'.format(version_in_msg)):
|
||||
self.validator.check_compatibility()
|
||||
|
||||
@mock.patch('fuel_plugin_builder.validators.base.utils')
|
||||
def test_check_compatibility_passed(self, utils_mock):
|
||||
utils_mock.parse_yaml.return_value = {
|
||||
'fuel_version': ['7.0'],
|
||||
'package_version': '3.0.0'}
|
||||
self.validator.check_compatibility()
|
|
@ -73,8 +73,21 @@ class BaseValidator(object):
|
|||
|
||||
return error_msg
|
||||
|
||||
def validate_file_by_schema(self, schema, file_path):
|
||||
def validate_file_by_schema(self, schema, file_path,
|
||||
check_file_exists=True):
|
||||
if not check_file_exists and not utils.exists(file_path):
|
||||
logger.debug('No file "%s". Skipping check.',
|
||||
self.network_roles_path)
|
||||
return
|
||||
|
||||
if not utils.exists(file_path):
|
||||
raise errors.FileDoesNotExist(file_path)
|
||||
|
||||
data = utils.parse_yaml(file_path)
|
||||
|
||||
if data is None:
|
||||
raise errors.FileIsEmpty(file_path)
|
||||
|
||||
self.validate_schema(data, schema, file_path)
|
||||
|
||||
@abc.abstractmethod
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from os.path import join as join_path
|
||||
|
||||
from fuel_plugin_builder import utils
|
||||
|
@ -61,7 +60,7 @@ class ValidatorV1(BaseValidator):
|
|||
|
||||
for idx, task in enumerate(tasks):
|
||||
self.validate_schema(
|
||||
task['parameters'],
|
||||
task.get('parameters'),
|
||||
schemas[task['type']],
|
||||
self.tasks_path,
|
||||
value_path=[idx, 'parameters'])
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from os.path import join as join_path
|
||||
|
||||
from fuel_plugin_builder import utils
|
||||
|
@ -47,13 +46,18 @@ class ValidatorV2(BaseValidator):
|
|||
self.check_releases_paths()
|
||||
self.check_compatibility()
|
||||
|
||||
def _parse_tasks(self):
|
||||
return utils.parse_yaml(self.tasks_path)
|
||||
|
||||
def check_tasks(self):
|
||||
"""Json schema doesn't have any conditions, so we have
|
||||
to make sure here, that puppet task is really puppet,
|
||||
shell or reboot tasks are correct too
|
||||
"""
|
||||
logger.debug('Start tasks checking "%s"', self.tasks_path)
|
||||
tasks = utils.parse_yaml(self.tasks_path)
|
||||
tasks = self._parse_tasks()
|
||||
if tasks is None:
|
||||
return
|
||||
|
||||
schemas = {
|
||||
'puppet': self.schema.puppet_parameters,
|
||||
|
@ -62,7 +66,7 @@ class ValidatorV2(BaseValidator):
|
|||
|
||||
for idx, task in enumerate(tasks):
|
||||
self.validate_schema(
|
||||
task['parameters'],
|
||||
task.get('parameters'),
|
||||
schemas[task['type']],
|
||||
self.tasks_path,
|
||||
value_path=[idx, 'parameters'])
|
||||
|
|
|
@ -14,14 +14,18 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
from os.path import join as join_path
|
||||
|
||||
from fuel_plugin_builder import errors
|
||||
from fuel_plugin_builder import utils
|
||||
from fuel_plugin_builder.validators.schemas import v3
|
||||
from fuel_plugin_builder.validators import validator_v2
|
||||
from fuel_plugin_builder.validators import ValidatorV2
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ValidatorV3(validator_v2.ValidatorV2):
|
||||
class ValidatorV3(ValidatorV2):
|
||||
|
||||
schema = v3.SchemaV3()
|
||||
|
||||
|
@ -34,12 +38,28 @@ class ValidatorV3(validator_v2.ValidatorV2):
|
|||
def basic_version(self):
|
||||
return '7.0'
|
||||
|
||||
def validate(self):
|
||||
super(ValidatorV3, self).validate()
|
||||
self.check_network_roles()
|
||||
def check_schemas(self):
|
||||
logger.debug('Start schema checking "%s"', self.plugin_path)
|
||||
self.validate_file_by_schema(
|
||||
self.schema.metadata_schema,
|
||||
self.meta_path)
|
||||
self.validate_file_by_schema(
|
||||
self.schema.tasks_schema,
|
||||
self.tasks_path,
|
||||
check_file_exists=False
|
||||
)
|
||||
self.validate_file_by_schema(
|
||||
self.schema.network_roles_schema,
|
||||
self.network_roles_path,
|
||||
check_file_exists=False
|
||||
)
|
||||
self.check_env_config_attrs()
|
||||
|
||||
def check_network_roles(self):
|
||||
network_roles = utils.parse_yaml(self.network_roles_path)
|
||||
self.validate_schema(
|
||||
network_roles, self.schema.network_roles_schema,
|
||||
self.network_roles_path)
|
||||
def _parse_tasks(self):
|
||||
if utils.exists(self.tasks_path):
|
||||
tasks = utils.parse_yaml(self.tasks_path)
|
||||
# Tasks schema is not checked in check_schemas, thus
|
||||
# we perform manual check on parsing tasks file
|
||||
if tasks is None:
|
||||
raise errors.FileIsEmpty(self.tasks_path)
|
||||
return None
|
||||
|
|
Loading…
Reference in New Issue