Merge "Remove ep_slices from klb on endpoint delete event"

This commit is contained in:
Zuul 2021-08-16 11:32:59 +00:00 committed by Gerrit Code Review
commit f4606db47e
4 changed files with 143 additions and 0 deletions

View File

@ -332,6 +332,9 @@ class EndpointsHandler(k8s_base.ResourceEventHandler):
else:
self._update_crd_spec(loadbalancer_crd, endpoints)
def on_deleted(self, endpoints, *args, **kwargs):
self._remove_endpoints(endpoints)
def _has_pods(self, endpoints):
ep_subsets = endpoints.get('subsets', [])
if not ep_subsets:
@ -431,3 +434,19 @@ class EndpointsHandler(k8s_base.ResourceEventHandler):
raise
return True
def _remove_endpoints(self, endpoints):
kubernetes = clients.get_kubernetes_client()
lb_name = endpoints['metadata']['name']
try:
kubernetes.patch_crd('spec',
utils.get_klb_crd_path(endpoints),
'endpointSlices',
action='remove')
except k_exc.K8sResourceNotFound:
LOG.debug('KuryrLoadBalancer CRD not found %s', lb_name)
except k_exc.K8sUnprocessableEntity:
LOG.warning('KuryrLoadBalancer %s modified, ignoring.', lb_name)
except k_exc.K8sClientException:
LOG.exception('Error updating KuryrLoadBalancer CRD %s', lb_name)
raise

View File

@ -13,12 +13,14 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
from unittest import mock
import os_vif.objects.network as osv_network
import os_vif.objects.subnet as osv_subnet
from kuryr_kubernetes.controller.handlers import lbaas as h_lbaas
from kuryr_kubernetes import exceptions as k_exc
from kuryr_kubernetes.tests import base as test_base
_SUPPORTED_LISTENER_PROT = ('HTTP', 'HTTPS', 'TCP')
@ -362,3 +364,105 @@ class TestServiceHandler(test_base.TestCase):
def test_get_lbaas_spec(self):
self.skipTest("skipping until generalised annotation handling is "
"implemented")
class TestEndpointsHandler(test_base.TestCase):
def setUp(self):
super().setUp()
self._ep_name = 'my-service'
self._ep_namespace = mock.sentinel.namespace
self._ep_ip = '1.2.3.4'
self._ep = {
"kind": "Endpoints",
"apiVersion": "v1",
"metadata": {
"name": self._ep_name,
"namespace": self._ep_namespace,
},
"subsets": [
{
"addresses": [
{
"ip": self._ep_ip
},
],
"ports": [
{
"port": 8080,
"protocol": "TCP"
}
]
}
]
}
self._klb_name = 'my-service'
self._klb_ip = '1.1.1.1'
self._klb = {
'apiVersion': 'openstack.org/v1',
'kind': 'KuryrLoadBalancer',
'metadata': {
'name': self._klb_name,
'finalizers': [''],
},
'spec': {
'ip': self._klb_ip
}
}
def test_on_deleted(self):
m_handler = mock.Mock(spec=h_lbaas.EndpointsHandler)
h_lbaas.EndpointsHandler.on_deleted(m_handler, self._ep)
m_handler._remove_endpoints.assert_called_once_with(self._ep)
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
@mock.patch('kuryr_kubernetes.utils.get_klb_crd_path')
def test__remove_endpoints(self, get_klb_crd_path, get_k8s_client):
k8s = mock.Mock()
get_k8s_client.return_value = k8s
h_lbaas.EndpointsHandler._remove_endpoints(self, self._ep)
k8s.patch_crd.assert_called_once_with('spec',
get_klb_crd_path(self._ep),
'endpointSlices',
action='remove')
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
@mock.patch.object(logging.getLogger(
'kuryr_kubernetes.controller.handlers.lbaas'),
'debug')
def test__remove_endpoints_not_found(self, get_k8s_client, log):
k8s = mock.Mock()
get_k8s_client.return_value = k8s
h_lbaas.EndpointsHandler._remove_endpoints(self, self._ep)
k8s.patch_crd.side_effect = k_exc.K8sResourceNotFound(self._ep)
log.assert_called_once()
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
def test__remove_endpoints_client_exception(self, get_k8s_client):
k8s = mock.Mock()
get_k8s_client.return_value = k8s
h_lbaas.EndpointsHandler._remove_endpoints(self, self._ep)
k8s.patch_crd.side_effect = k_exc.K8sClientException(self._ep)
self.assertRaises(k_exc.K8sClientException,
h_lbaas.EndpointsHandler._remove_endpoints,
self, self._ep)
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
@mock.patch.object(logging.getLogger(
'kuryr_kubernetes.controller.handlers.lbaas'),
'warning')
def test__remove_endpoints_unprocessable_entity(self, get_k8s_client, log):
k8s = mock.Mock()
get_k8s_client.return_value = k8s
h_lbaas.EndpointsHandler._remove_endpoints(self, self._ep)
k8s.patch_crd.side_effect = k_exc.K8sUnprocessableEntity(self._ep)
log.assert_called_once()

View File

@ -395,6 +395,15 @@ class TestUtils(test_base.TestCase):
target, ('10.0.1.208', 'test', 8080,
'4472fab1-f01c-46a7-b197-5cba4f2d7135'))
def test_get_klb_crd_path(self):
res = {'apiVersion': 'v1',
'kind': 'Endpoints',
'metadata': {'name': 'my-service',
'namespace': 'default'}}
self.assertEqual(utils.get_klb_crd_path(res),
'/apis/openstack.org/v1/namespaces/default/'
'kuryrloadbalancers/my-service')
def test_get_res_link_core_res(self):
res = {'apiVersion': 'v1',
'kind': 'Pod',

View File

@ -89,6 +89,17 @@ RESOURCE_MAP = {'Endpoints': 'endpoints',
API_RE = re.compile(r'v\d+')
def get_klb_crd_path(obj):
"""Return klb crd path from provided resource"""
namespace = obj['metadata']['namespace']
lb_name = obj['metadata']['name']
return (f"{constants.K8S_API_CRD_NAMESPACES}/"
f"{namespace}/"
f"kuryrloadbalancers/"
f"{lb_name}")
def get_res_link(obj):
"""Return selfLink equivalent for provided resource"""
# First try, if we still have it