blob: 5d4412821f38aafd434a2e0d2253987d505fb6ed [file] [log] [blame]
/**
* 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.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
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.client.FalconCLIConstants;
import org.apache.falcon.client.FalconCLIException;
import org.apache.falcon.client.FalconClient;
import org.apache.falcon.resource.ExtensionInstanceList;
import org.apache.falcon.resource.ExtensionJobList;
import java.io.IOException;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import static org.apache.falcon.cli.FalconEntityCLI.validateColo;
import static org.apache.falcon.client.FalconCLIConstants.COLO_OPT;
import static org.apache.falcon.client.FalconCLIConstants.COLO_OPT_DESCRIPTION;
/**
* Falcon extensions Command Line Interface - wraps the RESTful API for extensions.
*/
public class FalconExtensionCLI extends FalconCLI{
public static final AtomicReference<PrintStream> OUT = new AtomicReference<>(System.out);
// Extension commands
private static final String ENUMERATE_OPT = "enumerate";
private static final String DEFINITION_OPT = "definition";
private static final String DESCRIBE_OPT = "describe";
private static final String INSTANCES_OPT = "instances";
private static final String UNREGISTER_OPT = "unregister";
private static final String DETAIL_OPT = "detail";
private static final String REGISTER_OPT = "register";
private static final String ENABLE_OPT = "enable";
private static final String DISABLE_OPT = "disable";
// Input parameters
private static final String EXTENSION_NAME_OPT = "extensionName";
private static final String JOB_NAME_OPT = "jobName";
public static final String DESCRIPTION = "description";
private static final String PATH = "path";
FalconExtensionCLI() throws Exception {
super();
}
void extensionCommand(CommandLine commandLine, FalconClient client) throws IOException {
Set<String> optionsList = new HashSet<>();
for (Option option : commandLine.getOptions()) {
optionsList.add(option.getOpt());
}
String result;
String extensionName = commandLine.getOptionValue(EXTENSION_NAME_OPT);
String jobName = commandLine.getOptionValue(JOB_NAME_OPT);
String filePath = commandLine.getOptionValue(FalconCLIConstants.FILE_PATH_OPT);
String doAsUser = commandLine.getOptionValue(FalconCLIConstants.DO_AS_OPT);
String path = commandLine.getOptionValue(FalconCLIConstants.PATH);
String description = commandLine.getOptionValue(FalconCLIConstants.DESCRIPTION);
String colo = commandLine.getOptionValue(FalconCLIConstants.COLO_OPT);
colo = getColo(colo);
if (optionsList.contains(ENUMERATE_OPT)) {
result = client.enumerateExtensions().getMessage();
result = prettyPrintJson(result);
} else if (optionsList.contains(DEFINITION_OPT)) {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
result = client.getExtensionDefinition(extensionName).getMessage();
result = prettyPrintJson(result);
} else if (optionsList.contains(DESCRIBE_OPT)) {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
result = client.getExtensionDescription(extensionName).getMessage();
} else if (optionsList.contains(UNREGISTER_OPT)) {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
result = client.unregisterExtension(extensionName).getMessage();
} else if (optionsList.contains(DETAIL_OPT)) {
if (optionsList.contains(JOB_NAME_OPT)) {
validateRequiredParameter(jobName, JOB_NAME_OPT);
result = client.getExtensionJobDetails(jobName).getMessage();
result = prettyPrintJson(result);
} else {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
result = client.getExtensionDetail(extensionName).getMessage();
result = prettyPrintJson(result);
}
} else if (optionsList.contains(FalconCLIConstants.SUBMIT_OPT)) {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
validateRequiredParameter(jobName, JOB_NAME_OPT);
validateRequiredParameter(filePath, FalconCLIConstants.FILE_PATH_OPT);
validateColo(optionsList);
result = client.submitExtensionJob(extensionName, jobName, filePath, doAsUser).getMessage();
} else if (optionsList.contains(REGISTER_OPT)) {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
validateRequiredParameter(path, PATH);
result = client.registerExtension(extensionName, path, description).getMessage();
} else if (optionsList.contains(FalconCLIConstants.SUBMIT_AND_SCHEDULE_OPT)) {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
validateRequiredParameter(jobName, JOB_NAME_OPT);
validateRequiredParameter(filePath, FalconCLIConstants.FILE_PATH_OPT);
validateColo(optionsList);
result = client.submitAndScheduleExtensionJob(extensionName, jobName, filePath, doAsUser).getMessage();
} else if (optionsList.contains(FalconCLIConstants.UPDATE_OPT)) {
validateRequiredParameter(jobName, JOB_NAME_OPT);
validateRequiredParameter(filePath, FalconCLIConstants.FILE_PATH_OPT);
result = client.updateExtensionJob(jobName, filePath, doAsUser).getMessage();
} else if (optionsList.contains(FalconCLIConstants.VALIDATE_OPT)) {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
validateRequiredParameter(jobName, JOB_NAME_OPT);
validateRequiredParameter(filePath, FalconCLIConstants.FILE_PATH_OPT);
result = client.validateExtensionJob(extensionName, jobName, filePath, doAsUser).getMessage();
} else if (optionsList.contains(FalconCLIConstants.SCHEDULE_OPT)) {
validateRequiredParameter(jobName, JOB_NAME_OPT);
colo = getColo(colo);
result = client.scheduleExtensionJob(jobName, colo, doAsUser).getMessage();
} else if (optionsList.contains(FalconCLIConstants.SUSPEND_OPT)) {
validateRequiredParameter(jobName, JOB_NAME_OPT);
colo = getColo(colo);
result = client.suspendExtensionJob(jobName, colo, doAsUser).getMessage();
} else if (optionsList.contains(FalconCLIConstants.RESUME_OPT)) {
validateRequiredParameter(jobName, JOB_NAME_OPT);
colo = getColo(colo);
result = client.resumeExtensionJob(jobName, colo, doAsUser).getMessage();
} else if (optionsList.contains(FalconCLIConstants.DELETE_OPT)) {
validateRequiredParameter(jobName, JOB_NAME_OPT);
result = client.deleteExtensionJob(jobName, doAsUser).getMessage();
} else if (optionsList.contains(FalconCLIConstants.LIST_OPT)) {
ExtensionJobList jobs = client.getExtensionJobs(extensionName, doAsUser,
commandLine.getOptionValue(FalconCLIConstants.SORT_ORDER_OPT));
result = jobs != null ? jobs.toString() : "No extension job (" + extensionName + ") found.";
} else if (optionsList.contains(INSTANCES_OPT)) {
validateRequiredParameter(jobName, JOB_NAME_OPT);
ExtensionInstanceList instances = client.listExtensionInstance(jobName, doAsUser,
commandLine.getOptionValue(FalconCLIConstants.FIELDS_OPT),
commandLine.getOptionValue(FalconCLIConstants.START_OPT),
commandLine.getOptionValue(FalconCLIConstants.END_OPT),
commandLine.getOptionValue(FalconCLIConstants.INSTANCE_STATUS_OPT),
commandLine.getOptionValue(FalconCLIConstants.ORDER_BY_OPT),
commandLine.getOptionValue(FalconCLIConstants.SORT_ORDER_OPT),
commandLine.getOptionValue(FalconCLIConstants.OFFSET_OPT),
commandLine.getOptionValue(FalconCLIConstants.NUM_RESULTS_OPT));
result = instances != null ? instances.toString() : "No instance (" + jobName + ") found.";
} else if (optionsList.contains(ENABLE_OPT)) {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
result = client.enableExtension(extensionName).getMessage();
} else if (optionsList.contains(DISABLE_OPT)) {
validateRequiredParameter(extensionName, EXTENSION_NAME_OPT);
result = client.disableExtension(extensionName).getMessage();
} else {
throw new FalconCLIException("Invalid/missing extension command. Supported commands include "
+ "enumerate, definition, describe, list, instances, submit, submitAndSchedule, "
+ "schedule, suspend, resume, delete, update, validate, enable, disable. "
+ "Please refer to Falcon CLI twiki for more details.");
}
OUT.get().println(result);
}
Options createExtensionOptions() {
Options extensionOptions = new Options();
Option enumerate = new Option(ENUMERATE_OPT, false, "Enumerate all extensions");
Option definition = new Option(DEFINITION_OPT, false, "Get extension definition");
Option describe = new Option(DESCRIBE_OPT, false, "Get extension description");
Option list = new Option(FalconCLIConstants.LIST_OPT, false, "List extension jobs and associated entities");
Option instances = new Option(INSTANCES_OPT, false, "List instances of an extension job");
Option submit = new Option(FalconCLIConstants.SUBMIT_OPT, false, "Submit an extension job");
Option submitAndSchedule = new Option(FalconCLIConstants.SUBMIT_AND_SCHEDULE_OPT, false,
"Submit and schedule an extension job");
Option update = new Option(FalconCLIConstants.UPDATE_OPT, false, "Update an extension job");
Option validate = new Option(FalconCLIConstants.VALIDATE_OPT, false, "Validate an extension job");
Option schedule = new Option(FalconCLIConstants.SCHEDULE_OPT, false, "Schedule an extension job");
Option suspend = new Option(FalconCLIConstants.SUSPEND_OPT, false, "Suspend an extension job");
Option resume = new Option(FalconCLIConstants.RESUME_OPT, false, "Resume an extension job");
Option delete = new Option(FalconCLIConstants.DELETE_OPT, false, "Delete an extension job");
Option enable = new Option(FalconCLIConstants.ENABLE_OPT, false, "Enable an extension");
Option disable = new Option(FalconCLIConstants.DISABLE_OPT, false, "Disable an extension");
Option unregister = new Option(FalconCLIConstants.UREGISTER, false, "Un-register an extension. This will make"
+ " the extension unavailable for instantiation");
Option detail = new Option(FalconCLIConstants.DETAIL, false, "Show details of a given extension");
Option register = new Option(FalconCLIConstants.REGISTER, false, "Register an extension with Falcon. This will "
+ "make the extension available for instantiation for all users.");
Option colo = new Option(COLO_OPT, true, COLO_OPT_DESCRIPTION);
colo.setRequired(false);
OptionGroup group = new OptionGroup();
group.addOption(enumerate);
group.addOption(definition);
group.addOption(describe);
group.addOption(list);
group.addOption(instances);
group.addOption(submit);
group.addOption(submitAndSchedule);
group.addOption(update);
group.addOption(validate);
group.addOption(schedule);
group.addOption(suspend);
group.addOption(resume);
group.addOption(delete);
group.addOption(unregister);
group.addOption(detail);
group.addOption(register);
group.addOption(enable);
group.addOption(disable);
extensionOptions.addOptionGroup(group);
Option url = new Option(FalconCLIConstants.URL_OPTION, true, "Falcon URL");
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 extensionName = new Option(EXTENSION_NAME_OPT, true, "Extension name");
Option jobName = new Option(JOB_NAME_OPT, true, "Extension job name");
Option instanceStatus = new Option(FalconCLIConstants.INSTANCE_STATUS_OPT, true, "Instance status");
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 fields = new Option(FalconCLIConstants.FIELDS_OPT, true, "Entity fields to show for a request");
Option start = new Option(FalconCLIConstants.START_OPT, true, "Start time of instances");
Option end = new Option(FalconCLIConstants.END_OPT, true, "End time of instances");
Option status = new Option(FalconCLIConstants.STATUS_OPT, true, "Filter returned instances by status");
Option orderBy = new Option(FalconCLIConstants.ORDER_BY_OPT, true, "Order returned instances by this field");
Option filePath = new Option(FalconCLIConstants.FILE_PATH_OPT, true, "File path of extension parameters");
Option path = new Option(FalconCLIConstants.PATH, true, "Path of hdfs location for extension");
Option description = new Option(FalconCLIConstants.DESCRIPTION, true, "Short Description for extension");
extensionOptions.addOption(url);
extensionOptions.addOption(doAs);
extensionOptions.addOption(debug);
extensionOptions.addOption(extensionName);
extensionOptions.addOption(jobName);
extensionOptions.addOption(instanceStatus);
extensionOptions.addOption(sortOrder);
extensionOptions.addOption(offset);
extensionOptions.addOption(numResults);
extensionOptions.addOption(fields);
extensionOptions.addOption(start);
extensionOptions.addOption(end);
extensionOptions.addOption(status);
extensionOptions.addOption(orderBy);
extensionOptions.addOption(filePath);
extensionOptions.addOption(path);
extensionOptions.addOption(description);
extensionOptions.addOption(colo);
return extensionOptions;
}
private void validateRequiredParameter(final String parameter, final String parameterName) {
if (StringUtils.isBlank(parameter)) {
throw new FalconCLIException("The parameter " + parameterName + " cannot be null or empty");
}
}
private static String prettyPrintJson(final String jsonString) {
if (StringUtils.isBlank(jsonString)) {
return "No result returned";
}
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser jp = new JsonParser();
JsonElement je = jp.parse(jsonString.trim());
return gson.toJson(je);
}
}