diff --git a/kuryr_kubernetes/exceptions.py b/kuryr_kubernetes/exceptions.py index 39b68d14e..82bd8671f 100644 --- a/kuryr_kubernetes/exceptions.py +++ b/kuryr_kubernetes/exceptions.py @@ -58,6 +58,10 @@ class K8sUnprocessableEntity(K8sClientException): "Unprocessable: %r" % message) +class K8sFieldValueForbidden(K8sUnprocessableEntity): + pass + + class InvalidKuryrNetworkAnnotation(Exception): pass diff --git a/kuryr_kubernetes/k8s_client.py b/kuryr_kubernetes/k8s_client.py index 25bc5ed20..5fe5ea65d 100644 --- a/kuryr_kubernetes/k8s_client.py +++ b/kuryr_kubernetes/k8s_client.py @@ -88,6 +88,12 @@ class K8sClient(object): raise exc.K8sNamespaceTerminating(response.text) raise exc.K8sForbidden(response.text) if response.status_code == requests.codes.unprocessable_entity: + # NOTE(gryf): on k8s API code 422 is also Forbidden, but specified + # to FieldValueForbidden. Perhaps there are other usages for + # throwing unprocessable entity errors in different cases. + if ('FieldValueForbidden' in response.text and + 'Forbidden' in response.json()['message']): + raise exc.K8sFieldValueForbidden(response.text) raise exc.K8sUnprocessableEntity(response.text) if not response.ok: raise exc.K8sClientException(response.text) @@ -261,7 +267,7 @@ class K8sClient(object): try: self._raise_from_response(response) - except (exc.K8sForbidden, exc.K8sResourceNotFound): + except (exc.K8sFieldValueForbidden, exc.K8sResourceNotFound): # Object is being deleting or gone. Return. return False except exc.K8sConflict: @@ -306,8 +312,8 @@ class K8sClient(object): self._raise_from_response(response) except exc.K8sConflict: obj = self.get(path) - except exc.K8sResourceNotFound: - # Object is gone already, stop. + except (exc.K8sFieldValueForbidden, exc.K8sResourceNotFound): + # Object is being deleted or gone already, stop. return False # If after 3 iterations there's still conflict, just raise.