Skip to content

Commit 5c7da6d

Browse files
authored
HDDS-13592. Make InfoSubcommand validate all container IDs before proceeding (#9001)
1 parent 16a1e39 commit 5c7da6d

File tree

3 files changed

+57
-34
lines changed

3 files changed

+57
-34
lines changed

hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/container/InfoSubcommand.java

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -65,30 +65,23 @@ public class InfoSubcommand extends ScmSubcommand {
6565

6666
@Override
6767
public void execute(ScmClient scmClient) throws IOException {
68+
// validate all container IDs and fail fast
69+
List<Long> containerIDs = containerList.getValidatedIDs();
70+
6871
boolean first = true;
69-
multiContainer = containerList.size() > 1;
72+
multiContainer = containerIDs.size() > 1;
7073

7174
printHeader();
72-
// TODO HDDS-13592: Use ContainerIDParameters#getValidatedIDs to automatically handle type conversion and fail fast.
73-
for (String id : containerList) {
74-
printOutput(scmClient, id, first);
75+
for (Long containerID : containerIDs) {
76+
if (!first) {
77+
printBreak();
78+
}
79+
printDetails(scmClient, containerID);
7580
first = false;
7681
}
7782
printFooter();
7883
}
7984

80-
private void printOutput(ScmClient scmClient, String id, boolean first)
81-
throws IOException {
82-
long containerID;
83-
try {
84-
containerID = Long.parseLong(id);
85-
} catch (NumberFormatException e) {
86-
printError("Invalid container ID: " + id);
87-
return;
88-
}
89-
printDetails(scmClient, containerID, first);
90-
}
91-
9285
private void printHeader() {
9386
if (json && multiContainer) {
9487
System.out.println("[");
@@ -113,8 +106,7 @@ private void printBreak() {
113106
}
114107
}
115108

116-
private void printDetails(ScmClient scmClient, long containerID,
117-
boolean first) throws IOException {
109+
private void printDetails(ScmClient scmClient, long containerID) throws IOException {
118110
final ContainerWithPipeline container;
119111
try {
120112
container = scmClient.getContainerWithPipeline(containerID);
@@ -131,9 +123,6 @@ private void printDetails(ScmClient scmClient, long containerID,
131123
printError("Unable to retrieve the replica details: " + e.getMessage());
132124
}
133125

134-
if (!first) {
135-
printBreak();
136-
}
137126
if (json) {
138127
if (!container.getPipeline().isEmpty()) {
139128
ContainerWithPipelineAndReplicas wrapper =

hadoop-ozone/cli-admin/src/test/java/org/apache/hadoop/hdds/scm/cli/container/TestInfoSubCommand.java

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,22 @@ public void testMultipleContainersCanBePassed() throws Exception {
119119
when(scmClient.getContainerReplicas(anyLong())).thenReturn(getReplicas(true));
120120
cmd = new InfoSubcommand();
121121
CommandLine c = new CommandLine(cmd);
122-
c.parseArgs("1", "123", "456", "invalid", "789");
122+
c.parseArgs("1", "123", "456", "789");
123123
cmd.execute(scmClient);
124124
validateMultiOutput();
125125
}
126126

127+
@Test
128+
public void testMultipleInvalidContainerIdFails() throws Exception {
129+
cmd = new InfoSubcommand();
130+
CommandLine c = new CommandLine(cmd);
131+
c.parseArgs("1", "invalid", "-2", "0.5");
132+
validateInvalidContainerIDOutput();
133+
}
134+
127135
@Test
128136
public void testContainersCanBeReadFromStdin() throws IOException {
129-
String input = "1\n123\n456\ninvalid\n789\n";
137+
String input = "1\n123\n456\n789\n";
130138
ByteArrayInputStream inContent = new ByteArrayInputStream(input.getBytes(DEFAULT_ENCODING));
131139
System.setIn(inContent);
132140
cmd = new InfoSubcommand();
@@ -137,23 +145,38 @@ public void testContainersCanBeReadFromStdin() throws IOException {
137145
validateMultiOutput();
138146
}
139147

148+
@Test
149+
public void testInvalidContainerIdFromStdinFails() throws Exception {
150+
String input = "1\ninvalid\n-2\n0.5\n";
151+
ByteArrayInputStream inContent = new ByteArrayInputStream(input.getBytes(DEFAULT_ENCODING));
152+
System.setIn(inContent);
153+
cmd = new InfoSubcommand();
154+
CommandLine c = new CommandLine(cmd);
155+
c.parseArgs("-");
156+
validateInvalidContainerIDOutput();
157+
}
158+
140159
private void validateMultiOutput() throws UnsupportedEncodingException {
141160
// Ensure we have a log line for each containerID
142161
List<String> replica = Arrays.stream(outContent.toString(DEFAULT_ENCODING).split("\n"))
143162
.filter(m -> m.matches("(?s)^Container id: (1|123|456|789).*"))
144163
.collect(Collectors.toList());
145164
assertEquals(4, replica.size());
165+
}
146166

147-
Pattern p = Pattern.compile(
148-
"^Invalid\\scontainer\\sID:\\sinvalid.*", Pattern.MULTILINE);
149-
Matcher m = p.matcher(errContent.toString(DEFAULT_ENCODING));
150-
assertTrue(m.find());
167+
private void validateInvalidContainerIDOutput() throws Exception {
168+
CommandLine.ParameterException ex = assertThrows(
169+
CommandLine.ParameterException.class, () -> cmd.execute(scmClient));
170+
171+
assertThat(ex.getMessage())
172+
.isEqualTo("Container IDs must be positive integers. Invalid container IDs: invalid -2 0.5");
173+
assertThat(outContent.toString(DEFAULT_ENCODING)).isEmpty();
151174
}
152175

153176
@Test
154177
public void testContainersCanBeReadFromStdinJson()
155178
throws IOException {
156-
String input = "1\n123\n456\ninvalid\n789\n";
179+
String input = "1\n123\n456\n789\n";
157180
ByteArrayInputStream inContent = new ByteArrayInputStream(input.getBytes(DEFAULT_ENCODING));
158181
System.setIn(inContent);
159182
cmd = new InfoSubcommand();
@@ -164,12 +187,23 @@ public void testContainersCanBeReadFromStdinJson()
164187
validateJsonMultiOutput();
165188
}
166189

190+
@Test
191+
public void testInvalidContainerIdFromStdinJsonFails() throws Exception {
192+
String input = "1\ninvalid\n-2\n0.5\n";
193+
ByteArrayInputStream inContent = new ByteArrayInputStream(input.getBytes(DEFAULT_ENCODING));
194+
System.setIn(inContent);
195+
cmd = new InfoSubcommand();
196+
CommandLine c = new CommandLine(cmd);
197+
c.parseArgs("-", "--json");
198+
validateInvalidContainerIDOutput();
199+
}
200+
167201
@Test
168202
public void testMultipleContainersCanBePassedJson() throws Exception {
169203
when(scmClient.getContainerReplicas(anyLong())).thenReturn(getReplicas(true));
170204
cmd = new InfoSubcommand();
171205
CommandLine c = new CommandLine(cmd);
172-
c.parseArgs("1", "123", "456", "invalid", "789", "--json");
206+
c.parseArgs("1", "123", "456", "789", "--json");
173207
cmd.execute(scmClient);
174208

175209
validateJsonMultiOutput();
@@ -181,11 +215,6 @@ private void validateJsonMultiOutput() throws UnsupportedEncodingException {
181215
.filter(m -> m.matches("(?s)^.*\"containerInfo\".*"))
182216
.collect(Collectors.toList());
183217
assertEquals(4, replica.size());
184-
185-
Pattern p = Pattern.compile(
186-
"^Invalid\\scontainer\\sID:\\sinvalid.*", Pattern.MULTILINE);
187-
Matcher m = p.matcher(errContent.toString(DEFAULT_ENCODING));
188-
assertTrue(m.find());
189218
}
190219

191220
private void testReplicaIncludedInOutput(boolean includeIndex)

hadoop-ozone/dist/src/main/smoketest/admincli/container.robot

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ Container info
9393
Should contain ${output} Pipeline id
9494
Should contain ${output} Datanodes
9595

96+
Container info should fail with invalid container ID
97+
${output} = Execute And Ignore Error ozone admin container info "${CONTAINER}" -2 0.5 abc
98+
Should contain ${output} Container IDs must be positive integers.
99+
Should contain ${output} Invalid container IDs: -2 0.5 abc
100+
96101
Verbose container info
97102
${output} = Execute ozone admin --verbose container info "${CONTAINER}"
98103
Should contain ${output} Pipeline Info

0 commit comments

Comments
 (0)