Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KNOX-3071: New ability in list-alias to list for multiple clusters. N… #940

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
123 changes: 84 additions & 39 deletions gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ public class KnoxCLI extends Configured implements Tool {
" [" + JWKGenerator.USAGE + "]\n" +
" [" + GenerateDescriptorCommand.USAGE + "]\n" +
" [" + TokenMigration.USAGE + "]\n";
private static final String CLUSTER_STRING_SEPARATOR = ",";

/** allows stdout to be captured if necessary */
public PrintStream out = System.out;
Expand All @@ -162,6 +163,7 @@ public class KnoxCLI extends Configured implements Tool {
private boolean migrateExpiredTokens;
private boolean verbose;
private String alias;
private boolean listAliases;

private String remoteRegistryClient;
private String remoteRegistryEntryName;
Expand Down Expand Up @@ -337,12 +339,15 @@ private int init(String[] args) throws IOException {
}
} 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 BatchAliasCreateCommand) {
((BatchAliasCreateCommand) command).toMap(this.cluster);
}
} else if (args[i].equals("service-test")) {
if( i + 1 >= args.length) {
printKnoxShellUsage();
Expand Down Expand Up @@ -451,6 +456,8 @@ private int init(String[] args) throws IOException {
this.master = args[++i];
} else if (args[i].equals("--force")) {
this.force = true;
} else if (args[i].equals("--list")) {
this.listAliases = true;
} else if (args[i].equals("--help")) {
printKnoxShellUsage();
return -1;
Expand Down Expand Up @@ -663,6 +670,9 @@ private void printKnoxShellUsage() {
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 );
}
}

Expand Down Expand Up @@ -701,31 +711,34 @@ protected RemoteConfigurationRegistryClientService getRemoteConfigRegistryClient

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
Expand Down Expand Up @@ -1028,17 +1041,22 @@ public class BatchAliasCreateCommand extends Command {
"--alias alias1 [--value value1] " +
"--alias alias2 [--value value2] " +
"--alias aliasN [--value valueN] ... " +
"[--cluster clustername] " +
"[--generate]";
"--cluster cluster1 " +
"--alias aliasN [--value valueN] ..." +
"--cluster clusterN " +
"[--generate] " +
"[--list]";
public static final String DESC = "The create-aliases command will create multiple aliases\n"
+ "and secret pairs within the same credential store for the\n"
+ "indicated --cluster otherwise within the gateway\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.";
+ "for you) or user will be prompt to provide password.\n"
+ "Optionally the aliases for the clusters can be listed with --list.";

private List<String> names = new ArrayList<>();
private List<String> values = new ArrayList<>();
private final List<String> names = new ArrayList<>();
private final List<String> values = new ArrayList<>();
private final Map<String, Map<String, String>> aliasMap = new LinkedHashMap<>();

public void addName(String alias) {
if (names.contains(alias)) {
Expand All @@ -1055,12 +1073,36 @@ public void addValue(String value) {

@Override
public void execute() throws Exception {
Map<String, String> aliases = toMap();
List<String> generated = new ArrayList<>();
AliasService as = getAliasService();
if (cluster == null) {
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<>();
fillMissingValues(aliasesMapEntry.getValue(), generated);
aliasService.addAliasesForCluster(aliasesMapEntry.getKey(), aliasesMapEntry.getValue());
printResults(generated, aliasesMapEntry.getValue());
if(listAliases) {
listAliasesForCluster(aliasesMapEntry.getKey(), aliasService);
}
}
}

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

private 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)) {
Expand All @@ -1071,23 +1113,26 @@ public void execute() throws Exception {
}
}
}
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 void listAliasesForCluster(String cluster, AliasService aliasService) throws AliasServiceException {
out.println("Listing aliases for: " + cluster);
List<String> aliases = aliasService.getAliasesForCluster(cluster);
for (String alias : aliases) {
out.println(alias);
}
out.println("\n" + aliases.size() + " items.");
}

private Map<String, String> toMap() {
Map<String,String> aliases = new LinkedHashMap<>();
for (int i = 0; i < names.size(); i++) {
aliases.put(names.get(i), values.get(i));
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));
}
return aliases;

names.clear();
values.clear();
aliasMap.put(cluster, parsedAliases);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,183 @@ public void testGeneratingJwk512() throws Exception {
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-aliases", "--alias", "alias1", "--value", "value1", "--cluster", "cluster1",
"--alias", "alias2", "--value", "value2", "--alias", "alias1", "--value", "value1", "--cluster", "cluster2",
"--master", "master", "--list"};
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-aliases", "--alias", "alias1", "--cluster", "cluster1", "--alias",
"alias2", "--value", "value2", "--alias", "alias3", "--cluster", "cluster2",
"--master", "master", "--generate", "--list"};
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-aliases", "--alias", "alias1", "--cluster", "cluster1", "--alias",
"alias2", "--value", "value2", "--alias", "alias3",
"--master", "master", "--generate", "--list"};
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"));
}

@Test
public void testCreateAndListForMultipleClustersNoListing() throws Exception {
GatewayConfigImpl config = new GatewayConfigImpl();

outContent.reset();
String[] args1 = {"create-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]"));
assertFalse(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("2 alias(es) have been successfully created: [alias2, alias1]"));
assertFalse(outContent.toString(StandardCharsets.UTF_8.name()),
outContent.toString(StandardCharsets.UTF_8.name()).contains("Listing aliases for: cluster2"));
}

private void testGeneratingJWK(JWSAlgorithm jwkAlgorithm) throws Exception {
testGeneratingJWK(jwkAlgorithm, null);
}
Expand Down
Loading