murano-pkg-check/muranopkgcheck/validators/manifest.py

156 lines
6.7 KiB
Python

# Copyright (c) 2016 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 os.path
import semantic_version
import six
from muranopkgcheck import consts
from muranopkgcheck import error
from muranopkgcheck.i18n import _
from muranopkgcheck.validators import base
from muranopkgcheck import yaml_loader
error.register.E030(description='Not supported format')
error.register.E050(description='File is present in Manifest, '
'but not in filesystem')
error.register.E070(description='Tags should be a list')
error.register.E071(description='Type is invalid')
error.register.E072(description='UI is not a string')
error.register.E073(description='Invalid FullName')
error.register.E074(description='Logo is not a string')
error.register.W020(description='File is not present in Manifest, '
'but it is in filesystem')
error.register.W030(description='Not supported format version')
error.register.W073(description='There is no UI file')
error.register.W074(description='There is no Logo file')
class ManifestValidator(base.YamlValidator):
def __init__(self, loaded_package):
super(ManifestValidator, self).__init__(loaded_package,
'manifest.yaml$')
self.add_checker(self._valid_format, 'Format', False)
self.add_checker(self._valid_string, 'Author', False)
self.add_checker(self._valid_version, 'Version', False)
self.add_checker(self._valid_fullname, 'FullName')
self.add_checker(self._valid_string, 'Name', False)
self.add_checker(self._valid_classes, 'Classes', False)
self.add_checker(self._valid_tags, 'Tags', False)
self.add_checker(self._valid_require, 'Require', False)
self.add_checker(self._valid_type, 'Type')
self.add_checker(self._valid_description, 'Description')
self.add_checker(self._valid_ui, 'UI', False)
self.add_checker(self._valid_logo, 'Logo', False)
self.add_checker(self._valid_logo_ui_existance)
def _valid_description(self, desc):
if not isinstance(desc, six.string_types) and\
not isinstance(desc, yaml_loader.YamlNull):
yield error.report.E030('Value is not valid string "{0}"'
.format(desc), desc)
def _valid_format(self, value):
format_ = str(value).split('/', 1)
if len(format_) > 1:
if format_[0] != 'MuranoPL':
yield error.report.W030(_('Not supported format "{}"'
'').format(value), value)
return
ver = format_[-1]
if str(ver) not in ['1.0', '1.1', '1.2', '1.3', '1.4']:
yield error.report.W030(_('Not supported format version "{}"'
'').format(value), value)
def _valid_fullname(self, fullname):
if not self._check_fqn_name(fullname):
yield error.report.E073(_('Invalid FullName "{}"')
.format(fullname), fullname)
def _valid_tags(self, value):
if not isinstance(value, list):
yield error.report.E070(_('Tags should be a list'), value)
def _valid_require(self, value):
if not isinstance(value, dict):
yield error.report.E005(_('Require is not a dict type'), value)
return
for fqn, ver in six.iteritems(value):
if not self._check_fqn_name(fqn):
yield error.report.E005(_('Require key is not valid FQN "{}"'
'').format(fqn), fqn)
def _valid_type(self, value):
if value not in ('Application', 'Library'):
yield error.report.E071(_('Type is invalid "{}"').format(value),
value)
def _valid_version(self, version):
try:
semantic_version.Version.coerce(str(version))
except ValueError:
yield error.report.E071(_('Version format should be compatible '
'with SemVer not "{}"'
'').format(version), version)
def _valid_logo_ui_existance(self, ast):
if 'Logo' not in ast:
yield self._valid_logo('logo.png')
if 'UI' not in ast:
yield self._valid_ui('ui.yaml')
def _valid_ui(self, value):
if isinstance(value, six.string_types):
pkg_type = self._loaded_pkg.read(
consts.MANIFEST_PATH).yaml()[0]['Type']
if pkg_type == 'Library':
return
if not self._loaded_pkg.exists(os.path.join('UI', value)):
yield error.report.W073(_('There is no UI file "{}"'
'').format(value), value)
else:
yield error.report.E072(_('UI is not a string'), value)
def _valid_logo(self, value):
if isinstance(value, six.string_types):
pkg_type = self._loaded_pkg.read(
consts.MANIFEST_PATH).yaml()[0]['Type']
if pkg_type == 'Library':
return
if not self._loaded_pkg.exists(value):
yield error.report.W074(_('There is no Logo file "{}"'
'').format(value), value)
else:
yield error.report.E074(_('Logo is not a string'), value)
def _valid_classes(self, value):
if not isinstance(value, dict):
yield error.report.E074(_('Classes section should be a dict'),
value)
return
files = set(value.values())
existing_files = set(self._loaded_pkg.search_for('.*',
'Classes'))
for fname in files - existing_files:
yield error.report.E050(_('File "{}" is present in Manifest, '
'but not in filesystem'
'').format(fname), fname)
for fname in existing_files - files:
yield error.report.W020(_('File "{}" is not present in Manifest, '
'but it is in filesystem'
'').format(fname), fname)