From b2eccdcb1ab079e3e43b436907dfce4532b76e07 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 14 Feb 2025 12:31:58 +0000 Subject: [PATCH] Permit use of tuple API_VERSIONS The values of these dictionaries are not used when SDK is in use, which should soon account for all use cases. Eventually we should probably look for plugins to return a proper class or typeddict but that's a job for another day. This began as a fix for in openstackclient/object/client.py which referenced a non-existent class and quickly snowballed. Change-Id: I7b807ec3a97124b35828ffdecbb36f6fde11e7b5 Signed-off-by: Stephen Finucane --- openstackclient/compute/client.py | 7 ++----- openstackclient/identity/client.py | 3 +-- openstackclient/image/client.py | 7 ++----- openstackclient/network/client.py | 10 +++------- openstackclient/object/client.py | 5 ++--- openstackclient/shell.py | 27 ++++++++++++++++++++++----- 6 files changed, 32 insertions(+), 27 deletions(-) diff --git a/openstackclient/compute/client.py b/openstackclient/compute/client.py index 23979ec7f3..74979bef36 100644 --- a/openstackclient/compute/client.py +++ b/openstackclient/compute/client.py @@ -11,7 +11,6 @@ # 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 logging @@ -21,13 +20,11 @@ from openstackclient.i18n import _ LOG = logging.getLogger(__name__) +# global variables used when building the shell DEFAULT_API_VERSION = '2.1' API_VERSION_OPTION = 'os_compute_api_version' API_NAME = 'compute' -API_VERSIONS = { - '2': 'openstack.connection.Connection', - '2.1': 'openstack.connection.Connection', -} +API_VERSIONS = ('2', '2.1') def make_client(instance): diff --git a/openstackclient/identity/client.py b/openstackclient/identity/client.py index 013c599da0..707112cd05 100644 --- a/openstackclient/identity/client.py +++ b/openstackclient/identity/client.py @@ -11,7 +11,6 @@ # 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 logging @@ -20,9 +19,9 @@ from osc_lib import utils from openstackclient.i18n import _ - LOG = logging.getLogger(__name__) +# global variables used when building the shell DEFAULT_API_VERSION = '3' API_VERSION_OPTION = 'os_identity_api_version' API_NAME = 'identity' diff --git a/openstackclient/image/client.py b/openstackclient/image/client.py index d5ee52b35e..69a08d82f2 100644 --- a/openstackclient/image/client.py +++ b/openstackclient/image/client.py @@ -11,7 +11,6 @@ # 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 logging @@ -21,13 +20,11 @@ from openstackclient.i18n import _ LOG = logging.getLogger(__name__) +# global variables used when building the shell DEFAULT_API_VERSION = '2' API_VERSION_OPTION = 'os_image_api_version' API_NAME = 'image' -API_VERSIONS = { - '1': 'openstack.connection.Connection', - '2': 'openstack.connection.Connection', -} +API_VERSIONS = ('1', '2') def make_client(instance): diff --git a/openstackclient/network/client.py b/openstackclient/network/client.py index 1970ab7a85..faaa54e2b1 100644 --- a/openstackclient/network/client.py +++ b/openstackclient/network/client.py @@ -9,7 +9,6 @@ # 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 logging @@ -17,16 +16,13 @@ from osc_lib import utils from openstackclient.i18n import _ - LOG = logging.getLogger(__name__) +# global variables used when building the shell DEFAULT_API_VERSION = '2.0' API_VERSION_OPTION = 'os_network_api_version' -API_NAME = "network" -API_VERSIONS = { - "2.0": "openstack.connection.Connection", - "2": "openstack.connection.Connection", -} +API_NAME = 'network' +API_VERSIONS = ('2.0', '2') def make_client(instance): diff --git a/openstackclient/object/client.py b/openstackclient/object/client.py index 9eb7ad7baa..466f132ec2 100644 --- a/openstackclient/object/client.py +++ b/openstackclient/object/client.py @@ -19,12 +19,11 @@ from osc_lib import utils from openstackclient.api import object_store_v1 +# global variables used when building the shell DEFAULT_API_VERSION = '1' API_VERSION_OPTION = 'os_object_api_version' API_NAME = 'object_store' -API_VERSIONS = { - '1': 'openstackclient.object.client.ObjectClientv1', -} +API_VERSIONS = ('1',) def make_client(instance): diff --git a/openstackclient/shell.py b/openstackclient/shell.py index df60d3c073..50a767ec35 100644 --- a/openstackclient/shell.py +++ b/openstackclient/shell.py @@ -88,17 +88,34 @@ class OpenStackShell(shell.OpenStackShell): # this throws an exception if invalid skip_old_check = mod_check_api_version(version_opt) + # NOTE(stephenfin): API_VERSIONS has traditionally been a + # dictionary but the values are only used internally and are + # ignored for the modules using SDK. So we now support tuples + # instead. mod_versions = getattr(mod, 'API_VERSIONS', None) - if not skip_old_check and mod_versions: + if mod_versions is not None and not isinstance( + mod_versions, (dict, tuple) + ): + raise TypeError( + f'Plugin {mod} has incompatible API_VERSIONS. ' + f'Expected: tuple, dict. Got: {type(mod_versions)}. ' + f'Please report this to your package maintainer.' + ) + + if mod_versions and not skip_old_check: if version_opt not in mod_versions: sorted_versions = sorted( - mod.API_VERSIONS.keys(), + list(mod.API_VERSIONS), key=lambda s: list(map(int, s.split('.'))), ) self.log.warning( - "{} version {} is not in supported versions: {}".format( - api, version_opt, ', '.join(sorted_versions) - ) + "%(name)s API version %(version)s is not in " + "supported versions: %(supported)s", + { + 'name': api, + 'version': version_opt, + 'supported': ', '.join(sorted_versions), + }, ) # Command groups deal only with major versions