Manifest parsing: skip invalid manifest files (#32467)

* catch json schema errors and reraise as property of SpackError
* no need to catch subclass of given error
* Builtin json library for Python 2 uses more generic type
* Correct instantiation of SpackError (requires a string rather than an exception)
* Use exception chaining (where possible)
This commit is contained in:
Peter Scheibel 2022-09-14 13:02:51 -07:00 committed by GitHub
parent ebb20eb8f8
commit 7971985a06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 4 deletions

View file

@ -219,7 +219,7 @@ def _collect_and_consume_cray_manifest_files(
tty.debug("Reading manifest file: " + path)
try:
cray_manifest.read(path, not dry_run)
except (spack.compilers.UnknownCompilerError, spack.error.SpackError) as e:
except spack.error.SpackError as e:
if fail_on_error:
raise
else:

View file

@ -4,8 +4,10 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import json
import sys
import jsonschema
import jsonschema.exceptions
import six
import llnl.util.tty as tty
@ -161,10 +163,21 @@ def entries_to_specs(entries):
def read(path, apply_updates):
with open(path, "r") as json_file:
json_data = json.load(json_file)
if sys.version_info >= (3, 0):
decode_exception_type = json.decoder.JSONDecodeError
else:
decode_exception_type = ValueError
jsonschema.validate(json_data, manifest_schema)
try:
with open(path, "r") as json_file:
json_data = json.load(json_file)
jsonschema.validate(json_data, manifest_schema)
except (jsonschema.exceptions.ValidationError, decode_exception_type) as e:
raise six.raise_from(
ManifestValidationError("error parsing manifest JSON:", str(e)),
e,
)
specs = entries_to_specs(json_data["specs"])
tty.debug("{0}: {1} specs read from manifest".format(path, str(len(specs))))
@ -179,3 +192,8 @@ def read(path, apply_updates):
if apply_updates:
for spec in specs.values():
spack.store.db.add(spec, directory_layout=None)
class ManifestValidationError(spack.error.SpackError):
def __init__(self, msg, long_msg=None):
super(ManifestValidationError, self).__init__(msg, long_msg)

View file

@ -365,3 +365,38 @@ def test_read_old_manifest_v1_2(tmpdir, mutable_config, mock_packages, mutable_d
"""
)
cray_manifest.read(manifest_file_path, True)
def test_convert_validation_error(tmpdir, mutable_config, mock_packages, mutable_database):
manifest_dir = str(tmpdir.mkdir("manifest_dir"))
# Does not parse as valid JSON
invalid_json_path = os.path.join(manifest_dir, "invalid-json.json")
with open(invalid_json_path, "w") as f:
f.write(
"""\
{
"""
)
with pytest.raises(cray_manifest.ManifestValidationError) as e:
cray_manifest.read(invalid_json_path, True)
str(e)
# Valid JSON, but does not conform to schema (schema-version is not a string
# of length > 0)
invalid_schema_path = os.path.join(manifest_dir, "invalid-schema.json")
with open(invalid_schema_path, "w") as f:
f.write(
"""\
{
"_meta": {
"file-type": "cray-pe-json",
"system-type": "EX",
"schema-version": ""
},
"specs": []
}
"""
)
with pytest.raises(cray_manifest.ManifestValidationError) as e:
cray_manifest.read(invalid_schema_path, True)
str(e)