def _read_etsi_manifest(self, wd, tosca_meta): """ Tries to find ETSI Manifest file. - try 1: Use "Entry-Manifest" from TOSCA.meta - try 2: Look for *.mf file in root of package Returns list of blocks from that file or an empty list. """ try: if (tosca_meta is not None and tosca_meta[0].get("Entry-Manifest") is not None): # try 1: path = search_for_file( os.path.join(wd, tosca_meta[0].get("Entry-Manifest"))) if path is None: LOG.warning("Entry-Manifest '{}' not found.".format( tosca_meta[0].get("Entry-Manifest"))) # try 2: path = search_for_file(os.path.join(wd, "*.mf"), recursive=False) if path is None: raise MissingMetadataException( "Cannot find ETSI manifest file.") with open(path, "r") as f: return parse_block_based_meta_file(f) except BaseException as e: LOG.error("Cannot read ETSI manifest file: {}".format(e)) return [{}]
def _pack_read_project_descriptor(self, project_path): """ Searches and reads, validates project.y*l for packaging. """ # find file project_descriptor_path = search_for_file( path=os.path.join(project_path, "project.y*l")) if project_descriptor_path is None: raise MissingFileException( "project.y*l not found in {}".format(project_path)) # read file with open(project_descriptor_path, "r") as f: data = yaml.load(f) # validate contents for field in ["package", "files", "version"]: if field not in data: raise MetadataValidationException( "{} section missing in PD".format(field)) for field in ["name", "vendor", "version"]: if field not in data["package"]: raise MetadataValidationException( "{} field missing in PD/package".format(field)) # check if all linked files exist for f in data.get("files"): if (f.get("path") is None or not os.path.isfile( os.path.join(project_path, f.get("path"))) and not f.get("type") == "application/vnd.folder.compressed.zip"): raise MissingFileException( "Could not find file linked in project.yml:{}".format( f.get("path"))) return data return None
def _read_napd(self, wd, tosca_meta): """ Tries to read NAPD file and optionally validates it against its online schema. - try 1: Use block_1 from TOSCA.meta to find NAPD - try 2: Look for **/NAPD.yaml Returns valid NAPD schema formatted dict. and NAPD path """ try: path = None if (tosca_meta is not None and len(tosca_meta) > 1): # try 1: path = search_for_file( os.path.join(wd, tosca_meta[1].get("Name"))) if path is None: LOG.warning("TOSCA block_1 file '{}' not found.".format( tosca_meta[1].get("Name"))) # try 2: path = search_for_file(os.path.join(wd, "**/NAPD.yaml"), recursive=False) if path is None: LOG.warning("Couldn't find NAPD file: {}".format(wd)) return dict(), None # TODO return an empty NAPD skeleton here with open(path, "r") as f: data = yaml.load(f) if self.args.offline: LOG.warning("Skipping NAPD validation (--offline)") else: if not validate_yaml_online(data): raise NapdNotValidException( "Validation of {} failed.".format(path)) return data, path except NapdNotValidException as e: LOG.error("Validation error: {}".format(e)) raise e except BaseException as e: LOG.error("Cannot read NAPD.yaml file: {}".format(e)) # raise e return dict(), None # TODO return an empty NAPD skeleton here
def _read_tosca_meta(self, wd): """ Tries to find TOSCA.meta file. Returns list of blocks from that file or an list with a single empty block. """ try: path = search_for_file(os.path.join(wd, "**/TOSCA.meta")) if path is None: raise MissingMetadataException("Cannot find TOSCA.meta") with open(path, "r") as f: return parse_block_based_meta_file(f) except BaseException as e: LOG.error("Cannot read TOSCA metadata: {}".format(e)) return [{}]
def fuzzy_find_wd(wd): """ Zip files often contain a kind of 'root' folder, instead of placing the files themselves into the root of the archive. This function tries to find the 'real' root of the extracted package directory and returns it. Detection is done by 'TOSCA-Metadata' folder. """ found_path = search_for_file(os.path.join(wd, "**/TOSCA-Metadata")) if found_path is None: return wd wd_root = found_path.replace("TOSCA-Metadata", "").strip() if wd_root != wd: LOG.warning("Fuzzy found WD root: {}".format(wd_root)) return wd_root
def _validate_package_content_checksums(self, wd, napdr): """ Validates the checksums of all entries in the package_content list. (if algorithm field is not given, nothing is checked) Implemented on the ETSI level, because CSAR packages do not have checksums to check. """ # iterate over all content files and check them for ce in napdr.package_content: # check and validate ce data if "source" not in ce: raise MissingMetadataException( """Malformed package_content entry: source field missing: {}""".format(ce)) if ce.get("algorithm") is None: # warn and skip entry (a risk but makes things easier for now) LOG.warning("Package content without checksum: {}".format(ce)) continue if ce.get("algorithm") is not None and ce.get("hash") is None: raise ChecksumException("Checksum missing: {}".format(ce)) # find file path = search_for_file(os.path.join(wd, ce.get("source"))) if path is None: raise MissingFileException( "Checksum: File not found: {}".format( os.path.join(wd, ce.get("source")))) # validate checksum try: validate_file_checksum(path, ce.get("algorithm"), ce.get("hash")) except ChecksumException as e: # decide if checksum missmatch is error print(self.args.no_checksums) if self.args.no_checksums: # LOG.warning(e) LOG.warning("Ignoring error (--ignore-checksums)") else: raise e