From 465f323f60271231a587f53f2f436dd947e7263e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grant=20Pal=C3=A1u=20Spencer?= Date: Tue, 14 Nov 2023 00:05:34 -0800 Subject: [PATCH] Expose Evacuate Finished API in Helix-Rest (#2694) --- .../server/resources/AbstractResource.java | 3 +- .../resources/helix/PerInstanceAccessor.java | 10 ++++++ .../rest/server/TestPerInstanceAccessor.java | 33 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/helix-rest/src/main/java/org/apache/helix/rest/server/resources/AbstractResource.java b/helix-rest/src/main/java/org/apache/helix/rest/server/resources/AbstractResource.java index 64fbaff412..ce3d27273e 100644 --- a/helix-rest/src/main/java/org/apache/helix/rest/server/resources/AbstractResource.java +++ b/helix-rest/src/main/java/org/apache/helix/rest/server/resources/AbstractResource.java @@ -88,7 +88,8 @@ public enum Command { setInstanceOperation, // TODO: Name is just a place holder, may change in future canCompleteSwap, completeSwapIfPossible, - onDemandRebalance + onDemandRebalance, + isEvacuateFinished } @Context diff --git a/helix-rest/src/main/java/org/apache/helix/rest/server/resources/helix/PerInstanceAccessor.java b/helix-rest/src/main/java/org/apache/helix/rest/server/resources/helix/PerInstanceAccessor.java index b1b4f82642..f380975a33 100644 --- a/helix-rest/src/main/java/org/apache/helix/rest/server/resources/helix/PerInstanceAccessor.java +++ b/helix-rest/src/main/java/org/apache/helix/rest/server/resources/helix/PerInstanceAccessor.java @@ -477,6 +477,16 @@ public Response updateInstance(@PathParam("clusterId") String clusterId, OBJECT_MAPPER.getTypeFactory() .constructCollectionType(List.class, String.class))); break; + case isEvacuateFinished: + boolean evacuateFinished; + try { + evacuateFinished = admin.isEvacuateFinished(clusterId, instanceName); + } catch (HelixException e) { + LOG.error(String.format("Encountered error when checking if evacuation finished for cluster: " + + "{}, instance: {}", clusterId, instanceName), e); + return serverError(e); + } + return OK(OBJECT_MAPPER.writeValueAsString(Map.of("successful", evacuateFinished))); default: LOG.error("Unsupported command :" + command); return badRequest("Unsupported command :" + command); diff --git a/helix-rest/src/test/java/org/apache/helix/rest/server/TestPerInstanceAccessor.java b/helix-rest/src/test/java/org/apache/helix/rest/server/TestPerInstanceAccessor.java index a8675202a3..a1f46cce96 100644 --- a/helix-rest/src/test/java/org/apache/helix/rest/server/TestPerInstanceAccessor.java +++ b/helix-rest/src/test/java/org/apache/helix/rest/server/TestPerInstanceAccessor.java @@ -521,6 +521,39 @@ public void updateInstance() throws IOException { OBJECT_MAPPER.readValue(completeSwapIfPossibleResponse.readEntity(String.class), Map.class); Assert.assertFalse((boolean) responseMap.get("successful")); + // test isEvacuateFinished on instance with EVACUATE but has currentState + new JerseyUriRequestBuilder("clusters/{}/instances/{}?command=setInstanceOperation&instanceOperation=EVACUATE") + .format(CLUSTER_NAME, INSTANCE_NAME).post(this, entity); + instanceConfig = _configAccessor.getInstanceConfig(CLUSTER_NAME, INSTANCE_NAME); + Assert.assertEquals( + instanceConfig.getInstanceOperation(), InstanceConstants.InstanceOperation.EVACUATE.toString()); + + Response response = new JerseyUriRequestBuilder("clusters/{}/instances/{}?command=isEvacuateFinished") + .format(CLUSTER_NAME, INSTANCE_NAME).post(this, entity); + Map evacuateFinishedresult = OBJECT_MAPPER.readValue(response.readEntity(String.class), Map.class); + Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); + Assert.assertFalse(evacuateFinishedresult.get("successful")); + + // test isEvacuateFinished on instance with EVACUATE and no currentState + // Create new instance so no currentState or messages assigned to it + String test_instance_name = INSTANCE_NAME + "_foo"; + InstanceConfig newInstanceConfig = new InstanceConfig(test_instance_name); + Entity instanceEntity = Entity.entity(OBJECT_MAPPER.writeValueAsString(newInstanceConfig.getRecord()), + MediaType.APPLICATION_JSON_TYPE); + new JerseyUriRequestBuilder("clusters/{}/instances/{}").format(CLUSTER_NAME, test_instance_name) + .put(this, instanceEntity); + + new JerseyUriRequestBuilder("clusters/{}/instances/{}?command=setInstanceOperation&instanceOperation=EVACUATE") + .format(CLUSTER_NAME, test_instance_name).post(this, entity); + instanceConfig = _configAccessor.getInstanceConfig(CLUSTER_NAME, test_instance_name); + Assert.assertEquals( + instanceConfig.getInstanceOperation(), InstanceConstants.InstanceOperation.EVACUATE.toString()); + + response = new JerseyUriRequestBuilder("clusters/{}/instances/{}?command=isEvacuateFinished") + .format(CLUSTER_NAME, test_instance_name).post(this, entity); + evacuateFinishedresult = OBJECT_MAPPER.readValue(response.readEntity(String.class), Map.class); + Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); + Assert.assertTrue(evacuateFinishedresult.get("successful")); System.out.println("End test :" + TestHelper.getTestMethodName()); }