/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 gobblin.cli; import java.util.List; import java.util.Map; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; import com.linkedin.r2.RemoteInvocationException; import gobblin.rest.JobExecutionInfo; import gobblin.rest.QueryListType; /** * Logic to print out job state */ public class JobCommand implements Command { private Options options; private static class CommandException extends Exception { private static final long serialVersionUID = 1L; public CommandException(String msg) { super(msg); } } private interface SubCommand { void execute(CommandLine parsedArgs, AdminClient adminClient, int resultsLimit) throws CommandException; } private static final String HELP_OPT = "help"; private static final String DETAILS_OPT = "details"; private static final String LIST_OPT = "list"; private static final String NAME_OPT = "name"; private static final String ID_OPT = "id"; private static final String PROPS_OPT = "properties"; private static final String RECENT_OPT = "recent"; private static final int DEFAULT_RESULTS_LIMIT = 10; private static final Map<String, SubCommand> subCommandMap = ImmutableMap.of( LIST_OPT, new ListAllItemsCommand(), DETAILS_OPT, new ListOneItemWithDetails(), PROPS_OPT, new ListItemsWithPropertiesCommand() ); private SubCommand getAction(CommandLine parsedOpts) { for (Map.Entry<String, SubCommand> entry : subCommandMap.entrySet()) { if (parsedOpts.hasOption(entry.getKey())) { return entry.getValue(); } } printHelpAndExit("Unknown subcommand"); throw new IllegalStateException("unreached..."); } @Override public void execute(Cli.GlobalOptions globalOptions, String[] otherArgs) { this.options = createCommandLineOptions(); DefaultParser parser = new DefaultParser(); AdminClient adminClient = null; try { CommandLine parsedOpts = parser.parse(options, otherArgs); int resultLimit = parseResultsLimit(parsedOpts); adminClient = new AdminClient(globalOptions.getAdminServerHost(), globalOptions.getAdminServerPort()); try { getAction(parsedOpts).execute(parsedOpts, adminClient, resultLimit); } catch (CommandException e) { printHelpAndExit(e.getMessage()); } } catch (ParseException e) { printHelpAndExit("Failed to parse jobs arguments: " + e.getMessage()); } finally { if (adminClient != null) adminClient.close(); } } private static class ListAllItemsCommand implements SubCommand { @Override public void execute(CommandLine parsedOpts, AdminClient adminClient, int resultsLimit) throws CommandException { try { if (parsedOpts.hasOption(NAME_OPT)) { JobInfoPrintUtils.printJobRuns(adminClient.queryByJobName(parsedOpts.getOptionValue(NAME_OPT), resultsLimit)); } else if (parsedOpts.hasOption(RECENT_OPT)) { JobInfoPrintUtils.printAllJobs(adminClient.queryAllJobs(QueryListType.RECENT, resultsLimit), resultsLimit); } else { JobInfoPrintUtils.printAllJobs(adminClient.queryAllJobs(QueryListType.DISTINCT, resultsLimit), resultsLimit); } } catch (RemoteInvocationException e) { throw new CommandException("Error talking to adminServer: " + e.getMessage()); } } } private static class ListOneItemWithDetails implements SubCommand { @Override public void execute(CommandLine parsedOpts, AdminClient adminClient, int resultsLimit) throws CommandException { try { if (parsedOpts.hasOption(ID_OPT)) { JobInfoPrintUtils.printJob( adminClient.queryByJobId(parsedOpts.getOptionValue(ID_OPT)) ); } else { throw new CommandException("Please specify an id"); } } catch (RemoteInvocationException e) { throw new CommandException("Error talking to adminServer: " + e.getMessage()); } } } private static class ListItemsWithPropertiesCommand implements SubCommand { @Override public void execute(CommandLine parsedOpts, AdminClient adminClient, int resultsLimit) throws CommandException { try { if (parsedOpts.hasOption(ID_OPT)) { JobInfoPrintUtils.printJobProperties( adminClient.queryByJobId(parsedOpts.getOptionValue(ID_OPT)) ); } else if (parsedOpts.hasOption(NAME_OPT)) { List<JobExecutionInfo> infos = adminClient.queryByJobName(parsedOpts.getOptionValue(NAME_OPT), 1); if (infos.size() == 0) { System.out.println("No job by that name found"); } else { JobInfoPrintUtils.printJobProperties(Optional.of(infos.get(0))); } } else { throw new CommandException("Please specify a job id or name"); } } catch (RemoteInvocationException e) { throw new CommandException("Error talking to adminServer: " + e.getMessage()); } } } private Options createCommandLineOptions() { Options options = new Options(); OptionGroup actionGroup = new OptionGroup(); actionGroup.addOption(new Option("h", HELP_OPT, false, "Shows the help message.")); actionGroup.addOption(new Option("d", DETAILS_OPT, false, "Show details about a job/task.")); actionGroup.addOption(new Option("l", LIST_OPT, false, "List jobs/tasks.")); actionGroup.addOption(new Option("p", PROPS_OPT, false, "Fetch properties with the query.")); actionGroup.setRequired(true); options.addOptionGroup(actionGroup); OptionGroup idGroup = new OptionGroup(); idGroup.addOption(new Option("j", NAME_OPT, true, "Find job(s) matching given job name.")); idGroup.addOption(new Option("i", ID_OPT, true, "Find the job/task with the given id.")); options.addOptionGroup(idGroup); options.addOption("n", true, "Limit the number of results returned. (default:" + DEFAULT_RESULTS_LIMIT + ")"); options.addOption("r", RECENT_OPT, false, "List the most recent jobs (instead of a list of unique jobs)"); return options; } private int parseResultsLimit(CommandLine parsedOpts) { if (parsedOpts.hasOption("n")) { try { return Integer.parseInt(parsedOpts.getOptionValue("n")); } catch (NumberFormatException e) { printHelpAndExit("Could not parse integer value for option n."); return 0; } } else { return DEFAULT_RESULTS_LIMIT; } } /** * Print help and exit with the specified code. */ private void printHelpAndExit(String errorMsg) { System.out.println(errorMsg); HelpFormatter hf = new HelpFormatter(); hf.printHelp("gobblin-admin.sh jobs [options]", this.options); System.exit(1); } }