Exemple #1
0
    def create_package(self, input_folder: Path, output_file: Path, store_extenal_info: bool = True, tar_extra_args: list = None, validate_only: bool = False):
        """
        Create a leaf artifact from given folder containing a manifest.json
        """
        mffile = input_folder / LeafFiles.MANIFEST
        infofile = self.find_external_info_file(output_file)

        if not mffile.exists():
            raise LeafException("Cannot find manifest: {file}".format(file=mffile))

        manifest = Manifest.parse(mffile)
        manifest.validate_model()

        if not validate_only:
            if is_latest_package(manifest.identifier):
                raise LeafException("Invalid version for manifest {mf} ({kw} is a reserved keyword)".format(mf=mffile, kw=LeafConstants.LATEST))

            self.logger.print_default("Found package {mf.identifier} in {folder}".format(mf=manifest, folder=input_folder))

            # Check if external info file exists
            if not store_extenal_info and infofile.exists():
                raise LeafException(
                    "A previous info file ({file}) exists for your package".format(file=infofile),
                    hints="You should remove it with 'rm {file}'".format(file=infofile),
                )

            self.__exec_tar(output_file, input_folder, extra_args=tar_extra_args)

            self.logger.print_default("Leaf package created: {file}".format(file=output_file))

            if store_extenal_info:
                self.logger.print_default("Write info to {file}".format(file=infofile))
                jwritefile(infofile, self.__build_pkg_node(output_file, manifest=manifest), pp=True)
Exemple #2
0
 def build_packages_environment(self, items: list, ipmap=None):
     """
     Get the env vars declared by given packages
     @param items: a list of InstalledPackage or PackageIdentifier
     """
     ipmap = ipmap or self.list_installed_packages()
     out = Environment()
     for item in items:
         ip = None
         if isinstance(item, InstalledPackage):
             ip = item
         elif isinstance(item, PackageIdentifier):
             ip = None
             if is_latest_package(item):
                 ip = find_manifest(item, ipmap)
             else:
                 ip = ipmap.get(item)
             if ip is None:
                 raise InvalidPackageNameException(item)
         else:
             raise InvalidPackageNameException(item)
         vr = VariableResolver(ip, ipmap.values())
         out.append(ip.build_environment(vr=vr.resolve))
     return out
Exemple #3
0
    def generate_manifest(self,
                          output_file: Path,
                          fragment_files: list = None,
                          info_map: dict = None,
                          resolve_envvars: bool = False):
        """
        Used to create a manifest.json file
        """
        model = OrderedDict()

        # Load fragments
        if fragment_files is not None:
            for fragment_file in fragment_files:
                self.logger.print_default(
                    "Use json fragment: {fragment}".format(
                        fragment=fragment_file))
                jlayer_update(model,
                              jloadfile(fragment_file),
                              list_append=True)

        # Load model
        manifest = Manifest(model)
        info = manifest.jsonget(JsonConstants.INFO, default=OrderedDict())

        # Set the common info
        if info_map is not None:
            for key in (
                    JsonConstants.INFO_NAME,
                    JsonConstants.INFO_VERSION,
                    JsonConstants.INFO_DESCRIPTION,
                    JsonConstants.INFO_MASTER,
                    JsonConstants.INFO_DATE,
                    JsonConstants.INFO_REQUIRES,
                    JsonConstants.INFO_DEPENDS,
                    JsonConstants.INFO_TAGS,
                    JsonConstants.INFO_LEAF_MINVER,
                    JsonConstants.INFO_AUTOUPGRADE,
            ):
                if key in info_map:
                    value = info_map[key]
                    if value is not None:
                        if key in (JsonConstants.INFO_REQUIRES,
                                   JsonConstants.INFO_DEPENDS,
                                   JsonConstants.INFO_TAGS):
                            # Handle lists
                            model_list = manifest.jsonpath(
                                [JsonConstants.INFO, key], default=[])
                            for motif in value:
                                if motif not in model_list:
                                    if key == JsonConstants.INFO_DEPENDS:
                                        # Try to parse as a conditional package
                                        # identifier
                                        ConditionalPackageIdentifier.parse(
                                            motif)
                                    elif key == JsonConstants.INFO_REQUIRES:
                                        # Try to parse as a package identifier
                                        PackageIdentifier.parse(motif)

                                    self.logger.print_verbose(
                                        "Add '{motif}' to '{key}' list".format(
                                            motif=motif, key=key))
                                    model_list.append(motif)
                        else:
                            self.logger.print_verbose(
                                "Set '{key}' = '{value}'".format(key=key,
                                                                 value=value))
                            info[key] = value

        # String replacement
        jsonstr = jtostring(manifest.json, pp=True)
        if resolve_envvars:
            for var in set(
                    re.compile(r"#\{([a-zA-Z0-9_]+)\}").findall(jsonstr)):
                value = os.environ.get(var)
                if value is None:
                    raise LeafException(
                        "Cannot find '{var}' in env".format(var=var),
                        hints="Set the variable with 'export {var}=xxx'".
                        format(var=var))
                self.logger.print_default("Replace {key} --> {value}".format(
                    key=var, value=value))
                jsonstr = jsonstr.replace("#{{{var}}}".format(var=var), value)

        if is_latest_package(manifest.identifier):
            raise LeafException(
                "Invalid version ({word} is a reserved keyword)".format(
                    word=LeafConstants.LATEST))

        self.logger.print_default(
            "Save '{mf.identifier}' manifest to {file}".format(
                mf=manifest, file=output_file))

        with output_file.open("w") as fp:
            fp.write(jsonstr)
