Skip to content

Commit 01e198a

Browse files
symatnkalmar
authored andcommitted
ZOOKEEPER-3633: AdminServer commands throw NPE when only secure client port is used
When only secureClientPort is defined in the config and there is no regular clientPort, then both the stat and the conf commands on the AdminServer result in 500 Server Error caused by NullPointerExceptions. The problem is that no serverCnxFactory is defined in the ZooKeeperServer in this case, we have only secureServerCnxnFactory. In the fix we return info about both the secure and unsecure connections. Example of the stat command output for secure-only configuration: ``` { "version" : "3.6.0-SNAPSHOT-8e8905069f4bff670c0492fe9e28ced0f86bca00, built on 11/29/2019 08:04 GMT", "read_only" : false, "server_stats" : { "packets_sent" : 1, "packets_received" : 1, "fsync_threshold_exceed_count" : 0, "client_response_stats" : { "last_buffer_size" : -1, "min_buffer_size" : -1, "max_buffer_size" : -1 }, "data_dir_size" : 671094270, "log_dir_size" : 671094270, "last_processed_zxid" : 20, "outstanding_requests" : 0, "server_state" : "standalone", "avg_latency" : 5.0, "max_latency" : 5, "min_latency" : 5, "num_alive_client_connections" : 1, "provider_null" : false, "uptime" : 15020 }, "client_response" : { "last_buffer_size" : -1, "min_buffer_size" : -1, "max_buffer_size" : -1 }, "node_count" : 6, "connections" : [ ], "secure_connections" : [ { "remote_socket_address" : "127.0.0.1:57276", "interest_ops" : 1, "outstanding_requests" : 0, "packets_received" : 1, "packets_sent" : 1 } ], "command" : "stats", "error" : null } ``` Author: Mate Szalay-Beko <[email protected]> Reviewers: Andor Molnar <[email protected]>, Enrico Olivelli <[email protected]>, Norbert Kalmar <[email protected]> Closes #1161 from symat/ZOOKEEPER-3633
1 parent 815c8f2 commit 01e198a

3 files changed

Lines changed: 49 additions & 3 deletions

File tree

zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ public ZooKeeperServerConf getConf() {
414414
zkDb.snapLog.getSnapDir().getAbsolutePath(),
415415
zkDb.snapLog.getDataDir().getAbsolutePath(),
416416
getTickTime(),
417-
serverCnxnFactory.getMaxClientCnxnsPerHost(),
417+
getMaxClientCnxnsPerHost(),
418418
getMinSessionTimeout(),
419419
getMaxSessionTimeout(),
420420
getServerId(),

zookeeper-server/src/main/java/org/apache/zookeeper/server/admin/Commands.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,22 @@ public StatCommand() {
577577
@Override
578578
public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
579579
CommandResponse response = super.run(zkServer, kwargs);
580-
response.put("connections", zkServer.getServerCnxnFactory().getAllConnectionInfo(true));
580+
581+
final Iterable<Map<String, Object>> connections;
582+
if (zkServer.getServerCnxnFactory() != null) {
583+
connections = zkServer.getServerCnxnFactory().getAllConnectionInfo(true);
584+
} else {
585+
connections = Collections.emptyList();
586+
}
587+
response.put("connections", connections);
588+
589+
final Iterable<Map<String, Object>> secureConnections;
590+
if (zkServer.getSecureServerCnxnFactory() != null) {
591+
secureConnections = zkServer.getSecureServerCnxnFactory().getAllConnectionInfo(true);
592+
} else {
593+
secureConnections = Collections.emptyList();
594+
}
595+
response.put("secure_connections", secureConnections);
581596
return response;
582597
}
583598

zookeeper-server/src/test/java/org/apache/zookeeper/server/admin/CommandsTest.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.apache.zookeeper.metrics.MetricsUtils;
3434
import org.apache.zookeeper.server.ServerCnxnFactory;
3535
import org.apache.zookeeper.server.ServerStats;
36+
import org.apache.zookeeper.server.ZKDatabase;
3637
import org.apache.zookeeper.server.ZooKeeperServer;
3738
import org.apache.zookeeper.server.quorum.BufferStats;
3839
import org.apache.zookeeper.test.ClientBase;
@@ -219,7 +220,14 @@ public void testSetTraceMask() throws IOException, InterruptedException {
219220

220221
@Test
221222
public void testStat() throws IOException, InterruptedException {
222-
testCommand("stats", new Field("version", String.class), new Field("read_only", Boolean.class), new Field("server_stats", ServerStats.class), new Field("node_count", Integer.class), new Field("connections", Iterable.class), new Field("client_response", BufferStats.class));
223+
testCommand("stats",
224+
new Field("version", String.class),
225+
new Field("read_only", Boolean.class),
226+
new Field("server_stats", ServerStats.class),
227+
new Field("node_count", Integer.class),
228+
new Field("connections", Iterable.class),
229+
new Field("secure_connections", Iterable.class),
230+
new Field("client_response", BufferStats.class));
223231
}
224232

225233
@Test
@@ -264,4 +272,27 @@ public void testConsCommandSecureOnly() {
264272
assertThat(response.toMap().containsKey("secure_connections"), is(true));
265273
}
266274

275+
/**
276+
* testing Stat command, when only SecureClientPort is defined by the user and there is no
277+
* regular (non-SSL port) open. In this case zkServer.getServerCnxnFactory === null
278+
* see: ZOOKEEPER-3633
279+
*/
280+
@Test
281+
public void testStatCommandSecureOnly() {
282+
Commands.StatCommand cmd = new Commands.StatCommand();
283+
ZooKeeperServer zkServer = mock(ZooKeeperServer.class);
284+
ServerCnxnFactory cnxnFactory = mock(ServerCnxnFactory.class);
285+
ServerStats serverStats = mock(ServerStats.class);
286+
ZKDatabase zkDatabase = mock(ZKDatabase.class);
287+
when(zkServer.getSecureServerCnxnFactory()).thenReturn(cnxnFactory);
288+
when(zkServer.serverStats()).thenReturn(serverStats);
289+
when(zkServer.getZKDatabase()).thenReturn(zkDatabase);
290+
when(zkDatabase.getNodeCount()).thenReturn(0);
291+
292+
CommandResponse response = cmd.run(zkServer, null);
293+
294+
assertThat(response.toMap().containsKey("connections"), is(true));
295+
assertThat(response.toMap().containsKey("secure_connections"), is(true));
296+
}
297+
267298
}

0 commit comments

Comments
 (0)