Fix k8s client for handling empty list in response.

Implements: blueprint selflink
Change-Id: I0db851889017cfe19cc84acab36bdc67b04a9145
This commit is contained in:
Roman Dobosz 2021-01-08 17:25:03 +01:00
parent e69989c6e4
commit 9bc33d9b78
3 changed files with 36 additions and 1 deletions

View File

@ -133,12 +133,20 @@ class K8sClient(object):
# for custom resources there are both kind and apiVersion.. # for custom resources there are both kind and apiVersion..
if kind.endswith('List'): if kind.endswith('List'):
kind = kind[:-4] kind = kind[:-4]
# NOTE(gryf): In case we get null/None for items from the API,
# we need to convert it to the empty list, otherwise it might
# be propagated to the consumers of this method and sent back
# to the Kubernetes as is, and fail as a result.
if result['items'] is None:
result['items'] = []
for item in result['items']: for item in result['items']:
if not item.get('kind'): if not item.get('kind'):
item['kind'] = kind item['kind'] = kind
if not item.get('apiVersion'): if not item.get('apiVersion'):
item['apiVersion'] = api_version item['apiVersion'] = api_version
else:
if not result.get('apiVersion'): if not result.get('apiVersion'):
result['apiVersion'] = api_version result['apiVersion'] = api_version
else: else:

View File

@ -155,6 +155,27 @@ class TestK8sClient(test_base.TestCase):
self.assertRaises(exc.K8sClientException, self.client.get, path) self.assertRaises(exc.K8sClientException, self.client.get, path)
@mock.patch('requests.sessions.Session.get')
def test_get_null_on_items_list(self, m_get):
path = '/test'
req = {'kind': 'PodList',
'apiVersion': 'v1',
'metadata': {},
'items': None}
ret = {'kind': 'PodList',
'apiVersion': 'v1',
'metadata': {},
'items': []}
m_resp = mock.MagicMock()
m_resp.ok = True
m_resp.json.return_value = req
m_get.return_value = m_resp
self.assertEqual(self.client.get(path), ret)
@mock.patch('itertools.count') @mock.patch('itertools.count')
@mock.patch('requests.sessions.Session.patch') @mock.patch('requests.sessions.Session.patch')
def test_annotate(self, m_patch, m_count): def test_annotate(self, m_patch, m_count):

View File

@ -143,6 +143,12 @@ class Watcher(health.HealthHandler):
LOG.exception(f'Error getting path when reconciling.') LOG.exception(f'Error getting path when reconciling.')
return return
# NOTE(gryf): For some resources (like pods) we could observe that
# 'items' is set to None. I'm not sure if that's a K8s issue, since
# accroding to the documentation is should be list.
if not resources:
return
for resource in resources: for resource in resources:
event = { event = {
'type': 'MODIFIED', 'type': 'MODIFIED',