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);
   }

Reply via email to