Skip to content

Commit d9cb6f9

Browse files
committed
HADOOP-19161. Add ability to list all enabled capabilities
+use in BucketInfo Change-Id: I737dd7fe261b3a52e9c9d0df77edc2938c0c457d
1 parent 4756714 commit d9cb6f9

File tree

3 files changed

+67
-17
lines changed
  • hadoop-common-project/hadoop-common/src
  • hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard

3 files changed

+67
-17
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/impl/FlagSet.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.util.Arrays;
2222
import java.util.EnumSet;
23+
import java.util.List;
2324
import java.util.Map;
2425
import java.util.Objects;
2526
import java.util.Set;
@@ -169,6 +170,18 @@ public String toString() {
169170
+ '}';
170171
}
171172

173+
174+
/**
175+
* Generate the list of capabilities.
176+
* @return a possibly empty list.
177+
*/
178+
public List<String> pathCapabilities() {
179+
return namesToValues.keySet().stream()
180+
.filter(this::hasCapability)
181+
.collect(Collectors.toList());
182+
}
183+
184+
172185
/**
173186
* Equality is based on the set.
174187
* @param o other object

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/impl/TestFlagSet.java

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ public final class TestFlagSet extends AbstractHadoopTestBase {
3939

4040
private static final String KEY = "key";
4141

42+
public static final String CAPABILITY_B = KEY + ".b";
43+
44+
public static final String CAPABILITY_C = KEY + ".c";
45+
46+
public static final String CAPABILITY_A = KEY + ".a";
47+
4248
private static final String KEYDOT = KEY + ".";
4349

4450
/**
@@ -48,7 +54,7 @@ public final class TestFlagSet extends AbstractHadoopTestBase {
4854
createFlagSet(SimpleEnum.class, KEYDOT, noneOf(SimpleEnum.class));
4955

5056
/**
51-
* Simple Enums.
57+
* Simple Enums for the tests.
5258
*/
5359
private enum SimpleEnum { a, b, c }
5460

