From 1720c6c8c6641a7f6c95121928ed240dad2552bf Mon Sep 17 00:00:00 2001 From: Frode Nordahl Date: Thu, 7 Dec 2023 15:41:06 +0100 Subject: [PATCH] utilities: Convert juju base into Ubuntu series Juju 3.x replaced the `series` status key with a `base` key that consists of Distribution type and version number. To avoid maintenance burden we add a Launchpad module that implements functions to look up available Ubuntu series data. Update the `get_machine_series` helper function to determine Ubuntu series from `base` when no `series` key is available. Signed-off-by: Frode Nordahl --- zaza/utilities/juju.py | 19 ++++++++++++-- zaza/utilities/launchpad.py | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 zaza/utilities/launchpad.py diff --git a/zaza/utilities/juju.py b/zaza/utilities/juju.py index d0ef1c54d..e11b4a8a8 100644 --- a/zaza/utilities/juju.py +++ b/zaza/utilities/juju.py @@ -279,11 +279,26 @@ def get_machine_series(machine, model_name=None): :returns: Juju series :rtype: string """ - return get_machine_status( + status = get_machine_status( machine=machine, - key='series', model_name=model_name ) + try: + if 'series' in status: + return status.get('series') + except KeyError: + # libjuju will raise make the above check return KeyError when not + # present... + pass + + distro, version = status.get('base', '@').split('@') + if not distro: + raise ValueError("Unable to determine distro from status: '{}'" + .format(status)) + if distro != 'ubuntu': + raise NotImplementedError("Series resolution not implemented for " + "distro: '{}'".format(distro)) + return get_ubuntu_series_by_version()[version]['name'] def get_machine_uuids_for_application(application, model_name=None): diff --git a/zaza/utilities/launchpad.py b/zaza/utilities/launchpad.py new file mode 100644 index 000000000..c0336c0fd --- /dev/null +++ b/zaza/utilities/launchpad.py @@ -0,0 +1,50 @@ +# Copyright 2023 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import requests +import typing + + +def get_ubuntu_series() -> typing.Dict[str,typing.List[typing.Dict[str,any]]]: + """Contact Launchpad API and retrieve a list of all Ubuntu releases. + + Launchpad documentation for the returned data structure can be found here: + https://launchpad.net/+apidoc/devel.html#distribution + https://launchpad.net/+apidoc/devel.html#distro_series + """ + r = requests.get('https://api.launchpad.net/devel/ubuntu/series') + return json.loads(r.text) + + +def get_ubuntu_series_by_version() -> typing.Dict[str,typing.Dict[str,any]]: + """Get a Dict of distro series information indexed by version number. + + Please refer to the `get_ubuntu_series()` function docstring for docs. + """ + return { + entry['version']: entry + for entry in get_ubuntu_series().get('entries', {}) + } + + +def get_ubuntu_series_by_name() -> typing.Dict[str,typing.Dict[str,any]]: + """Get a Dict of distro series information indexed by version name. + + Please refer to the `get_ubuntu_series()` function docstring for docs. + """ + return { + entry['name']: entry + for entry in get_ubuntu_series().get('entries', {}) + }