This is an automated email from the ASF dual-hosted git repository. jackie pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git
The following commit(s) were added to refs/heads/master by this push: new 47ff09b Adding new Controller API for and setting tag for an instance (#4952) 47ff09b is described below commit 47ff09b4c5d726355a4516d2e1eb72c9705b81b9 Author: icefury71 <cso...@uber.com> AuthorDate: Wed Jul 1 17:35:19 2020 -0700 Adding new Controller API for and setting tag for an instance (#4952) This PR addresses the issue raised in #4082. It introduces a new Controller API to update the instance config for an existing instance in the cluster: - `PUT /instances/{instanceName}` with `Instance` object as the pay-load --- .../api/resources/PinotInstanceRestletResource.java | 19 +++++++++++++++++++ .../controller/helix/ControllerRequestURLBuilder.java | 6 +----- .../helix/core/PinotHelixResourceManager.java | 15 +++++++++++++++ .../api/PinotInstanceRestletResourceTest.java | 18 +++++++++++++++++- .../tests/OfflineClusterIntegrationTest.java | 6 +++--- 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotInstanceRestletResource.java b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotInstanceRestletResource.java index 6f2e28f..4ba9ae2 100644 --- a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotInstanceRestletResource.java +++ b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotInstanceRestletResource.java @@ -31,6 +31,7 @@ import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -177,4 +178,22 @@ public class PinotInstanceRestletResource { } return new SuccessResponse("Successfully dropped instance"); } + + @PUT + @Path("/instances/{instanceName}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Update the specified instance", consumes = MediaType.APPLICATION_JSON, notes = "Update specified instance with given instance config") + @ApiResponses(value = {@ApiResponse(code = 200, message = "Success"), @ApiResponse(code = 500, message = "Internal error")}) + public SuccessResponse updateInstance( + @ApiParam(value = "Instance name", required = true, example = "Server_a.b.com_20000 | Broker_my.broker.com_30000") @PathParam("instanceName") String instanceName, + Instance instance) { + LOGGER.info("Instance update request received for instance: {}", instanceName); + PinotResourceManagerResponse response = pinotHelixResourceManager.updateInstance(instanceName, instance); + if (!response.isSuccessful()) { + throw new ControllerApplicationException(LOGGER, "Failure to update instance. Reason: " + response.getMessage(), + Response.Status.INTERNAL_SERVER_ERROR); + } + return new SuccessResponse("Instance successfully updated"); + } } diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/ControllerRequestURLBuilder.java b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/ControllerRequestURLBuilder.java index 94b6e18..802d085 100644 --- a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/ControllerRequestURLBuilder.java +++ b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/ControllerRequestURLBuilder.java @@ -45,15 +45,11 @@ public class ControllerRequestURLBuilder { return StringUtil.join("/", _baseUrl, "instances"); } - public String forInstanceDelete(String instanceName) { - return StringUtil.join("/", _baseUrl, "instances", instanceName); - } - public String forInstanceState(String instanceName) { return StringUtil.join("/", _baseUrl, "instances", instanceName, "state"); } - public String forInstanceInformation(String instanceName) { + public String forInstance(String instanceName) { return StringUtil.join("/", _baseUrl, "instances", instanceName); } diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/PinotHelixResourceManager.java b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/PinotHelixResourceManager.java index 7abe59a..5a0fa7c 100644 --- a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/PinotHelixResourceManager.java +++ b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/PinotHelixResourceManager.java @@ -362,6 +362,21 @@ public class PinotHelixResourceManager { } /** + * Update a given instance for the specified Instance ID + */ + public synchronized PinotResourceManagerResponse updateInstance(String instanceIdToUpdate, Instance newInstance) { + if (getHelixInstanceConfig(instanceIdToUpdate) == null) { + return PinotResourceManagerResponse.failure("Instance " + instanceIdToUpdate + " does not exists"); + } else { + InstanceConfig newConfig = InstanceUtils.toHelixInstanceConfig(newInstance); + if(!_helixDataAccessor.setProperty(_keyBuilder.instanceConfig(instanceIdToUpdate), newConfig)) { + return PinotResourceManagerResponse.failure("Unable to update instance: " + instanceIdToUpdate); + } + return PinotResourceManagerResponse.SUCCESS; + } + } + + /** * Tenant related APIs */ // TODO: move tenant related APIs here diff --git a/pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotInstanceRestletResourceTest.java b/pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotInstanceRestletResourceTest.java index 02a9ad7..1919b4f 100644 --- a/pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotInstanceRestletResourceTest.java +++ b/pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotInstanceRestletResourceTest.java @@ -119,6 +119,22 @@ public class PinotInstanceRestletResourceTest extends ControllerTest { checkInstanceInfo("Broker_2.3.4.5_1234", "Broker_2.3.4.5", 1234, new String[]{"tag_BROKER"}, null, null); checkInstanceInfo("Server_2.3.4.5_2345", "Server_2.3.4.5", 2345, new String[]{"tag_OFFLINE", "tag_REALTIME"}, new String[]{"tag_OFFLINE", "tag_REALTIME"}, new int[]{0, 1}); + + // Test PUT Instance API + String newBrokerTag = "new-broker-tag"; + Instance newBrokerInstance = new Instance("1.2.3.4", 1234, InstanceType.BROKER, Collections.singletonList(newBrokerTag), null); + String brokerInstanceId = "Broker_1.2.3.4_1234"; + String brokerInstanceUrl = _controllerRequestURLBuilder.forInstance(brokerInstanceId); + sendPutRequest(brokerInstanceUrl, newBrokerInstance.toJsonString()); + + String newServerTag = "new-server-tag"; + Instance newServerInstance = new Instance("1.2.3.4", 2345, InstanceType.SERVER, Collections.singletonList(newServerTag), null); + String serverInstanceId = "Server_1.2.3.4_2345"; + String serverInstanceUrl = _controllerRequestURLBuilder.forInstance(serverInstanceId); + sendPutRequest(serverInstanceUrl, newServerInstance.toJsonString()); + + checkInstanceInfo(brokerInstanceId, "Broker_1.2.3.4", 1234, new String[]{newBrokerTag}, null, null); + checkInstanceInfo(serverInstanceId, "Server_1.2.3.4", 2345, new String[]{newServerTag}, null, null); } private void checkInstanceInfo(String instanceName, String hostName, int port, String[] tags, String[] pools, @@ -128,7 +144,7 @@ public class PinotInstanceRestletResourceTest extends ControllerTest { @Override public Boolean apply(@Nullable Void aVoid) { try { - String getResponse = sendGetRequest(_controllerRequestURLBuilder.forInstanceInformation(instanceName)); + String getResponse = sendGetRequest(_controllerRequestURLBuilder.forInstance(instanceName)); JsonNode instance = JsonUtils.stringToJsonNode(getResponse); boolean result = (instance.get("instanceName") != null) && (instance.get("instanceName").asText().equals(instanceName)) diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/OfflineClusterIntegrationTest.java b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/OfflineClusterIntegrationTest.java index fa75eb2..4ed5469 100644 --- a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/OfflineClusterIntegrationTest.java +++ b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/OfflineClusterIntegrationTest.java @@ -942,7 +942,7 @@ public class OfflineClusterIntegrationTest extends BaseClusterIntegrationTestSet assertEquals(numInstances, getNumBrokers() + getNumServers() + 1); // Try to delete a server that does not exist - String deleteInstanceRequest = _controllerRequestURLBuilder.forInstanceDelete("potato"); + String deleteInstanceRequest = _controllerRequestURLBuilder.forInstance("potato"); try { sendDeleteRequest(deleteInstanceRequest); fail("Delete should have returned a failure status (404)"); @@ -963,7 +963,7 @@ public class OfflineClusterIntegrationTest extends BaseClusterIntegrationTestSet } // Try to delete a live server - deleteInstanceRequest = _controllerRequestURLBuilder.forInstanceDelete(serverName); + deleteInstanceRequest = _controllerRequestURLBuilder.forInstance(serverName); try { sendDeleteRequest(deleteInstanceRequest); fail("Delete should have returned a failure status (409)"); @@ -991,7 +991,7 @@ public class OfflineClusterIntegrationTest extends BaseClusterIntegrationTestSet // Try to delete a broker whose information is still live try { - deleteInstanceRequest = _controllerRequestURLBuilder.forInstanceDelete(brokerName); + deleteInstanceRequest = _controllerRequestURLBuilder.forInstance(brokerName); sendDeleteRequest(deleteInstanceRequest); fail("Delete should have returned a failure status (409)"); } catch (IOException e) { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org