#!/usr/bin/env python# -*- coding: utf-8; -*-# Copyright (c) 2021, 2022 Oracle and/or its affiliates.# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/importfsspecimportjsonimportyamlfromcerberusimportValidatorfromosimportpathJOB_SCHEMA_PATH="job_schema.json"RUNTIME_SCHEMA_PATH="runtime_schema.json"INFRASTRUCTURE_SCHEMA_PATH="infrastructure_schema.json"
[docs]defload_schema(schema_path):ifpath.exists(path.join(path.dirname(__file__),schema_path)):withfsspec.open(path.join(path.dirname(__file__),schema_path),mode="r",encoding="utf8")asf:schema=json.load(f)returnschemaelse:raiseFileNotFoundError(f"{schema_path} does not exist")
[docs]classValidateRuntime:"""Class used to validate a Runtime YAML"""def__init__(self,file):self.file=fileself.schema=load_schema(RUNTIME_SCHEMA_PATH)
[docs]defvalidate(self):"""Validates the Runtime YAML Raises: ValueError: if invalid Returns: [dict]: Returns normalized dictionary if input matches a known schema, else raises error """v=Validator(self.schema)valid=v.validate(self.file)ifnotvalid:raiseValueError(json.dumps(v.errors,indent=2))returnv.normalized(self.file)
[docs]classValidateInfrastructure:"""Class used to validate an Engine YAML"""def__init__(self,file):self.file=fileself.schema=load_schema(INFRASTRUCTURE_SCHEMA_PATH)
[docs]defvalidate(self):"""Validates the Engine YAML Raises: ValueError: if invalid Returns: [dict]: Returns normalized dictionary if input matches a known schema, else raises error """v=Validator(self.schema)valid=v.validate(self.file)ifnotvalid:raiseValueError(json.dumps(v.errors,indent=2))returnv.normalized(self.file)
[docs]classValidateJob:"""Class used to validate a Job YAML"""def__init__(self,file):self.file=fileself.schema=load_schema(JOB_SCHEMA_PATH)
[docs]defvalidate(self):"""Validates the Job YAML Raises: ValueError: if invalid Returns: [dict]: Returns normalized dictionary if input matches a known schema, else raises error """v=Validator(self.schema)job_valid=v.validate(self.file)infrastructure_valid,runtime_valid=True,Trueif"infrastructure"inself.file["spec"]:infrastructure_valid=ValidateInfrastructure(self.file["spec"]["infrastructure"]).validate()if"runtime"inself.file["spec"]:runtime_valid=ValidateRuntime(self.file["spec"]["runtime"]).validate()ifnotjob_validornotinfrastructure_validornotruntime_valid:raiseValueError(json.dumps(v.errors,indent=2))returnv.normalized(self.file)
[docs]classValidatorFactory:"""ValidatorFactory is a factory class that calls appropriate Validator class based on the 'kind' Usage: spec = {} validated_dict = ValidatorFactory(spec).validate(): """def__init__(self,file):iftype(file)!=dict:raiseValueError("Input is not a dictionary")else:self.file=file
[docs]defvalidate(self):"""Calls correct validator based on 'kind' Raises: TypeError: raised when 'kind' is not known Returns: [boolean]: Returns True if input matches a known schema, else False """if"kind"notinself.file:raiseValueError("No 'kind' found in input spec")ifself.file["kind"]=="job":returnValidateJob(self.file).validate()elifself.file["kind"]=="infrastructure":returnValidateInfrastructure(self.file).validate()elifself.file["kind"]=="runtime":returnValidateRuntime(self.file).validate()else:raiseTypeError(f"Unknown Kind: {self.file['kind']}")