Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,33 @@ public BootstrapMetadata bootstrapMetadata() {
return bootstrapMetadata;
}

/**
* Validates the correctness of the given cluster id. A valid cluster id is a base64, urlencoded, no padding
* representation of a {@link Uuid}. These checks do not validate the absence of <code>-</code> character as
* {@link Uuid#randomUuid()} avoids them only for convenience reasons.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would explicitly mention support for already generated CIDs. Basically it's for historical reasons.

*/
private void validateClusterId(String clusterId) {
if (clusterId == null) {
throw new FormatterException("You must specify the cluster id.");
}
if (clusterId.contains("=")) {
throw new FormatterException("The specified cluster id, " + clusterId + " is invalid: contains padding");
}
try {
Uuid uuid = Uuid.fromString(clusterId);
if (Uuid.RESERVED.contains(uuid)) {
throw new FormatterException("The specified cluster id, " + clusterId + " is reserved");
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's also validate the starting - sign.

Copy link
Copy Markdown
Contributor Author

@gaurav-narula gaurav-narula May 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these are cosmetic improvemenst that've been added over time but have no bearing on correctness. Failing validation on them would hinder migration from older clusters where - was allowed.

The motivation for avoiding - in the beginning was to avoid shell escaping issues when passing cluster id in CLI tools. https://issues.apache.org/jira/browse/KAFKA-13741

Lately, https://issues.apache.org/jira/browse/KAFKA-20072 avoided - altogether to allow easier copy-pasting.

Copy link
Copy Markdown
Contributor

@fvaleri fvaleri May 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Let's add a comment about this for future reference.

} catch (IllegalArgumentException e) {
throw new FormatterException("The specified cluster id, " + clusterId + " is invalid", e);
}
}

public void run() throws Exception {
if (nodeId < 0) {
throw new RuntimeException("You must specify a valid non-negative node ID.");
}
if (clusterId == null) {
throw new FormatterException("You must specify the cluster id.");
}
validateClusterId(clusterId);
if (directories.isEmpty()) {
throw new FormatterException("You must specify at least one directory to format");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,4 +587,28 @@ public void testFormatWithNoInitialControllers() throws Exception {
assertNotNull(logDirProps1);
}
}

@ParameterizedTest
@ValueSource(strings = {"unrvTtQISjar0JUWGU/8Pg", "igNUVIdeSPO5JCZYFhOh7Q==", "AAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAAQ"})
public void testFormatWithInvalidClusterId(String clusterId) throws Exception {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no corresponding positive test showing that a valid CID passes validation. This would guard against the validation being too aggressive.

try (TestEnv testEnv = new TestEnv(2)) {
FormatterContext formatter1 = testEnv.newFormatter();
formatter1.formatter.setClusterId(clusterId);
String expectedPrefix = "The specified cluster id, " + clusterId;
assertEquals(expectedPrefix,
assertThrows(FormatterException.class,
formatter1.formatter::run).
getMessage().substring(0, expectedPrefix.length()));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't be easier to rewrite like:

assertTrue(message.startsWith(expectedPrefix))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm indifferent here - I followed the convention used in another test in the same class

}
}

@ParameterizedTest
@ValueSource(strings = {"iIygKoNNSpGzNeAEr_QW7w", "-w_KF-snTmuEnKPqZ0RDzA", "dZMgZA7nTLqZTdzb0zbvSQ", "hxqHyN2OSSmPajVhm_DR-Q"})
public void testFormatWithValidClusterId(String clusterId) throws Exception {
try (TestEnv testEnv = new TestEnv(2)) {
FormatterContext formatter1 = testEnv.newFormatter();
formatter1.formatter.setClusterId(clusterId);
formatter1.formatter.run();
}
}
}