FALCON-1895 Refactoring of FalconCLI and FalconClient Author: Praveen Adlakha <[email protected]>
Reviewers: Peeyush Bishnoi<[email protected]>, Balu<[email protected]>, Sowmya<[email protected]> Closes #94 from PraveenAdlakha/1895 and squashes the following commits: 00a65a2 [Praveen Adlakha] merge conflicts resolved d069466 [Praveen Adlakha] sync from upstream 4e79efc [Praveen Adlakha] extra space removed d8bc106 [Praveen Adlakha] FALCON-1895 Refactoring of FalconCLI and FalconClient Project: http://git-wip-us.apache.org/repos/asf/falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/falcon/commit/6655e90a Tree: http://git-wip-us.apache.org/repos/asf/falcon/tree/6655e90a Diff: http://git-wip-us.apache.org/repos/asf/falcon/diff/6655e90a Branch: refs/heads/master Commit: 6655e90a7b3990cbe8dffd2e20d3657c249b123e Parents: 3e22a77 Author: Praveen Adlakha <[email protected]> Authored: Wed Apr 13 21:09:37 2016 +0530 Committer: peeyush b <[email protected]> Committed: Wed Apr 13 21:09:37 2016 +0530 ---------------------------------------------------------------------- cli/pom.xml | 15 +- .../org/apache/falcon/cli/FalconAdminCLI.java | 111 ++++++ .../java/org/apache/falcon/cli/FalconCLI.java | 283 +++++++++++++++ .../org/apache/falcon/cli/FalconEntityCLI.java | 362 +++++++++++++++++++ .../apache/falcon/cli/FalconInstanceCLI.java | 340 +++++++++++++++++ .../apache/falcon/cli/FalconMetadataCLI.java | 256 +++++++++++++ .../org/apache/falcon/FalconCLIConstants.java | 76 ++++ .../java/org/apache/falcon/cli/CLIParser.java | 155 -------- .../org/apache/falcon/cli/FalconAdminCLI.java | 109 ------ .../java/org/apache/falcon/cli/FalconCLI.java | 318 ---------------- .../org/apache/falcon/cli/FalconEntityCLI.java | 360 ------------------ .../apache/falcon/cli/FalconInstanceCLI.java | 336 ----------------- .../apache/falcon/cli/FalconMetadataCLI.java | 256 ------------- .../org/apache/falcon/client/FalconClient.java | 21 +- .../org/apache/falcon/cli/TestCLIParser.java | 69 ---- .../org/apache/falcon/cliParser/CLIParser.java | 155 ++++++++ .../falcon/tools/FalconStateStoreDBCLI.java | 2 +- common/src/test/java/cli/TestCLIParser.java | 70 ++++ webapp/pom.xml | 6 + .../java/org/apache/falcon/cli/FalconCLIIT.java | 52 +-- .../org/apache/falcon/resource/TestContext.java | 5 +- 21 files changed, 1710 insertions(+), 1647 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/falcon/blob/6655e90a/cli/pom.xml ---------------------------------------------------------------------- diff --git a/cli/pom.xml b/cli/pom.xml index 408c6ee..ff4a16b 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -53,10 +53,7 @@ </profiles> <dependencies> - <dependency> - <groupId>org.apache.falcon</groupId> - <artifactId>falcon-client</artifactId> - </dependency> + <dependency> <groupId>commons-net</groupId> @@ -142,6 +139,16 @@ <artifactId>spring-beans</artifactId> <version>4.0.3.RELEASE</version> </dependency> + <dependency> + <groupId>org.apache.falcon</groupId> + <artifactId>falcon-client</artifactId> + <version>0.10-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.falcon</groupId> + <artifactId>falcon-common</artifactId> + <version>0.10-SNAPSHOT</version> + </dependency> </dependencies> http://git-wip-us.apache.org/repos/asf/falcon/blob/6655e90a/cli/src/main/java/org/apache/falcon/cli/FalconAdminCLI.java ---------------------------------------------------------------------- diff --git a/cli/src/main/java/org/apache/falcon/cli/FalconAdminCLI.java b/cli/src/main/java/org/apache/falcon/cli/FalconAdminCLI.java new file mode 100644 index 0000000..56cc5b9 --- /dev/null +++ b/cli/src/main/java/org/apache/falcon/cli/FalconAdminCLI.java @@ -0,0 +1,111 @@ +/** + * 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 org.apache.falcon.cli; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.falcon.FalconCLIConstants; +import org.apache.falcon.client.FalconCLIException; +import org.apache.falcon.client.FalconClient; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +/** + * Admin extension to Falcon Command Line Interface - wraps the RESTful API for admin commands. + */ +public class FalconAdminCLI extends FalconCLI { + + private static final String STACK_OPTION = "stack"; + + public FalconAdminCLI() throws Exception { + super(); + } + + public Options createAdminOptions() { + Options adminOptions = new Options(); + Option url = new Option(FalconCLIConstants.URL_OPTION, true, "Falcon URL"); + adminOptions.addOption(url); + + OptionGroup group = new OptionGroup(); + Option status = new Option(FalconCLIConstants.STATUS_OPT, false, + "show the current system status"); + Option version = new Option(FalconCLIConstants.VERSION_OPT, false, + "show Falcon server build version"); + Option stack = new Option(STACK_OPTION, false, + "show the thread stack dump"); + Option doAs = new Option(FalconCLIConstants.DO_AS_OPT, true, + "doAs user"); + Option help = new Option("help", false, "show Falcon help"); + Option debug = new Option(FalconCLIConstants.DEBUG_OPTION, false, + "Use debug mode to see debugging statements on stdout"); + group.addOption(status); + group.addOption(version); + group.addOption(stack); + group.addOption(help); + + adminOptions.addOptionGroup(group); + adminOptions.addOption(doAs); + adminOptions.addOption(debug); + return adminOptions; + } + + public int adminCommand(CommandLine commandLine, FalconClient client, + String falconUrl) throws FalconCLIException, IOException { + String result; + Set<String> optionsList = new HashSet<String>(); + for (Option option : commandLine.getOptions()) { + optionsList.add(option.getOpt()); + } + + String doAsUser = commandLine.getOptionValue(FalconCLIConstants.DO_AS_OPT); + + if (optionsList.contains(STACK_OPTION)) { + result = client.getThreadDump(doAsUser); + OUT.get().println(result); + } + + int exitValue = 0; + if (optionsList.contains(FalconCLIConstants.STATUS_OPT)) { + try { + int status = client.getStatus(doAsUser); + if (status != 200) { + ERR.get().println("Falcon server is not fully operational (on " + falconUrl + "). " + + "Please check log files."); + exitValue = status; + } else { + OUT.get().println("Falcon server is running (on " + falconUrl + ")"); + } + } catch (Exception e) { + ERR.get().println("Falcon server doesn't seem to be running on " + falconUrl); + exitValue = -1; + } + } else if (optionsList.contains(FalconCLIConstants.VERSION_OPT)) { + result = client.getVersion(doAsUser); + OUT.get().println("Falcon server build version: " + result); + } else if (optionsList.contains(FalconCLIConstants.HELP_CMD)) { + OUT.get().println("Falcon Help"); + } + return exitValue; + } + +} http://git-wip-us.apache.org/repos/asf/falcon/blob/6655e90a/cli/src/main/java/org/apache/falcon/cli/FalconCLI.java ---------------------------------------------------------------------- diff --git a/cli/src/main/java/org/apache/falcon/cli/FalconCLI.java b/cli/src/main/java/org/apache/falcon/cli/FalconCLI.java new file mode 100644 index 0000000..a414c94 --- /dev/null +++ b/cli/src/main/java/org/apache/falcon/cli/FalconCLI.java @@ -0,0 +1,283 @@ +/** + * 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 org.apache.falcon.cli; + +import com.sun.jersey.api.client.ClientHandlerException; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.falcon.FalconCLIConstants; +import org.apache.falcon.cliParser.CLIParser; +import org.apache.falcon.client.FalconCLIException; +import org.apache.falcon.client.FalconClient; +import org.apache.falcon.entity.v0.EntityType; +import org.apache.falcon.resource.EntityList; +import org.apache.falcon.resource.InstancesResult; +import org.apache.falcon.resource.InstancesSummaryResult; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Falcon Command Line Interface - wraps the RESTful API. + */ +public class FalconCLI { + + public static final AtomicReference<PrintStream> ERR = new AtomicReference<PrintStream>(System.err); + public static final AtomicReference<PrintStream> OUT = new AtomicReference<PrintStream>(System.out); + + private static final String FALCON_URL = "FALCON_URL"; + private final Properties clientProperties; + + public FalconCLI() throws Exception { + clientProperties = getClientProperties(); + } + + /** + * Entry point for the Falcon CLI when invoked from the command line. Upon + * completion this method exits the JVM with '0' (success) or '-1' + * (failure). + * + * @param args options and arguments for the Falcon CLI. + */ + public static void main(final String[] args) throws Exception { + System.exit(new FalconCLI().run(args)); + } + + // TODO help and headers + private static final String[] FALCON_HELP = { "the env variable '" + FALCON_URL + + "' is used as default value for the '-" + + FalconCLIConstants.URL_OPTION + "' option", + "custom headers for Falcon web services can be specified using '-D" + + FalconClient.WS_HEADER_PREFIX + "NAME=VALUE'", }; + /** + * Run a CLI programmatically. + * <p/> + * It does not exit the JVM. + * <p/> + * A CLI instance can be used only once. + * + * @param args options and arguments for the Oozie CLI. + * @return '0' (success), '-1' (failure). + */ + public synchronized int run(final String[] args) throws Exception { + + CLIParser parser = new CLIParser("falcon", FALCON_HELP); + + FalconAdminCLI adminCLI = new FalconAdminCLI(); + FalconEntityCLI entityCLI = new FalconEntityCLI(); + FalconInstanceCLI instanceCLI = new FalconInstanceCLI(); + FalconMetadataCLI metadataCLI = new FalconMetadataCLI(); + + parser.addCommand(FalconCLIConstants.ADMIN_CMD, "", "admin operations", adminCLI.createAdminOptions(), true); + parser.addCommand(FalconCLIConstants.HELP_CMD, "", "display usage", new Options(), false); + parser.addCommand(FalconCLIConstants.ENTITY_CMD, "", + "Entity operations like submit, suspend, resume, delete, status, definition, submitAndSchedule", + entityCLI.createEntityOptions(), false); + parser.addCommand(FalconCLIConstants.INSTANCE_CMD, "", + "Process instances operations like running, status, kill, suspend, resume, rerun, logs", + instanceCLI.createInstanceOptions(), false); + parser.addCommand(FalconCLIConstants.METADATA_CMD, "", "Metadata operations like list, relations", + metadataCLI.createMetadataOptions(), true); + parser.addCommand(FalconCLIConstants.VERSION_OPT, "", "show client version", new Options(), false); + + try { + CLIParser.Command command = parser.parse(args); + int exitValue = 0; + if (command.getName().equals(FalconCLIConstants.HELP_CMD)) { + parser.showHelp(); + } else { + CommandLine commandLine = command.getCommandLine(); + String falconUrl = getFalconEndpoint(commandLine); + FalconClient client = new FalconClient(falconUrl, clientProperties); + + setDebugMode(client, commandLine.hasOption(FalconCLIConstants.DEBUG_OPTION)); + if (command.getName().equals(FalconCLIConstants.ADMIN_CMD)) { + exitValue = adminCLI.adminCommand(commandLine, client, falconUrl); + } else if (command.getName().equals(FalconCLIConstants.ENTITY_CMD)) { + entityCLI.entityCommand(commandLine, client); + } else if (command.getName().equals(FalconCLIConstants.INSTANCE_CMD)) { + instanceCLI.instanceCommand(commandLine, client); + } else if (command.getName().equals(FalconCLIConstants.METADATA_CMD)) { + metadataCLI.metadataCommand(commandLine, client); + } + } + return exitValue; + } catch (ParseException ex) { + ERR.get().println("Invalid sub-command: " + ex.getMessage()); + ERR.get().println(); + ERR.get().println(parser.shortHelp()); + ERR.get().println("Stacktrace:"); + ex.printStackTrace(); + return -1; + } catch (ClientHandlerException ex) { + ERR.get().print("Unable to connect to Falcon server, " + + "please check if the URL is correct and Falcon server is up and running\n"); + ERR.get().println("Stacktrace:"); + ex.printStackTrace(); + return -1; + } catch (FalconCLIException e) { + ERR.get().println("ERROR: " + e.getMessage()); + return -1; + } catch (Exception ex) { + ERR.get().println("Stacktrace:"); + ex.printStackTrace(); + return -1; + } + } + + protected Integer parseIntegerInput(String optionValue, Integer defaultVal, String optionName) + throws FalconCLIException { + Integer integer = defaultVal; + if (optionValue != null) { + try { + return Integer.parseInt(optionValue); + } catch (NumberFormatException e) { + throw new FalconCLIException("Input value provided for queryParam \""+ optionName + +"\" is not a valid Integer"); + } + } + return integer; + } + + protected void validateEntityTypeForSummary(String type) throws FalconCLIException { + EntityType entityType = EntityType.getEnum(type); + if (!entityType.isSchedulable()) { + throw new FalconCLIException("Invalid entity type " + entityType + + " for EntitySummary API. Valid options are feed or process"); + } + } + + protected void validateNotEmpty(String paramVal, String paramName) throws FalconCLIException { + if (StringUtils.isBlank(paramVal)) { + throw new FalconCLIException("Missing argument : " + paramName); + } + } + + protected void validateSortOrder(String sortOrder) throws FalconCLIException { + if (!StringUtils.isBlank(sortOrder)) { + if (!sortOrder.equalsIgnoreCase("asc") && !sortOrder.equalsIgnoreCase("desc")) { + throw new FalconCLIException("Value for param sortOrder should be \"asc\" or \"desc\". It is : " + + sortOrder); + } + } + } + + protected String getColo(String colo) throws FalconCLIException, IOException { + if (colo == null) { + Properties prop = getClientProperties(); + colo = prop.getProperty(FalconCLIConstants.CURRENT_COLO, "*"); + } + return colo; + } + + protected void validateFilterBy(String filterBy, String filterType) throws FalconCLIException { + if (StringUtils.isEmpty(filterBy)) { + return; + } + String[] filterSplits = filterBy.split(","); + for (String s : filterSplits) { + String[] tempKeyVal = s.split(":", 2); + try { + if (filterType.equals("entity")) { + EntityList.EntityFilterByFields.valueOf(tempKeyVal[0].toUpperCase()); + } else if (filterType.equals("instance")) { + InstancesResult.InstanceFilterFields.valueOf(tempKeyVal[0].toUpperCase()); + }else if (filterType.equals("summary")) { + InstancesSummaryResult.InstanceSummaryFilterFields.valueOf(tempKeyVal[0].toUpperCase()); + } else { + throw new IllegalArgumentException("Invalid API call: filterType is not valid"); + } + } catch (IllegalArgumentException ie) { + throw new FalconCLIException("Invalid filterBy argument : " + tempKeyVal[0] + " in : " + s); + } + } + } + + protected void validateOrderBy(String orderBy, String action) throws FalconCLIException { + if (StringUtils.isBlank(orderBy)) { + return; + } + if (action.equals("instance")) { + if (Arrays.asList(new String[]{"status", "cluster", "starttime", "endtime"}) + .contains(orderBy.toLowerCase())) { + return; + } + } else if (action.equals("entity")) { + if (Arrays.asList(new String[] {"type", "name"}).contains(orderBy.toLowerCase())) { + return; + } + } else if (action.equals("summary")) { + if (Arrays.asList(new String[]{"cluster"}) + .contains(orderBy.toLowerCase())) { + return; + } + } + throw new FalconCLIException("Invalid orderBy argument : " + orderBy); + } + + protected String getFalconEndpoint(CommandLine commandLine) throws FalconCLIException, IOException { + String url = commandLine.getOptionValue(FalconCLIConstants.URL_OPTION); + if (url == null) { + url = System.getenv(FALCON_URL); + } + if (url == null) { + if (clientProperties.containsKey("falcon.url")) { + url = clientProperties.getProperty("falcon.url"); + } + } + if (url == null) { + throw new FalconCLIException("Failed to get falcon url from cmdline, or environment or client properties"); + } + + return url; + } + + private void setDebugMode(FalconClient client, boolean debugOpt) { + String debug = System.getenv(FalconCLIConstants.ENV_FALCON_DEBUG); + if (debugOpt) { // CLI argument "-debug" used + client.setDebugMode(true); + } else if (StringUtils.isNotBlank(debug)) { + System.out.println(FalconCLIConstants.ENV_FALCON_DEBUG + ": " + debug); + if (debug.trim().toLowerCase().equals("true")) { + client.setDebugMode(true); + } + } + } + + private Properties getClientProperties() throws IOException { + InputStream inputStream = null; + try { + inputStream = FalconCLI.class.getResourceAsStream(FalconCLIConstants.CLIENT_PROPERTIES); + Properties prop = new Properties(); + if (inputStream != null) { + prop.load(inputStream); + } + return prop; + } finally { + IOUtils.closeQuietly(inputStream); + } + } +} http://git-wip-us.apache.org/repos/asf/falcon/blob/6655e90a/cli/src/main/java/org/apache/falcon/cli/FalconEntityCLI.java ---------------------------------------------------------------------- diff --git a/cli/src/main/java/org/apache/falcon/cli/FalconEntityCLI.java b/cli/src/main/java/org/apache/falcon/cli/FalconEntityCLI.java new file mode 100644 index 0000000..fa71d67 --- /dev/null +++ b/cli/src/main/java/org/apache/falcon/cli/FalconEntityCLI.java @@ -0,0 +1,362 @@ +/** + * 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 org.apache.falcon.cli; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.commons.lang3.StringUtils; +import org.apache.falcon.FalconCLIConstants; +import org.apache.falcon.ResponseHelper; +import org.apache.falcon.client.FalconCLIException; +import org.apache.falcon.client.FalconClient; +import org.apache.falcon.entity.v0.EntityType; +import org.apache.falcon.entity.v0.SchemaHelper; +import org.apache.falcon.resource.EntityList; +import org.apache.falcon.resource.FeedLookupResult; +import org.apache.falcon.resource.SchedulableEntityInstanceResult; + +import java.io.IOException; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +/** + * Entity extension to Falcon Command Line Interface - wraps the RESTful API for entities. + */ +public class FalconEntityCLI extends FalconCLI { + + private static final String SUBMIT_OPT = "submit"; + private static final String UPDATE_OPT = "update"; + private static final String DELETE_OPT = "delete"; + private static final String SUBMIT_AND_SCHEDULE_OPT = "submitAndSchedule"; + private static final String VALIDATE_OPT = "validate"; + private static final String DEFINITION_OPT = "definition"; + public static final String SLA_MISS_ALERT_OPT = "slaAlert"; + + private static final String LOOKUP_OPT = "lookup"; + private static final String PATH_OPT = "path"; + private static final String TOUCH_OPT = "touch"; + private static final String PROPS_OPT = "properties"; + private static final String FIELDS_OPT = "fields"; + private static final String TAGS_OPT = "tags"; + private static final String NUM_INSTANCES_OPT = "numInstances"; + private static final String NAMESEQ_OPT = "nameseq"; + private static final String TAGKEYS_OPT = "tagkeys"; + private static final String SHOWSCHEDULER_OPT = "showScheduler"; + + public FalconEntityCLI() throws Exception { + super(); + } + + public Options createEntityOptions() { + + Options entityOptions = new Options(); + + Option submit = new Option(SUBMIT_OPT, false, + "Submits an entity xml to Falcon"); + Option update = new Option(UPDATE_OPT, false, + "Updates an existing entity xml"); + Option schedule = new Option(FalconCLIConstants.SCHEDULE_OPT, false, + "Schedules a submited entity in Falcon"); + Option suspend = new Option(FalconCLIConstants.SUSPEND_OPT, false, + "Suspends a running entity in Falcon"); + Option resume = new Option(FalconCLIConstants.RESUME_OPT, false, + "Resumes a suspended entity in Falcon"); + Option delete = new Option(DELETE_OPT, false, + "Deletes an entity in Falcon, and kills its instance from workflow engine"); + Option submitAndSchedule = new Option(SUBMIT_AND_SCHEDULE_OPT, false, + "Submits and entity to Falcon and schedules it immediately"); + Option validate = new Option(VALIDATE_OPT, false, + "Validates an entity based on the entity type"); + Option status = new Option(FalconCLIConstants.STATUS_OPT, false, + "Gets the status of entity"); + Option definition = new Option(DEFINITION_OPT, false, + "Gets the Definition of entity"); + Option dependency = new Option(FalconCLIConstants.DEPENDENCY_OPT, false, + "Gets the dependencies of entity"); + Option list = new Option(FalconCLIConstants.LIST_OPT, false, + "List entities registered for a type"); + Option lookup = new Option(LOOKUP_OPT, false, "Lookup a feed given its instance's path"); + Option slaAlert = new Option(SLA_MISS_ALERT_OPT, false, "Get missing feed instances which missed SLA"); + Option entitySummary = new Option(FalconCLIConstants.SUMMARY_OPT, false, + "Get summary of instances for list of entities"); + Option touch = new Option(TOUCH_OPT, false, + "Force update the entity in workflow engine(even without any changes to entity)"); + + OptionGroup group = new OptionGroup(); + group.addOption(submit); + group.addOption(update); + group.addOption(schedule); + group.addOption(suspend); + group.addOption(resume); + group.addOption(delete); + group.addOption(submitAndSchedule); + group.addOption(validate); + group.addOption(status); + group.addOption(definition); + group.addOption(dependency); + group.addOption(list); + group.addOption(lookup); + group.addOption(slaAlert); + group.addOption(entitySummary); + group.addOption(touch); + + Option url = new Option(FalconCLIConstants.URL_OPTION, true, "Falcon URL"); + Option entityType = new Option(FalconCLIConstants.TYPE_OPT, true, + "Entity type, can be cluster, feed or process xml"); + Option filePath = new Option(FalconCLIConstants.FILE_PATH_OPT, true, + "Path to entity xml file"); + Option entityName = new Option(FalconCLIConstants.ENTITY_NAME_OPT, true, + "Entity type, can be cluster, feed or process xml"); + Option start = new Option(FalconCLIConstants.START_OPT, true, "Start time is optional for summary"); + Option end = new Option(FalconCLIConstants.END_OPT, true, "End time is optional for summary"); + Option colo = new Option(FalconCLIConstants.COLO_OPT, true, "Colo name"); + Option cluster = new Option(FalconCLIConstants.CLUSTER_OPT, true, "Cluster name"); + colo.setRequired(false); + Option fields = new Option(FIELDS_OPT, true, "Entity fields to show for a request"); + Option filterBy = new Option(FalconCLIConstants.FILTER_BY_OPT, true, + "Filter returned entities by the specified status"); + Option filterTags = new Option(TAGS_OPT, true, "Filter returned entities by the specified tags"); + Option nameSubsequence = new Option(NAMESEQ_OPT, true, "Subsequence of entity name"); + Option tagKeywords = new Option(TAGKEYS_OPT, true, "Keywords in tags"); + Option orderBy = new Option(FalconCLIConstants.ORDER_BY_OPT, true, + "Order returned entities by this field"); + Option sortOrder = new Option(FalconCLIConstants.SORT_ORDER_OPT, true, "asc or desc order for results"); + Option offset = new Option(FalconCLIConstants.OFFSET_OPT, true, + "Start returning entities from this offset"); + Option numResults = new Option(FalconCLIConstants.NUM_RESULTS_OPT, true, + "Number of results to return per request"); + Option numInstances = new Option(NUM_INSTANCES_OPT, true, + "Number of instances to return per entity summary request"); + Option path = new Option(PATH_OPT, true, "Path for a feed's instance"); + Option skipDryRun = new Option(FalconCLIConstants.SKIPDRYRUN_OPT, false, "skip dry run in workflow engine"); + Option doAs = new Option(FalconCLIConstants.DO_AS_OPT, true, "doAs user"); + Option userProps = new Option(PROPS_OPT, true, "User supplied comma separated key value properties"); + Option showScheduler = new Option(SHOWSCHEDULER_OPT, false, "To return the scheduler " + + "on which the entity is scheduled."); + Option debug = new Option(FalconCLIConstants.DEBUG_OPTION, false, + "Use debug mode to see debugging statements on stdout"); + + entityOptions.addOption(url); + entityOptions.addOption(path); + entityOptions.addOptionGroup(group); + entityOptions.addOption(entityType); + entityOptions.addOption(entityName); + entityOptions.addOption(filePath); + entityOptions.addOption(colo); + entityOptions.addOption(cluster); + entityOptions.addOption(start); + entityOptions.addOption(end); + entityOptions.addOption(fields); + entityOptions.addOption(filterBy); + entityOptions.addOption(filterTags); + entityOptions.addOption(nameSubsequence); + entityOptions.addOption(tagKeywords); + entityOptions.addOption(orderBy); + entityOptions.addOption(sortOrder); + entityOptions.addOption(offset); + entityOptions.addOption(numResults); + entityOptions.addOption(numInstances); + entityOptions.addOption(skipDryRun); + entityOptions.addOption(doAs); + entityOptions.addOption(userProps); + entityOptions.addOption(debug); + entityOptions.addOption(showScheduler); + + return entityOptions; + } + + public void entityCommand(CommandLine commandLine, FalconClient client) throws FalconCLIException, IOException { + Set<String> optionsList = new HashSet<String>(); + for (Option option : commandLine.getOptions()) { + optionsList.add(option.getOpt()); + } + + String result = null; + String entityType = commandLine.getOptionValue(FalconCLIConstants.TYPE_OPT); + String entityName = commandLine.getOptionValue(FalconCLIConstants.ENTITY_NAME_OPT); + String filePath = commandLine.getOptionValue(FalconCLIConstants.FILE_PATH_OPT); + String colo = commandLine.getOptionValue(FalconCLIConstants.COLO_OPT); + colo = getColo(colo); + String cluster = commandLine.getOptionValue(FalconCLIConstants.CLUSTER_OPT); + String start = commandLine.getOptionValue(FalconCLIConstants.START_OPT); + String end = commandLine.getOptionValue(FalconCLIConstants.END_OPT); + String orderBy = commandLine.getOptionValue(FalconCLIConstants.ORDER_BY_OPT); + String sortOrder = commandLine.getOptionValue(FalconCLIConstants.SORT_ORDER_OPT); + String filterBy = commandLine.getOptionValue(FalconCLIConstants.FILTER_BY_OPT); + String filterTags = commandLine.getOptionValue(TAGS_OPT); + String nameSubsequence = commandLine.getOptionValue(NAMESEQ_OPT); + String tagKeywords = commandLine.getOptionValue(TAGKEYS_OPT); + String fields = commandLine.getOptionValue(FIELDS_OPT); + String feedInstancePath = commandLine.getOptionValue(PATH_OPT); + Integer offset = parseIntegerInput(commandLine.getOptionValue(FalconCLIConstants.OFFSET_OPT), 0, "offset"); + Integer numResults = parseIntegerInput(commandLine.getOptionValue(FalconCLIConstants.NUM_RESULTS_OPT), + null, "numResults"); + String doAsUser = commandLine.getOptionValue(FalconCLIConstants.DO_AS_OPT); + + Integer numInstances = parseIntegerInput(commandLine.getOptionValue(NUM_INSTANCES_OPT), 7, "numInstances"); + Boolean skipDryRun = null; + if (optionsList.contains(FalconCLIConstants.SKIPDRYRUN_OPT)) { + skipDryRun = true; + } + + String userProps = commandLine.getOptionValue(PROPS_OPT); + boolean showScheduler = false; + if (optionsList.contains(SHOWSCHEDULER_OPT)) { + showScheduler = true; + } + + EntityType entityTypeEnum = null; + if (optionsList.contains(FalconCLIConstants.LIST_OPT)) { + if (entityType == null) { + entityType = ""; + } + if (StringUtils.isNotEmpty(entityType)) { + String[] types = entityType.split(","); + for (String type : types) { + EntityType.getEnum(type); + } + } + } else { + validateNotEmpty(entityType, FalconCLIConstants.TYPE_OPT); + entityTypeEnum = EntityType.getEnum(entityType); + } + validateSortOrder(sortOrder); + String entityAction = "entity"; + + if (optionsList.contains(SLA_MISS_ALERT_OPT)) { + validateNotEmpty(entityType, FalconCLIConstants.TYPE_OPT); + validateNotEmpty(start, FalconCLIConstants.START_OPT); + parseDateString(start); + parseDateString(end); + SchedulableEntityInstanceResult response = client.getFeedSlaMissPendingAlerts(entityType, + entityName, start, end, colo); + result = ResponseHelper.getString(response); + } else if (optionsList.contains(SUBMIT_OPT)) { + validateNotEmpty(filePath, "file"); + validateColo(optionsList); + result = client.submit(entityType, filePath, doAsUser).getMessage(); + } else if (optionsList.contains(LOOKUP_OPT)) { + validateNotEmpty(feedInstancePath, PATH_OPT); + FeedLookupResult resp = client.reverseLookUp(entityType, feedInstancePath, doAsUser); + result = ResponseHelper.getString(resp); + } else if (optionsList.contains(UPDATE_OPT)) { + validateNotEmpty(filePath, "file"); + validateColo(optionsList); + validateNotEmpty(entityName, FalconCLIConstants.ENTITY_NAME_OPT); + result = client.update(entityType, entityName, filePath, skipDryRun, doAsUser).getMessage(); + } else if (optionsList.contains(SUBMIT_AND_SCHEDULE_OPT)) { + validateNotEmpty(filePath, "file"); + validateColo(optionsList); + result = client.submitAndSchedule(entityType, filePath, skipDryRun, doAsUser, userProps).getMessage(); + } else if (optionsList.contains(VALIDATE_OPT)) { + validateNotEmpty(filePath, "file"); + validateColo(optionsList); + result = client.validate(entityType, filePath, skipDryRun, doAsUser).getMessage(); + } else if (optionsList.contains(FalconCLIConstants.SCHEDULE_OPT)) { + validateNotEmpty(entityName, FalconCLIConstants.ENTITY_NAME_OPT); + colo = getColo(colo); + result = client.schedule(entityTypeEnum, entityName, colo, skipDryRun, doAsUser, userProps).getMessage(); + } else if (optionsList.contains(FalconCLIConstants.SUSPEND_OPT)) { + validateNotEmpty(entityName, FalconCLIConstants.ENTITY_NAME_OPT); + colo = getColo(colo); + result = client.suspend(entityTypeEnum, entityName, colo, doAsUser).getMessage(); + } else if (optionsList.contains(FalconCLIConstants.RESUME_OPT)) { + validateNotEmpty(entityName, FalconCLIConstants.ENTITY_NAME_OPT); + colo = getColo(colo); + result = client.resume(entityTypeEnum, entityName, colo, doAsUser).getMessage(); + } else if (optionsList.contains(DELETE_OPT)) { + validateColo(optionsList); + validateNotEmpty(entityName, FalconCLIConstants.ENTITY_NAME_OPT); + result = client.delete(entityTypeEnum, entityName, doAsUser).getMessage(); + } else if (optionsList.contains(FalconCLIConstants.STATUS_OPT)) { + validateNotEmpty(entityName, FalconCLIConstants.ENTITY_NAME_OPT); + colo = getColo(colo); + result = client.getStatus(entityTypeEnum, entityName, colo, doAsUser, showScheduler).getMessage(); + } else if (optionsList.contains(DEFINITION_OPT)) { + validateColo(optionsList); + validateNotEmpty(entityName, FalconCLIConstants.ENTITY_NAME_OPT); + result = client.getDefinition(entityType, entityName, doAsUser).toString(); + } else if (optionsList.contains(FalconCLIConstants.DEPENDENCY_OPT)) { + validateColo(optionsList); + validateNotEmpty(entityName, FalconCLIConstants.ENTITY_NAME_OPT); + result = client.getDependency(entityType, entityName, doAsUser).toString(); + } else if (optionsList.contains(FalconCLIConstants.LIST_OPT)) { + validateColo(optionsList); + validateEntityFields(fields); + validateOrderBy(orderBy, entityAction); + validateFilterBy(filterBy, entityAction); + EntityList entityList = client.getEntityList(entityType, fields, nameSubsequence, tagKeywords, + filterBy, filterTags, orderBy, sortOrder, offset, numResults, doAsUser); + result = entityList != null ? entityList.toString() : "No entity of type (" + entityType + ") found."; + } else if (optionsList.contains(FalconCLIConstants.SUMMARY_OPT)) { + validateEntityTypeForSummary(entityType); + validateNotEmpty(cluster, FalconCLIConstants.CLUSTER_OPT); + validateEntityFields(fields); + validateFilterBy(filterBy, entityAction); + validateOrderBy(orderBy, entityAction); + result = ResponseHelper.getString(client.getEntitySummary( + entityType, cluster, start, end, fields, filterBy, filterTags, + orderBy, sortOrder, offset, numResults, numInstances, doAsUser)); + } else if (optionsList.contains(TOUCH_OPT)) { + validateNotEmpty(entityName, FalconCLIConstants.ENTITY_NAME_OPT); + colo = getColo(colo); + result = client.touch(entityType, entityName, colo, skipDryRun, doAsUser).getMessage(); + } else if (optionsList.contains(FalconCLIConstants.HELP_CMD)) { + OUT.get().println("Falcon Help"); + } else { + throw new FalconCLIException("Invalid command"); + } + OUT.get().println(result); + } + + private void validateColo(Set<String> optionsList) throws FalconCLIException { + if (optionsList.contains(FalconCLIConstants.COLO_OPT)) { + throw new FalconCLIException("Invalid argument : " + FalconCLIConstants.COLO_OPT); + } + } + + private void validateEntityFields(String fields) throws FalconCLIException { + if (StringUtils.isEmpty(fields)) { + return; + } + String[] fieldsList = fields.split(","); + for (String s : fieldsList) { + try { + EntityList.EntityFieldList.valueOf(s.toUpperCase()); + } catch (IllegalArgumentException ie) { + throw new FalconCLIException("Invalid fields argument : " + FIELDS_OPT); + } + } + } + + private Date parseDateString(String time) throws FalconCLIException { + if (time != null && !time.isEmpty()) { + try { + return SchemaHelper.parseDateUTC(time); + } catch(Exception e) { + throw new FalconCLIException("Time " + time + " is not valid", e); + } + } + return null; + } + +} http://git-wip-us.apache.org/repos/asf/falcon/blob/6655e90a/cli/src/main/java/org/apache/falcon/cli/FalconInstanceCLI.java ---------------------------------------------------------------------- diff --git a/cli/src/main/java/org/apache/falcon/cli/FalconInstanceCLI.java b/cli/src/main/java/org/apache/falcon/cli/FalconInstanceCLI.java new file mode 100644 index 0000000..afbba12 --- /dev/null +++ b/cli/src/main/java/org/apache/falcon/cli/FalconInstanceCLI.java @@ -0,0 +1,340 @@ +/** + * 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 org.apache.falcon.cli; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.falcon.FalconCLIConstants; +import org.apache.falcon.LifeCycle; +import org.apache.falcon.ResponseHelper; +import org.apache.falcon.client.FalconCLIException; +import org.apache.falcon.client.FalconClient; +import org.apache.falcon.resource.InstanceDependencyResult; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Instance extension to Falcon Command Line Interface - wraps the RESTful API for instances. + */ +public class FalconInstanceCLI extends FalconCLI { + + private static final String FORCE_RERUN_FLAG = "force"; + private static final String INSTANCE_TIME_OPT = "instanceTime"; + private static final String RUNNING_OPT = "running"; + private static final String KILL_OPT = "kill"; + private static final String RERUN_OPT = "rerun"; + private static final String LOG_OPT = "logs"; + private static final String ALL_ATTEMPTS = "allAttempts"; + private static final String RUNID_OPT = "runid"; + private static final String CLUSTERS_OPT = "clusters"; + private static final String SOURCECLUSTER_OPT = "sourceClusters"; + private static final String LIFECYCLE_OPT = "lifecycle"; + private static final String PARARMS_OPT = "params"; + private static final String LISTING_OPT = "listing"; + private static final String TRIAGE_OPT = "triage"; + + public FalconInstanceCLI() throws Exception { + super(); + } + + public Options createInstanceOptions() { + + Options instanceOptions = new Options(); + + Option running = new Option(RUNNING_OPT, false, + "Gets running process instances for a given process"); + Option list = new Option(FalconCLIConstants.LIST_OPT, false, + "Gets all instances for a given process in the range start time and optional end time"); + Option status = new Option(FalconCLIConstants.STATUS_OPT, false, + "Gets status of process instances for a given process in the range start time and optional end time"); + Option summary = new Option(FalconCLIConstants.SUMMARY_OPT, false, + "Gets summary of instances for a given process in the range start time and optional end time"); + Option kill = new Option(KILL_OPT, false, + "Kills active process instances for a given process in the range start time and optional end time"); + Option suspend = new Option(FalconCLIConstants.SUSPEND_OPT, false, + "Suspends active process instances for a given process in the range start time and optional end time"); + Option resume = new Option(FalconCLIConstants.RESUME_OPT, false, + "Resumes suspended process instances for a given process " + + "in the range start time and optional end time"); + Option rerun = new Option(RERUN_OPT, false, + "Reruns process instances for a given process in the range start time and " + + "optional end time and overrides properties present in job.properties file"); + Option logs = new Option(LOG_OPT, false, + "Logs print the logs for process instances for a given process in " + + "the range start time and optional end time"); + Option params = new Option(PARARMS_OPT, false, + "Displays the workflow parameters for a given instance of specified nominal time" + + "start time represents nominal time and end time is not considered"); + Option listing = new Option(LISTING_OPT, false, + "Displays feed listing and their status between a start and end time range."); + Option dependency = new Option(FalconCLIConstants.DEPENDENCY_OPT, false, + "Displays dependent instances for a specified instance."); + Option triage = new Option(TRIAGE_OPT, false, + "Triage a feed or process instance and find the failures in it's lineage."); + + OptionGroup group = new OptionGroup(); + group.addOption(running); + group.addOption(list); + group.addOption(status); + group.addOption(summary); + group.addOption(kill); + group.addOption(resume); + group.addOption(suspend); + group.addOption(resume); + group.addOption(rerun); + group.addOption(logs); + group.addOption(params); + group.addOption(listing); + group.addOption(dependency); + group.addOption(triage); + + Option url = new Option(FalconCLIConstants.URL_OPTION, true, "Falcon URL"); + Option start = new Option(FalconCLIConstants.START_OPT, true, + "Start time is required for commands, status, kill, suspend, resume and re-run" + + "and it is nominal time while displaying workflow params"); + Option end = new Option(FalconCLIConstants.END_OPT, true, + "End time is optional for commands, status, kill, suspend, resume and re-run; " + + "if not specified then current time is considered as end time"); + Option runid = new Option(RUNID_OPT, true, + "Instance runid is optional and user can specify the runid, defaults to 0"); + Option clusters = new Option(CLUSTERS_OPT, true, + "clusters is optional for commands kill, suspend and resume, " + + "should not be specified for other commands"); + Option sourceClusters = new Option(SOURCECLUSTER_OPT, true, + " source cluster is optional for commands kill, suspend and resume, " + + "should not be specified for other commands (required for only feed)"); + Option filePath = new Option(FalconCLIConstants.FILE_PATH_OPT, true, + "Path to job.properties file is required for rerun command, " + + "it should contain name=value pair for properties to override for rerun"); + Option entityType = new Option(FalconCLIConstants.TYPE_OPT, true, + "Entity type, can be feed or process xml"); + Option entityName = new Option(FalconCLIConstants.ENTITY_NAME_OPT, true, + "Entity name, can be feed or process name"); + Option colo = new Option(FalconCLIConstants.COLO_OPT, true, + "Colo on which the cmd has to be executed"); + Option lifecycle = new Option(LIFECYCLE_OPT, true, + "describes life cycle of entity , for feed it can be replication/retention " + + "and for process it can be execution"); + Option filterBy = new Option(FalconCLIConstants.FILTER_BY_OPT, true, + "Filter returned instances by the specified fields"); + Option orderBy = new Option(FalconCLIConstants.ORDER_BY_OPT, true, + "Order returned instances by this field"); + Option sortOrder = new Option(FalconCLIConstants.SORT_ORDER_OPT, true, "asc or desc order for results"); + Option offset = new Option(FalconCLIConstants.OFFSET_OPT, true, + "Start returning instances from this offset"); + Option numResults = new Option(FalconCLIConstants.NUM_RESULTS_OPT, true, + "Number of results to return per request"); + Option forceRerun = new Option(FORCE_RERUN_FLAG, false, + "Flag to forcefully rerun entire workflow of an instance"); + Option doAs = new Option(FalconCLIConstants.DO_AS_OPT, true, "doAs user"); + Option debug = new Option(FalconCLIConstants.DEBUG_OPTION, false, "Use debug mode to see" + + " debugging statements on stdout"); + + Option instanceTime = new Option(INSTANCE_TIME_OPT, true, "Time for an instance"); + + Option allAttempts = new Option(ALL_ATTEMPTS, false, "To get all attempts of corresponding instances"); + + instanceOptions.addOption(url); + instanceOptions.addOptionGroup(group); + instanceOptions.addOption(start); + instanceOptions.addOption(end); + instanceOptions.addOption(filePath); + instanceOptions.addOption(entityType); + instanceOptions.addOption(entityName); + instanceOptions.addOption(runid); + instanceOptions.addOption(clusters); + instanceOptions.addOption(sourceClusters); + instanceOptions.addOption(colo); + instanceOptions.addOption(lifecycle); + instanceOptions.addOption(filterBy); + instanceOptions.addOption(offset); + instanceOptions.addOption(orderBy); + instanceOptions.addOption(sortOrder); + instanceOptions.addOption(numResults); + instanceOptions.addOption(forceRerun); + instanceOptions.addOption(doAs); + instanceOptions.addOption(debug); + instanceOptions.addOption(instanceTime); + instanceOptions.addOption(allAttempts); + + return instanceOptions; + } + + public void instanceCommand(CommandLine commandLine, FalconClient client) throws FalconCLIException, IOException { + Set<String> optionsList = new HashSet<String>(); + for (Option option : commandLine.getOptions()) { + optionsList.add(option.getOpt()); + } + + String result; + String type = commandLine.getOptionValue(FalconCLIConstants.TYPE_OPT); + String entity = commandLine.getOptionValue(FalconCLIConstants.ENTITY_NAME_OPT); + String instanceTime = commandLine.getOptionValue(INSTANCE_TIME_OPT); + String start = commandLine.getOptionValue(FalconCLIConstants.START_OPT); + String end = commandLine.getOptionValue(FalconCLIConstants.END_OPT); + String filePath = commandLine.getOptionValue(FalconCLIConstants.FILE_PATH_OPT); + String runId = commandLine.getOptionValue(RUNID_OPT); + String colo = commandLine.getOptionValue(FalconCLIConstants.COLO_OPT); + String clusters = commandLine.getOptionValue(CLUSTERS_OPT); + String sourceClusters = commandLine.getOptionValue(SOURCECLUSTER_OPT); + List<LifeCycle> lifeCycles = getLifeCycle(commandLine.getOptionValue(LIFECYCLE_OPT)); + String filterBy = commandLine.getOptionValue(FalconCLIConstants.FILTER_BY_OPT); + String orderBy = commandLine.getOptionValue(FalconCLIConstants.ORDER_BY_OPT); + String sortOrder = commandLine.getOptionValue(FalconCLIConstants.SORT_ORDER_OPT); + String doAsUser = commandLine.getOptionValue(FalconCLIConstants.DO_AS_OPT); + Integer offset = parseIntegerInput(commandLine.getOptionValue(FalconCLIConstants.OFFSET_OPT), 0, "offset"); + Integer numResults = parseIntegerInput(commandLine.getOptionValue(FalconCLIConstants.NUM_RESULTS_OPT), + null, "numResults"); + + colo = getColo(colo); + String instanceAction = "instance"; + validateSortOrder(sortOrder); + validateInstanceCommands(optionsList, entity, type, colo); + + if (optionsList.contains(TRIAGE_OPT)) { + validateNotEmpty(colo, FalconCLIConstants.COLO_OPT); + validateNotEmpty(start, FalconCLIConstants.START_OPT); + validateNotEmpty(type, FalconCLIConstants.TYPE_OPT); + validateEntityTypeForSummary(type); + validateNotEmpty(entity, FalconCLIConstants.ENTITY_NAME_OPT); + result = client.triage(type, entity, start, colo).toString(); + } else if (optionsList.contains(FalconCLIConstants.DEPENDENCY_OPT)) { + validateNotEmpty(instanceTime, INSTANCE_TIME_OPT); + InstanceDependencyResult response = client.getInstanceDependencies(type, entity, instanceTime, colo); + result = ResponseHelper.getString(response); + + } else if (optionsList.contains(RUNNING_OPT)) { + validateOrderBy(orderBy, instanceAction); + validateFilterBy(filterBy, instanceAction); + result = ResponseHelper.getString(client.getRunningInstances(type, + entity, colo, lifeCycles, filterBy, orderBy, sortOrder, offset, numResults, doAsUser)); + } else if (optionsList.contains(FalconCLIConstants.STATUS_OPT) + || optionsList.contains(FalconCLIConstants.LIST_OPT)) { + boolean allAttempts = false; + if (optionsList.contains(ALL_ATTEMPTS)) { + allAttempts = true; + } + validateOrderBy(orderBy, instanceAction); + validateFilterBy(filterBy, instanceAction); + result = ResponseHelper.getString(client.getStatusOfInstances(type, entity, start, end, colo, + lifeCycles, filterBy, orderBy, sortOrder, offset, numResults, doAsUser, allAttempts)); + } else if (optionsList.contains(FalconCLIConstants.SUMMARY_OPT)) { + validateOrderBy(orderBy, "summary"); + validateFilterBy(filterBy, "summary"); + result = ResponseHelper.getString(client.getSummaryOfInstances(type, entity, start, end, colo, + lifeCycles, filterBy, orderBy, sortOrder, doAsUser)); + } else if (optionsList.contains(KILL_OPT)) { + validateNotEmpty(start, FalconCLIConstants.START_OPT); + validateNotEmpty(end, FalconCLIConstants.END_OPT); + result = ResponseHelper.getString(client.killInstances(type, entity, start, end, colo, clusters, + sourceClusters, lifeCycles, doAsUser)); + } else if (optionsList.contains(FalconCLIConstants.SUSPEND_OPT)) { + validateNotEmpty(start, FalconCLIConstants.START_OPT); + validateNotEmpty(end, FalconCLIConstants.END_OPT); + result = ResponseHelper.getString(client.suspendInstances(type, entity, start, end, colo, clusters, + sourceClusters, lifeCycles, doAsUser)); + } else if (optionsList.contains(FalconCLIConstants.RESUME_OPT)) { + validateNotEmpty(start, FalconCLIConstants.START_OPT); + validateNotEmpty(end, FalconCLIConstants.END_OPT); + result = ResponseHelper.getString(client.resumeInstances(type, entity, start, end, colo, clusters, + sourceClusters, lifeCycles, doAsUser)); + } else if (optionsList.contains(RERUN_OPT)) { + validateNotEmpty(start, FalconCLIConstants.START_OPT); + validateNotEmpty(end, FalconCLIConstants.END_OPT); + boolean isForced = false; + if (optionsList.contains(FORCE_RERUN_FLAG)) { + isForced = true; + } + result = ResponseHelper.getString(client.rerunInstances(type, entity, start, end, filePath, colo, + clusters, sourceClusters, lifeCycles, isForced, doAsUser)); + } else if (optionsList.contains(LOG_OPT)) { + validateOrderBy(orderBy, instanceAction); + validateFilterBy(filterBy, instanceAction); + result = ResponseHelper.getString(client.getLogsOfInstances(type, entity, start, end, colo, runId, + lifeCycles, filterBy, orderBy, sortOrder, offset, numResults, doAsUser), runId); + } else if (optionsList.contains(PARARMS_OPT)) { + // start time is the nominal time of instance + result = ResponseHelper.getString(client.getParamsOfInstance(type, entity, + start, colo, lifeCycles, doAsUser)); + } else if (optionsList.contains(LISTING_OPT)) { + result = ResponseHelper.getString(client.getFeedInstanceListing(type, entity, start, end, colo, doAsUser)); + } else { + throw new FalconCLIException("Invalid command"); + } + + OUT.get().println(result); + } + + private void validateInstanceCommands(Set<String> optionsList, + String entity, String type, + String colo) throws FalconCLIException { + + validateNotEmpty(entity, FalconCLIConstants.ENTITY_NAME_OPT); + validateNotEmpty(type, FalconCLIConstants.TYPE_OPT); + validateNotEmpty(colo, FalconCLIConstants.COLO_OPT); + + if (optionsList.contains(CLUSTERS_OPT)) { + if (optionsList.contains(RUNNING_OPT) + || optionsList.contains(LOG_OPT) + || optionsList.contains(FalconCLIConstants.STATUS_OPT) + || optionsList.contains(FalconCLIConstants.SUMMARY_OPT)) { + throw new FalconCLIException("Invalid argument: clusters"); + } + } + + if (optionsList.contains(SOURCECLUSTER_OPT)) { + if (optionsList.contains(RUNNING_OPT) + || optionsList.contains(LOG_OPT) + || optionsList.contains(FalconCLIConstants.STATUS_OPT) + || optionsList.contains(FalconCLIConstants.SUMMARY_OPT) || !type.equals("feed")) { + throw new FalconCLIException("Invalid argument: sourceClusters"); + } + } + + if (optionsList.contains(FORCE_RERUN_FLAG)) { + if (!optionsList.contains(RERUN_OPT)) { + throw new FalconCLIException("Force option can be used only with instance rerun"); + } + } + } + + private List<LifeCycle> getLifeCycle(String lifeCycleValue) throws FalconCLIException { + + if (lifeCycleValue != null) { + String[] lifeCycleValues = lifeCycleValue.split(","); + List<LifeCycle> lifeCycles = new ArrayList<LifeCycle>(); + try { + for (String lifeCycle : lifeCycleValues) { + lifeCycles.add(LifeCycle.valueOf(lifeCycle.toUpperCase().trim())); + } + } catch (IllegalArgumentException e) { + throw new FalconCLIException("Invalid life cycle values: " + lifeCycles, e); + } + return lifeCycles; + } + return null; + } + +} http://git-wip-us.apache.org/repos/asf/falcon/blob/6655e90a/cli/src/main/java/org/apache/falcon/cli/FalconMetadataCLI.java ---------------------------------------------------------------------- diff --git a/cli/src/main/java/org/apache/falcon/cli/FalconMetadataCLI.java b/cli/src/main/java/org/apache/falcon/cli/FalconMetadataCLI.java new file mode 100644 index 0000000..b3e138f --- /dev/null +++ b/cli/src/main/java/org/apache/falcon/cli/FalconMetadataCLI.java @@ -0,0 +1,256 @@ +/** + * 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 org.apache.falcon.cli; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.commons.lang3.StringUtils; +import org.apache.falcon.FalconCLIConstants; +import org.apache.falcon.client.FalconCLIException; +import org.apache.falcon.client.FalconClient; +import org.apache.falcon.entity.v0.EntityType; +import org.apache.falcon.metadata.RelationshipType; + +import java.io.PrintStream; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Metadata extension to Falcon Command Line Interface - wraps the RESTful API for Metadata. + */ +public class FalconMetadataCLI extends FalconCLI { + + public static final AtomicReference<PrintStream> OUT = new AtomicReference<PrintStream>(System.out); + + // Discovery Commands + public static final String DISCOVERY_OPT = "discovery"; + public static final String LIST_OPT = "list"; + public static final String URL_OPTION = "url"; + + // Lineage Commands + public static final String LINEAGE_OPT = "lineage"; + public static final String VERTEX_CMD = "vertex"; + public static final String VERTICES_CMD = "vertices"; + public static final String VERTEX_EDGES_CMD = "edges"; + public static final String EDGE_CMD = "edge"; + public static final String ID_OPT = "id"; + public static final String KEY_OPT = "key"; + public static final String VALUE_OPT = "value"; + public static final String DIRECTION_OPT = "direction"; + + public FalconMetadataCLI() throws Exception { + super(); + } + + public Options createMetadataOptions() { + Options metadataOptions = new Options(); + + OptionGroup group = new OptionGroup(); + Option discovery = new Option(DISCOVERY_OPT, false, "Discover falcon metadata relations"); + Option lineage = new Option(LINEAGE_OPT, false, "Get falcon metadata lineage information"); + group.addOption(discovery); + group.addOption(lineage); + Option pipeline = new Option(FalconCLIConstants.PIPELINE_OPT, true, + "Get lineage graph for the entities in a pipeline"); + metadataOptions.addOptionGroup(group); + + // Add discovery options + + Option list = new Option(LIST_OPT, false, "List all dimensions"); + Option relations = new Option(FalconCLIConstants.RELATIONS_OPT, false, "List all relations for a dimension"); + metadataOptions.addOption(list); + metadataOptions.addOption(relations); + + Option url = new Option(URL_OPTION, true, "Falcon URL"); + Option type = new Option(FalconCLIConstants.TYPE_OPT, true, "Dimension type"); + Option name = new Option(FalconCLIConstants.NAME_OPT, true, "Dimension name"); + Option cluster = new Option(FalconCLIConstants.CLUSTER_OPT, true, "Cluster name"); + Option feed = new Option(FalconCLIConstants.FEED_OPT, true, "Feed Entity name"); + Option process = new Option(FalconCLIConstants.PROCESS_OPT, true, "Process Entity name"); + Option numResults = new Option(FalconCLIConstants.NUM_RESULTS_OPT, true, + "Number of results to return per request"); + + // Add lineage options + metadataOptions.addOption(pipeline); + + metadataOptions.addOption(url); + metadataOptions.addOption(type); + metadataOptions.addOption(cluster); + metadataOptions.addOption(name); + metadataOptions.addOption(feed); + metadataOptions.addOption(process); + metadataOptions.addOption(numResults); + + Option vertex = new Option(VERTEX_CMD, false, "show the vertices"); + Option vertices = new Option(VERTICES_CMD, false, "show the vertices"); + Option vertexEdges = new Option(VERTEX_EDGES_CMD, false, "show the edges for a given vertex"); + Option edges = new Option(EDGE_CMD, false, "show the edges"); + Option id = new Option(ID_OPT, true, "vertex or edge id"); + Option key = new Option(KEY_OPT, true, "key property"); + Option value = new Option(VALUE_OPT, true, "value property"); + Option direction = new Option(DIRECTION_OPT, true, "edge direction property"); + Option debug = new Option(FalconCLIConstants.DEBUG_OPTION, false, + "Use debug mode to see debugging statements on stdout"); + + metadataOptions.addOption(vertex); + metadataOptions.addOption(vertices); + metadataOptions.addOption(vertexEdges); + metadataOptions.addOption(edges); + metadataOptions.addOption(id); + metadataOptions.addOption(key); + metadataOptions.addOption(value); + metadataOptions.addOption(direction); + metadataOptions.addOption(debug); + + Option doAs = new Option(FalconCLIConstants.DO_AS_OPT, true, "doAs user"); + metadataOptions.addOption(doAs); + + return metadataOptions; + } + + public void metadataCommand(CommandLine commandLine, FalconClient client) throws FalconCLIException { + Set<String> optionsList = new HashSet<String>(); + for (Option option : commandLine.getOptions()) { + optionsList.add(option.getOpt()); + } + + String result; + String dimensionType = commandLine.getOptionValue(FalconCLIConstants.TYPE_OPT); + String cluster = commandLine.getOptionValue(FalconCLIConstants.CLUSTER_OPT); + String feed = commandLine.getOptionValue(FalconCLIConstants.FEED_OPT); + String process = commandLine.getOptionValue(FalconCLIConstants.PROCESS_OPT); + String dimensionName = commandLine.getOptionValue(FalconCLIConstants.NAME_OPT); + String id = commandLine.getOptionValue(ID_OPT); + String key = commandLine.getOptionValue(KEY_OPT); + String value = commandLine.getOptionValue(VALUE_OPT); + String direction = commandLine.getOptionValue(DIRECTION_OPT); + String pipeline = commandLine.getOptionValue(FalconCLIConstants.PIPELINE_OPT); + String doAsUser = commandLine.getOptionValue(FalconCLIConstants.DO_AS_OPT); + Integer numResults = parseIntegerInput(commandLine.getOptionValue(FalconCLIConstants.NUM_RESULTS_OPT), + null, "numResults"); + + if (optionsList.contains(LINEAGE_OPT)) { + validatePipelineName(pipeline); + result = client.getEntityLineageGraph(pipeline, doAsUser).getDotNotation(); + } else if (optionsList.contains(LIST_OPT)) { + validateDimensionType(dimensionType.toUpperCase()); + if (!(dimensionType.toUpperCase()) + .equals(RelationshipType.REPLICATION_METRICS.name())) { + result = client.getDimensionList(dimensionType, cluster, doAsUser); + } else { + String schedEntityType = null; + String schedEntityName = null; + if (StringUtils.isNotEmpty(feed)) { + schedEntityType = EntityType.getEnum(FalconCLIConstants.FEED_OPT).name(); + schedEntityName = feed; + } else if (StringUtils.isNotEmpty(process)) { + schedEntityType = EntityType.getEnum(FalconCLIConstants.PROCESS_OPT).name(); + schedEntityName = process; + } + validateScheduleEntity(schedEntityType, schedEntityName); + + result = client.getReplicationMetricsDimensionList(schedEntityType, schedEntityName, + numResults, doAsUser); + } + } else if (optionsList.contains(FalconCLIConstants.RELATIONS_OPT)) { + validateDimensionType(dimensionType.toUpperCase()); + validateDimensionName(dimensionName, FalconCLIConstants.RELATIONS_OPT); + result = client.getDimensionRelations(dimensionType, dimensionName, doAsUser); + } else if (optionsList.contains(VERTEX_CMD)) { + validateId(id); + result = client.getVertex(id, doAsUser); + } else if (optionsList.contains(VERTICES_CMD)) { + validateVerticesCommand(key, value); + result = client.getVertices(key, value, doAsUser); + } else if (optionsList.contains(VERTEX_EDGES_CMD)) { + validateVertexEdgesCommand(id, direction); + result = client.getVertexEdges(id, direction, doAsUser); + } else if (optionsList.contains(EDGE_CMD)) { + validateId(id); + result = client.getEdge(id, doAsUser); + } else { + throw new FalconCLIException("Invalid metadata command"); + } + + OUT.get().println(result); + } + + private void validatePipelineName(String pipeline) throws FalconCLIException { + if (StringUtils.isEmpty(pipeline)) { + throw new FalconCLIException("Invalid value for pipeline"); + } + } + + private void validateDimensionType(String dimensionType) throws FalconCLIException { + if (StringUtils.isEmpty(dimensionType) + || dimensionType.contains("INSTANCE")) { + throw new FalconCLIException("Invalid value provided for queryParam \"type\" " + dimensionType); + } + try { + RelationshipType.valueOf(dimensionType); + } catch (IllegalArgumentException iae) { + throw new FalconCLIException("Invalid value provided for queryParam \"type\" " + dimensionType); + } + } + + private void validateDimensionName(String dimensionName, String action) throws FalconCLIException { + if (StringUtils.isEmpty(dimensionName)) { + throw new FalconCLIException("Dimension ID cannot be empty or null for action " + action); + } + } + + private void validateScheduleEntity(String schedEntityType, String schedEntityName) throws FalconCLIException { + if (StringUtils.isBlank(schedEntityType)) { + throw new FalconCLIException("Entity must be schedulable type : -feed/process"); + } + + if (StringUtils.isBlank(schedEntityName)) { + throw new FalconCLIException("Entity name is missing"); + } + } + + private void validateId(String id) throws FalconCLIException { + if (id == null || id.length() == 0) { + throw new FalconCLIException("Missing argument: id"); + } + } + + private void validateVerticesCommand(String key, String value) throws FalconCLIException { + if (key == null || key.length() == 0) { + throw new FalconCLIException("Missing argument: key"); + } + + if (value == null || value.length() == 0) { + throw new FalconCLIException("Missing argument: value"); + } + } + + private void validateVertexEdgesCommand(String id, String direction) throws FalconCLIException { + if (id == null || id.length() == 0) { + throw new FalconCLIException("Missing argument: id"); + } + + if (direction == null || direction.length() == 0) { + throw new FalconCLIException("Missing argument: direction"); + } + } +} http://git-wip-us.apache.org/repos/asf/falcon/blob/6655e90a/client/src/main/java/org/apache/falcon/FalconCLIConstants.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/falcon/FalconCLIConstants.java b/client/src/main/java/org/apache/falcon/FalconCLIConstants.java new file mode 100644 index 0000000..eb4cf3f --- /dev/null +++ b/client/src/main/java/org/apache/falcon/FalconCLIConstants.java @@ -0,0 +1,76 @@ +/** + * 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 org.apache.falcon; + +/** +* FalconCLI Constants. +*/ +public final class FalconCLIConstants { + private FalconCLIConstants(){ + + } + public static final String ENV_FALCON_DEBUG = "FALCON_DEBUG"; + public static final String DEBUG_OPTION = "debug"; + public static final String URL_OPTION = "url"; + + public static final String ADMIN_CMD = "admin"; + public static final String HELP_CMD = "help"; + public static final String METADATA_CMD = "metadata"; + public static final String ENTITY_CMD = "entity"; + public static final String INSTANCE_CMD = "instance"; + public static final String RECIPE_CMD = "recipe"; + + public static final String TYPE_OPT = "type"; + public static final String COLO_OPT = "colo"; + public static final String CLUSTER_OPT = "cluster"; + public static final String FEED_OPT = "feed"; + public static final String PROCESS_OPT = "process"; + public static final String ENTITY_NAME_OPT = "name"; + public static final String FILE_PATH_OPT = "file"; + public static final String VERSION_OPT = "version"; + public static final String SCHEDULE_OPT = "schedule"; + public static final String SUSPEND_OPT = "suspend"; + public static final String RESUME_OPT = "resume"; + public static final String STATUS_OPT = "status"; + public static final String SUMMARY_OPT = "summary"; + public static final String DEPENDENCY_OPT = "dependency"; + public static final String LIST_OPT = "list"; + public static final String SKIPDRYRUN_OPT = "skipDryRun"; + public static final String FILTER_BY_OPT = "filterBy"; + public static final String ORDER_BY_OPT = "orderBy"; + public static final String SORT_ORDER_OPT = "sortOrder"; + public static final String OFFSET_OPT = "offset"; + public static final String NUM_RESULTS_OPT = "numResults"; + public static final String START_OPT = "start"; + public static final String END_OPT = "end"; + public static final String CURRENT_COLO = "current.colo"; + public static final String CLIENT_PROPERTIES = "/client.properties"; + public static final String DO_AS_OPT = "doAs"; + public static final String RELATIONS_OPT = "relations"; + public static final String PIPELINE_OPT = "pipeline"; + public static final String NAME_OPT = "name"; + + /** + * Recipe operation enum. + */ + public enum RecipeOperation { + HDFS_REPLICATION, + HIVE_DISASTER_RECOVERY + } +} http://git-wip-us.apache.org/repos/asf/falcon/blob/6655e90a/client/src/main/java/org/apache/falcon/cli/CLIParser.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/falcon/cli/CLIParser.java b/client/src/main/java/org/apache/falcon/cli/CLIParser.java deleted file mode 100644 index 9d8554f..0000000 --- a/client/src/main/java/org/apache/falcon/cli/CLIParser.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * 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 org.apache.falcon.cli; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.GnuParser; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.commons.cli.HelpFormatter; - -import java.io.PrintWriter; -import java.text.MessageFormat; -import java.util.LinkedHashMap; -import java.util.Map; - - -/** - * Cannibalized from Oozie CLIParser into Falcon - * Command line parser based on Apache common-cli 1.x that supports subcommands. - */ -public class CLIParser { - private static final String LEFT_PADDING = " "; - - private String cliName; - private String[] cliHelp; - private Map<String, Options> commands = new LinkedHashMap<String, Options>(); - private Map<String, Boolean> commandWithArgs = new LinkedHashMap<String, Boolean>(); - private Map<String, String> commandsHelp = new LinkedHashMap<String, String>(); - - /** - * Create a parser. - * - * @param aCliName name of the parser, for help purposes. - * @param aCliHelp help for the CLI. - */ - public CLIParser(String aCliName, String[] aCliHelp) { - this.cliName = aCliName; - this.cliHelp = aCliHelp.clone(); - } - - /** - * Add a command to the parser. - * - * @param command comand name. - * @param argsHelp command arguments help. - * @param commandHelp command description. - * @param commandOptions command options. - * @param hasArguments has args - */ - public void addCommand(String command, String argsHelp, String commandHelp, Options commandOptions, - boolean hasArguments) { - String helpMsg = argsHelp + ((hasArguments) ? "<ARGS> " : "") + ": " + commandHelp; - commandsHelp.put(command, helpMsg); - commands.put(command, commandOptions); - commandWithArgs.put(command, hasArguments); - } - - /** - * Bean that represents a parsed command. - */ - public static final class Command { - private String name; - private CommandLine commandLine; - - private Command(String name, CommandLine commandLine) { - this.name = name; - this.commandLine = commandLine; - } - - /** - * Return the command name. - * - * @return the command name. - */ - public String getName() { - return name; - } - - /** - * Return the command line. - * - * @return the command line. - */ - public CommandLine getCommandLine() { - return commandLine; - } - } - - /** - * Parse a array of arguments into a command. - * - * @param args array of arguments. - * @return the parsed Command. - * @throws ParseException thrown if the arguments could not be parsed. - */ - public Command parse(String[] args) throws ParseException { - if (args.length == 0) { - throw new ParseException("missing sub-command"); - } else { - if (commands.containsKey(args[0])) { - GnuParser parser = new GnuParser(); - String[] minusCommand = new String[args.length - 1]; - System.arraycopy(args, 1, minusCommand, 0, minusCommand.length); - return new Command(args[0], parser.parse(commands.get(args[0]), minusCommand, - commandWithArgs.get(args[0]))); - } else { - throw new ParseException(MessageFormat.format("invalid sub-command [{0}]", args[0])); - } - } - } - - public String shortHelp() { - return "use 'help' sub-command for help details"; - } - - /** - * Print the help for the parser to standard output. - */ - public void showHelp() { - PrintWriter pw = new PrintWriter(System.out); - pw.println("usage: "); - for (String s : cliHelp) { - pw.println(LEFT_PADDING + s); - } - pw.println(); - HelpFormatter formatter = new HelpFormatter(); - for (Map.Entry<String, Options> entry : commands.entrySet()) { - String s = LEFT_PADDING + cliName + " " + entry.getKey() + " "; - if (entry.getValue().getOptions().size() > 0) { - pw.println(s + "<OPTIONS> " + commandsHelp.get(entry.getKey())); - formatter.printOptions(pw, 100, entry.getValue(), s.length(), 3); - } else { - pw.println(s + commandsHelp.get(entry.getKey())); - } - pw.println(); - } - pw.flush(); - } -} http://git-wip-us.apache.org/repos/asf/falcon/blob/6655e90a/client/src/main/java/org/apache/falcon/cli/FalconAdminCLI.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/falcon/cli/FalconAdminCLI.java b/client/src/main/java/org/apache/falcon/cli/FalconAdminCLI.java deleted file mode 100644 index 6360743..0000000 --- a/client/src/main/java/org/apache/falcon/cli/FalconAdminCLI.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * 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 org.apache.falcon.cli; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.OptionGroup; -import org.apache.commons.cli.Options; -import org.apache.falcon.client.FalconCLIException; -import org.apache.falcon.client.FalconClient; - -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; - -/** - * Admin extension to Falcon Command Line Interface - wraps the RESTful API for admin commands. - */ -public class FalconAdminCLI extends FalconCLI { - - private static final String STACK_OPTION = "stack"; - - public FalconAdminCLI() throws Exception { - super(); - } - - public Options createAdminOptions() { - Options adminOptions = new Options(); - Option url = new Option(URL_OPTION, true, "Falcon URL"); - adminOptions.addOption(url); - - OptionGroup group = new OptionGroup(); - Option status = new Option(STATUS_OPT, false, - "show the current system status"); - Option version = new Option(VERSION_OPT, false, - "show Falcon server build version"); - Option stack = new Option(STACK_OPTION, false, - "show the thread stack dump"); - Option doAs = new Option(DO_AS_OPT, true, - "doAs user"); - Option help = new Option("help", false, "show Falcon help"); - Option debug = new Option(DEBUG_OPTION, false, "Use debug mode to see debugging statements on stdout"); - group.addOption(status); - group.addOption(version); - group.addOption(stack); - group.addOption(help); - - adminOptions.addOptionGroup(group); - adminOptions.addOption(doAs); - adminOptions.addOption(debug); - return adminOptions; - } - - public int adminCommand(CommandLine commandLine, FalconClient client, - String falconUrl) throws FalconCLIException, IOException { - String result; - Set<String> optionsList = new HashSet<String>(); - for (Option option : commandLine.getOptions()) { - optionsList.add(option.getOpt()); - } - - String doAsUser = commandLine.getOptionValue(DO_AS_OPT); - - if (optionsList.contains(STACK_OPTION)) { - result = client.getThreadDump(doAsUser); - OUT.get().println(result); - } - - int exitValue = 0; - if (optionsList.contains(STATUS_OPT)) { - try { - int status = client.getStatus(doAsUser); - if (status != 200) { - ERR.get().println("Falcon server is not fully operational (on " + falconUrl + "). " - + "Please check log files."); - exitValue = status; - } else { - OUT.get().println("Falcon server is running (on " + falconUrl + ")"); - } - } catch (Exception e) { - ERR.get().println("Falcon server doesn't seem to be running on " + falconUrl); - exitValue = -1; - } - } else if (optionsList.contains(VERSION_OPT)) { - result = client.getVersion(doAsUser); - OUT.get().println("Falcon server build version: " + result); - } else if (optionsList.contains(HELP_CMD)) { - OUT.get().println("Falcon Help"); - } - return exitValue; - } - -}