@@ -146,9 +152,10 @@ public void assertConfigurationStringMatches(final String expected) {
146152
public void testConfEntry() {
147153
flagSet = flagSetFromConfig("a\t,\nc ", true);
148154
assertFlagSetMatches(flagSet, SimpleEnum.a, SimpleEnum.c);
149-
assertHasCapability(KEY + ".a");
150-
assertHasCapability(KEY + ".c");
151-
assertLacksCapability(KEY + ".b");
155+
assertHasCapability(CAPABILITY_A);
156+
assertHasCapability(CAPABILITY_C);
157+
assertLacksCapability(CAPABILITY_B);
158+
assertPathCapabilitiesMatch(flagSet, CAPABILITY_A, CAPABILITY_C);
152159
}
153160

154161
/**
@@ -160,8 +167,7 @@ public void testConfEntry() {
160167
private static FlagSet<SimpleEnum> flagSetFromConfig(final String string,
161168
final boolean ignoreUnknown) {
162169
final Configuration conf = mkConf(string);
163-
final FlagSet<SimpleEnum> fs = buildFlagSet(SimpleEnum.class, conf, KEY, ignoreUnknown);
164-
return fs;
170+
return buildFlagSet(SimpleEnum.class, conf, KEY, ignoreUnknown);
165171
}
166172

167173
/**
@@ -172,8 +178,8 @@ private static FlagSet<SimpleEnum> flagSetFromConfig(final String string,
172178
public void testConfEntryWithUnknownIgnored() {
173179
flagSet = flagSetFromConfig("a, unknown", true);
174180
assertFlagSetMatches(flagSet, SimpleEnum.a);
175-
assertHasCapability(KEY + ".a");
176-
assertLacksCapability(KEY + ".b");
181+
assertHasCapability(CAPABILITY_A);
182+
assertLacksCapability(CAPABILITY_B);
177183
}
178184

179185
/**
@@ -184,7 +190,7 @@ public void testConfEntryWithUnknownIgnored() {
184190
public void testDuplicateConfEntry() {
185191
flagSet = flagSetFromConfig("a,\ta,\na\"", true);
186192
assertFlagSetMatches(flagSet, SimpleEnum.a);
187-
assertHasCapability(KEY + ".a");
193+
assertHasCapability(CAPABILITY_A);
188194
}
189195

190196
/**
@@ -231,16 +237,21 @@ private void assertLacksCapability(final String capability) {
231237
* Test the * binding.
232238
*/
233239
@Test
234-
public void testFlagSetStarEntry() {
240+
public void testStarEntry() {
235241
flagSet = flagSetFromConfig("*", false);
236242
assertFlags(SimpleEnum.a, SimpleEnum.b, SimpleEnum.c);
237-
assertHasCapability(KEY + ".a");
238-
assertHasCapability(KEY + ".b");
243+
assertHasCapability(CAPABILITY_A);
244+
assertHasCapability(CAPABILITY_B);
245+
Assertions.assertThat(flagSet.pathCapabilities())
246+
.describedAs("path capabilities of %s", flagSet)
247+
.containsExactlyInAnyOrder(CAPABILITY_A, CAPABILITY_B, CAPABILITY_C);
239248
}
240249

241250
@Test
242251
public void testRoundTrip() {
243-
final FlagSet<SimpleEnum> s1 = createFlagSet(SimpleEnum.class, KEYDOT, allOf(SimpleEnum.class));
252+
final FlagSet<SimpleEnum> s1 = createFlagSet(SimpleEnum.class,
253+
KEYDOT,
254+
allOf(SimpleEnum.class));
244255
final FlagSet<SimpleEnum> s2 = roundTrip(s1);
245256
Assertions.assertThat(s1.flags()).isEqualTo(s2.flags());
246257
assertFlagSetMatches(s2, SimpleEnum.a, SimpleEnum.b, SimpleEnum.c);
@@ -257,6 +268,9 @@ public void testEmptyRoundTrip() {
257268
.describedAs("empty flagset %s", s2)
258269
.isTrue();
259270
assertFlagSetMatches(flagSet);
271+
Assertions.assertThat(flagSet.pathCapabilities())
272+
.describedAs("path capabilities of %s", flagSet)
273+
.isEmpty();
260274
}
261275

262276
@Test
@@ -323,8 +337,8 @@ private void assertEnabled(final SimpleEnum flag) {
323337
* @param flag flag to check
324338
*/
325339
private void assertDisabled(final SimpleEnum flag) {
326-
Assertions.assertThat(flagSet.enabled(flag)).
327-
describedAs("status of flag %s in %s", flag, flagSet)
340+
Assertions.assertThat(flagSet.enabled(flag))
341+
.describedAs("status of flag %s in %s", flag, flagSet)
328342
.isFalse();
329343
}
330344

@@ -345,7 +359,23 @@ private void assertFlags(final SimpleEnum... flags) {
345359
private void assertFlagSetMatches(
346360
FlagSet<SimpleEnum> fs,
347361
SimpleEnum... flags) {
348-
Assertions.assertThat(fs.flags()).containsExactly(flags);
362+
Assertions.assertThat(fs.flags())
363+
.describedAs("path capabilities of %s", fs)
364+
.containsExactly(flags);
349365
}
350366

367+
/**
368+
* Assert that a flagset contains exactly the capabilities.
369+
* This is calculated by getting the list of active capabilities
370+
* and asserting on the list.
371+
* @param fs flagset
372+
* @param capabilities capabilities
373+
*/
374+
private void assertPathCapabilitiesMatch(
375+
FlagSet<SimpleEnum> fs,
376+
String... capabilities) {
377+
Assertions.assertThat(fs.pathCapabilities())
378+
.describedAs("path capabilities of %s", fs)
379+
.containsExactlyInAnyOrder(capabilities);
380+
}
351381
}

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/S3GuardTool.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ public static class BucketInfo extends S3GuardTool {
392392
"\tThe S3A connector is compatible with buckets where"
393393
+ " directory markers are not deleted";
394394

395+
public static final String CAPABILITY_FORMAT = "\t%s %s%n";
396+
395397
public BucketInfo(Configuration conf) {
396398
super(conf, GUARDED_FLAG, UNGUARDED_FLAG, FIPS_FLAG, MAGIC_FLAG);
397399
CommandFormat format = getCommandFormat();
@@ -560,9 +562,14 @@ public int run(String[] args, PrintStream out)
560562
// and check for capabilities
561563
println(out, "%nStore Capabilities");
562564
for (String capability : S3A_DYNAMIC_CAPABILITIES) {
563-
out.printf("\t%s %s%n", capability,
565+
out.printf(CAPABILITY_FORMAT, capability,
564566
fs.hasPathCapability(root, capability));
565567
}
568+
// the performance flags are dynamically generated
569+
fs.createStoreContext().getPerformanceFlags().pathCapabilities()
570+
.forEach(capability -> out.printf(CAPABILITY_FORMAT, capability));
571+
572+
// finish with a newline
566573
println(out, "");
567574

568575
if (commands.getOpt(FIPS_FLAG) && !fs.hasPathCapability(root, FIPS_ENDPOINT)) {

0 commit comments

Comments
 (0)