diff --git a/pinot-broker/src/main/java/org/apache/pinot/broker/api/resources/PinotBrokerDebug.java b/pinot-broker/src/main/java/org/apache/pinot/broker/api/resources/PinotBrokerDebug.java index f9799d7e753f..8f079ca351b2 100644 --- a/pinot-broker/src/main/java/org/apache/pinot/broker/api/resources/PinotBrokerDebug.java +++ b/pinot-broker/src/main/java/org/apache/pinot/broker/api/resources/PinotBrokerDebug.java @@ -48,6 +48,7 @@ import org.apache.pinot.broker.broker.AccessControlFactory; import org.apache.pinot.broker.routing.BrokerRoutingManager; import org.apache.pinot.common.request.BrokerRequest; +import org.apache.pinot.common.utils.DatabaseUtils; import org.apache.pinot.core.auth.Actions; import org.apache.pinot.core.auth.Authorize; import org.apache.pinot.core.auth.ManualAuthorization; @@ -60,12 +61,18 @@ import org.apache.pinot.spi.utils.builder.TableNameBuilder; import org.apache.pinot.sql.parsers.CalciteSqlCompiler; +import static org.apache.pinot.spi.utils.CommonConstants.DATABASE; import static org.apache.pinot.spi.utils.CommonConstants.SWAGGER_AUTHORIZATION_KEY; -@Api(tags = "Debug", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY)}) -@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = @ApiKeyAuthDefinition(name = - HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = SWAGGER_AUTHORIZATION_KEY))) +@Api(tags = "Debug", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY), + @Authorization(value = DATABASE)}) +@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = { + @ApiKeyAuthDefinition(name = HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, + key = SWAGGER_AUTHORIZATION_KEY), + @ApiKeyAuthDefinition(name = DATABASE, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = DATABASE, + description = "Database context passed through http header. If no context is provided 'default' database " + + "context will be considered.")})) @Path("/") // TODO: Add APIs to return the RoutingTable (with unavailable segments) public class PinotBrokerDebug { @@ -93,7 +100,9 @@ public class PinotBrokerDebug { @ApiResponse(code = 500, message = "Internal server error") }) public TimeBoundaryInfo getTimeBoundary( - @ApiParam(value = "Name of the table") @PathParam("tableName") String tableName) { + @ApiParam(value = "Name of the table") @PathParam("tableName") String tableName, + @Context HttpHeaders headers) { + tableName = DatabaseUtils.translateTableName(tableName, headers); String offlineTableName = TableNameBuilder.OFFLINE.tableNameWithType(TableNameBuilder.extractRawTableName(tableName)); TimeBoundaryInfo timeBoundaryInfo = _routingManager.getTimeBoundaryInfo(offlineTableName); @@ -115,7 +124,9 @@ public TimeBoundaryInfo getTimeBoundary( @ApiResponse(code = 500, message = "Internal server error") }) public Map>> getRoutingTable( - @ApiParam(value = "Name of the table") @PathParam("tableName") String tableName) { + @ApiParam(value = "Name of the table") @PathParam("tableName") String tableName, + @Context HttpHeaders headers) { + tableName = DatabaseUtils.translateTableName(tableName, headers); Map>> result = new TreeMap<>(); getRoutingTable(tableName, (tableNameWithType, routingTable) -> result.put(tableNameWithType, removeOptionalSegments(routingTable.getServerInstanceToSegmentsMap()))); @@ -137,7 +148,9 @@ public Map>> getRoutingTable( @ApiResponse(code = 500, message = "Internal server error") }) public Map, List>>> getRoutingTableWithOptionalSegments( - @ApiParam(value = "Name of the table") @PathParam("tableName") String tableName) { + @ApiParam(value = "Name of the table") @PathParam("tableName") String tableName, + @Context HttpHeaders headers) { + tableName = DatabaseUtils.translateTableName(tableName, headers); Map, List>>> result = new TreeMap<>(); getRoutingTable(tableName, (tableNameWithType, routingTable) -> result.put(tableNameWithType, routingTable.getServerInstanceToSegmentsMap())); diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableSize.java b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableSize.java index dd8f7f78d311..a3a23bc083c9 100644 --- a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableSize.java +++ b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableSize.java @@ -33,11 +33,13 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.pinot.common.metrics.ControllerMetrics; +import org.apache.pinot.common.utils.DatabaseUtils; import org.apache.pinot.controller.ControllerConf; import org.apache.pinot.controller.api.exception.ControllerApplicationException; import org.apache.pinot.controller.helix.core.PinotHelixResourceManager; @@ -48,12 +50,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.apache.pinot.spi.utils.CommonConstants.DATABASE; import static org.apache.pinot.spi.utils.CommonConstants.SWAGGER_AUTHORIZATION_KEY; -@Api(tags = Constants.TABLE_TAG, authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY)}) -@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = @ApiKeyAuthDefinition(name = - HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = SWAGGER_AUTHORIZATION_KEY))) +@Api(tags = Constants.TABLE_TAG, authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY), + @Authorization(value = DATABASE)}) +@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = { + @ApiKeyAuthDefinition(name = HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, + key = SWAGGER_AUTHORIZATION_KEY), + @ApiKeyAuthDefinition(name = DATABASE, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = DATABASE, + description = "Database context passed through http header. If no context is provided 'default' database " + + "context will be considered.")})) @Path("/") public class TableSize { private static final Logger LOGGER = LoggerFactory.getLogger(TableSize.class); @@ -82,7 +90,8 @@ public class TableSize { }) public TableSizeReader.TableSizeDetails getTableSize( @ApiParam(value = "Table name without type", required = true, example = "myTable | myTable_OFFLINE") - @PathParam("tableName") String tableName) { + @PathParam("tableName") String tableName, @Context HttpHeaders headers) { + tableName = DatabaseUtils.translateTableName(tableName, headers); TableSizeReader tableSizeReader = new TableSizeReader(_executor, _connectionManager, _controllerMetrics, _pinotHelixResourceManager); TableSizeReader.TableSizeDetails tableSizeDetails = null; diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableViews.java b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableViews.java index d6bb06e80476..5bae03024f85 100644 --- a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableViews.java +++ b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableViews.java @@ -35,11 +35,13 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.helix.model.ExternalView; import org.apache.helix.model.IdealState; +import org.apache.pinot.common.utils.DatabaseUtils; import org.apache.pinot.controller.api.exception.ControllerApplicationException; import org.apache.pinot.controller.helix.core.PinotHelixResourceManager; import org.apache.pinot.core.auth.Actions; @@ -50,12 +52,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.apache.pinot.spi.utils.CommonConstants.DATABASE; import static org.apache.pinot.spi.utils.CommonConstants.SWAGGER_AUTHORIZATION_KEY; -@Api(tags = Constants.TABLE_TAG, authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY)}) -@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = @ApiKeyAuthDefinition(name = - HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = SWAGGER_AUTHORIZATION_KEY))) +@Api(tags = Constants.TABLE_TAG, authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY), + @Authorization(value = DATABASE)}) +@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = { + @ApiKeyAuthDefinition(name = HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, + key = SWAGGER_AUTHORIZATION_KEY), + @ApiKeyAuthDefinition(name = DATABASE, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = DATABASE, + description = "Database context passed through http header. If no context is provided 'default' database " + + "context will be considered.")})) @Path("/") public class TableViews { @@ -80,7 +88,9 @@ public static class TableView { @ApiOperation(value = "Get table ideal state", notes = "Get table ideal state") public TableView getIdealState( @ApiParam(value = "Name of the table", required = true) @PathParam("tableName") String tableName, - @ApiParam(value = "realtime|offline", required = false) @QueryParam("tableType") String tableTypeStr) { + @ApiParam(value = "realtime|offline", required = false) @QueryParam("tableType") String tableTypeStr, + @Context HttpHeaders headers) { + tableName = DatabaseUtils.translateTableName(tableName, headers); TableType tableType = validateTableType(tableTypeStr); return getTableState(tableName, IDEALSTATE, tableType); } @@ -92,7 +102,9 @@ public TableView getIdealState( @ApiOperation(value = "Get table external view", notes = "Get table external view") public TableView getExternalView( @ApiParam(value = "Name of the table", required = true) @PathParam("tableName") String tableName, - @ApiParam(value = "realtime|offline", required = false) @QueryParam("tableType") String tableTypeStr) { + @ApiParam(value = "realtime|offline", required = false) @QueryParam("tableType") String tableTypeStr, + @Context HttpHeaders headers) { + tableName = DatabaseUtils.translateTableName(tableName, headers); TableType tableType = validateTableType(tableTypeStr); return getTableState(tableName, EXTERNALVIEW, tableType); } diff --git a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/ControllerJobStatusResource.java b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/ControllerJobStatusResource.java index d3bd9358a486..66ebdd88cc79 100644 --- a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/ControllerJobStatusResource.java +++ b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/ControllerJobStatusResource.java @@ -27,7 +27,10 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; +import org.apache.pinot.common.utils.DatabaseUtils; import org.apache.pinot.segment.local.data.manager.SegmentDataManager; import org.apache.pinot.segment.local.data.manager.TableDataManager; import org.apache.pinot.server.starter.ServerInstance; @@ -48,8 +51,10 @@ public class ControllerJobStatusResource { @ApiOperation(value = "Task status", notes = "Return the status of a given reload job") public String reloadJobStatus(@PathParam("tableNameWithType") String tableNameWithType, @QueryParam("reloadJobTimestamp") long reloadJobSubmissionTimestamp, - @QueryParam("segmentName") String segmentName) + @QueryParam("segmentName") String segmentName, + @Context HttpHeaders headers) throws Exception { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, headers); TableDataManager tableDataManager = ServerResourceUtils.checkGetTableDataManager(_serverInstance, tableNameWithType); diff --git a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/DebugResource.java b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/DebugResource.java index 5c666a28bdb7..c75761d43d20 100644 --- a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/DebugResource.java +++ b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/DebugResource.java @@ -38,12 +38,14 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import org.apache.commons.io.FileUtils; import org.apache.pinot.common.restlet.resources.SegmentConsumerInfo; import org.apache.pinot.common.restlet.resources.SegmentErrorInfo; import org.apache.pinot.common.restlet.resources.SegmentServerDebugInfo; +import org.apache.pinot.common.utils.DatabaseUtils; import org.apache.pinot.core.data.manager.offline.ImmutableSegmentDataManager; import org.apache.pinot.core.data.manager.realtime.RealtimeSegmentDataManager; import org.apache.pinot.segment.local.data.manager.SegmentDataManager; @@ -54,15 +56,21 @@ import org.apache.pinot.spi.stream.ConsumerPartitionState; import org.apache.pinot.spi.utils.builder.TableNameBuilder; +import static org.apache.pinot.spi.utils.CommonConstants.DATABASE; import static org.apache.pinot.spi.utils.CommonConstants.SWAGGER_AUTHORIZATION_KEY; /** * Debug resource for Pinot Server. */ -@Api(tags = "Debug", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY)}) -@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = @ApiKeyAuthDefinition(name = - HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = SWAGGER_AUTHORIZATION_KEY))) +@Api(tags = "Debug", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY), + @Authorization(value = DATABASE)}) +@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = { + @ApiKeyAuthDefinition(name = HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, + key = SWAGGER_AUTHORIZATION_KEY), + @ApiKeyAuthDefinition(name = DATABASE, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = DATABASE, + description = "Database context passed through http header. If no context is provided 'default' database " + + "context will be considered.")})) @Path("/debug/") public class DebugResource { @@ -76,7 +84,8 @@ public class DebugResource { notes = "This is a debug endpoint, and won't maintain backward compatibility") public List getSegmentsDebugInfo( @ApiParam(value = "Name of the table (with type)", required = true) @PathParam("tableName") - String tableNameWithType) { + String tableNameWithType, @Context HttpHeaders headers) { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, headers); TableType tableType = TableNameBuilder.getTableTypeFromTableName(tableNameWithType); return getSegmentServerDebugInfo(tableNameWithType, tableType); } @@ -89,7 +98,9 @@ public List getSegmentsDebugInfo( public SegmentServerDebugInfo getSegmentDebugInfo( @ApiParam(value = "Name of the table (with type)", required = true) @PathParam("tableName") String tableNameWithType, - @ApiParam(value = "Name of the segment", required = true) @PathParam("segmentName") String segmentName) { + @ApiParam(value = "Name of the segment", required = true) @PathParam("segmentName") String segmentName, + @Context HttpHeaders headers) { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, headers); TableType tableType = TableNameBuilder.getTableTypeFromTableName(tableNameWithType); TableDataManager tableDataManager = ServerResourceUtils.checkGetTableDataManager(_serverInstance, tableNameWithType); diff --git a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/MmapDebugResource.java b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/MmapDebugResource.java index 08e94fe85540..96f7faa8ced0 100644 --- a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/MmapDebugResource.java +++ b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/MmapDebugResource.java @@ -35,10 +35,12 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.pinot.common.restlet.resources.ResourceUtils; +import org.apache.pinot.common.utils.DatabaseUtils; import org.apache.pinot.core.data.manager.InstanceDataManager; import org.apache.pinot.core.data.manager.realtime.RealtimeTableDataManager; import org.apache.pinot.segment.spi.memory.PinotDataBuffer; @@ -46,6 +48,7 @@ import org.apache.pinot.spi.config.table.TableType; import org.apache.pinot.spi.utils.builder.TableNameBuilder; +import static org.apache.pinot.spi.utils.CommonConstants.DATABASE; import static org.apache.pinot.spi.utils.CommonConstants.SWAGGER_AUTHORIZATION_KEY; @@ -53,9 +56,14 @@ * Debug endpoint to check memory allocation. */ @Api(value = "debug", description = "Debug information", tags = "Debug", - authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY)}) -@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = @ApiKeyAuthDefinition(name = - HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = SWAGGER_AUTHORIZATION_KEY))) + authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY), + @Authorization(value = DATABASE)}) +@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = { + @ApiKeyAuthDefinition(name = HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, + key = SWAGGER_AUTHORIZATION_KEY), + @ApiKeyAuthDefinition(name = DATABASE, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = DATABASE, + description = "Database context passed through http header. If no context is provided 'default' database " + + "context will be considered.")})) @Path("debug") public class MmapDebugResource { @@ -83,8 +91,10 @@ public List getOffHeapSizes() { @ApiResponse(code = 404, message = "Table not found") }) public String getTableSize( - @ApiParam(value = "Table Name with type", required = true) @PathParam("tableName") String tableName) + @ApiParam(value = "Table Name with type", required = true) @PathParam("tableName") String tableName, + @Context HttpHeaders headers) throws WebApplicationException { + tableName = DatabaseUtils.translateTableName(tableName, headers); TableType tableType = TableNameBuilder.getTableTypeFromTableName(tableName); if (tableType != TableType.REALTIME) { throw new WebApplicationException("This api cannot be used with non real-time table: " + tableName, diff --git a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TableSizeResource.java b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TableSizeResource.java index 217bd88a46d9..03ce060435a9 100644 --- a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TableSizeResource.java +++ b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TableSizeResource.java @@ -37,12 +37,14 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.pinot.common.restlet.resources.ResourceUtils; import org.apache.pinot.common.restlet.resources.SegmentSizeInfo; import org.apache.pinot.common.restlet.resources.TableSizeInfo; +import org.apache.pinot.common.utils.DatabaseUtils; import org.apache.pinot.core.data.manager.InstanceDataManager; import org.apache.pinot.core.data.manager.offline.ImmutableSegmentDataManager; import org.apache.pinot.segment.local.data.manager.SegmentDataManager; @@ -50,15 +52,21 @@ import org.apache.pinot.segment.spi.ImmutableSegment; import org.apache.pinot.server.starter.ServerInstance; +import static org.apache.pinot.spi.utils.CommonConstants.DATABASE; import static org.apache.pinot.spi.utils.CommonConstants.SWAGGER_AUTHORIZATION_KEY; /** * API to provide table sizes */ -@Api(tags = "Table", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY)}) -@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = @ApiKeyAuthDefinition(name = - HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = SWAGGER_AUTHORIZATION_KEY))) +@Api(tags = "Table", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY), + @Authorization(value = DATABASE)}) +@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = { + @ApiKeyAuthDefinition(name = HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, + key = SWAGGER_AUTHORIZATION_KEY), + @ApiKeyAuthDefinition(name = DATABASE, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = DATABASE, + description = "Database context passed through http header. If no context is provided 'default' database " + + "context will be considered.")})) @Path("/") public class TableSizeResource { @@ -76,8 +84,10 @@ public class TableSizeResource { }) public String getTableSize( @ApiParam(value = "Table Name with type", required = true) @PathParam("tableName") String tableName, - @ApiParam(value = "Provide detailed information") @DefaultValue("true") @QueryParam("detailed") boolean detailed) + @ApiParam(value = "Provide detailed information") @DefaultValue("true") @QueryParam("detailed") boolean detailed, + @Context HttpHeaders headers) throws WebApplicationException { + tableName = DatabaseUtils.translateTableName(tableName, headers); InstanceDataManager instanceDataManager = _serverInstance.getInstanceDataManager(); if (instanceDataManager == null) { @@ -132,8 +142,9 @@ public String getTableSize( @Deprecated public String getTableSizeOld( @ApiParam(value = "Table Name with type", required = true) @PathParam("tableName") String tableName, - @ApiParam(value = "Provide detailed information") @DefaultValue("true") @QueryParam("detailed") boolean detailed) + @ApiParam(value = "Provide detailed information") @DefaultValue("true") @QueryParam("detailed") boolean detailed, + @Context HttpHeaders headers) throws WebApplicationException { - return this.getTableSize(tableName, detailed); + return this.getTableSize(tableName, detailed, headers); } } diff --git a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TableTierResource.java b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TableTierResource.java index 47df55f8d7d7..3117e86182c2 100644 --- a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TableTierResource.java +++ b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TableTierResource.java @@ -39,11 +39,13 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.pinot.common.restlet.resources.ResourceUtils; import org.apache.pinot.common.restlet.resources.TableTierInfo; +import org.apache.pinot.common.utils.DatabaseUtils; import org.apache.pinot.common.utils.URIUtils; import org.apache.pinot.core.data.manager.InstanceDataManager; import org.apache.pinot.core.data.manager.offline.ImmutableSegmentDataManager; @@ -52,15 +54,21 @@ import org.apache.pinot.segment.spi.ImmutableSegment; import org.apache.pinot.server.starter.ServerInstance; +import static org.apache.pinot.spi.utils.CommonConstants.DATABASE; import static org.apache.pinot.spi.utils.CommonConstants.SWAGGER_AUTHORIZATION_KEY; /** * A server-side API to get the storage tiers of immutable segments of the given table from the server being requested. */ -@Api(tags = "Table", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY)}) -@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = @ApiKeyAuthDefinition(name = - HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = SWAGGER_AUTHORIZATION_KEY))) +@Api(tags = "Table", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY), + @Authorization(value = DATABASE)}) +@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = { + @ApiKeyAuthDefinition(name = HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, + key = SWAGGER_AUTHORIZATION_KEY), + @ApiKeyAuthDefinition(name = DATABASE, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = DATABASE, + description = "Database context passed through http header. If no context is provided 'default' database " + + "context will be considered.")})) @Path("/") public class TableTierResource { @@ -77,8 +85,9 @@ public class TableTierResource { @ApiResponse(code = 404, message = "Table not found") }) public String getTableTiers(@ApiParam(value = "Table name with type", required = true) @PathParam("tableNameWithType") - String tableNameWithType) + String tableNameWithType, @Context HttpHeaders headers) throws WebApplicationException { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, headers); InstanceDataManager instanceDataManager = _serverInstance.getInstanceDataManager(); if (instanceDataManager == null) { throw new WebApplicationException("Invalid server initialization", Response.Status.INTERNAL_SERVER_ERROR); @@ -120,8 +129,10 @@ public String getTableTiers(@ApiParam(value = "Table name with type", required = public String getTableSegmentTiers( @ApiParam(value = "Table name with type", required = true) @PathParam("tableNameWithType") String tableNameWithType, - @ApiParam(value = "Name of the segment", required = true) @PathParam("segmentName") @Encoded String segmentName) + @ApiParam(value = "Name of the segment", required = true) @PathParam("segmentName") @Encoded String segmentName, + @Context HttpHeaders headers) throws WebApplicationException { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, headers); segmentName = URIUtils.decode(segmentName); InstanceDataManager instanceDataManager = _serverInstance.getInstanceDataManager(); if (instanceDataManager == null) { diff --git a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TablesResource.java b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TablesResource.java index 0c298f802165..1baa52ffa4c9 100644 --- a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TablesResource.java +++ b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/TablesResource.java @@ -72,6 +72,7 @@ import org.apache.pinot.common.restlet.resources.TablesList; import org.apache.pinot.common.restlet.resources.ValidDocIdsBitmapResponse; import org.apache.pinot.common.restlet.resources.ValidDocIdsType; +import org.apache.pinot.common.utils.DatabaseUtils; import org.apache.pinot.common.utils.LLCSegmentName; import org.apache.pinot.common.utils.RoaringBitmapUtils; import org.apache.pinot.common.utils.TarGzCompressionUtils; @@ -106,12 +107,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.apache.pinot.spi.utils.CommonConstants.DATABASE; import static org.apache.pinot.spi.utils.CommonConstants.SWAGGER_AUTHORIZATION_KEY; -@Api(tags = "Table", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY)}) -@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = @ApiKeyAuthDefinition(name = - HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = SWAGGER_AUTHORIZATION_KEY))) +@Api(tags = "Table", authorizations = {@Authorization(value = SWAGGER_AUTHORIZATION_KEY), + @Authorization(value = DATABASE)}) +@SwaggerDefinition(securityDefinition = @SecurityDefinition(apiKeyAuthDefinitions = { + @ApiKeyAuthDefinition(name = HttpHeaders.AUTHORIZATION, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, + key = SWAGGER_AUTHORIZATION_KEY), + @ApiKeyAuthDefinition(name = DATABASE, in = ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = DATABASE, + description = "Database context passed through http header. If no context is provided 'default' database " + + "context will be considered.")})) @Path("/") public class TablesResource { private static final Logger LOGGER = LoggerFactory.getLogger(TablesResource.class); @@ -153,7 +160,8 @@ public String listTables() { }) public String listTableSegments( @ApiParam(value = "Table name including type", required = true, example = "myTable_OFFLINE") - @PathParam("tableName") String tableName) { + @PathParam("tableName") String tableName, @Context HttpHeaders headers) { + tableName = DatabaseUtils.translateTableName(tableName, headers); TableDataManager tableDataManager = ServerResourceUtils.checkGetTableDataManager(_serverInstance, tableName); List segmentDataManagers = tableDataManager.acquireAllSegments(); try { @@ -183,8 +191,9 @@ public String listTableSegments( public String getSegmentMetadata( @ApiParam(value = "Table Name with type", required = true) @PathParam("tableName") String tableName, @ApiParam(value = "Column name", allowMultiple = true) @QueryParam("columns") @DefaultValue("") - List columns) + List columns, @Context HttpHeaders headers) throws WebApplicationException { + tableName = DatabaseUtils.translateTableName(tableName, headers); InstanceDataManager instanceDataManager = _serverInstance.getInstanceDataManager(); if (instanceDataManager == null) { @@ -319,8 +328,9 @@ public String getSegmentMetadata( }) public String getTableIndexes( @ApiParam(value = "Table name including type", required = true, example = "myTable_OFFLINE") - @PathParam("tableName") String tableName) + @PathParam("tableName") String tableName, @Context HttpHeaders headers) throws Exception { + tableName = DatabaseUtils.translateTableName(tableName, headers); TableDataManager tableDataManager = ServerResourceUtils.checkGetTableDataManager(_serverInstance, tableName); List allSegments = tableDataManager.acquireAllSegments(); try { @@ -367,7 +377,8 @@ public String getSegmentMetadata( @PathParam("tableName") String tableName, @ApiParam(value = "Segment name", required = true) @PathParam("segmentName") String segmentName, @ApiParam(value = "Column name", allowMultiple = true) @QueryParam("columns") @DefaultValue("") - List columns) { + List columns, @Context HttpHeaders headers) { + tableName = DatabaseUtils.translateTableName(tableName, headers); for (int i = 0; i < columns.size(); i++) { try { columns.set(i, URLDecoder.decode(columns.get(i), StandardCharsets.UTF_8.name())); @@ -410,7 +421,8 @@ public String getSegmentMetadata( }) public String getCrcMetadataForTable( @ApiParam(value = "Table name including type", required = true, example = "myTable_OFFLINE") - @PathParam("tableName") String tableName) { + @PathParam("tableName") String tableName, @Context HttpHeaders headers) { + tableName = DatabaseUtils.translateTableName(tableName, headers); TableDataManager tableDataManager = ServerResourceUtils.checkGetTableDataManager(_serverInstance, tableName); List segmentDataManagers = tableDataManager.acquireAllSegments(); try { @@ -441,6 +453,7 @@ public Response downloadSegment( @ApiParam(value = "Name of the segment", required = true) @PathParam("segmentName") @Encoded String segmentName, @Context HttpHeaders httpHeaders) throws Exception { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, httpHeaders); LOGGER.info("Received a request to download segment {} for table {}", segmentName, tableNameWithType); // Validate data access ServerResourceUtils.validateDataAccess(_accessControlFactory, tableNameWithType, httpHeaders); @@ -495,6 +508,7 @@ public ValidDocIdsBitmapResponse downloadValidDocIdsBitmap( @QueryParam("validDocIdsType") String validDocIdsType, @ApiParam(value = "Name of the segment", required = true) @PathParam("segmentName") @Encoded String segmentName, @Context HttpHeaders httpHeaders) { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, httpHeaders); segmentName = URIUtils.decode(segmentName); LOGGER.info("Received a request to download validDocIds for segment {} table {}", segmentName, tableNameWithType); // Validate data access @@ -555,6 +569,7 @@ public Response downloadValidDocIds( @ApiParam(value = "Name of the segment", required = true) @PathParam("segmentName") @Encoded String segmentName, @ApiParam(value = "Valid doc ids type") @QueryParam("validDocIdsType") String validDocIdsType, @Context HttpHeaders httpHeaders) { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, httpHeaders); segmentName = URIUtils.decode(segmentName); LOGGER.info("Received a request to download validDocIds for segment {} table {}", segmentName, tableNameWithType); // Validate data access @@ -613,7 +628,9 @@ public String getValidDocIdsMetadata( @PathParam("tableNameWithType") String tableNameWithType, @ApiParam(value = "Valid doc ids type") @QueryParam("validDocIdsType") String validDocIdsType, - @ApiParam(value = "Segment name", allowMultiple = true) @QueryParam("segmentNames") List segmentNames) { + @ApiParam(value = "Segment name", allowMultiple = true) @QueryParam("segmentNames") List segmentNames, + @Context HttpHeaders headers) { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, headers); return ResourceUtils.convertToJsonString( processValidDocIdsMetadata(tableNameWithType, segmentNames, validDocIdsType)); } @@ -631,7 +648,9 @@ public String getValidDocIdsMetadata( @ApiParam(value = "Table name including type", required = true, example = "myTable_REALTIME") @PathParam("tableNameWithType") String tableNameWithType, @ApiParam(value = "Valid doc ids type") - @QueryParam("validDocIdsType") String validDocIdsType, TableSegments tableSegments) { + @QueryParam("validDocIdsType") String validDocIdsType, TableSegments tableSegments, + @Context HttpHeaders headers) { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, headers); List segmentNames = tableSegments.getSegments(); return ResourceUtils.convertToJsonString( processValidDocIdsMetadata(tableNameWithType, segmentNames, validDocIdsType)); @@ -751,8 +770,10 @@ public String uploadLLCSegment( @ApiParam(value = "Name of the REALTIME table", required = true) @PathParam("realtimeTableName") String realtimeTableName, @ApiParam(value = "Name of the segment", required = true) @PathParam("segmentName") String segmentName, - @QueryParam("uploadTimeoutMs") @DefaultValue("-1") int timeoutMs) + @QueryParam("uploadTimeoutMs") @DefaultValue("-1") int timeoutMs, + @Context HttpHeaders headers) throws Exception { + realtimeTableName = DatabaseUtils.translateTableName(realtimeTableName, headers); LOGGER.info("Received a request to upload low level consumer segment {} for table {}", segmentName, realtimeTableName); @@ -823,7 +844,8 @@ public String uploadLLCSegment( + "currentOffsetsMap") public List getConsumingSegmentsInfo( @ApiParam(value = "Name of the REALTIME table", required = true) @PathParam("realtimeTableName") - String realtimeTableName) { + String realtimeTableName, @Context HttpHeaders headers) { + realtimeTableName = DatabaseUtils.translateTableName(realtimeTableName, headers); TableType tableType = TableNameBuilder.getTableTypeFromTableName(realtimeTableName); if (TableType.OFFLINE == tableType) { throw new WebApplicationException("Cannot get consuming segment info for OFFLINE table: " + realtimeTableName); @@ -873,7 +895,8 @@ public List getConsumingSegmentsInfo( "Validates if the ideal state matches with the segment state on this server") public TableSegmentValidationInfo validateTableSegmentState( @ApiParam(value = "Name of the table", required = true) @PathParam("tableNameWithType") - String tableNameWithType) { + String tableNameWithType, @Context HttpHeaders headers) { + tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, headers); // Get table current ideal state IdealState tableIdealState = HelixHelper.getTableIdealState(_serverInstance.getHelixManager(), tableNameWithType); TableDataManager tableDataManager =