Working with charm libraries
Charm libraries are special Python modules used in charmed operators deployed by Juju. They are an easy way to distribute reusable code without needing to involve any particular package build system. Fundamentally, charm libraries are used to provide a means for charm developers to make the implementation of any relation they define as simple as possible for other charm developers.
Note
Comphrensive documentation on how to write/develop/use charm libraries are beyond the scope of this documentation. If you are interested in learning more about charm libraries, please refer to their official documentation here: https://juju.is/docs/sdk/libraries
Charmlib class
Charmlib
is a package metaclass that represents the charm library installation command charmcraft fetch-lib.
Its constructor accepts two arguments:
auth_token_path (str)
: File path to a Charmhub authentication token. This token is needed to download charm libraries from charmhub.io.charmlibs (List[str])
: List of charm libraries to install inside the test environment instance.
Charm libraries are not installed a special directory such as site-packages or dist-packages; they are directly
installed to a lib/ directory under your current working directory. Therefore, the Charmlib
class modifies the
PYTHONPATH environment variable to inform the Python interpreter that there are importable modules under lib/.
Example usage
First, you need to create a Charmhub authentication token. This can be accomplished by using the following command in your shell:
After authenticating with Charmhub (you may need to create an Ubuntu One account), you can now use the example test script below:
#!/usr/bin/env python3
"""Example usage of Charmlib package metaclass."""
import os
import pathlib
from cleantest.control import Configure
from cleantest.control.hooks import StartEnvHook
from cleantest.data.pkg import Charmlib
from cleantest.provider import lxd
@lxd(image="ubuntu-jammy-amd64", preserve=False)
def install_snapd():
import sys
import charms.operator_libs_linux.v0.apt as apt
try:
apt.update()
apt.add_package("snapd")
print("snapd installed.", file=sys.stdout)
except apt.PackageNotFoundError:
print("Package could not be found in cache or system.", file=sys.stderr)
sys.exit(1)
except apt.PackageError as e:
print(f"Could not install package. Reason: {e}", file=sys.stderr)
sys.exit(1)
try:
snapd = apt.DebianPackage.from_installed_package("snapd")
print(f"snapd version {snapd.fullversion} is installed.", file=sys.stdout)
except apt.PackageNotFoundError:
print("Snapd failed to install.", file=sys.stderr)
sys.exit(1)
sys.exit(0)
def test_local_lxd(clean_slate) -> None:
root = pathlib.Path(os.path.dirname(os.path.realpath(__file__)))
config = Configure("lxd")
start_hook = StartEnvHook(
name="setup_deps",
packages=[
Charmlib(
auth_token_path=root / "charmhub.secret",
charmlibs=["charms.operator_libs_linux.v0.apt"],
),
],
)
config.register_hook(start_hook)
for name, result in install_snapd():
assert result.exit_code == 0