Merge "Added function for figure out link for the resource."
This commit is contained in:
commit
c86332c915
|
@ -116,7 +116,34 @@ class K8sClient(object):
|
|||
url = self._base_url + path
|
||||
response = self.session.get(url, headers=headers)
|
||||
self._raise_from_response(response)
|
||||
result = response.json() if json else response.text
|
||||
|
||||
if json:
|
||||
result = response.json()
|
||||
kind = result['kind']
|
||||
|
||||
api_version = result.get('apiVersion')
|
||||
if not api_version:
|
||||
api_version = utils.get_api_ver(path)
|
||||
|
||||
# Strip List from e.g. PodList. For some reason `.items` of a list
|
||||
# returned from API doesn't have `kind` set.
|
||||
# NOTE(gryf): Also, for the sake of calculating selfLink
|
||||
# equivalent, we need to have both: kind and apiVersion, while the
|
||||
# latter is not present on items list for core resources, while
|
||||
# for custom resources there are both kind and apiVersion..
|
||||
if kind.endswith('List'):
|
||||
kind = kind[:-4]
|
||||
for item in result['items']:
|
||||
if not item.get('kind'):
|
||||
item['kind'] = kind
|
||||
if not item.get('apiVersion'):
|
||||
item['apiVersion'] = api_version
|
||||
else:
|
||||
if not result.get('apiVersion'):
|
||||
result['apiVersion'] = api_version
|
||||
else:
|
||||
result = response.text
|
||||
|
||||
return result
|
||||
|
||||
def _get_url_and_header(self, path, content_type):
|
||||
|
|
|
@ -111,7 +111,7 @@ class TestK8sClient(test_base.TestCase):
|
|||
@mock.patch('requests.sessions.Session.get')
|
||||
def test_get(self, m_get):
|
||||
path = '/test'
|
||||
ret = {'test': 'value'}
|
||||
ret = {'kind': 'Pod', 'apiVersion': 'v1'}
|
||||
|
||||
m_resp = mock.MagicMock()
|
||||
m_resp.ok = True
|
||||
|
@ -121,6 +121,30 @@ class TestK8sClient(test_base.TestCase):
|
|||
self.assertEqual(ret, self.client.get(path))
|
||||
m_get.assert_called_once_with(self.base_url + path, headers=None)
|
||||
|
||||
@mock.patch('requests.sessions.Session.get')
|
||||
def test_get_list(self, m_get):
|
||||
path = '/test'
|
||||
ret = {'kind': 'PodList',
|
||||
'apiVersion': 'v1',
|
||||
'items': [{'metadata': {'name': 'pod1'},
|
||||
'spec': {},
|
||||
'status': {}}]}
|
||||
res = {'kind': 'PodList',
|
||||
'apiVersion': 'v1',
|
||||
'items': [{'metadata': {'name': 'pod1'},
|
||||
'spec': {},
|
||||
'status': {},
|
||||
'kind': 'Pod',
|
||||
'apiVersion': 'v1'}]}
|
||||
|
||||
m_resp = mock.MagicMock()
|
||||
m_resp.ok = True
|
||||
m_resp.json.return_value = ret
|
||||
m_get.return_value = m_resp
|
||||
|
||||
self.assertDictEqual(res, self.client.get(path))
|
||||
m_get.assert_called_once_with(self.base_url + path, headers=None)
|
||||
|
||||
@mock.patch('requests.sessions.Session.get')
|
||||
def test_get_exception(self, m_get):
|
||||
path = '/test'
|
||||
|
|
|
@ -375,3 +375,66 @@ class TestUtils(test_base.TestCase):
|
|||
self.assertEqual(
|
||||
target, ('10.0.1.208', 'test', 8080,
|
||||
'4472fab1-f01c-46a7-b197-5cba4f2d7135'))
|
||||
|
||||
def test_get_res_link_core_res(self):
|
||||
res = {'apiVersion': 'v1',
|
||||
'kind': 'Pod',
|
||||
'metadata': {'name': 'pod-1',
|
||||
'namespace': 'default'}}
|
||||
self.assertEqual(utils.get_res_link(res),
|
||||
'/api/v1/namespaces/default/pods/pod-1')
|
||||
|
||||
def test_get_res_link_no_existent(self):
|
||||
res = {'apiVersion': 'customapi/v1',
|
||||
'kind': 'ItsATrap!',
|
||||
'metadata': {'name': 'pod-1',
|
||||
'namespace': 'default'}}
|
||||
self.assertRaises(KeyError, utils.get_res_link, res)
|
||||
|
||||
def test_get_res_link_beta_res(self):
|
||||
res = {'apiVersion': 'networking.k8s.io/v2beta2',
|
||||
'kind': 'NetworkPolicy',
|
||||
'metadata': {'name': 'np-1',
|
||||
'namespace': 'default'}}
|
||||
self.assertEqual(utils.get_res_link(res), '/apis/networking.k8s.io/'
|
||||
'v2beta2/namespaces/default/networkpolicies/np-1')
|
||||
|
||||
def test_get_res_link_no_namespace(self):
|
||||
res = {'apiVersion': 'v1',
|
||||
'kind': 'Namespace',
|
||||
'metadata': {'name': 'ns-1'}}
|
||||
|
||||
self.assertEqual(utils.get_res_link(res), '/api/v1/namespaces/ns-1')
|
||||
|
||||
def test_get_res_link_custom_api(self):
|
||||
res = {'apiVersion': 'openstack.org/v1',
|
||||
'kind': 'KuryrPort',
|
||||
'metadata': {'name': 'kp-1',
|
||||
'namespace': 'default'}}
|
||||
|
||||
self.assertEqual(utils.get_res_link(res),
|
||||
'/apis/openstack.org/v1/namespaces/default/'
|
||||
'kuryrports/kp-1')
|
||||
|
||||
def test_get_res_link_no_apiversion(self):
|
||||
res = {'kind': 'KuryrPort',
|
||||
'metadata': {'name': 'kp-1',
|
||||
'namespace': 'default'}}
|
||||
self.assertRaises(KeyError, utils.get_res_link, res)
|
||||
|
||||
def test_get_api_ver_core_api(self):
|
||||
path = '/api/v1/namespaces/default/pods/pod-123'
|
||||
self.assertEqual(utils.get_api_ver(path), 'v1')
|
||||
|
||||
def test_get_api_ver_custom_resource(self):
|
||||
path = '/apis/openstack.org/v1/namespaces/default/kuryrport/pod-123'
|
||||
self.assertEqual(utils.get_api_ver(path), 'openstack.org/v1')
|
||||
|
||||
def test_get_api_ver_random_path(self):
|
||||
path = '/?search=foo'
|
||||
self.assertRaises(ValueError, utils.get_api_ver, path)
|
||||
|
||||
def test_get_res_selflink_still_available(self):
|
||||
res = {'metadata': {'selfLink': '/foo'}}
|
||||
|
||||
self.assertEqual(utils.get_res_link(res), '/foo')
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
import ipaddress
|
||||
import random
|
||||
import re
|
||||
import socket
|
||||
import time
|
||||
|
||||
|
@ -72,6 +73,70 @@ MEMOIZE_NODE = cache.get_memoization_decorator(
|
|||
CONF, nodes_cache_region, "nodes_caching")
|
||||
cache.configure_cache_region(CONF, nodes_cache_region)
|
||||
|
||||
RESOURCE_MAP = {'Endpoints': 'endpoints',
|
||||
'KuryrLoadBalancer': 'kuryrloadbalancers',
|
||||
'KuryrPort': 'kuryrports',
|
||||
'KuryrNetworkPolicy': 'kuryrnetworkpolicies',
|
||||
'KuryrNetwork': 'kuryrnetworks',
|
||||
'Namespace': 'namespaces',
|
||||
'NetworkPolicy': 'networkpolicies',
|
||||
'Node': 'nodes',
|
||||
'Pod': 'pods',
|
||||
'Service': 'services'}
|
||||
API_RE = re.compile(r'v\d+')
|
||||
|
||||
|
||||
def get_res_link(obj):
|
||||
"""Return selfLink equivalent for provided resource"""
|
||||
# First try, if we still have it
|
||||
try:
|
||||
return obj['metadata']['selfLink']
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# If not, let's proceed with the path assembling.
|
||||
try:
|
||||
res_type = RESOURCE_MAP[obj['kind']]
|
||||
except KeyError:
|
||||
LOG.error('Unknown resource kind: %s', obj.get('kind'))
|
||||
raise
|
||||
|
||||
namespace = ''
|
||||
if obj['metadata'].get('namespace'):
|
||||
namespace = f"/namespaces/{obj['metadata']['namespace']}"
|
||||
|
||||
try:
|
||||
api = f"/apis/{obj['apiVersion']}"
|
||||
if API_RE.match(obj['apiVersion']):
|
||||
api = f"/api/{obj['apiVersion']}"
|
||||
except KeyError:
|
||||
LOG.error("Object doesn't have an apiVersion available: %s", obj)
|
||||
raise
|
||||
|
||||
return f"{api}{namespace}/{res_type}/{obj['metadata']['name']}"
|
||||
|
||||
|
||||
def get_api_ver(path):
|
||||
"""Get apiVersion out of resource path.
|
||||
|
||||
Path usually is something simillar to:
|
||||
|
||||
/api/v1/namespaces/default/pods/pod-5bb648d658-55n76
|
||||
|
||||
in case of core resources, and:
|
||||
|
||||
/apis/openstack.org/v1/namespaces/default/kuryrloadbalancers/lb-324
|
||||
|
||||
in case of custom resoures.
|
||||
"""
|
||||
if path.startswith('/api/'):
|
||||
return path.split('/')[2]
|
||||
|
||||
if path.startswith('/apis/'):
|
||||
return '/'.join(path.split('/')[2:4])
|
||||
|
||||
raise ValueError('Provided path is not Kubernetes api path: %s', path)
|
||||
|
||||
|
||||
def utf8_json_decoder(byte_data):
|
||||
"""Deserializes the bytes into UTF-8 encoded JSON.
|
||||
|
|
|
@ -16,12 +16,13 @@
|
|||
import sys
|
||||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from kuryr_kubernetes import clients
|
||||
from kuryr_kubernetes import exceptions
|
||||
from kuryr_kubernetes.handlers import health
|
||||
from kuryr_kubernetes import utils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
@ -143,13 +144,6 @@ class Watcher(health.HealthHandler):
|
|||
return
|
||||
|
||||
for resource in resources:
|
||||
kind = response['kind']
|
||||
# Strip List from e.g. PodList. For some reason `.items` of a list
|
||||
# returned from API doesn't have `kind` set.
|
||||
if kind.endswith('List'):
|
||||
kind = kind[:-4]
|
||||
resource['kind'] = kind
|
||||
|
||||
event = {
|
||||
'type': 'MODIFIED',
|
||||
'object': resource,
|
||||
|
|
Loading…
Reference in New Issue