We are testing our code using the kubernetes client.
We experienced some interesting behaviour, in case of deletion e.g. a config map:
GET
return 200
, DELETE
returns 200
: delete()
returns true
GET
return 200
, DELETE
returns 404
: delete()
returns true
GET
return 404
, DELETE
is not called at all: delete()
returns false
GET
return 200
, DELETE
returns 400
: delete()
throws KubernetesClientException
GET
return 400
: delete()
throws KubernetesClientException
So we wonder, if it is really consistent, that 200/404
returns true
and 404/nc
returns false
. Both should return true
or both should return false
.
So we wonder, is it perhaps a bug?
According io.fabric8.kubernetes.client.dsl.base.BaseOperation.delete()
it is meant to return false
in case of 404
try {
deleteList();
return true;
} catch (KubernetesClientException e) {
if (e.getCode() != 404) {
throw e;
}
return false;
}
Here is the test example:
// GET return 200
// DELETE return 200
// kubernetesClient.delete() return TRUE
server.expect().get().withPath(format("/api/v1/namespaces/{}/configmaps?labelSelector={}%3D{}", namespace, name, value)).andReturn(200, configMapList).once();
server.expect().delete().withPath(format("/api/v1/namespaces/{}/configmaps/{}", namespace, configMapName)).andReturn(200, StringUtils.EMPTY).once();
actual = kubernetesClient.configMaps().inNamespace(namespace).withLabelSelector(labelSelector).delete();
assertTrue(actual)
// GET return 200
// DELETE return 404
// kubernetesClient.delete() return TRUE
server.expect().get().withPath(format("/api/v1/namespaces/{}/configmaps?labelSelector={}%3D{}", namespace, name, value)).andReturn(200, configMapList).once();
server.expect().delete().withPath(format("/api/v1/namespaces/{}/configmaps/{}", namespace, configMapName)).andReturn(404, StringUtils.EMPTY).once();
actual = kubernetesClient.configMaps().inNamespace(namespace).withLabelSelector(labelSelector).delete();
assertTrue(actual)
// GET return 404
// kubernetesClient.delete() return FALSE
server.expect().get().withPath(format("/api/v1/namespaces/{}/configmaps?labelSelector={}%3D{}", namespace, name, value)).andReturn(404, StringUtils.EMPTY).once();
actual = kubernetesClient.configMaps().inNamespace(namespace).withLabelSelector(labelSelector).delete();
assertFalse(actual)
// GET return 200
// DELETE return 400
// kubernetesClient.delete() throws KubernetesClientException
server.expect().get().withPath(format("/api/v1/namespaces/{}/configmaps?labelSelector={}%3D{}", namespace, name, value)).andReturn(200, configMapList).once();
server.expect().delete().withPath(format("/api/v1/namespaces/{}/configmaps/{}", namespace, configMapName)).andReturn(400, StringUtils.EMPTY).once();
try {
kubernetesClient.configMaps().inNamespace(namespace).withLabelSelector(labelSelector).delete();
fail();
} catch (io.fabric8.kubernetes.client.KubernetesClientException e) {
assertTrue(true);
}
// GET return 400
// kubernetesClient.delete() throws KubernetesClientException
server.expect().get().withPath(format("/api/v1/namespaces/{}/configmaps?labelSelector={}%3D{}", namespace, name, value)).andReturn(400, StringUtils.EMPTY).once();
try {
kubernetesClient.configMaps().inNamespace(namespace).withLabelSelector(labelSelector).delete();
fail();
} catch (io.fabric8.kubernetes.client.KubernetesClientException e) {
assertTrue(true);
}