This is an automated email from the ASF dual-hosted git repository.
pzampino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new 1f1f3547a KNOX-3071: New ability in list-alias to list for multiple
clusters. New create-list-alias command to create multiple aliases for multiple
clusters and also list them. (#940)
1f1f3547a is described below
commit 1f1f3547a75df4553cc210e0ab6b2d3bf7ab4645
Author: hanicz <[email protected]>
AuthorDate: Wed Apr 23 20:04:46 2025 +0200
KNOX-3071: New ability in list-alias to list for multiple clusters. New
create-list-alias command to create multiple aliases for multiple clusters and
also list them. (#940)
* KNOX-3071: New ability in list-alias to list for multiple clusters. New
create-list-alias command to create multiple aliases for multiple clusters and
also list them.
---
.../java/org/apache/knox/gateway/util/KnoxCLI.java | 146 ++++++++++++++++----
.../org/apache/knox/gateway/util/KnoxCLITest.java | 153 +++++++++++++++++++++
2 files changed, 271 insertions(+), 28 deletions(-)
diff --git
a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
index b2d3b3059..14653d371 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
@@ -136,7 +136,9 @@ public class KnoxCLI extends Configured implements Tool {
" [" + TopologyConverter.USAGE + "]\n" +
" [" + JWKGenerator.USAGE + "]\n" +
" [" + GenerateDescriptorCommand.USAGE + "]\n" +
- " [" + TokenMigration.USAGE + "]\n";
+ " [" + TokenMigration.USAGE + "]\n" +
+ " [" + CreateListAliasesCommand.USAGE + "]\n";
+ private static final String CLUSTER_STRING_SEPARATOR = ",";
/** allows stdout to be captured if necessary */
public PrintStream out = System.out;
@@ -275,6 +277,12 @@ public class KnoxCLI extends Configured implements Tool {
printKnoxShellUsage();
return -1;
}
+ } else if (args[i].equals("create-list-aliases")) {
+ command = new CreateListAliasesCommand();
+ if (args.length < 3 || "--help".equals(alias)) {
+ printKnoxShellUsage();
+ return -1;
+ }
} else if (args[i].equals("create-cert")) {
command = new CertCreateCommand();
if ((args.length > i + 1) && args[i + 1].equals("--help")) {
@@ -337,12 +345,15 @@ public class KnoxCLI extends Configured implements Tool {
}
} else if( args[i].equals("list-topologies") ){
command = new ListTopologiesCommand();
- }else if ( args[i].equals("--cluster") || args[i].equals("--topology") )
{
+ } else if ( args[i].equals("--cluster") || args[i].equals("--topology")
) {
if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
printKnoxShellUsage();
return -1;
}
this.cluster = args[++i];
+ if(command instanceof CreateListAliasesCommand) {
+ ((CreateListAliasesCommand) command).toMap(this.cluster);
+ }
} else if (args[i].equals("service-test")) {
if( i + 1 >= args.length) {
printKnoxShellUsage();
@@ -663,6 +674,12 @@ public class KnoxCLI extends Configured implements Tool {
out.println(JWKGenerator.USAGE + "\n\n" + JWKGenerator.DESC);
out.println();
out.println( div );
+ out.println(BatchAliasCreateCommand.USAGE + "\n\n" +
BatchAliasCreateCommand.DESC);
+ out.println();
+ out.println( div );
+ out.println(CreateListAliasesCommand.USAGE + "\n\n" +
CreateListAliasesCommand.DESC);
+ out.println();
+ out.println( div );
}
}
@@ -701,31 +718,34 @@ public class KnoxCLI extends Configured implements Tool {
private class AliasListCommand extends Command {
- public static final String USAGE = "list-alias [--cluster clustername]";
+ public static final String USAGE = "list-alias [--cluster
cluster1,clusterN]";
public static final String DESC = "The list-alias command lists all of the
aliases\n" +
- "for the given hadoop --cluster. The
default\n" +
+ "for the given hadoop --cluster(s). The
default\n" +
"--cluster being the gateway itself.";
@Override
public void execute() throws Exception {
AliasService as = getAliasService();
- KeystoreService keystoreService = getKeystoreService();
+ KeystoreService keystoreService = getKeystoreService();
if (cluster == null) {
cluster = "__gateway";
}
- boolean credentialStoreForClusterAvailable =
- keystoreService.isCredentialStoreForClusterAvailable(cluster);
- if (credentialStoreForClusterAvailable) {
- out.println("Listing aliases for: " + cluster);
- List<String> aliases = as.getAliasesForCluster(cluster);
- for (String alias : aliases) {
- out.println(alias);
- }
- out.println("\n" + aliases.size() + " items.");
- } else {
- out.println("Invalid cluster name provided: " + cluster);
- }
+ String[] clusters = cluster.split(CLUSTER_STRING_SEPARATOR);
+ for (String currentCluster : clusters) {
+ boolean credentialStoreForClusterAvailable =
+
keystoreService.isCredentialStoreForClusterAvailable(currentCluster);
+ if (credentialStoreForClusterAvailable) {
+ out.println("Listing aliases for: " + currentCluster);
+ List<String> aliases = as.getAliasesForCluster(currentCluster);
+ for (String alias : aliases) {
+ out.println(alias);
+ }
+ out.println("\n" + aliases.size() + " items.");
+ } else {
+ out.println("Invalid cluster name provided: " + currentCluster);
+ }
+ }
}
@Override
@@ -1037,8 +1057,8 @@ public class KnoxCLI extends Configured implements Tool {
+ "the --value option or --generate (will create a random secret\n"
+ "for you) or user will be prompt to provide password.";
- private List<String> names = new ArrayList<>();
- private List<String> values = new ArrayList<>();
+ protected List<String> names = new ArrayList<>();
+ protected List<String> values = new ArrayList<>();
public void addName(String alias) {
if (names.contains(alias)) {
@@ -1061,6 +1081,23 @@ public class KnoxCLI extends Configured implements Tool {
if (cluster == null) {
cluster = "__gateway";
}
+ fillMissingValues(aliases, generated);
+ as.addAliasesForCluster(cluster, aliases);
+ printResults(generated, aliases);
+ }
+
+ protected void printResults(List<String> generated, Map<String, String>
aliases) {
+ if (!generated.isEmpty()) {
+ out.println(generated.size() + " alias(es) have been successfully
generated: " + generated);
+ }
+ List<String> created = new ArrayList<>(aliases.keySet());
+ created.removeAll(generated);
+ if (!created.isEmpty()) {
+ out.println(created.size() + " alias(es) have been successfully
created: " + created);
+ }
+ }
+
+ protected void fillMissingValues(Map<String, String> aliases, List<String>
generated) {
for (Map.Entry<String, String> entry : aliases.entrySet()) {
if (entry.getValue() == null) {
if (Boolean.parseBoolean(generate)) {
@@ -1071,15 +1108,6 @@ public class KnoxCLI extends Configured implements Tool {
}
}
}
- as.addAliasesForCluster(cluster, aliases);
- if (!generated.isEmpty()) {
- out.println(generated.size() + " alias(es) have been successfully
generated: " + generated);
- }
- List<String> created = new ArrayList<>(aliases.keySet());
- created.removeAll(generated);
- if (!created.isEmpty()) {
- out.println(created.size() + " alias(es) have been successfully
created: " + created);
- }
}
private Map<String, String> toMap() {
@@ -1096,6 +1124,68 @@ public class KnoxCLI extends Configured implements Tool {
}
}
+ public class CreateListAliasesCommand extends BatchAliasCreateCommand {
+ public static final String USAGE = "create-list-aliases " +
+ "--alias alias1 [--value value1] " +
+ "--alias alias2 [--value value2] " +
+ "--alias aliasN [--value valueN] ... " +
+ "--cluster cluster1 " +
+ "--alias aliasN [--value valueN] ..." +
+ "--cluster clusterN " +
+ "[--generate]";
+ public static final String DESC = "The create-list-aliases command will
create multiple aliases\n"
+ + "and secret pairs within the same credential store for the\n"
+ + "indicated --cluster(s) otherwise within the gateway\n"
+ + "credential store. The actual secret may be specified via\n"
+ + "the --value option or --generate (will create a random secret\n"
+ + "for you) or user will be prompt to provide password.";
+
+ private final Map<String, Map<String, String>> aliasMap = new
LinkedHashMap<>();
+
+ @Override
+ public void execute() throws Exception {
+ if (cluster == null || !names.isEmpty()) {
+ cluster = "__gateway";
+ this.toMap(cluster);
+ }
+
+ AliasService aliasService = getAliasService();
+
+ for (Map.Entry<String, Map<String, String>> aliasesMapEntry :
aliasMap.entrySet()) {
+ List<String> generated = new ArrayList<>();
+ this.fillMissingValues(aliasesMapEntry.getValue(), generated);
+ aliasService.addAliasesForCluster(aliasesMapEntry.getKey(),
aliasesMapEntry.getValue());
+ this.printResults(generated, aliasesMapEntry.getValue());
+ this.listAliasesForCluster(aliasesMapEntry.getKey(), aliasService);
+ }
+ }
+
+ private void listAliasesForCluster(String cluster, AliasService as) throws
AliasServiceException {
+ out.println("Listing aliases for: " + cluster);
+ List<String> aliases = as.getAliasesForCluster(cluster);
+ for (String alias : aliases) {
+ out.println(alias);
+ }
+ out.println("\n" + aliases.size() + " items.");
+ }
+
+ private void toMap(String cluster) {
+ Map<String, String> parsedAliases = new LinkedHashMap<>();
+ for (int i = 0; i < values.size(); i++) {
+ parsedAliases.put(names.get(i), values.get(i));
+ }
+
+ names.clear();
+ values.clear();
+ aliasMap.put(cluster, parsedAliases);
+ }
+
+ @Override
+ public String getUsage() {
+ return USAGE + ":\n\n" + DESC;
+ }
+ }
+
public static char[] promptUserForPassword() {
char[] password = null;
Console c = System.console();
diff --git
a/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
b/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
index 88c48f6c0..ff2823161 100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
@@ -1309,6 +1309,159 @@ public class KnoxCLITest {
testGeneratingJWK(JWSAlgorithm.HS512);
}
+ @Test
+ public void testListingAliasesForMultipleClusters() throws Exception {
+ GatewayConfigImpl config = new GatewayConfigImpl();
+
+ outContent.reset();
+ String[] args1 = {"create-alias", "multiplealias", "--value",
"multiplealias", "--cluster", "cluster1", "--master", "master"};
+ int rc;
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(config);
+ rc = cli.run(args1);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("multiplealias has
been successfully " +
+ "created."));
+
+ outContent.reset();
+ String[] args2 = {"create-alias", "multiplealias2", "--value",
"multiplealias2", "--cluster", "test",
+ "--master", "master"};
+ cli = new KnoxCLI();
+ cli.setConf( config );
+ rc = cli.run(args2);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
outContent.toString(StandardCharsets.UTF_8.name()).contains("multiplealias2 has
been successfully " +
+ "created."));
+
+ outContent.reset();
+ String[] args3 = { "list-alias", "--cluster", "cluster1,test", "--master",
"master" };
+ rc = cli.run(args3);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("multiplealias"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("multiplealias2"));
+
+ outContent.reset();
+ String[] args4 = { "list-alias", "--cluster",
"cluster1,test,invalidcluster", "--master", "master" };
+ rc = cli.run(args4);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("multiplealias"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("multiplealias2"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("Invalid cluster
name provided: invalidcluster"));
+
+ outContent.reset();
+ String[] args5 = {"delete-alias", "multiplealias", "--cluster",
"cluster1", "--master", "master"};
+ rc = cli.run(args5);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
outContent.toString(StandardCharsets.UTF_8.name()).contains("multiplealias has
been successfully " +
+ "deleted."));
+
+ outContent.reset();
+ String[] args6 = {"delete-alias", "multiplealias2", "--cluster", "test",
"--master", "master"};
+ rc = cli.run(args6);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
outContent.toString(StandardCharsets.UTF_8.name()).contains("multiplealias2 has
been successfully " +
+ "deleted."));
+
+ outContent.reset();
+ rc = cli.run(args3);
+ assertEquals(0, rc);
+ assertFalse(outContent.toString(StandardCharsets.UTF_8.name()),
outContent.toString(StandardCharsets.UTF_8.name()).contains("multiplealias2"));
+ }
+
+ @Test
+ public void testCreateAndListForMultipleClusters() throws Exception {
+ GatewayConfigImpl config = new GatewayConfigImpl();
+
+ outContent.reset();
+ String[] args1 = {"create-list-aliases", "--alias", "alias1", "--value",
"value1", "--cluster", "cluster1",
+ "--alias", "alias2", "--value", "value2", "--alias", "alias1",
"--value", "value1", "--cluster", "cluster2",
+ "--master", "master"};
+ int rc;
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(config);
+ rc = cli.run(args1);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+ outContent.toString(StandardCharsets.UTF_8.name()).contains("1
alias(es) have been successfully created: [alias1]"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("Listing aliases
for: cluster1"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("alias1"));
+
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+ outContent.toString(StandardCharsets.UTF_8.name()).contains("2
alias(es) have been successfully created: [alias2, alias1]"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("Listing aliases
for: cluster2"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("alias2"));
+ }
+
+ @Test
+ public void testCreateAndListForMultipleClustersWithGenerate() throws
Exception {
+ GatewayConfigImpl config = new GatewayConfigImpl();
+
+ outContent.reset();
+ String[] args1 = {"create-list-aliases", "--alias", "alias1", "--cluster",
"cluster1", "--alias",
+ "alias2", "--value", "value2", "--alias", "alias3", "--cluster",
"cluster2",
+ "--master", "master", "--generate"};
+ int rc;
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(config);
+ rc = cli.run(args1);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+ outContent.toString(StandardCharsets.UTF_8.name()).contains("1
alias(es) have been successfully generated: [alias1]"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("Listing aliases
for: cluster1"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("alias1"));
+
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+ outContent.toString(StandardCharsets.UTF_8.name()).contains("1
alias(es) have been successfully created: [alias2]"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+ outContent.toString(StandardCharsets.UTF_8.name()).contains("1
alias(es) have been successfully generated: [alias3]"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("Listing aliases
for: cluster2"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("alias3"));
+ }
+
+ @Test
+ public void testCreateAndListForMultipleClustersNoCLuster() throws Exception
{
+ GatewayConfigImpl config = new GatewayConfigImpl();
+
+ outContent.reset();
+ String[] args1 = {"create-list-aliases", "--alias", "alias1", "--cluster",
"cluster1", "--alias",
+ "alias2", "--value", "value2", "--alias", "alias3",
+ "--master", "master", "--generate"};
+ int rc;
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(config);
+ rc = cli.run(args1);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+ outContent.toString(StandardCharsets.UTF_8.name()).contains("1
alias(es) have been successfully generated: [alias1]"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("Listing aliases
for: cluster1"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("alias1"));
+
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+ outContent.toString(StandardCharsets.UTF_8.name()).contains("1
alias(es) have been successfully created: [alias2]"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+ outContent.toString(StandardCharsets.UTF_8.name()).contains("1
alias(es) have been successfully generated: [alias3]"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("Listing aliases
for: __gateway"));
+ assertTrue(outContent.toString(StandardCharsets.UTF_8.name()),
+
outContent.toString(StandardCharsets.UTF_8.name()).contains("alias3"));
+ }
+
private void testGeneratingJWK(JWSAlgorithm jwkAlgorithm) throws Exception {
testGeneratingJWK(jwkAlgorithm, null);
}