def reset(self, name: str, force: bool = False, skip_host_plugins: bool = False): """ Reset package to defaults version Args: name: SONiC Package name. force: Force the installation. skip_host_plugins: Skip host plugins installation. Raises: PackageManagerError """ with failure_ignore(force): if not self.is_installed(name): raise PackageManagerError(f'{name} is not installed') package = self.get_installed_package(name) default_reference = package.entry.default_reference if default_reference is None: raise PackageManagerError( f'package {name} has no default reference') package_ref = PackageReference(name, default_reference) source = self.get_package_source(package_ref=package_ref) self.upgrade_from_source(source, force=force, allow_downgrade=True, skip_host_plugins=skip_host_plugins)
def changelog(ctx, package_expr, from_repository, from_tarball): """ Show package changelog. """ manager: PackageManager = ctx.obj try: source = manager.get_package_source(package_expr, from_repository, from_tarball) package = source.get_package() changelog = package.manifest['package']['changelog'] if not changelog: raise PackageManagerError(f'No changelog for package {package.name}') for version, entry in changelog.items(): author = entry.get('author') or 'N/A' email = entry.get('email') or 'N/A' changes = entry.get('changes') or [] date = entry.get('date') or 'N/A' click.secho(f'{version}:\n', fg='green', bold=True) for line in changes: click.secho(f' {BULLET_UC} {line}', bold=True) click.secho(f'\n {author} ' f'({email}) {date}', fg='green', bold=True) click.secho('') except Exception as err: exit_cli(f'Failed to print package changelog: {err}', fg='red')
def wrapped_function(*args, **kwargs): sig = signature(func) unsupported_opts = [opt for opt in kwargs if opt not in sig.parameters] if unsupported_opts: raise PackageManagerError( f'Unsupported options {unsupported_opts} for {func.__name__}') return func(*args, **kwargs)
def _get_cli_plugin_path(cls, package: Package, command): pkg_loader = pkgutil.get_loader(f'{command}.plugins') if pkg_loader is None: raise PackageManagerError( f'Failed to get plugins path for {command} CLI') plugins_pkg_path = os.path.dirname(pkg_loader.path) return os.path.join(plugins_pkg_path, cls._get_cli_plugin_name(package))
def get_package_source(self, package_expression: Optional[str] = None, repository_reference: Optional[str] = None, tarboll_path: Optional[str] = None, package_ref: Optional[PackageReference] = None): """ Returns PackageSource object based on input source. Args: package_expression: SONiC Package expression string repository_reference: Install from REPO[:TAG][@DIGEST] tarboll_path: Install from image tarball package_ref: Package reference object Returns: SONiC Package object. Raises: ValueError if no source specified. """ if package_expression: ref = parse_reference_expression(package_expression) return self.get_package_source(package_ref=ref) elif repository_reference: repo_ref = utils.DockerReference.parse(repository_reference) repository = repo_ref['name'] reference = repo_ref['tag'] or repo_ref['digest'] reference = reference or 'latest' return RegistrySource(repository, reference, self.database, self.docker, self.metadata_resolver) elif tarboll_path: return TarballSource(tarboll_path, self.database, self.docker, self.metadata_resolver) elif package_ref: package_entry = self.database.get_package(package_ref.name) # Determine the reference if not specified. # If package is installed assume the installed # one is requested, otherwise look for default # reference defined for this package. In case package # does not have a default reference raise an error. if package_ref.reference is None: if package_entry.installed: return LocalSource(package_entry, self.database, self.docker, self.metadata_resolver) if package_entry.default_reference is not None: package_ref.reference = package_entry.default_reference else: raise PackageManagerError( 'No default reference tag. ' 'Please specify the version or tag explicitly') return RegistrySource(package_entry.repository, package_ref.reference, self.database, self.docker, self.metadata_resolver) else: raise ValueError('No package source provided')
def remove_package(self, name: str): """ Removes package entry from database. Args: name: repository name. Raises: PackageNotFoundError: Raises when package with the given name does not exist in the database. """ pkg = self.get_package(name) if pkg.built_in: raise PackageManagerError( f'Package {name} is built-in, cannot remove it') if pkg.installed: raise PackageManagerError( f'Package {name} is installed, uninstall it first') self._database.pop(name)
def package_constraint_to_reference(constraint: PackageConstraint) -> PackageReference: package_name, version_constraint = constraint.name, constraint.constraint # Allow only specific version for now. # Later we can improve package manager to support # installing packages using expressions like 'package>1.0.0' if version_constraint == VersionRange(): # empty range means any version return PackageReference(package_name, None) if not isinstance(version_constraint, Version): raise PackageManagerError(f'Can only install specific version. ' f'Use only following expression "{package_name}=<version>" ' f'to install specific version') return PackageReference(package_name, version_to_tag(version_constraint))
def get_cli_plugin_directory(command: str) -> str: """ Returns a plugins package directory for command group. Args: command: SONiC command: "show"/"config"/"clear". Returns: Path to plugins package directory. """ pkg_loader = pkgutil.get_loader(f'{command}.plugins') if pkg_loader is None: raise PackageManagerError( f'Failed to get plugins path for {command} CLI') plugins_pkg_path = os.path.dirname(pkg_loader.path) return plugins_pkg_path
def package_constraint_to_reference( constraint: PackageConstraint) -> PackageReference: package_name, version_constraint = constraint.name, constraint.constraint # Allow only specific version for now. # Later we can improve package manager to support # installing packages using expressions like 'package>1.0.0' if version_constraint.expression == '*': return PackageReference(package_name, None) if not version_constraint.is_exact(): raise PackageManagerError( f'Can only install specific version. ' f'Use only following expression "{package_name}=<version>" ' f'to install specific version') version = version_constraint.get_exact_version() return PackageReference(package_name, version_to_tag(version))
def validate_package_cli_can_be_skipped(package: Package, skip: bool): """ Checks whether package CLI installation can be skipped. Args: package: Package to validate skip: Whether to skip installing CLI Raises: PackageManagerError """ if package.manifest['cli']['mandatory'] and skip: raise PackageManagerError(f'CLI is mandatory for package {package.name} ' f'but it was requested to be not installed') elif skip: log.warning(f'Package {package.name} CLI plugin will not be installed')