Merge "Fix issues with CSAR error handling"
This commit is contained in:
commit
cd560b8f26
@ -37,6 +37,7 @@ class CSAR(object):
|
||||
self.path = csar_file
|
||||
self.a_file = a_file
|
||||
self.is_validated = False
|
||||
self.error_caught = False
|
||||
self.csar = None
|
||||
self.temp_dir = None
|
||||
|
||||
@ -51,12 +52,14 @@ class CSAR(object):
|
||||
if not os.path.isfile(self.path):
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=missing_err_msg))
|
||||
return False
|
||||
else:
|
||||
self.csar = self.path
|
||||
else: # a URL
|
||||
if not UrlUtils.validate_url(self.path):
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=missing_err_msg))
|
||||
return False
|
||||
else:
|
||||
response = requests.get(self.path)
|
||||
self.csar = BytesIO(response.content)
|
||||
@ -66,6 +69,7 @@ class CSAR(object):
|
||||
err_msg = (_('"%s" is not a valid zip file.') % self.path)
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=err_msg))
|
||||
return False
|
||||
|
||||
# validate that it contains the metadata file in the correct location
|
||||
self.zfile = zipfile.ZipFile(self.csar, 'r')
|
||||
@ -76,6 +80,7 @@ class CSAR(object):
|
||||
'"TOSCA-Metadata".') % self.path)
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=err_msg))
|
||||
return False
|
||||
|
||||
# validate that 'Entry-Definitions' property exists in TOSCA.meta
|
||||
data = self.zfile.read('TOSCA-Metadata/TOSCA.meta')
|
||||
@ -84,33 +89,40 @@ class CSAR(object):
|
||||
'content.') % self.path)
|
||||
try:
|
||||
meta = yaml.load(data)
|
||||
if type(meta) is not dict:
|
||||
if type(meta) is dict:
|
||||
self.metadata = meta
|
||||
else:
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=invalid_yaml_err_msg))
|
||||
self.metadata = meta
|
||||
return False
|
||||
except yaml.YAMLError:
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=invalid_yaml_err_msg))
|
||||
return False
|
||||
|
||||
if 'Entry-Definitions' not in self.metadata:
|
||||
err_msg = (_('The CSAR "%s" is missing the required metadata '
|
||||
'"Entry-Definitions" in "TOSCA-Metadata/TOSCA.meta".')
|
||||
'"Entry-Definitions" in '
|
||||
'"TOSCA-Metadata/TOSCA.meta".')
|
||||
% self.path)
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=err_msg))
|
||||
return False
|
||||
|
||||
# validate that 'Entry-Definitions' metadata value points to an
|
||||
# existing file in the CSAR
|
||||
entry = self.metadata['Entry-Definitions']
|
||||
if entry not in filelist:
|
||||
err_msg = (_('The "Entry-Definitions" file defined in the CSAR '
|
||||
'"%s" does not exist.') % self.path)
|
||||
entry = self.metadata.get('Entry-Definitions')
|
||||
if entry and entry not in filelist:
|
||||
err_msg = (_('The "Entry-Definitions" file defined in the '
|
||||
'CSAR "%s" does not exist.') % self.path)
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=err_msg))
|
||||
return False
|
||||
|
||||
# validate that external references in the main template actually exist
|
||||
# and are accessible
|
||||
# validate that external references in the main template actually
|
||||
# exist and are accessible
|
||||
self._validate_external_references()
|
||||
return not self.error_caught
|
||||
|
||||
def get_metadata(self):
|
||||
"""Return the metadata dictionary."""
|
||||
@ -125,7 +137,7 @@ class CSAR(object):
|
||||
def _get_metadata(self, key):
|
||||
if not self.is_validated:
|
||||
self.validate()
|
||||
return self.metadata[key] if key in self.metadata else None
|
||||
return self.metadata.get(key)
|
||||
|
||||
def get_author(self):
|
||||
return self._get_metadata('Created-By')
|
||||
@ -134,24 +146,27 @@ class CSAR(object):
|
||||
return self._get_metadata('CSAR-Version')
|
||||
|
||||
def get_main_template(self):
|
||||
return self._get_metadata('Entry-Definitions')
|
||||
entry_def = self._get_metadata('Entry-Definitions')
|
||||
if entry_def in self.zfile.namelist():
|
||||
return entry_def
|
||||
|
||||
def get_main_template_yaml(self):
|
||||
main_template = self.get_main_template()
|
||||
data = self.zfile.read(main_template)
|
||||
invalid_tosca_yaml_err_msg = (
|
||||
_('The file "%(template)s" in the CSAR "%(csar)s" does not '
|
||||
'contain valid TOSCA YAML content.') %
|
||||
{'template': main_template, 'csar': self.path})
|
||||
try:
|
||||
tosca_yaml = yaml.load(data)
|
||||
if type(tosca_yaml) is not dict:
|
||||
if main_template:
|
||||
data = self.zfile.read(main_template)
|
||||
invalid_tosca_yaml_err_msg = (
|
||||
_('The file "%(template)s" in the CSAR "%(csar)s" does not '
|
||||
'contain valid TOSCA YAML content.') %
|
||||
{'template': main_template, 'csar': self.path})
|
||||
try:
|
||||
tosca_yaml = yaml.load(data)
|
||||
if type(tosca_yaml) is not dict:
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=invalid_tosca_yaml_err_msg))
|
||||
return tosca_yaml
|
||||
except Exception:
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=invalid_tosca_yaml_err_msg))
|
||||
return tosca_yaml
|
||||
except Exception:
|
||||
ExceptionCollector.appendException(
|
||||
ValidationError(message=invalid_tosca_yaml_err_msg))
|
||||
|
||||
def get_description(self):
|
||||
desc = self._get_metadata('Description')
|
||||
@ -159,7 +174,7 @@ class CSAR(object):
|
||||
return desc
|
||||
|
||||
self.metadata['Description'] = \
|
||||
self.get_main_template_yaml()['description']
|
||||
self.get_main_template_yaml().get('description')
|
||||
return self.metadata['Description']
|
||||
|
||||
def decompress(self):
|
||||
@ -180,6 +195,8 @@ class CSAR(object):
|
||||
try:
|
||||
self.decompress()
|
||||
main_tpl_file = self.get_main_template()
|
||||
if not main_tpl_file:
|
||||
return
|
||||
main_tpl = self.get_main_template_yaml()
|
||||
|
||||
if 'imports' in main_tpl:
|
||||
@ -212,6 +229,7 @@ class CSAR(object):
|
||||
ValueError(_('Unexpected artifact '
|
||||
'definition for "%s".')
|
||||
% artifact_key))
|
||||
self.error_caught = True
|
||||
if 'interfaces' in node_template:
|
||||
interfaces = node_template['interfaces']
|
||||
for interface_key in interfaces:
|
||||
@ -250,9 +268,11 @@ class CSAR(object):
|
||||
else:
|
||||
ExceptionCollector.appendException(
|
||||
URLException(what=msg))
|
||||
self.error_caught = True
|
||||
except Exception:
|
||||
ExceptionCollector.appendException(
|
||||
URLException(what=msg))
|
||||
self.error_caught = True
|
||||
|
||||
if os.path.isfile(os.path.join(self.temp_dir,
|
||||
os.path.dirname(tpl_file),
|
||||
@ -263,3 +283,4 @@ class CSAR(object):
|
||||
ExceptionCollector.appendException(
|
||||
ValueError(_('The resource "%s" does not exist.')
|
||||
% resource_file))
|
||||
self.error_caught = True
|
||||
|
@ -157,7 +157,7 @@ class CSARPrereqTest(TestCase):
|
||||
def test_valid_csar(self):
|
||||
path = os.path.join(self.base_path, "data/CSAR/csar_hello_world.zip")
|
||||
csar = CSAR(path)
|
||||
self.assertIsNone(csar.validate())
|
||||
self.assertTrue(csar.validate())
|
||||
self.assertTrue(csar.temp_dir is None or
|
||||
not os.path.exists(csar.temp_dir))
|
||||
|
||||
@ -165,7 +165,7 @@ class CSARPrereqTest(TestCase):
|
||||
path = os.path.join(self.base_path, "data/CSAR/csar_wordpress_with_url"
|
||||
"_import_and_script.zip")
|
||||
csar = CSAR(path)
|
||||
self.assertIsNone(csar.validate())
|
||||
self.assertTrue(csar.validate())
|
||||
self.assertTrue(csar.temp_dir is None or
|
||||
not os.path.exists(csar.temp_dir))
|
||||
|
||||
@ -225,6 +225,6 @@ class CSARPrereqTest(TestCase):
|
||||
def test_alternate_csar_extension(self):
|
||||
path = os.path.join(self.base_path, "data/CSAR/csar_elk.csar")
|
||||
csar = CSAR(path)
|
||||
self.assertIsNone(csar.validate())
|
||||
self.assertTrue(csar.validate())
|
||||
self.assertTrue(csar.temp_dir is None or
|
||||
not os.path.exists(csar.temp_dir))
|
||||
|
@ -54,6 +54,7 @@ class ToscaTemplate(object):
|
||||
def __init__(self, path, parsed_params=None, a_file=True):
|
||||
ExceptionCollector.start()
|
||||
self.a_file = a_file
|
||||
self.input_path = path
|
||||
self.path = self._get_path(path)
|
||||
if self.path:
|
||||
self.tpl = YAML_LOADER(self.path, self.a_file)
|
||||
@ -187,10 +188,10 @@ class ToscaTemplate(object):
|
||||
elif path.lower().endswith(('.zip', '.csar')):
|
||||
# a CSAR archive
|
||||
csar = CSAR(path, self.a_file)
|
||||
csar.validate()
|
||||
csar.decompress()
|
||||
self.a_file = True # the file has been decompressed locally
|
||||
return os.path.join(csar.temp_dir, csar.get_main_template())
|
||||
if csar.validate():
|
||||
csar.decompress()
|
||||
self.a_file = True # the file has been decompressed locally
|
||||
return os.path.join(csar.temp_dir, csar.get_main_template())
|
||||
else:
|
||||
ExceptionCollector.appendException(
|
||||
ValueError(_('"%(path)s" is not a valid file.')
|
||||
@ -201,10 +202,10 @@ class ToscaTemplate(object):
|
||||
raise ValidationError(
|
||||
message=(_('\nThe input "%(path)s" failed validation with the '
|
||||
'following error(s): \n\n\t')
|
||||
% {'path': self.path}) +
|
||||
% {'path': self.input_path}) +
|
||||
'\n\t'.join(ExceptionCollector.getExceptionsReport()))
|
||||
else:
|
||||
msg = (_('The input "%(path)s" successfully passed validation.') %
|
||||
{'path': self.path})
|
||||
{'path': self.input_path})
|
||||
log.info(msg)
|
||||
print(msg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user