From 0eca545d27f1d6f36c2dcb3a967b70cf94521e4b Mon Sep 17 00:00:00 2001 From: ejacques Date: Fri, 6 Dec 2024 14:25:51 -0500 Subject: [PATCH] allow resource names >2 parts Dynamic client discovery for resources with three part names, the processing fails. Allow for processing names with >2 parts. This was failing on an OpenShift environment with the resource 'virtualmachineinstances/sev/fetchcertchain' --- kubernetes_asyncio/dynamic/discovery.py | 3 +- kubernetes_asyncio/dynamic/discovery_test.py | 32 ++++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/kubernetes_asyncio/dynamic/discovery.py b/kubernetes_asyncio/dynamic/discovery.py index 740d5411e..ae616270c 100644 --- a/kubernetes_asyncio/dynamic/discovery.py +++ b/kubernetes_asyncio/dynamic/discovery.py @@ -189,7 +189,8 @@ async def get_resources_for_api_version(self, prefix, group, version, preferred) resources_raw = list(filter(lambda r: '/' not in r['name'], resources_response)) subresources_raw = list(filter(lambda r: '/' in r['name'], resources_response)) for subresource in subresources_raw: - resource, name = subresource['name'].split('/') + # Handle resources with >2 parts in their name + resource, name = subresource['name'].split('/', 1) if not subresources.get(resource): subresources[resource] = {} subresources[resource][name] = subresource diff --git a/kubernetes_asyncio/dynamic/discovery_test.py b/kubernetes_asyncio/dynamic/discovery_test.py index d360cb363..f86dc1d4e 100644 --- a/kubernetes_asyncio/dynamic/discovery_test.py +++ b/kubernetes_asyncio/dynamic/discovery_test.py @@ -14,9 +14,11 @@ import os import unittest +from unittest.mock import AsyncMock, MagicMock, patch from kubernetes_asyncio.client import api_client from kubernetes_asyncio.dynamic import DynamicClient +from kubernetes_asyncio.dynamic.discovery import Discoverer from kubernetes_asyncio.e2e_test import base @@ -56,7 +58,7 @@ async def test_cache_decoder_resource_and_subresource(self): deploy1 = await client.resources.get(kind='Deployment', api_version="apps/v1") # do Discoverer.__init__ - # async with api_client.ApiClient(configuration=self.config) as apic: + async with api_client.ApiClient(configuration=self.config) as apic: client2 = await DynamicClient(apic) # the resources of client will use _cache['resources'] decode from cache file deploy2 = await client2.resources.get(kind='Deployment', api_version="apps/v1") @@ -65,5 +67,29 @@ async def test_cache_decoder_resource_and_subresource(self): # test Resource is the same self.assertDictEqual(deploy1.to_dict(), deploy2.to_dict()) - # test Subresource is the same - self.assertDictEqual(deploy1.status.to_dict(), deploy2.status.to_dict()) + @patch('kubernetes_asyncio.dynamic.discovery.Discoverer.get_resources_for_api_version', new_callable=AsyncMock) + async def test_get_resources_for_api_version(self, mock_get_resources): + """Test case for get_resources_for_api_version""" + mock_get_resources.return_value = { + 'resources': [{'name': 'pods', 'kind': 'Pod'}], + 'subresources': { + 'virtualmachineinstances': { + 'sev/fetchcertchain': {'name': 'virtualmachineinstances/sev/fetchcertchain'} + } + } + } + + # Create a mock client with the necessary attributes + mock_client = MagicMock() + mock_client.configuration.host = "https://mock-host" + + discoverer = Discoverer(client=mock_client) + response = await discoverer.get_resources_for_api_version('api', 'v1', 'pods', True) + self.assertEqual(response['resources'][0]['name'], 'pods') + self.assertEqual(response['resources'][0]['kind'], 'Pod') + self.assertIn('virtualmachineinstances', response['subresources']) + self.assertIn('sev/fetchcertchain', response['subresources']['virtualmachineinstances']) + + +if __name__ == '__main__': + unittest.main()