From d6928c27d95d9c1bc2b2927f5ad3434e1b2d1b0a Mon Sep 17 00:00:00 2001 From: feynmanlin Date: Wed, 14 Jul 2021 14:47:46 +0800 Subject: [PATCH] Generate documentation of webSocket automatically (#11256) Master Issue: #10041 ### Motivation Generate documentation of webSocket automatically --- .../utils/CmdGenerateDocumentation.java | 8 +- .../java/org/apache/pulsar/utils/CmdTest.java | 14 ++- .../service/WebSocketProxyConfiguration.java | 100 ++++++++++++------ 3 files changed, 83 insertions(+), 39 deletions(-) diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/utils/CmdGenerateDocumentation.java b/pulsar-broker/src/main/java/org/apache/pulsar/utils/CmdGenerateDocumentation.java index 41096f8f9abd2..cfb47a889e796 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/utils/CmdGenerateDocumentation.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/utils/CmdGenerateDocumentation.java @@ -30,6 +30,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.pulsar.broker.ServiceConfiguration; import org.apache.pulsar.common.configuration.FieldContext; +import org.apache.pulsar.websocket.service.WebSocketProxyConfiguration; @Data @Parameters(commandDescription = "Generate documentation automatically.") @@ -79,12 +80,15 @@ public boolean run(String[] args) throws Exception { public String generateDocumentByClassName(String className) throws Exception { if (ServiceConfiguration.class.getName().equals(className)) { - return generateDocForServiceConfiguration(className, "Broker"); + return generateDocByFieldContext(className, "Broker"); + } + if (WebSocketProxyConfiguration.class.getName().equals(className)) { + return generateDocByFieldContext(className, "WebSocket"); } return "Class [" + className + "] not found"; } - protected String generateDocForServiceConfiguration(String className, String type) throws Exception { + protected String generateDocByFieldContext(String className, String type) throws Exception { Class clazz = Class.forName(className); Object obj = clazz.getDeclaredConstructor().newInstance(); Field[] fields = clazz.getDeclaredFields(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/utils/CmdTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/utils/CmdTest.java index fc595b7109c61..9a49da9eb8593 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/utils/CmdTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/utils/CmdTest.java @@ -31,13 +31,23 @@ public class CmdTest { @Test public void cmdParserTest() throws Exception { + generateDoc("org.apache.pulsar.broker.ServiceConfiguration"); + } + + @Test + public void cmdParserWebSocketTest() throws Exception { + generateDoc("org.apache.pulsar.websocket.service.WebSocketProxyConfiguration"); + } + + private void generateDoc(String clazz) throws Exception { PrintStream oldStream = System.out; try (ByteArrayOutputStream baoStream = new ByteArrayOutputStream(2048); PrintStream cacheStream = new PrintStream(baoStream);) { System.setOut(cacheStream); - CmdGenerateDocumentation.main("-c org.apache.pulsar.broker.ServiceConfiguration".split(" ")); + CmdGenerateDocumentation.main(("-c " + clazz).split(" ")); String message = baoStream.toString(); - Field[] fields = ServiceConfiguration.class.getDeclaredFields(); + Class cls = Class.forName(clazz); + Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); FieldContext fieldContext = field.getAnnotation(FieldContext.class); diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/WebSocketProxyConfiguration.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/WebSocketProxyConfiguration.java index 6ce27e6e50033..db7685f619073 100644 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/WebSocketProxyConfiguration.java +++ b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/WebSocketProxyConfiguration.java @@ -42,94 +42,124 @@ public class WebSocketProxyConfiguration implements PulsarConfiguration { // Number of threads used by Global ZK public static final int GLOBAL_ZK_THREADS = 8; - // Name of the cluster to which this broker belongs to - @FieldContext(required = true) + @FieldContext(required = true, doc = "Name of the cluster to which this broker belongs to") private String clusterName; - // Pulsar cluster url to connect to broker (optional if configurationStoreServers present) + @FieldContext(doc = "The HTTPS REST service URL to connect to broker") private String serviceUrl; + + @FieldContext(doc = "The HTTPS REST service TLS URL") private String serviceUrlTls; + + @FieldContext(doc = "The broker binary service URL (for produce and consume operations)") private String brokerServiceUrl; + + @FieldContext(doc = "The secured broker binary service URL (for produce and consume operations)") private String brokerServiceUrlTls; - // Path for the file used to determine the rotation status for the broker - // when responding to service discovery health checks + @FieldContext(doc = "Path for the file used to determine the rotation status for the broker " + + "when responding to service discovery health checks") private String statusFilePath; - // Configuration Store connection string @Deprecated + @FieldContext( + doc = "Configuration Store connection string", + deprecated = true + ) private String globalZookeeperServers; + + @FieldContext(doc = "Connection string of configuration store servers") private String configurationStoreServers; - // Zookeeper session timeout in milliseconds + + @FieldContext(doc = "ZooKeeper session timeout in milliseconds") private long zooKeeperSessionTimeoutMillis = 30000; - // ZooKeeper cache expiry time in seconds + + @FieldContext(doc = "ZooKeeper cache expiry time in seconds") private int zooKeeperCacheExpirySeconds = 300; - // Port to use to server HTTP request + @FieldContext(doc = "Port to use to server HTTP request") private Optional webServicePort = Optional.of(8080); - // Port to use to server HTTPS request + + @FieldContext(doc = "Port to use to server HTTPS request") private Optional webServicePortTls = Optional.empty(); - // Hostname or IP address the service binds on, default is 0.0.0.0. + + @FieldContext(doc = "Hostname or IP address the service binds on, default is 0.0.0.0.") private String bindAddress; - // The maximum size of a text message during parsing in WebSocket proxy + + @FieldContext(doc = "Maximum size of a text message during parsing in WebSocket proxy") private int webSocketMaxTextFrameSize = 1024 * 1024; // --- Authentication --- - // Enable authentication + @FieldContext(doc = "Enable authentication") private boolean authenticationEnabled; - // Authentication provider name list, which is a list of class names + + @FieldContext(doc = "Authentication provider name list, which is a list of class names") private Set authenticationProviders = Sets.newTreeSet(); - // Enforce authorization + + @FieldContext(doc = "Enforce authorization") private boolean authorizationEnabled; - // Authorization provider fully qualified class-name + + @FieldContext(doc = "Authorization provider fully qualified class name") private String authorizationProvider = PulsarAuthorizationProvider.class.getName(); - // Role names that are treated as "super-user", meaning they will be able to - // do all admin operations and publish/consume from all topics + @FieldContext(doc = "Role names that are treated as \"super-user\", " + + "which means they can do all admin operations and publish to or consume from all topics") private Set superUserRoles = Sets.newTreeSet(); - // Allow wildcard matching in authorization - // (wildcard matching only applicable if wildcard-char: - // * presents at first or last position eg: *.pulsar.service, pulsar.service.*) + @FieldContext(doc = "Allow wildcard matching in authorization " + + "(wildcard matching only applicable if wildcard-char: " + + "presents at first or last position. For example: *.pulsar.service,pulsar.service.*)") private boolean authorizationAllowWildcardsMatching = false; - // Authentication settings of the proxy itself. Used to connect to brokers + @FieldContext(doc = "Proxy authentication settings used to connect to brokers") private String brokerClientAuthenticationPlugin; + + @FieldContext(doc = "Proxy authentication parameters used to connect to brokers") private String brokerClientAuthenticationParameters; - // Path for the trusted TLS certificate file for outgoing connection to a server (broker) + + @FieldContext(doc = "Path for the trusted TLS certificate file for outgoing connection to a server (broker)") private String brokerClientTrustCertsFilePath = ""; - // Number of IO threads in Pulsar Client used in WebSocket proxy + @FieldContext(doc = "Number of IO threads in Pulsar client used in WebSocket proxy") private int webSocketNumIoThreads = Runtime.getRuntime().availableProcessors(); - // Number of threads to use in HTTP server + @FieldContext(doc = "Number of threads to used in HTTP server") private int numHttpServerThreads = Math.max(6, Runtime.getRuntime().availableProcessors()); - // Number of connections per Broker in Pulsar Client used in WebSocket proxy + @FieldContext(doc = "Number of connections per broker in Pulsar client used in WebSocket proxy") private int webSocketConnectionsPerBroker = Runtime.getRuntime().availableProcessors(); - // Time in milliseconds that idle WebSocket session times out + + @FieldContext(doc = "Timeout of idling WebSocket session (in millisecond)") private int webSocketSessionIdleTimeoutMillis = 300000; - // When this parameter is not empty, unauthenticated users perform as anonymousUserRole + @FieldContext(doc = "When this parameter is not empty, unauthenticated users perform as anonymousUserRole") private String anonymousUserRole = null; /***** --- TLS --- ****/ @Deprecated private boolean tlsEnabled = false; + @FieldContext(doc = "Enable TLS of broker client") private boolean brokerClientTlsEnabled = false; - // Path for the TLS certificate file + + @FieldContext(doc = "Path for the TLS certificate file") private String tlsCertificateFilePath; - // Path for the TLS private key file + + @FieldContext(doc = "Path for the TLS private key file") private String tlsKeyFilePath; - // Path for the trusted TLS certificate file + + @FieldContext(doc = "Path for the trusted TLS certificate file") private String tlsTrustCertsFilePath = ""; - // Accept untrusted TLS certificate from client + + @FieldContext(doc = "Accept untrusted TLS certificate from client") private boolean tlsAllowInsecureConnection = false; - // Specify whether Client certificates are required for TLS - // Reject the Connection if the Client Certificate is not trusted. + + @FieldContext(doc = "Specify whether client certificates are required for " + + "TLS rejecting the connection if the client certificate is not trusted") private boolean tlsRequireTrustedClientCertOnConnect = false; - // Tls cert refresh duration in seconds (set 0 to check on every new connection) + + @FieldContext(doc = "TLS cert refresh duration (in second). 0 means checking every new connection.") private long tlsCertRefreshCheckDurationSec = 300; + @FieldContext(doc = "Key-value properties. Types are all String") private Properties properties = new Properties(); }