Operator Libs Linux
- Jon Seager
Channel | Revision | Published | Runs on |
---|---|---|---|
latest/stable | 2 | 09 Mar 2023 | |
latest/stable | 1 | 28 Oct 2021 |
juju deploy operator-libs-linux
Deploy universal operators easily with Juju, the Universal Operator Lifecycle Manager.
Platform:
charms.operator_libs_linux.v0.apt
-
- Last updated 05 Dec 2024
- Revision Library version 0.15
Abstractions for the system's Debian/Ubuntu package information and repositories.
This module contains abstractions and wrappers around Debian/Ubuntu-style repositories and packages, in order to easily provide an idiomatic and Pythonic mechanism for adding packages and/or repositories to systems for use in machine charms.
A sane default configuration is attainable through nothing more than instantiation of the
appropriate classes. DebianPackage
objects provide information about the architecture, version,
name, and status of a package.
DebianPackage
will try to look up a package either from dpkg -L
or from apt-cache
when
provided with a string indicating the package name. If it cannot be located, PackageNotFoundError
will be returned, as apt
and dpkg
otherwise return 100
for all errors, and a meaningful error
message if the package is not known is desirable.
To install packages with convenience methods:
try:
# Run `apt-get update`
apt.update()
apt.add_package("zsh")
apt.add_package(["vim", "htop", "wget"])
except PackageNotFoundError:
logger.error("a specified package not found in package cache or on system")
except PackageError as e:
logger.error("could not install package. Reason: %s", e.message)
To find details of a specific package:
try:
vim = apt.DebianPackage.from_system("vim")
# To find from the apt cache only
# apt.DebianPackage.from_apt_cache("vim")
# To find from installed packages only
# apt.DebianPackage.from_installed_package("vim")
vim.ensure(PackageState.Latest)
logger.info("updated vim to version: %s", vim.fullversion)
except PackageNotFoundError:
logger.error("a specified package not found in package cache or on system")
except PackageError as e:
logger.error("could not install package. Reason: %s", e.message)
RepositoryMapping
will return a dict-like object containing enabled system repositories
and their properties (available groups, baseuri. gpg key). This class can add, disable, or
manipulate repositories. Items can be retrieved as DebianRepository
objects.
In order add a new repository with explicit details for fields, a new DebianRepository
can
be added to RepositoryMapping
RepositoryMapping
provides an abstraction around the existing repositories on the system,
and can be accessed and iterated over like any Mapping
object, to retrieve values by key,
iterate, or perform other operations.
Keys are constructed as {repo_type}-{}-{release}
in order to uniquely identify a repository.
Repositories can be added with explicit values through a Python constructor.
Example:
repositories = apt.RepositoryMapping()
if "deb-example.com-focal" not in repositories:
repositories.add(DebianRepository(enabled=True, repotype="deb",
uri="https://example.com", release="focal", groups=["universe"]))
Alternatively, any valid sources.list
line may be used to construct a new
DebianRepository
.
Example:
repositories = apt.RepositoryMapping()
if "deb-us.archive.ubuntu.com-xenial" not in repositories:
line = "deb http://us.archive.ubuntu.com/ubuntu xenial main restricted"
repo = DebianRepository.from_repo_line(line)
repositories.add(repo)
class Error
Description
Base class of most errors raised by this library. None
Methods
Error. __repr__( self )
Description
Represent the Error. None
Error. name( self )
Description
Return a string representation of the model plus class. None
Error. message( self )
Description
Return the message passed as an argument. None
class PackageError
Description
Raised when there's an error installing or removing a package. None
class PackageNotFoundError
Description
Raised when a requested package is not known to the system. None
class PackageState
Description
A class to represent possible package states. None
class DebianPackage
Represents a traditional Debian package and its utility functions.
Description
DebianPackage
wraps information and functionality around a known package, whether installed
or available. The version, epoch, name, and architecture can be easily queried and compared
against other DebianPackage
objects to determine the latest version or to install a specific
version.
The representation of this object as a string mimics the output from dpkg
for familiarity.
Installation and removal of packages is handled through the state
property or ensure
method, with the following options:
apt.PackageState.Absent
apt.PackageState.Available
apt.PackageState.Present
apt.PackageState.Latest
When DebianPackage
is initialized, the state of a given DebianPackage
object will be set to
Available
, Present
, or Latest
, with Absent
implemented as a convenience for removal
(though it operates essentially the same as Available
).
Methods
DebianPackage. __init__( self , name: str , version: str , epoch: str , arch: str , state: PackageState )
DebianPackage. __eq__( self , other )
Equality for comparison.
Arguments
a DebianPackage
object for comparison
Returns
A boolean reflecting equality
DebianPackage. __hash__( self )
Description
Return a hash of this package. None
DebianPackage. __repr__( self )
Description
Represent the package. None
DebianPackage. __str__( self )
Description
Return a human-readable representation of the package. None
DebianPackage. name( self )
Description
Returns the name of the package. None
DebianPackage. ensure( self , state: PackageState )
Ensure that a package is in a given state.
Description
Args:
state: a PackageState
to reconcile the package to
Raises: PackageError from the underlying call to apt
DebianPackage. present( self )
Description
Returns whether or not a package is present. None
DebianPackage. latest( self )
Description
Returns whether the package is the most recent version. None
DebianPackage. state( self )
Description
Returns the current package state. None
DebianPackage. state( self , state: PackageState )
Set the package state to a given value.
Description
Args:
state: a PackageState
to reconcile the package to
Raises: PackageError from the underlying call to apt
DebianPackage. version( self )
Description
Returns the version for a package. None
DebianPackage. epoch( self )
Description
Returns the epoch for a package. May be unset. None
DebianPackage. arch( self )
Description
Returns the architecture for a package. None
DebianPackage. fullversion( self )
Description
Returns the name+epoch for a package. None
DebianPackage. from_system( cls , package: str , version , arch )
Locates a package, either on the system or known to apt, and serializes the information.
Arguments
a string representing the package
an optional string if a specific version is requested
an optional architecture, defaulting to dpkg --print-architecture
. If an
architecture is not specified, this will be used for selection.
DebianPackage. from_installed_package( cls , package: str , version , arch )
Check whether the package is already installed and return an instance.
Arguments
a string representing the package
an optional string if a specific version is requested
an optional architecture, defaulting to dpkg --print-architecture
.
If an architecture is not specified, this will be used for selection.
DebianPackage. from_apt_cache( cls , package: str , version , arch )
Check whether the package is already installed and return an instance.
Arguments
a string representing the package
an optional string if a specific version is requested
an optional architecture, defaulting to dpkg --print-architecture
.
If an architecture is not specified, this will be used for selection.
class Version
An abstraction around package versions.
Description
This seems like it should be strictly unnecessary, except that apt_pkg
is not usable inside a
venv, and wedging version comparisons into DebianPackage
would overcomplicate it.
This class implements the algorithm found here: https://www.debian.org/doc/debian-policy/ch-controlfields.html#version
Methods
Version. __init__( self , version: str , epoch: str )
Version. __repr__( self )
Description
Represent the package. None
Version. __str__( self )
Description
Return human-readable representation of the package. None
Version. epoch( self )
Description
Returns the epoch for a package. May be empty. None
Version. number( self )
Description
Returns the version number for a package. None
Version. __lt__( self , other )
Description
Less than magic method impl. None
Version. __eq__( self , other )
Description
Equality magic method impl. None
Version. __gt__( self , other )
Description
Greater than magic method impl. None
Version. __le__( self , other )
Description
Less than or equal to magic method impl. None
Version. __ge__( self , other )
Description
Greater than or equal to magic method impl. None
Version. __ne__( self , other )
Description
Not equal to magic method impl. None
def
add_package(
package_names,
version,
arch,
update_cache
)
Add a package or list of packages to the system.
Description
Args:
package_names: single package name, or list of package names
name: the name(s) of the package(s)
version: an (Optional) version as a string. Defaults to the latest known
arch: an optional architecture for the package
update_cache: whether or not to run apt-get update
prior to operating
Raises: TypeError if no package name is given, or explicit version is set for multiple packages PackageNotFoundError if the package is not in the cache. PackageError if packages fail to install
def remove_package(package_names)
Remove package(s) from the system.
Arguments
the name of a package
def update()
Description
Update the apt cache via apt-get update
. None
def import_key(key: str)
Import an ASCII Armor key.
Description
A Radix64 format keyid is also supported for backwards compatibility. In this case Ubuntu keyserver will be queried for a key via HTTPS by its keyid. This method is less preferable because https proxy servers may require traffic decryption which is equivalent to a man-in-the-middle attack (a proxy server impersonates keyserver TLS certificates and has to be explicitly trusted by the system).
Args: key: A GPG key in ASCII armor format, including BEGIN and END markers or a keyid.
Returns: The GPG key filename written.
Raises: GPGKeyError if the key could not be imported
class InvalidSourceError
Description
Exceptions for invalid source entries. None
class GPGKeyError
Description
Exceptions for GPG keys. None
class DebianRepository
Description
An abstraction to represent a repository. None
Methods
DebianRepository. __init__( self , enabled: bool , repotype: str , uri: str , release: str , groups , filename: str , gpg_key_filename: str , options )
DebianRepository. enabled( self )
Description
Return whether or not the repository is enabled. None
DebianRepository. repotype( self )
Description
Return whether it is binary or source. None
DebianRepository. uri( self )
Description
Return the URI. None
DebianRepository. release( self )
Description
Return which Debian/Ubuntu releases it is valid for. None
DebianRepository. groups( self )
Description
Return the enabled package groups. None
DebianRepository. filename( self )
Description
Returns the filename for a repository. None
DebianRepository. filename( self , fname: str )
Set the filename used when a repo is written back to disk.
Arguments
a filename to write the repository information to.
DebianRepository. gpg_key( self )
Description
Returns the path to the GPG key for this repository. None
DebianRepository. options( self )
Description
Returns any additional repo options which are set. None
DebianRepository. make_options_string( self , include_signed_by: bool )
Generate the complete one-line-style options string for a repository.
Description
Combining gpg_key
, if set (and include_signed_by is True), with any other
provided options to form the options section of a one-line-style definition.
DebianRepository. prefix_from_uri( uri: str )
Description
Get a repo list prefix from the uri, depending on whether a path is set. None
DebianRepository. from_repo_line( repo_line: str , write_file )
Instantiate a new DebianRepository
from a sources.list
entry line.
Arguments
a string representing a repository entry
boolean to enable writing the new repo to disk. True by default. Expect it to result in an add-apt-repository call under the hood, like: add-apt-repository --no-update --sourceslist="$repo_line"
DebianRepository. disable( self )
Remove this repository by disabling it in the source file.
Description
WARNING: This method does NOT alter the self.enabled
flag.
WARNING: disable is currently not implemented for repositories defined by a deb822 stanza. Raises a NotImplementedError in this case.
DebianRepository. import_key( self , key: str )
Import an ASCII Armor key.
Description
A Radix64 format keyid is also supported for backwards compatibility. In this case Ubuntu keyserver will be queried for a key via HTTPS by its keyid. This method is less preferable because https proxy servers may require traffic decryption which is equivalent to a man-in-the-middle attack (a proxy server impersonates keyserver TLS certificates and has to be explicitly trusted by the system).
Args: key: A GPG key in ASCII armor format, including BEGIN and END markers or a keyid.
Raises: GPGKeyError if the key could not be imported
class RepositoryMapping
An representation of known repositories.
Description
Instantiation of RepositoryMapping
will iterate through the
filesystem, parse out repository files in /etc/apt/...
, and create
DebianRepository
objects in this list.
Typical usage:
repositories = apt.RepositoryMapping()
repositories.add(DebianRepository(
enabled=True, repotype="deb", uri="https://example.com", release="focal",
groups=["universe"]
))
Methods
RepositoryMapping. __init__( self )
RepositoryMapping. __contains__( self , key: Any )
Magic method for checking presence of repo in mapping.
Description
Checks against the string names used to identify repositories.
RepositoryMapping. __len__( self )
Description
Return number of repositories in map. None
RepositoryMapping. __iter__( self )
Return iterator for RepositoryMapping.
Description
Iterates over the DebianRepository values rather than the string names. FIXME: this breaks the expectations of the Mapping abstract base class for example when it provides methods like keys and items
RepositoryMapping. __getitem__( self , repository_uri: str )
Description
Return a given DebianRepository
. None
RepositoryMapping. __setitem__( self , repository_uri: str , repository: DebianRepository )
Description
Add a DebianRepository
to the cache. None
RepositoryMapping. load_deb822( self , filename: str )
Load a deb822 format repository source file into the cache.
Description
In contrast to one-line-style, the deb822 format specifies a repository using a multi-line stanza. Stanzas are separated by whitespace, and each definition consists of lines that are either key: value pairs, or continuations of the previous value.
Read more about the deb822 format here: https://manpages.ubuntu.com/manpages/noble/en/man5/sources.list.5.html For instance, ubuntu 24.04 (noble) lists its sources using deb822 style in: /etc/apt/sources.list.d/ubuntu.sources
RepositoryMapping. load( self , filename: str )
Load a one-line-style format repository source file into the cache.
Arguments
the path to the repository file
RepositoryMapping. add( self , repo: DebianRepository , default_filename )
Add a new repository to the system using add-apt-repository.
Arguments
a DebianRepository object if repo.enabled is falsey, will return without adding the repository
RepositoryMapping. disable( self , repo: DebianRepository )
Remove a repository by disabling it in the source file.
Description
WARNING: disable is currently not implemented for repositories defined by a deb822 stanza, and will raise a NotImplementedError if called on one.
WARNING: This method does NOT alter the .enabled
flag on the DebianRepository.
class MissingRequiredKeyError
Description
Missing a required value in a source file. None
Methods
MissingRequiredKeyError. __init__( self , message: str )
class BadValueError
Description
Bad value for an entry in a source file. None
Methods
BadValueError. __init__( self , message: str )