Merge "Add finalizer for the pod as soon as possible."

This commit is contained in:
Zuul 2020-08-11 16:07:33 +00:00 committed by Gerrit Code Review
commit 31770d7ada
4 changed files with 76 additions and 11 deletions

View File

@ -63,6 +63,12 @@ class VIFHandler(k8s_base.ResourceEventHandler):
drivers.ServiceSecurityGroupsDriver.get_instance())
def on_present(self, pod):
# NOTE(gryf): Set the finalizer as soon, as we have pod created. On
# subsequent updates of the pod, add_finalizer will ignore this if
# finalizer exists.
k8s = clients.get_kubernetes_client()
k8s.add_finalizer(pod, constants.POD_FINALIZER)
if self._move_annotations_to_crd(pod):
return
@ -88,14 +94,15 @@ class VIFHandler(k8s_base.ResourceEventHandler):
if not kp:
try:
self._add_kuryrport_crd(pod)
except k_exc.K8sNamespaceTerminating:
# The underlying namespace is being terminated, we can
# ignore this and let `on_finalize` handle this now.
return
except k_exc.K8sClientException as ex:
LOG.exception("Kubernetes Client Exception creating "
"KuryrPort CRD: %s", ex)
raise k_exc.ResourceNotReady(pod)
k8s = clients.get_kubernetes_client()
k8s.add_finalizer(pod, constants.POD_FINALIZER)
def on_finalize(self, pod):
k8s = clients.get_kubernetes_client()
try:
@ -193,6 +200,11 @@ class VIFHandler(k8s_base.ResourceEventHandler):
try:
self._add_kuryrport_crd(pod, vifs)
except k_exc.K8sNamespaceTerminating:
# The underlying namespace is being terminated, we can
# ignore this and let `on_finalize` handle this now. Still
# returning True to make sure `on_present` won't continue.
return True
except k_exc.K8sClientException as ex:
LOG.exception("Kubernetes Client Exception recreating "
"KuryrPort CRD from annotation: %s", ex)

View File

@ -39,6 +39,19 @@ class K8sConflict(K8sClientException):
super(K8sConflict, self).__init__("Conflict: %r" % message)
class K8sForbidden(K8sClientException):
def __init__(self, message):
super(K8sForbidden, self).__init__("Forbidden: %r" % message)
class K8sNamespaceTerminating(K8sForbidden):
# This is raised when K8s complains about operation failing because
# namespace is being terminated.
def __init__(self, message):
super(K8sNamespaceTerminating, self).__init__(
"Namespace already terminated: %r" % message)
class InvalidKuryrNetworkAnnotation(Exception):
pass

View File

@ -83,6 +83,10 @@ class K8sClient(object):
raise exc.K8sResourceNotFound(response.text)
if response.status_code == requests.codes.conflict:
raise exc.K8sConflict(response.text)
if response.status_code == requests.codes.forbidden:
if 'because it is being terminated' in response.json()['message']:
raise exc.K8sNamespaceTerminating(response.text)
raise exc.K8sForbidden(response.text)
if not response.ok:
raise exc.K8sClientException(response.text)

View File