Exemple #4
0
    def generate_index(
        self,
        index_file: Path,
        artifacts: list,
        name: str = None,
        description: str = None,
        use_external_info: bool = True,
        use_extra_tags: bool = True,
        prettyprint: bool = False,
        resolve: bool = True,
    ):
        """
        Create an index.json referencing all given artifacts
        """
        if not index_file.exists():
            index_file.touch()
        if resolve:
            index_file = index_file.resolve()

        try:
            # Create the "info" node
            info_node = OrderedDict()
            if name is not None:
                info_node[JsonConstants.REMOTE_NAME] = name
            if description is not None:
                info_node[JsonConstants.REMOTE_DESCRIPTION] = description
            info_node[JsonConstants.REMOTE_DATE] = self.__get_date_now()

            packages_map = OrderedDict()
            # Resolve artifacts if needed
            if resolve:
                artifacts = [a.resolve() for a in artifacts]
            for artifact in artifacts:
                artifact_node = None

                if use_external_info:
                    infofile = self.find_external_info_file(artifact)
                    if infofile.exists():
                        self.logger.print_default(
                            "Reading info from {file}".format(file=infofile))
                        artifact_node = jloadfile(infofile)

                if artifact_node is None:
                    self.logger.print_default(
                        "Compute info for {artifact}".format(
                            artifact=artifact))
                    artifact_node = self.__build_pkg_node(artifact)

                ap = AvailablePackage(artifact_node)
                pi = ap.identifier
                if is_latest_package(pi):
                    raise LeafException(
                        "Invalid version for package {artifact} ({word} is a reserved keyword)"
                        .format(artifact=artifact, word=LeafConstants.LATEST))

                if pi in packages_map:
                    self.logger.print_default(
                        "Artifact already present: {pi}".format(pi=pi))
                    if ap.hashsum != AvailablePackage(
                            packages_map[pi]).hashsum:
                        raise LeafException(
                            "Artifact {pi} has multiple different artifacts for same version"
                            .format(pi=pi))
                else:
                    # Read extra tags
                    extratags_file = artifact.parent / (artifact.name +
                                                        ".tags")
                    if use_extra_tags and extratags_file.exists():
                        with extratags_file.open() as fp:
                            for tag in filter(
                                    None, map(str.strip,
                                              fp.read().splitlines())):
                                if tag not in ap.tags:
                                    self.logger.print_default(
                                        "Add extra tag {tag}".format(tag=tag))
                                    ap.tags.append(tag)

                    self.logger.print_default("Add package {pi}".format(pi=pi))
                    try:

                        relative_path = artifact.relative_to(index_file.parent)
                        artifact_node[JsonConstants.REMOTE_PACKAGE_FILE] = str(
                            relative_path)
                    except ValueError:
                        raise LeafException(
                            "Artifact {a} must be relative to {i.parent}".
                            format(a=artifact, i=index_file))
                    packages_map[pi] = artifact_node

            # Create the json structure
            root_node = OrderedDict()
            root_node[JsonConstants.INFO] = info_node
            root_node[JsonConstants.REMOTE_PACKAGES] = list(
                packages_map.values())

            jwritefile(index_file, root_node, pp=prettyprint)
            self.logger.print_default(
                "Index created: {index}".format(index=index_file))
        except BaseException as e:
            # Clean the invalid index file
            if index_file.exists():
                index_file.unlink()
            raise e