Closed hloeung closed 1 year ago
Hello, Haw,
Python dependency management across a wide set of Python versions and architectures is indeed a non-trivial activity.
The preferred method of building reactive charms is to use charmcraft and its bases support together with charm-tools.
This allows you to build multiple artifacts for the same charm and also define which one is suited to run on which versions of the target operating system. charmhub.io has gained the same capabilities and will allow Juju to select the correct charm. Launchpad charm recipes is also ready to help you build across the defined matrix of series and architectures.
When building with charmcraft dependency managements can be further enhanced by using the support for binary builds (#620), which allows pip's dependency resolution engine to work for python build dependencies.
As for your specific request:
I think
charm-tools
should bundle multiple versions of Python packages and let wheelhouse select the appropriate version to install. For example, layer-basic's wheelhouse.txt has the following:
To achieve this a single build instance would have to have multiple versions of python and its dependencies installed and would complicate a already complicated process. As laid out above, the path chosen is to build multiple artifacts using build/run bases and the infrastructure to support it in Launchpad and Charmhub.
So a charmcraft pack should bundle MarkupSafe 1.1.1, 2.0.1, and the latest, 2.1.1.
This would actually require layer-basic to work out which one to install, as it installs everything in the wheelhouse/
directory. Or there would need to be multiple wheelhouse/
directories, one for each python version.
It's actually just easier to build separate charms for each base (16.04, 18.04, 20.04, 22.04) and let the charmhub serve up the 'right' charm when juju requests a charm for a particular series. i.e. the latest/stable channel can have multiple revisions 'active' if they have different bases, which allows older bases to co-exist with newer ones. As @fnordahl mentioned, this is possible with charmcraft and the build-on, run-on sections in the bases
key. e.g. see https://opendev.org/openstack/charm-octavia/src/commit/a70543515682ccae99f64a46653bc9d6601083e5/charmcraft.yaml#L35 as an example.
As you noticed with layer-basic, it is possible to have a wheelhouse.txt that declares different module versions for different python versions, and then using bases to build the charm on different Ubuntu versions for the different versions. e.g. Xenial, is py35, bionic is py36, focal is py38, and jammy is py310.
In wheelhouse.txt:
some_module < 1; python_version == '3.5' # xenial
some_module < 2; python_version == '3.6' # bionic
some_module < 3; python_version == '3.8' # focal
some_module < 4; python_version >= '3.10' # jammy and later
If using a build.lock
file, leave those modules out of the build.lock
.
However, I would recommend that you split your repository into separate branches and have different build recipes for xenial, etc. The use the launchpad recipes to build multiple charms with charmcraft, one for each series, using the reactive plugin and push to the relevant channel(s). As the charms would have different bases they could all push to latest/stable.
Trying to get a single source that can build against all the different versions of python (particularly as python 3.5 and 3.6 are now deprecated, which means that modules are dropping support for them) will probably be more of a maintenance burden, particularly when the older versions of the charms are less likely to require changes.
Checklist
What version am I running?
I ran the following command:
snap info charm
and got the following ouput:I am using: Ubuntu 22.10
Issue/Feature
We need to support various versions of Ubuntu in some of our charms. For instance, the autocert charm (https://charmhub.io/autocert-charmers-autocert) needs to support Jammy all the way back to Xenial.
Unfortunately, building the charms as is results in failures to execute on older series/releases. Pinning via wheelhouse.txt works for some series but still breaks on others. This is a reactive charm and uses layer-basic which now has more complicated pinning, see https://github.com/juju-solutions/layer-basic/commit/fb767dcf0786d1d5364199bb3b40bdc86518b45b
I think
charm-tools
should bundle multiple versions of Python packages and let wheelhouse select the appropriate version to install. For example, layer-basic's wheelhouse.txt has the following:So a
charmcraft pack
should bundle MarkupSafe 1.1.1, 2.0.1, and the latest, 2.1.1.I expect/expected the following
juju upgrade-charm
and all units should successfully execute their hooks.What I got
juju upgrade-charm
on various deployed autocert applications (because https://bugs.launchpad.net/juju/+bug/1992881), one for each series and we get all kinds of Python dependency issues resulting in failure to run charm hooks.