@ -168,59 +168,83 @@ class TestVIFHandler(test_base.TestCase):
self.assertTrue(h_vif.VIFHandler._is_pod_completed({'status': {'phase':
k_const.K8S_POD_STATUS_FAILED}}))
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.is_host_network')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_kuryrport')
def test_on_present_host_network(self, m_get_kuryrport, m_host_network):
def test_on_present_host_network(self, m_get_kuryrport, m_host_network,
m_get_k8s_client):
m_get_kuryrport.return_value = self._kp
m_host_network.return_value = True
self._matc.return_value = False
k8s = mock.MagicMock()
m_get_k8s_client.return_value = k8s
h_vif.VIFHandler.on_present(self._handler, self._pod)
k8s.add_finalizer.assert_called_once_with(self._pod,
k_const.POD_FINALIZER)
self._matc.assert_called_once_with(self._pod)
m_get_kuryrport.assert_called_once()
self._request_vif.assert_not_called()
self._request_additional_vifs.assert_not_called()
self._activate_vif.assert_not_called()
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.is_host_network')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_kuryrport')
def test_on_present_not_pending(self, m_get_kuryrport, m_host_network):
def test_on_present_not_pending(self, m_get_kuryrport, m_host_network,
m_get_k8s_client):
m_get_kuryrport.return_value = self._kp
m_host_network.return_value = False
self._is_pod_scheduled.return_value = False
self._matc.return_value = False
k8s = mock.MagicMock()
m_get_k8s_client.return_value = k8s
h_vif.VIFHandler.on_present(self._handler, self._pod)
k8s.add_finalizer.assert_called_once_with(self._pod,
k_const.POD_FINALIZER)
self._matc.assert_called_once_with(self._pod)
m_get_kuryrport.assert_called_once()
self._request_vif.assert_not_called()
self._request_additional_vifs.assert_not_called()
self._activate_vif.assert_not_called()
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_kuryrport')
def test_on_present_on_completed_with_annotation(self, m_get_kuryrport):
def test_on_present_on_completed_with_annotation(self, m_get_kuryrport,
m_get_k8s_client):
self._is_pod_completed.return_value = True
m_get_kuryrport.return_value = self._kp
self._matc.return_value = False
k8s = mock.MagicMock()
m_get_k8s_client.return_value = k8s
h_vif.VIFHandler.on_present(self._handler, self._pod)
k8s.add_finalizer.assert_called_once_with(self._pod,
k_const.POD_FINALIZER)
self._matc.assert_called_once_with(self._pod)
self._handler.on_finalize.assert_called_once_with(self._pod)
self._request_vif.assert_not_called()
self._request_additional_vifs.assert_not_called()
self._activate_vif.assert_not_called()
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_kuryrport')
def test_on_present_on_completed_without_annotation(self, m_get_kuryrport):
def test_on_present_on_completed_without_annotation(self, m_get_kuryrport,
m_get_k8s_client):
self._is_pod_completed.return_value = True
m_get_kuryrport.return_value = None
self._matc.return_value = False
k8s = mock.MagicMock()
m_get_k8s_client.return_value = k8s
h_vif.VIFHandler.on_present(self._handler, self._pod)
k8s.add_finalizer.assert_called_once_with(self._pod,
k_const.POD_FINALIZER)
self._matc.assert_called_once_with(self._pod)
self._handler.on_finalize.assert_not_called()
self._request_vif.assert_not_called()
@ -240,34 +264,46 @@ class TestVIFHandler(test_base.TestCase):
h_vif.VIFHandler.on_present(self._handler, self._pod)
k8s.add_finalizer.assert_called_once_with(self._pod,
k_const.POD_FINALIZER)
m_get_kuryrport.assert_called_once_with(self._pod)
self._matc.assert_called_once_with(self._pod)
self._handler._add_kuryrport_crd.assert_called_once_with(self._pod)
k8s.add_finalizer.assert_called_once_with(self._pod,
k_const.POD_FINALIZER)
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.is_host_network')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_kuryrport')
def test_on_present_update(self, m_get_kuryrport, m_host_network):
def test_on_present_update(self, m_get_kuryrport, m_host_network,
m_get_k8s_client):
m_get_kuryrport.return_value = self._kp
m_host_network.return_value = False
self._matc.return_value = False
k8s = mock.MagicMock()
m_get_k8s_client.return_value = k8s
h_vif.VIFHandler.on_present(self._handler, self._pod)
k8s.add_finalizer.assert_called_once_with(self._pod,
k_const.POD_FINALIZER)
self._matc.assert_called_once_with(self._pod)
m_get_kuryrport.assert_called_once_with(self._pod)
self._handler._add_kuryrport_crd.assert_not_called()
@mock.patch('kuryr_kubernetes.clients.get_kubernetes_client')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.is_host_network')
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_kuryrport')
def test_on_present_upgrade(self, m_get_kuryrport, m_host_network):
def test_on_present_upgrade(self, m_get_kuryrport, m_host_network,
m_get_k8s_client):
m_get_kuryrport.return_value = self._kp
m_host_network.return_value = True
self._matc.return_value = True
k8s = mock.MagicMock()
m_get_k8s_client.return_value = k8s
h_vif.VIFHandler.on_present(self._handler, self._pod)
k8s.add_finalizer.assert_called_once_with(self._pod,
k_const.POD_FINALIZER)
self._matc.assert_called_once_with(self._pod)
m_get_kuryrport.assert_not_called()
self._request_vif.assert_not_called()