diff --git a/util/src/main/java/io/kubernetes/client/util/generic/GenericKubernetesApi.java b/util/src/main/java/io/kubernetes/client/util/generic/GenericKubernetesApi.java index 33fec11c2a..38b5960f51 100644 --- a/util/src/main/java/io/kubernetes/client/util/generic/GenericKubernetesApi.java +++ b/util/src/main/java/io/kubernetes/client/util/generic/GenericKubernetesApi.java @@ -37,6 +37,8 @@ import io.kubernetes.client.util.generic.options.PatchOptions; import io.kubernetes.client.util.generic.options.UpdateOptions; import java.io.IOException; +import java.util.Arrays; +import java.util.function.Function; import okhttp3.Call; import okhttp3.HttpUrl; @@ -476,6 +478,63 @@ public KubernetesApiResponse update(ApiType object, final UpdateOptions }); } + /** + * Create kubernetes api response, if the namespace in the object is present, it will send a + * namespace-scoped requests, vice versa. + * + * @param object the object + * @param status function to extract the status from the object + * @return the kubernetes api response + */ + public KubernetesApiResponse updateStatus( + ApiType object, Function status) { + return updateStatus(object, status, new UpdateOptions()); + } + + /** + * Update status of kubernetes api response. + * + * @param object the object + * @param status function to extract the status from the object + * @param updateOptions the update options + * @return the kubernetes api response + */ + public KubernetesApiResponse updateStatus( + ApiType object, Function status, final UpdateOptions updateOptions) { + V1ObjectMeta objectMeta = object.getMetadata(); + return executeCall( + customObjectsApi.getApiClient(), + apiTypeClass, + () -> { + //// TODO(yue9944882): judge namespaced object via api discovery + boolean isNamespaced = !Strings.isNullOrEmpty(objectMeta.getNamespace()); + if (isNamespaced) { + return customObjectsApi.patchNamespacedCustomObjectStatusCall( + this.apiGroup, + this.apiVersion, + objectMeta.getNamespace(), + this.resourcePlural, + objectMeta.getName(), + Arrays.asList(new StatusPatch(status.apply(object))), + updateOptions.getDryRun(), + updateOptions.getFieldManager(), + null, + null); + } else { + return customObjectsApi.patchClusterCustomObjectStatusCall( + this.apiGroup, + this.apiVersion, + this.resourcePlural, + objectMeta.getName(), + Arrays.asList(new StatusPatch(status.apply(object))), + updateOptions.getDryRun(), + updateOptions.getFieldManager(), + null, + null); + } + }); + } + /** * Patch kubernetes api response. * @@ -771,4 +830,41 @@ private Call tweakCallForCoreV1Group(Call call) { .getHttpClient() .newCall(call.request().newBuilder().url(tweakedUrl).build()); } + + public static class StatusPatch { + + private String op = "replace"; + + private String path = "/status"; + + private Object value; + + public StatusPatch(Object value) { + this.value = value; + } + + public String getOp() { + return op; + } + + public void setOp(String op) { + this.op = op; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + } } diff --git a/util/src/test/java/io/kubernetes/client/util/generic/GenericKubernetesApiTest.java b/util/src/test/java/io/kubernetes/client/util/generic/GenericKubernetesApiTest.java index d465b74143..4c69549530 100644 --- a/util/src/test/java/io/kubernetes/client/util/generic/GenericKubernetesApiTest.java +++ b/util/src/test/java/io/kubernetes/client/util/generic/GenericKubernetesApiTest.java @@ -22,6 +22,7 @@ import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.models.V1Job; import io.kubernetes.client.openapi.models.V1JobList; +import io.kubernetes.client.openapi.models.V1JobStatus; import io.kubernetes.client.openapi.models.V1ListMeta; import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1Status; @@ -152,6 +153,23 @@ public void updateNamespacedJobReturningObject() { verify(1, putRequestedFor(urlPathEqualTo("/apis/batch/v1/namespaces/default/jobs/foo1"))); } + @Test + public void updateStatusNamespacedJobReturningObject() { + V1Job foo1 = + new V1Job().kind("Job").metadata(new V1ObjectMeta().namespace("default").name("foo1")); + foo1.setStatus(new V1JobStatus().failed(1)); + + stubFor( + patch(urlEqualTo("/apis/batch/v1/namespaces/default/jobs/foo1/status")) + .willReturn(aResponse().withStatus(200).withBody(new Gson().toJson(foo1)))); + KubernetesApiResponse jobListResp = jobClient.updateStatus(foo1, t -> t.getStatus()); + assertTrue(jobListResp.isSuccess()); + assertEquals(foo1, jobListResp.getObject()); + assertNull(jobListResp.getStatus()); + verify( + 1, patchRequestedFor(urlPathEqualTo("/apis/batch/v1/namespaces/default/jobs/foo1/status"))); + } + @Test public void patchNamespacedJobReturningObject() { V1Patch v1Patch = new V1Patch("{}");