Skip to content

Commit 7d1700e

Browse files
author
Vincent Royer
authored
Add an AsciiDoc generator for any ConfigDef class (#8)
* Fixup some setting description and error messages * Add the AsciiDocGenerator utility class
1 parent 41366b1 commit 7d1700e

File tree

7 files changed

+140
-8
lines changed

7 files changed

+140
-8
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright DataStax, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.datastax.oss.common.sink.config;
17+
18+
import java.io.FileWriter;
19+
import java.io.IOException;
20+
import java.io.PrintWriter;
21+
import java.nio.file.Path;
22+
import java.util.*;
23+
import org.apache.kafka.common.config.ConfigDef;
24+
25+
/** Generates Asiidoc documentation for a ConfigDef */
26+
public class AsciiDocGenerator {
27+
28+
public static String toAscidoc(ConfigDef configDef) {
29+
StringBuilder b = new StringBuilder();
30+
for (ConfigDef.ConfigKey key : sortedConfigs(configDef)) {
31+
if (key.internalConfig) {
32+
continue;
33+
}
34+
getConfigKeyAsciiDoc(configDef, key, b);
35+
b.append("\n");
36+
}
37+
return b.toString();
38+
}
39+
40+
protected static void getConfigKeyAsciiDoc(
41+
ConfigDef configDef, ConfigDef.ConfigKey key, StringBuilder b) {
42+
b.append("[#").append(key.name).append("]").append("\n");
43+
for (String docLine : key.documentation.split("\n")) {
44+
if (docLine.length() == 0) {
45+
continue;
46+
}
47+
b.append(docLine).append("\n+\n");
48+
}
49+
b.append("Type: ").append(getConfigValue(key, "Type")).append("\n");
50+
if (key.hasDefault()) {
51+
b.append("Default: ").append(getConfigValue(key, "Default")).append("\n");
52+
}
53+
if (key.validator != null) {
54+
b.append("Valid Values: ").append(getConfigValue(key, "Valid Values")).append("\n");
55+
}
56+
b.append("Importance: ").append(getConfigValue(key, "Importance")).append("\n");
57+
}
58+
59+
protected static String getConfigValue(ConfigDef.ConfigKey key, String headerName) {
60+
switch (headerName) {
61+
case "Name":
62+
return key.name;
63+
case "Description":
64+
return key.documentation;
65+
case "Type":
66+
return key.type.toString().toLowerCase(Locale.ROOT);
67+
case "Default":
68+
if (key.hasDefault()) {
69+
if (key.defaultValue == null) return "null";
70+
String defaultValueStr = ConfigDef.convertToString(key.defaultValue, key.type);
71+
if (defaultValueStr.isEmpty()) return "\"\"";
72+
else return defaultValueStr;
73+
} else return "";
74+
case "Valid Values":
75+
return key.validator != null ? key.validator.toString() : "";
76+
case "Importance":
77+
return key.importance.toString().toLowerCase(Locale.ROOT);
78+
default:
79+
throw new RuntimeException(
80+
"Can't find value for header '" + headerName + "' in " + key.name);
81+
}
82+
}
83+
84+
protected static List<ConfigDef.ConfigKey> sortedConfigs(ConfigDef configDef) {
85+
final Map<String, Integer> groupOrd = new HashMap<>(configDef.groups().size());
86+
int ord = 0;
87+
for (String group : configDef.groups()) {
88+
groupOrd.put(group, ord++);
89+
}
90+
91+
List<ConfigDef.ConfigKey> configs = new ArrayList<>(configDef.configKeys().values());
92+
Collections.sort(configs, (k1, k2) -> compare(k1, k2, groupOrd));
93+
return configs;
94+
}
95+
96+
protected static int compare(
97+
ConfigDef.ConfigKey k1, ConfigDef.ConfigKey k2, Map<String, Integer> groupOrd) {
98+
int cmp =
99+
k1.group == null
100+
? (k2.group == null ? 0 : -1)
101+
: (k2.group == null
102+
? 1
103+
: Integer.compare(groupOrd.get(k1.group), groupOrd.get(k2.group)));
104+
if (cmp == 0) {
105+
cmp = Integer.compare(k1.orderInGroup, k2.orderInGroup);
106+
if (cmp == 0) {
107+
// first take anything with no default value
108+
if (!k1.hasDefault() && k2.hasDefault()) cmp = -1;
109+
else if (!k2.hasDefault() && k1.hasDefault()) cmp = 1;
110+
else {
111+
cmp = k1.importance.compareTo(k2.importance);
112+
if (cmp == 0) return k1.name.compareTo(k2.name);
113+
}
114+
}
115+
}
116+
return cmp;
117+
}
118+
119+
public static void generateConfigDefDoc(Path path, String name, String title, ConfigDef configDef)
120+
throws IOException {
121+
try (FileWriter fileWriter = new FileWriter(path.resolve(name).toFile())) {
122+
PrintWriter pw = new PrintWriter(fileWriter);
123+
pw.append("= ").append(title).append("\n\n");
124+
pw.append("== Parameters").append("\n\n");
125+
pw.append(toAscidoc(configDef));
126+
pw.flush();
127+
}
128+
}
129+
}

common/src/main/java/com/datastax/oss/common/sink/config/AuthenticatorConfig.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ public class AuthenticatorConfig extends AbstractConfig {
4848
PROVIDER_OPT,
4949
ConfigDef.Type.STRING,
5050
"None",
51+
ConfigDef.ValidString.in("None", "PLAIN", "GSSAPI"),
5152
ConfigDef.Importance.HIGH,
52-
"None | PLAIN | GSSAPI")
53+
"Authentication provider")
5354
.define(
5455
USERNAME_OPT,
5556
ConfigDef.Type.STRING,

common/src/main/java/com/datastax/oss/common/sink/config/CassandraSinkConfig.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,9 @@ public class CassandraSinkConfig {
163163
COMPRESSION_OPT,
164164
ConfigDef.Type.STRING,
165165
"None",
166+
ConfigDef.CaseInsensitiveValidString.in("NONE", "LZ4", "SNAPPY"),
166167
ConfigDef.Importance.HIGH,
167-
"None | LZ4 | Snappy")
168+
"Compression algorithm to use when issuing requests to the database server")
168169
.define(
169170
QUERY_EXECUTION_TIMEOUT_OPT,
170171
ConfigDef.Type.INT,

common/src/main/java/com/datastax/oss/common/sink/config/SslConfig.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ public class SslConfig extends AbstractConfig {
5757
PROVIDER_OPT,
5858
ConfigDef.Type.STRING,
5959
"None",
60+
ConfigDef.ValidString.in("None", "JDK", "OpenSSL"),
6061
ConfigDef.Importance.HIGH,
61-
"None | JDK | OpenSSL")
62+
"SSL/TLS provider")
6263
.define(
6364
CIPHER_SUITES_OPT,
6465
ConfigDef.Type.LIST,

common/src/test/java/com/datastax/oss/common/sink/config/AuthenticatorConfigTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ void should_error_invalid_provider() {
151151
Map<String, String> props =
152152
ImmutableMap.<String, String>builder().put(PROVIDER_OPT, "foo").build();
153153
assertThatThrownBy(() -> new AuthenticatorConfig(props))
154-
.isInstanceOf(ConfigException.class)
154+
.isInstanceOf(org.apache.kafka.common.config.ConfigException.class)
155155
.hasMessage(
156156
String.format(
157-
"Invalid value foo for configuration %s: valid values are None, PLAIN, GSSAPI",
157+
"Invalid value foo for configuration %s: String must be one of: None, PLAIN, GSSAPI",
158158
PROVIDER_OPT));
159159
}
160160

common/src/test/java/com/datastax/oss/common/sink/config/CassandraSinkConfigTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ void should_error_invalid_compression_type() {
194194
.isInstanceOf(ConfigException.class)
195195
.hasMessageContaining(
196196
String.format(
197-
"Invalid value foo for configuration %s: valid values are none, snappy, lz4",
197+
"Invalid value foo for configuration %s: String must be one of (case insensitive): LZ4, NONE, SNAPPY",
198198
COMPRESSION_OPT));
199199
}
200200

common/src/test/java/com/datastax/oss/common/sink/config/SslConfigTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ void should_error_invalid_provider() {
211211
Map<String, String> props =
212212
ImmutableMap.<String, String>builder().put(PROVIDER_OPT, "foo").build();
213213
assertThatThrownBy(() -> new SslConfig(props))
214-
.isInstanceOf(ConfigException.class)
214+
.isInstanceOf(org.apache.kafka.common.config.ConfigException.class)
215215
.hasMessage(
216216
"Invalid value foo for configuration ssl.provider: "
217-
+ "valid values are None, JDK, OpenSSL");
217+
+ "String must be one of: None, JDK, OpenSSL");
218218
}
219219
}

0 commit comments

Comments
 (0)