diff --git a/docs/querying/sql-metadata-tables.md b/docs/querying/sql-metadata-tables.md index cd2db5cf14c2..aa1804e29d56 100644 --- a/docs/querying/sql-metadata-tables.md +++ b/docs/querying/sql-metadata-tables.md @@ -236,6 +236,7 @@ Servers table lists all discovered servers in the cluster. |max_size|BIGINT|Max size in bytes this server recommends to assign to segments see [druid.server.maxSize](../configuration/index.md#historical-general-configuration). Only valid for HISTORICAL type, for other types it's 0| |is_leader|BIGINT|1 if the server is currently the 'leader' (for services which have the concept of leadership), otherwise 0 if the server is not the leader, or null if the server type does not have the concept of leadership| |start_time|STRING|Timestamp in ISO8601 format when the server was announced in the cluster| +|version|VARCHAR|Druid version running on the server| To retrieve information about all servers, use the query: ```sql diff --git a/integration-tests/src/test/java/org/apache/druid/tests/security/AbstractAuthConfigurationTest.java b/integration-tests/src/test/java/org/apache/druid/tests/security/AbstractAuthConfigurationTest.java index c92ae0676678..53803b098136 100644 --- a/integration-tests/src/test/java/org/apache/druid/tests/security/AbstractAuthConfigurationTest.java +++ b/integration-tests/src/test/java/org/apache/druid/tests/security/AbstractAuthConfigurationTest.java @@ -284,7 +284,7 @@ public void test_systemSchemaAccess_admin() throws Exception verifySystemSchemaServerQuery( adminClient, SYS_SCHEMA_SERVERS_QUERY, - getServersWithoutCurrentSizeAndStartTime(adminServers) + getServersWithoutNonConfigurableFields(adminServers) ); LOG.info("Checking sys.server_segments query as admin..."); @@ -858,7 +858,7 @@ protected void verifySystemSchemaQueryBase( String content = responseHolder.getContent(); List> responseMap = jsonMapper.readValue(content, SYS_SCHEMA_RESULTS_TYPE_REFERENCE); if (isServerQuery) { - responseMap = getServersWithoutCurrentSizeAndStartTime(responseMap); + responseMap = getServersWithoutNonConfigurableFields(responseMap); } Assert.assertEquals(responseMap, expectedResults); } @@ -1005,7 +1005,7 @@ protected void setExpectedSystemSchemaObjects() throws IOException SYS_SCHEMA_RESULTS_TYPE_REFERENCE ); - adminServers = getServersWithoutCurrentSizeAndStartTime( + adminServers = getServersWithoutNonConfigurableFields( jsonMapper.readValue( fillServersTemplate( config, @@ -1025,10 +1025,12 @@ protected void setExpectedSystemSchemaObjects() throws IOException } /** - * curr_size on historicals changes because cluster state is not isolated across different + * curr_size on historicals changes because cluster state is not isolated across + * different * integration tests, zero it out for consistent test results + * version and start_time are not configurable therefore we zero them as well */ - protected static List> getServersWithoutCurrentSizeAndStartTime(List> servers) + protected static List> getServersWithoutNonConfigurableFields(List> servers) { return Lists.transform( servers, @@ -1036,6 +1038,7 @@ protected static List> getServersWithoutCurrentSizeAndStartT Map newServer = new HashMap<>(server); newServer.put("curr_size", 0); newServer.put("start_time", "0"); + newServer.put("version", "0.0.0"); return newServer; } ); diff --git a/integration-tests/src/test/resources/results/auth_test_sys_schema_servers.json b/integration-tests/src/test/resources/results/auth_test_sys_schema_servers.json index 8c4fb14c5206..520fde8ff56e 100644 --- a/integration-tests/src/test/resources/results/auth_test_sys_schema_servers.json +++ b/integration-tests/src/test/resources/results/auth_test_sys_schema_servers.json @@ -9,7 +9,8 @@ "curr_size": 2208932412, "max_size": 5000000000, "is_leader": null, - "start_time": "0" + "start_time": "0", + "version": "0.0.0" }, { "server": "%%BROKER%%:8282", @@ -21,6 +22,7 @@ "curr_size": 0, "max_size": 1000000000, "is_leader": null, - "start_time": "0" + "start_time": "0", + "version": "0.0.0" } ] diff --git a/server/src/main/java/org/apache/druid/server/DruidNode.java b/server/src/main/java/org/apache/druid/server/DruidNode.java index 225f054c73ef..0e3b3e4b4d02 100644 --- a/server/src/main/java/org/apache/druid/server/DruidNode.java +++ b/server/src/main/java/org/apache/druid/server/DruidNode.java @@ -44,6 +44,8 @@ */ public class DruidNode { + public static final String UNKNOWN_VERSION = "unknown"; + @JsonProperty("service") @NotNull private String serviceName; @@ -86,7 +88,7 @@ public class DruidNode @NotNull private final String version = GuavaUtils.firstNonNull( DruidNode.class.getPackage().getImplementationVersion(), - "unknown" + UNKNOWN_VERSION ); public DruidNode( diff --git a/server/src/test/java/org/apache/druid/server/DruidNodeTest.java b/server/src/test/java/org/apache/druid/server/DruidNodeTest.java index f0fde0117ac9..77edaaad1379 100644 --- a/server/src/test/java/org/apache/druid/server/DruidNodeTest.java +++ b/server/src/test/java/org/apache/druid/server/DruidNodeTest.java @@ -53,7 +53,7 @@ public void testDefaultsAndSanity() // Hosts which report only ipv6 will have getDefaultHost() report something like fe80::6e40:8ff:fe93:9230 // but getHostAndPort() reports [fe80::6e40:8ff:fe93:9230] Assert.assertEquals(HostAndPort.fromString(DruidNode.getDefaultHost()).toString(), node.getHostAndPort()); - Assert.assertEquals("unknown", node.getVersion()); // unknown because not compiled with version + Assert.assertEquals(DruidNode.UNKNOWN_VERSION, node.getVersion()); // unknown because not compiled with version node = new DruidNode(service, "2001:db8:85a3::8a2e:370:7334", false, -1, null, true, false); Assert.assertEquals("2001:db8:85a3::8a2e:370:7334", node.getHost()); diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/schema/SystemSchema.java b/sql/src/main/java/org/apache/druid/sql/calcite/schema/SystemSchema.java index 76e6f37ab597..932404f21e78 100644 --- a/sql/src/main/java/org/apache/druid/sql/calcite/schema/SystemSchema.java +++ b/sql/src/main/java/org/apache/druid/sql/calcite/schema/SystemSchema.java @@ -180,6 +180,7 @@ public class SystemSchema extends AbstractSchema .add("max_size", ColumnType.LONG) .add("is_leader", ColumnType.LONG) .add("start_time", ColumnType.STRING) + .add("version", ColumnType.STRING) .build(); static final RowSignature SERVER_SEGMENTS_SIGNATURE = RowSignature @@ -639,7 +640,8 @@ private static Object[] buildRowForNonDataServer(DiscoveryDruidNode discoveryDru UNKNOWN_SIZE, UNKNOWN_SIZE, null, - toStringOrNull(discoveryDruidNode.getStartTime()) + toStringOrNull(discoveryDruidNode.getStartTime()), + node.getVersion() }; } @@ -662,7 +664,8 @@ private static Object[] buildRowForNonDataServerWithLeadership( UNKNOWN_SIZE, UNKNOWN_SIZE, isLeader ? 1L : 0L, - toStringOrNull(discoveryDruidNode.getStartTime()) + toStringOrNull(discoveryDruidNode.getStartTime()), + node.getVersion() }; } @@ -697,7 +700,8 @@ private static Object[] buildRowForDiscoverableDataServer( currentSize, druidServerToUse.getMaxSize(), null, - toStringOrNull(discoveryDruidNode.getStartTime()) + toStringOrNull(discoveryDruidNode.getStartTime()), + node.getVersion() }; } diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/schema/SystemSchemaTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/schema/SystemSchemaTest.java index 0fc01c1aa09c..d523d970fccf 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/schema/SystemSchemaTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/schema/SystemSchemaTest.java @@ -44,6 +44,7 @@ import org.apache.druid.client.TimelineServerView; import org.apache.druid.client.coordinator.CoordinatorClient; import org.apache.druid.client.coordinator.NoopCoordinatorClient; +import org.apache.druid.common.guava.GuavaUtils; import org.apache.druid.data.input.InputRow; import org.apache.druid.data.input.impl.DimensionsSpec; import org.apache.druid.data.input.impl.StringDimensionSchema; @@ -381,6 +382,11 @@ public void setUp(@TempDir File tmpDir) throws Exception private final DateTime startTime = DateTimes.nowUtc(); + private final String version = GuavaUtils.firstNonNull( + SystemSchemaTest.class.getPackage().getImplementationVersion(), + DruidNode.UNKNOWN_VERSION + ); + private final DiscoveryDruidNode coordinator = new DiscoveryDruidNode( new DruidNode("s1", "localhost", false, 8081, null, true, false), NodeRole.COORDINATOR, @@ -552,7 +558,7 @@ public void testGetTableMap() final SystemSchema.ServersTable serversTable = (SystemSchema.ServersTable) schema.getTableMap().get("servers"); final RelDataType serverRowType = serversTable.getRowType(new JavaTypeFactoryImpl()); final List serverFields = serverRowType.getFieldList(); - Assert.assertEquals(10, serverFields.size()); + Assert.assertEquals(11, serverFields.size()); Assert.assertEquals("server", serverFields.get(0).getName()); Assert.assertEquals(SqlTypeName.VARCHAR, serverFields.get(0).getType().getSqlTypeName()); } @@ -851,7 +857,8 @@ public void testServersTable() throws URISyntaxException 0L, 0L, nonLeader, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -865,7 +872,8 @@ public void testServersTable() throws URISyntaxException 0L, 1000L, nonLeader, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -879,7 +887,8 @@ public void testServersTable() throws URISyntaxException 400L, 1000L, nonLeader, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -893,7 +902,8 @@ public void testServersTable() throws URISyntaxException 0L, 1000L, nonLeader, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -907,7 +917,8 @@ public void testServersTable() throws URISyntaxException 0L, 1000L, nonLeader, - startTimeStr + startTimeStr, + version ) ); expectedRows.add(createExpectedRow( @@ -920,7 +931,8 @@ public void testServersTable() throws URISyntaxException 0L, 1000L, nonLeader, - startTimeStr + startTimeStr, + version )); expectedRows.add( createExpectedRow( @@ -933,7 +945,8 @@ public void testServersTable() throws URISyntaxException 0L, 0L, 1L, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -947,7 +960,8 @@ public void testServersTable() throws URISyntaxException 0L, 0L, nonLeader, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -961,7 +975,8 @@ public void testServersTable() throws URISyntaxException 200L, 1000L, nonLeader, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -975,7 +990,8 @@ public void testServersTable() throws URISyntaxException 0L, 0L, 1L, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -989,7 +1005,8 @@ public void testServersTable() throws URISyntaxException 0L, 0L, 0L, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -1003,7 +1020,8 @@ public void testServersTable() throws URISyntaxException 0L, 0L, 0L, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -1017,7 +1035,8 @@ public void testServersTable() throws URISyntaxException 0L, 0L, nonLeader, - startTimeStr + startTimeStr, + version ) ); expectedRows.add( @@ -1031,7 +1050,8 @@ public void testServersTable() throws URISyntaxException 0L, 0L, nonLeader, - startTimeStr + startTimeStr, + version ) ); expectedRows.add(createExpectedRow( @@ -1044,7 +1064,8 @@ public void testServersTable() throws URISyntaxException 0L, 1000L, nonLeader, - startTimeStr + startTimeStr, + version )); Assert.assertEquals(expectedRows.size(), rows.size()); for (int i = 0; i < rows.size(); i++) { @@ -1077,7 +1098,8 @@ private Object[] createExpectedRow( @Nullable Long currSize, @Nullable Long maxSize, @Nullable Long isLeader, - String startTime + String startTime, + String version ) { return new Object[]{ @@ -1090,7 +1112,8 @@ private Object[] createExpectedRow( currSize, maxSize, isLeader, - startTime + startTime, + version }; } diff --git a/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap b/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap index 329a7fd3562a..b21581166968 100644 --- a/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap +++ b/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap @@ -58,6 +58,7 @@ exports[`ServicesView renders data 1`] = ` "Max size", "Usage", "Start time", + "Version", "Detail", ] } @@ -208,6 +209,14 @@ exports[`ServicesView renders data 1`] = ` "show": true, "width": 200, }, + { + "Aggregated": [Function], + "Cell": [Function], + "Header": "Version", + "accessor": "version", + "show": true, + "width": 200, + }, { "Aggregated": [Function], "Cell": [Function], diff --git a/web-console/src/views/services-view/services-view.tsx b/web-console/src/views/services-view/services-view.tsx index ea9c5653e9dc..1ac4e42c712a 100644 --- a/web-console/src/views/services-view/services-view.tsx +++ b/web-console/src/views/services-view/services-view.tsx @@ -84,6 +84,7 @@ const TABLE_COLUMNS_BY_MODE: Record '', }, + { + Header: 'Version', + show: visibleColumns.shown('Version'), + accessor: 'version', + width: 200, + Cell: this.renderFilterableCell('version'), + Aggregated: () => '', + }, { Header: 'Detail', show: visibleColumns.shown('Detail'),