/* * Copyright 2015-2016 OpenCB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.opencb.opencga.app.cli.admin; import com.beust.jcommander.*; import org.opencb.commons.utils.CommandLineUtils; import org.opencb.opencga.app.cli.GeneralCliOptions; import org.opencb.opencga.app.cli.GeneralCliOptions.GeneralOptions; import org.opencb.opencga.catalog.models.Account; import org.opencb.opencga.core.common.GitRepositoryState; import java.util.List; import java.util.Map; /** * Created by imedina on 02/03/15. */ public class AdminCliOptionsParser { private final JCommander jCommander; private final GeneralOptions generalOptions; private final AdminCommonCommandOptions commonCommandOptions; private CatalogCommandOptions catalogCommandOptions; private UsersCommandOptions usersCommandOptions; private AuditCommandOptions auditCommandOptions; private ToolsCommandOptions toolsCommandOptions; private ServerCommandOptions serverCommandOptions; public AdminCliOptionsParser() { generalOptions = new GeneralOptions(); jCommander = new JCommander(generalOptions); jCommander.setProgramName("opencga-admin.sh"); commonCommandOptions = new AdminCommonCommandOptions(); catalogCommandOptions = new CatalogCommandOptions(); jCommander.addCommand("catalog", catalogCommandOptions); JCommander catalogSubCommands = jCommander.getCommands().get("catalog"); catalogSubCommands.addCommand("demo", catalogCommandOptions.demoCatalogCommandOptions); catalogSubCommands.addCommand("install", catalogCommandOptions.installCatalogCommandOptions); catalogSubCommands.addCommand("delete", catalogCommandOptions.deleteCatalogCommandOptions); catalogSubCommands.addCommand("index", catalogCommandOptions.indexCatalogCommandOptions); catalogSubCommands.addCommand("clean", catalogCommandOptions.cleanCatalogCommandOptions); catalogSubCommands.addCommand("stats", catalogCommandOptions.statsCatalogCommandOptions); catalogSubCommands.addCommand("dump", catalogCommandOptions.dumpCatalogCommandOptions); catalogSubCommands.addCommand("import", catalogCommandOptions.importCatalogCommandOptions); catalogSubCommands.addCommand("daemon", catalogCommandOptions.daemonCatalogCommandOptions); usersCommandOptions = new UsersCommandOptions(); jCommander.addCommand("users", usersCommandOptions); JCommander usersSubCommands = jCommander.getCommands().get("users"); usersSubCommands.addCommand("create", usersCommandOptions.createUserCommandOptions); usersSubCommands.addCommand("import", usersCommandOptions.importUserCommandOptions); usersSubCommands.addCommand("delete", usersCommandOptions.deleteUserCommandOptions); usersSubCommands.addCommand("quota", usersCommandOptions.QuotaUserCommandOptions); usersSubCommands.addCommand("stats", usersCommandOptions.statsUserCommandOptions); auditCommandOptions = new AuditCommandOptions(); jCommander.addCommand("audit", auditCommandOptions); JCommander auditSubCommands = jCommander.getCommands().get("audit"); auditSubCommands.addCommand("query", auditCommandOptions.queryAuditCommandOptions); auditSubCommands.addCommand("stats", auditCommandOptions.statsAuditCommandOptions); toolsCommandOptions = new ToolsCommandOptions(); jCommander.addCommand("tools", toolsCommandOptions); JCommander toolsSubCommands = jCommander.getCommands().get("tools"); toolsSubCommands.addCommand("install", toolsCommandOptions.installToolCommandOptions); toolsSubCommands.addCommand("list", toolsCommandOptions.listToolCommandOptions); toolsSubCommands.addCommand("show", toolsCommandOptions.showToolCommandOptions); serverCommandOptions = new ServerCommandOptions(); jCommander.addCommand("server", serverCommandOptions); JCommander serverSubCommands = jCommander.getCommands().get("server"); serverSubCommands.addCommand("rest", serverCommandOptions.restServerCommandOptions); serverSubCommands.addCommand("grpc", serverCommandOptions.grpcServerCommandOptions); } public void parse(String[] args) throws ParameterException { jCommander.parse(args); } public String getCommand() { return (jCommander.getParsedCommand() != null) ? jCommander.getParsedCommand() : ""; } public String getSubCommand() { String parsedCommand = jCommander.getParsedCommand(); if (jCommander.getCommands().containsKey(parsedCommand)) { String subCommand = jCommander.getCommands().get(parsedCommand).getParsedCommand(); return subCommand != null ? subCommand: ""; } else { return null; } } public boolean isHelp() { String parsedCommand = jCommander.getParsedCommand(); if (parsedCommand != null) { JCommander jCommander2 = jCommander.getCommands().get(parsedCommand); List<Object> objects = jCommander2.getObjects(); if (!objects.isEmpty() && objects.get(0) instanceof AdminCommonCommandOptions) { return ((AdminCommonCommandOptions) objects.get(0)).help; } } return commonCommandOptions.help; } /** * This class contains all those parameters available for all 'commands' */ public class CommandOptions { @Parameter(names = {"-h", "--help"}, description = "This parameter prints this help", help = true) public boolean help; public JCommander getSubCommand() { return jCommander.getCommands().get(getCommand()).getCommands().get(getSubCommand()); } public String getParsedSubCommand() { String parsedCommand = jCommander.getParsedCommand(); if (jCommander.getCommands().containsKey(parsedCommand)) { String subCommand = jCommander.getCommands().get(parsedCommand).getParsedCommand(); return subCommand != null ? subCommand: ""; } else { return ""; } } } /** * This class contains all those common parameters available for all 'subcommands' */ public class AdminCommonCommandOptions extends GeneralCliOptions.CommonCommandOptions { @Parameter(names = {"-p", "--password"}, description = "Admin password", required = false, password = true, arity = 0) public String adminPassword; } /* * Catalog CLI options */ @Parameters(commandNames = {"catalog"}, commandDescription = "Implements different tools interact with Catalog database") public class CatalogCommandOptions extends CommandOptions { DemoCatalogCommandOptions demoCatalogCommandOptions; InstallCatalogCommandOptions installCatalogCommandOptions; DeleteCatalogCommandOptions deleteCatalogCommandOptions; IndexCatalogCommandOptions indexCatalogCommandOptions; CleanCatalogCommandOptions cleanCatalogCommandOptions; StatsCatalogCommandOptions statsCatalogCommandOptions; DumpCatalogCommandOptions dumpCatalogCommandOptions; ImportCatalogCommandOptions importCatalogCommandOptions; DaemonCatalogCommandOptions daemonCatalogCommandOptions; AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; public CatalogCommandOptions() { this.demoCatalogCommandOptions = new DemoCatalogCommandOptions(); this.installCatalogCommandOptions = new InstallCatalogCommandOptions(); this.deleteCatalogCommandOptions = new DeleteCatalogCommandOptions(); this.indexCatalogCommandOptions = new IndexCatalogCommandOptions(); this.cleanCatalogCommandOptions = new CleanCatalogCommandOptions(); this.statsCatalogCommandOptions = new StatsCatalogCommandOptions(); this.dumpCatalogCommandOptions = new DumpCatalogCommandOptions(); this.importCatalogCommandOptions = new ImportCatalogCommandOptions(); this.daemonCatalogCommandOptions = new DaemonCatalogCommandOptions(); } } /* * Users CLI options */ @Parameters(commandNames = {"users"}, commandDescription = "Implements different tools for working with users") public class UsersCommandOptions extends CommandOptions { CreateUserCommandOptions createUserCommandOptions; ImportUserCommandOptions importUserCommandOptions; DeleteUserCommandOptions deleteUserCommandOptions; StatsUserCommandOptions statsUserCommandOptions; QuotaUserCommandOptions QuotaUserCommandOptions; AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; public UsersCommandOptions() { this.createUserCommandOptions = new CreateUserCommandOptions(); this.importUserCommandOptions = new ImportUserCommandOptions(); this.deleteUserCommandOptions = new DeleteUserCommandOptions(); this.statsUserCommandOptions = new StatsUserCommandOptions(); this.QuotaUserCommandOptions = new QuotaUserCommandOptions(); } } /* * Audit CLI options */ @Parameters(commandNames = {"audit"}, commandDescription = "Implements different tools for working with audit") public class AuditCommandOptions extends CommandOptions { QueryAuditCommandOptions queryAuditCommandOptions; StatsAuditCommandOptions statsAuditCommandOptions; AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; public AuditCommandOptions() { this.queryAuditCommandOptions= new QueryAuditCommandOptions(); this.statsAuditCommandOptions= new StatsAuditCommandOptions(); } } /* * Tools CLI options */ @Parameters(commandNames = {"tools"}, commandDescription = "Implements different tools for working with tools") public class ToolsCommandOptions extends CommandOptions { InstallToolCommandOptions installToolCommandOptions; ListToolCommandOptions listToolCommandOptions; ShowToolCommandOptions showToolCommandOptions; AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; public ToolsCommandOptions() { this.installToolCommandOptions = new InstallToolCommandOptions(); this.listToolCommandOptions = new ListToolCommandOptions(); this.showToolCommandOptions = new ShowToolCommandOptions(); } } /* * Server CLI options */ @Parameters(commandNames = {"server"}, commandDescription = "Manage REST and gRPC servers") public class ServerCommandOptions extends CommandOptions { RestServerCommandOptions restServerCommandOptions; GrpcServerCommandOptions grpcServerCommandOptions; AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; public ServerCommandOptions() { this.restServerCommandOptions = new RestServerCommandOptions(); this.grpcServerCommandOptions = new GrpcServerCommandOptions(); } } /** * Auxiliary class for Database connection. */ class CatalogDatabaseCommandOptions { @Parameter(names = {"-d", "--database-prefix"}, description = "Prefix name of the catalog database. If not present this is read " + "from configuration.yml.") public String prefix; @Parameter(names = {"--database-host"}, description = "Database host and port, eg. localhost:27017. If not present is read from configuration.yml") public String databaseHost; @Parameter(names = {"--database-user"}, description = "Database user name. If not present is read from configuration.yml") public String databaseUser; @Parameter(names = {"--database-password"}, description = "Database password. If not present is read from configuration.yml", password = true, arity = 0) public String databasePassword; } /* * CATALOG SUB-COMMANDS */ @Parameters(commandNames = {"demo"}, commandDescription = "Install and populate a catalog database with demonstration purposes.") public class DemoCatalogCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--database-prefix"}, description = "Prefix name for the catalog demo database. If not present, it will be " + "set to 'demo'.") public String prefix; @Parameter(names = {"--force"}, description = "If this parameters is set, it will override the database installation.") public boolean force; } @Parameters(commandNames = {"install"}, commandDescription = "Install Catalog database and collections together with the indexes") public class InstallCatalogCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; // @Parameter(names = {"--overwrite"}, description = "Reset the database if exists before installing") // public boolean overwrite; } @Parameters(commandNames = {"delete"}, commandDescription = "Delete the Catalog database") public class DeleteCatalogCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; } @Parameters(commandNames = {"index"}, commandDescription = "Create the non-existing indices in Catalog database") public class IndexCatalogCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--reset"}, description = "Remove existing indexes before creting the new one") public boolean reset; } @Parameters(commandNames = {"clean"}, commandDescription = "Query audit data from Catalog database") public class CleanCatalogCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--collections"}, description = "A comma-separated list of collections to clean up") public String filter = "ALL"; } @Parameters(commandNames = {"stats"}, commandDescription = "Print some summary stats of Catalog database") public class StatsCatalogCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--collections"}, description = "A comma-separated list of collections for the stats") public String collections = "ALL"; } @Parameters(commandNames = {"dump"}, commandDescription = "Create a dump of Catalog database") public class DumpCatalogCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--collections"}, description = "A comma-separated list of collections to be dumped", arity = 1) public String collections = "ALL"; } @Parameters(commandNames = {"import"}, commandDescription = "Create a dump of Catalog database") public class ImportCatalogCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--collections"}, description = "A comma-separated list of collections to be imported", arity = 1) public String collections = "ALL"; } @Parameters(commandNames = {"daemon"}, commandDescription = "Start and stop Catalog daemons") public class DaemonCatalogCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--start"}, description = "File with the new tool to be installed", arity = 0) public boolean start; @Parameter(names = {"--stop"}, description = "File with the new tool to be installed", arity = 0) public boolean stop; } /* * AUDIT SUB-COMMANDS */ @Parameters(commandNames = {"query"}, commandDescription = "Query audit data from Catalog database") public class QueryAuditCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--filter"}, description = "Query filter for data") public String filter; } @Parameters(commandNames = {"stats"}, commandDescription = "Print summary stats for an user") public class StatsAuditCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; } /* * USER SUB-COMMANDS */ @Parameters(commandNames = {"create"}, commandDescription = "Create a new user") public class CreateUserCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"-u", "--id"}, description = "User id", required = true, arity = 1) public String userId; @Parameter(names = {"--name"}, description = "User name", required = true, arity = 1) public String userName; @Parameter(names = {"--user-password"}, description = "User password", required = true, arity = 1) public String userPassword; @Parameter(names = {"--type"}, description = "User account type of the user (guest or full).", arity = 1) public String type = Account.FULL; @Parameter(names = {"--email"}, description = "User email", required = true, arity = 1) public String userEmail; @Parameter(names = {"--organization"}, description = "User organization", required = false, arity = 1) public String userOrganization; @Parameter(names = {"--quota"}, description = "User disk quota", required = false, arity = 1) public Long userQuota; } @Parameters(commandNames = {"import"}, commandDescription = "Import users from an authentication origin into catalog") public class ImportUserCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"-u", "--users"}, description = "Comma separated list of user ids", required = true, arity = 1) public String users; @Parameter(names = {"-g", "--groups"}, description = "Comma separated list of group ids [PENDING]", arity = 1) public String groups; @Parameter(names = {"--auth-origin"}, description = "Authentication id (as defined in the catalog configuration file) of the origin" + " to be used to import users from.", arity = 1, required = true) public String authOrigin; @Parameter(names = {"--type"}, description = "User account type of the users to be imported (guest or full).", arity = 1) public String type = Account.FULL; @Parameter(names = {"--expiration-date"}, description = "Expiration date (DD/MM/YYYY). By default, 1 year starting from the " + "import day", arity = 1) public String expDate; @Parameter(names = {"--studies"}, description = "Comma separated list of studies where the imported users will be synchronized " + "with their belonging groups. If empty, users will not have any special permission.", arity = 1) public String studies; } @Parameters(commandNames = {"delete"}, commandDescription = "Delete the user Catalog database entry and the workspace") public class DeleteUserCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"-u", "--user-id"}, description = "Full name of the study where the file is classified", required = true, arity = 1) public String userId; } @Parameters(commandNames = {"quota"}, commandDescription = "Set a new disk quota for an user") public class QuotaUserCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"-u", "--user-id"}, description = "User id to get stats from", required = true, arity = 1) public String userId; @Parameter(names = {"--quota"}, description = "Disk quota in GB", required = true, arity = 1) public long quota; } @Parameters(commandNames = {"stats"}, commandDescription = "Print summary stats for an user") public class StatsUserCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"-u", "--user-id"}, description = "User id to get stats from", required = true, arity = 1) public String userId; } /* * TOOL SUB-COMMANDS */ @Parameters(commandNames = {"install"}, commandDescription = "Install and check a new tool") public class InstallToolCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"-i", "--input"}, description = "File with the new tool to be installed", required = true, arity = 1) public String study; } @Parameters(commandNames = {"list"}, commandDescription = "Print a summary list of all tools") public class ListToolCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--filter"}, description = "Some kind of filter", arity = 1) public String study; } @Parameters(commandNames = {"show"}, commandDescription = "Show a summary of the tool") public class ShowToolCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--tool-id"}, description = "Full name of the study where the file is classified", arity = 1) public String study; } /* * SERVER SUB-COMMANDS */ @Parameters(commandNames = {"rest"}, commandDescription = "Install and check a new tool") public class RestServerCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--start"}, description = "File with the new tool to be installed", arity = 0) public boolean start; @Parameter(names = {"--stop"}, description = "File with the new tool to be installed", arity = 0) public boolean stop; } @Parameters(commandNames = {"grpc"}, commandDescription = "Print a summary list of all tools") public class GrpcServerCommandOptions extends CatalogDatabaseCommandOptions { @ParametersDelegate public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions; @Parameter(names = {"--start"}, description = "File with the new tool to be installed", arity = 0) public boolean start; @Parameter(names = {"--stop"}, description = "File with the new tool to be installed", arity = 0) public boolean stop; } public void printUsage() { String parsedCommand = getCommand(); if (parsedCommand.isEmpty()) { System.err.println(""); System.err.println("Program: OpenCGA Admin (OpenCB)"); System.err.println("Version: " + GitRepositoryState.get().getBuildVersion()); System.err.println("Git commit: " + GitRepositoryState.get().getCommitId()); System.err.println("Description: Big Data platform for processing and analysing NGS data"); System.err.println(""); System.err.println("Usage: opencga-admin.sh [-h|--help] [--version] <command> [options]"); System.err.println(""); System.err.println("Commands:"); printMainUsage(); System.err.println(""); } else { String parsedSubCommand = getSubCommand(); if (parsedSubCommand.isEmpty()) { System.err.println(""); System.err.println("Usage: opencga-admin.sh " + parsedCommand + " <subcommand> [options]"); System.err.println(""); System.err.println("Subcommands:"); printCommands(jCommander.getCommands().get(parsedCommand)); System.err.println(""); } else { System.err.println(""); System.err.println("Usage: opencga-admin.sh " + parsedCommand + " " + parsedSubCommand + " [options]"); System.err.println(""); System.err.println("Options:"); CommandLineUtils.printCommandUsage(jCommander.getCommands().get(parsedCommand).getCommands().get(parsedSubCommand)); System.err.println(""); } } } private void printMainUsage() { for (String s : jCommander.getCommands().keySet()) { System.err.printf("%14s %s\n", s, jCommander.getCommandDescription(s)); } } private void printCommands(JCommander commander) { for (Map.Entry<String, JCommander> entry : commander.getCommands().entrySet()) { System.err.printf("%14s %s\n", entry.getKey(), commander.getCommandDescription(entry.getKey())); } } public GeneralOptions getGeneralOptions() { return generalOptions; } public AdminCommonCommandOptions getCommonOptions() { return commonCommandOptions; } public CatalogCommandOptions getCatalogCommandOptions() { return catalogCommandOptions; } public UsersCommandOptions getUsersCommandOptions() { return usersCommandOptions; } public AuditCommandOptions getAuditCommandOptions() { return auditCommandOptions; } public ToolsCommandOptions getToolsCommandOptions() { return toolsCommandOptions; } public ServerCommandOptions getServerCommandOptions() { return serverCommandOptions; } }