Skip to content

Commit c7dd985

Browse files
committed
Use PUT request to enable/disable table/instance
1 parent 35d7a8f commit c7dd985

File tree

3 files changed

+90
-5
lines changed

3 files changed

+90
-5
lines changed

pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotInstanceRestletResource.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,48 @@ public SuccessResponse addInstance(
216216
}
217217
}
218218

219+
@PUT
220+
@Path("/instances/{instanceName}/state")
221+
@Authenticate(AccessType.UPDATE)
222+
@Produces(MediaType.APPLICATION_JSON)
223+
@Consumes(MediaType.TEXT_PLAIN)
224+
@ApiOperation(value = "Enable/disable an instance", notes = "Enable/disable an instance")
225+
@ApiResponses(value = {
226+
@ApiResponse(code = 200, message = "Success"),
227+
@ApiResponse(code = 400, message = "Bad Request"),
228+
@ApiResponse(code = 404, message = "Instance not found"),
229+
@ApiResponse(code = 500, message = "Internal error")
230+
})
231+
public SuccessResponse toggleInstanceState(
232+
@ApiParam(value = "Instance name", required = true, example = "Server_a.b.com_20000 | Broker_my.broker.com_30000")
233+
@PathParam("instanceName") String instanceName,
234+
@ApiParam(value = "enable|disable", required = true) @QueryParam("state") String state) {
235+
if (!_pinotHelixResourceManager.instanceExists(instanceName)) {
236+
throw new ControllerApplicationException(LOGGER, "Instance '" + instanceName + "' does not exist",
237+
Response.Status.NOT_FOUND);
238+
}
239+
240+
if (StateType.ENABLE.name().equalsIgnoreCase(state)) {
241+
PinotResourceManagerResponse response = _pinotHelixResourceManager.enableInstance(instanceName);
242+
if (!response.isSuccessful()) {
243+
throw new ControllerApplicationException(LOGGER,
244+
"Failed to enable instance '" + instanceName + "': " + response.getMessage(),
245+
Response.Status.INTERNAL_SERVER_ERROR);
246+
}
247+
} else if (StateType.DISABLE.name().equalsIgnoreCase(state)) {
248+
PinotResourceManagerResponse response = _pinotHelixResourceManager.disableInstance(instanceName);
249+
if (!response.isSuccessful()) {
250+
throw new ControllerApplicationException(LOGGER,
251+
"Failed to disable instance '" + instanceName + "': " + response.getMessage(),
252+
Response.Status.INTERNAL_SERVER_ERROR);
253+
}
254+
} else {
255+
throw new ControllerApplicationException(LOGGER, "Unknown state '" + state + "'", Response.Status.BAD_REQUEST);
256+
}
257+
return new SuccessResponse("Request to " + state + " instance '" + instanceName + "' is successful");
258+
}
259+
260+
@Deprecated
219261
@POST
220262
@Path("/instances/{instanceName}/state")
221263
@Authenticate(AccessType.UPDATE)
@@ -229,7 +271,7 @@ public SuccessResponse addInstance(
229271
@ApiResponse(code = 409, message = "Instance cannot be dropped"),
230272
@ApiResponse(code = 500, message = "Internal error")
231273
})
232-
public SuccessResponse toggleInstanceState(
274+
public SuccessResponse toggleInstanceStateDeprecated(
233275
@ApiParam(value = "Instance name", required = true, example = "Server_a.b.com_20000 | Broker_my.broker.com_30000")
234276
@PathParam("instanceName") String instanceName, String state) {
235277
if (!_pinotHelixResourceManager.instanceExists(instanceName)) {

pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotTableRestletResource.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import io.swagger.annotations.ApiKeyAuthDefinition;
2929
import io.swagger.annotations.ApiOperation;
3030
import io.swagger.annotations.ApiParam;
31+
import io.swagger.annotations.ApiResponse;
32+
import io.swagger.annotations.ApiResponses;
3133
import io.swagger.annotations.Authorization;
3234
import io.swagger.annotations.SecurityDefinition;
3335
import io.swagger.annotations.SwaggerDefinition;
@@ -90,6 +92,7 @@
9092
import org.apache.pinot.controller.api.exception.InvalidTableConfigException;
9193
import org.apache.pinot.controller.api.exception.TableAlreadyExistsException;
9294
import org.apache.pinot.controller.helix.core.PinotHelixResourceManager;
95+
import org.apache.pinot.controller.helix.core.PinotResourceManagerResponse;
9396
import org.apache.pinot.controller.helix.core.minion.PinotHelixTaskResourceManager;
9497
import org.apache.pinot.controller.helix.core.rebalance.RebalanceResult;
9598
import org.apache.pinot.controller.helix.core.rebalance.TableRebalanceProgressStats;
@@ -363,9 +366,7 @@ private String listTableConfigs(String tableName, @Nullable String tableTypeStr)
363366
@GET
364367
@Produces(MediaType.APPLICATION_JSON)
365368
@Path("/tables/{tableName}")
366-
@ApiOperation(value = "Get/Enable/Disable/Drop a table",
367-
notes = "Get/Enable/Disable/Drop a table. If table name is the only parameter specified "
368-
+ ", the tableconfig will be printed")
369+
@ApiOperation(value = "Lists the table configs")
369370
public String alterTableStateOrListTableConfig(
370371
@ApiParam(value = "Name of the table", required = true) @PathParam("tableName") String tableName,
371372
@ApiParam(value = "enable|disable|drop") @QueryParam("state") String stateStr,
@@ -376,6 +377,8 @@ public String alterTableStateOrListTableConfig(
376377
return listTableConfigs(tableName, tableTypeStr);
377378
}
378379

380+
// TODO: DO NOT allow toggling state with GET request
381+
379382
StateType stateType = Constants.validateState(stateStr);
380383
TableType tableType = Constants.validateTableType(tableTypeStr);
381384

@@ -717,6 +720,45 @@ public String getTableState(
717720
}
718721
}
719722

723+
@PUT
724+
@Path("/tables/{tableName}/state")
725+
@Authenticate(AccessType.UPDATE)
726+
@Produces(MediaType.APPLICATION_JSON)
727+
@Consumes(MediaType.TEXT_PLAIN)
728+
@ApiOperation(value = "Enable/disable a table", notes = "Enable/disable a table")
729+
@ApiResponses(value = {
730+
@ApiResponse(code = 200, message = "Success"),
731+
@ApiResponse(code = 400, message = "Bad Request"),
732+
@ApiResponse(code = 404, message = "Table not found"),
733+
@ApiResponse(code = 500, message = "Internal error")
734+
})
735+
public SuccessResponse toggleTableState(
736+
@ApiParam(value = "Table name", required = true) @PathParam("tableName") String tableName,
737+
@ApiParam(value = "realtime|offline", required = true) @QueryParam("type") String tableTypeStr,
738+
@ApiParam(value = "enable|disable", required = true) @QueryParam("state") String state) {
739+
String tableNameWithType = constructTableNameWithType(tableName, tableTypeStr);
740+
StateType stateType;
741+
if (StateType.ENABLE.name().equalsIgnoreCase(state)) {
742+
stateType = StateType.ENABLE;
743+
} else if (StateType.DISABLE.name().equalsIgnoreCase(state)) {
744+
stateType = StateType.DISABLE;
745+
} else {
746+
throw new ControllerApplicationException(LOGGER, "Unknown state '" + state + "'", Response.Status.BAD_REQUEST);
747+
}
748+
if (!_pinotHelixResourceManager.hasTable(tableNameWithType)) {
749+
throw new ControllerApplicationException(LOGGER, "Table '" + tableName + "' does not exist",
750+
Response.Status.NOT_FOUND);
751+
}
752+
PinotResourceManagerResponse response = _pinotHelixResourceManager.toggleTableState(tableNameWithType, stateType);
753+
if (response.isSuccessful()) {
754+
return new SuccessResponse("Request to " + state + " table '" + tableNameWithType + "' is successful");
755+
} else {
756+
throw new ControllerApplicationException(LOGGER,
757+
"Failed to " + state + " table '" + tableNameWithType + "': " + response.getMessage(),
758+
Response.Status.INTERNAL_SERVER_ERROR);
759+
}
760+
}
761+
720762
@GET
721763
@Produces(MediaType.APPLICATION_JSON)
722764
@Authenticate(AccessType.UPDATE)

pinot-controller/src/test/java/org/apache/pinot/controller/helix/ControllerInstanceToggleTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ private void toggleInstanceState(String instanceName, String state) {
116116
// It may take time for an instance to toggle the state.
117117
TestUtils.waitForCondition(aVoid -> {
118118
try {
119-
sendPostRequest(DEFAULT_INSTANCE.getControllerRequestURLBuilder().forInstanceState(instanceName), state);
119+
sendPutRequest(
120+
DEFAULT_INSTANCE.getControllerRequestURLBuilder().forInstanceState(instanceName) + "?state=" + state);
120121
} catch (IOException ioe) {
121122
// receive non-200 status code
122123
return false;

0 commit comments

Comments
 (0)