/**
* 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.client.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;
import static org.apache.falcon.client.FalconCLIConstants.DISCOVERY_OPT;
import static org.apache.falcon.client.FalconCLIConstants.DISCOVERY_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.LINEAGE_OPT;
import static org.apache.falcon.client.FalconCLIConstants.LINEAGE_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.PIPELINE_OPT;
import static org.apache.falcon.client.FalconCLIConstants.PIPELINE_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.LIST_OPT;
import static org.apache.falcon.client.FalconCLIConstants.LIST_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.RELATIONS_OPT;
import static org.apache.falcon.client.FalconCLIConstants.RELATIONS_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.URL_OPTION;
import static org.apache.falcon.client.FalconCLIConstants.URL_OPTION_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.TYPE_OPT;
import static org.apache.falcon.client.FalconCLIConstants.TYPE_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.NAME_OPT;
import static org.apache.falcon.client.FalconCLIConstants.NAME_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.DEBUG_OPTION;
import static org.apache.falcon.client.FalconCLIConstants.DEBUG_OPTION_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.DIRECTION_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.DIRECTION_OPT;
import static org.apache.falcon.client.FalconCLIConstants.VALUE_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.VALUE_OPT;
import static org.apache.falcon.client.FalconCLIConstants.KEY_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.KEY_OPT;
import static org.apache.falcon.client.FalconCLIConstants.ID_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.ID_OPT;
import static org.apache.falcon.client.FalconCLIConstants.EDGE_CMD_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.EDGE_CMD;
import static org.apache.falcon.client.FalconCLIConstants.VERTEX_EDGES_CMD_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.VERTEX_EDGES_CMD;
import static org.apache.falcon.client.FalconCLIConstants.VERTICES_CMD_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.VERTICES_CMD;
import static org.apache.falcon.client.FalconCLIConstants.VERTEX_CMD_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.VERTEX_CMD;
import static org.apache.falcon.client.FalconCLIConstants.NUM_RESULTS_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.NUM_RESULTS_OPT;
import static org.apache.falcon.client.FalconCLIConstants.PROCESS_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.PROCESS_OPT;
import static org.apache.falcon.client.FalconCLIConstants.FEED_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.FEED_OPT;
import static org.apache.falcon.client.FalconCLIConstants.CLUSTER_OPT_DESCRIPTION;
import static org.apache.falcon.client.FalconCLIConstants.CLUSTER_OPT;
import static org.apache.falcon.client.FalconCLIConstants.DO_AS_OPT;
import static org.apache.falcon.client.FalconCLIConstants.DO_AS_DESCRIPTION;
import static org.apache.falcon.ValidationUtil.validateDimensionName;
import static org.apache.falcon.ValidationUtil.validateDimensionType;
import static org.apache.falcon.ValidationUtil.validateId;
import static org.apache.falcon.ValidationUtil.validateScheduleEntity;
import static org.apache.falcon.ValidationUtil.validateVertexEdgesCommand;
import static org.apache.falcon.ValidationUtil.validateVerticesCommand;
import static org.apache.falcon.ValidationUtil.validatePipelineName;
/**
* 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);
public FalconMetadataCLI() throws Exception {
super();
}
public Options createMetadataOptions() {
Options metadataOptions = new Options();
OptionGroup group = new OptionGroup();
Option discovery = new Option(DISCOVERY_OPT, false, DISCOVERY_OPT_DESCRIPTION);
Option lineage = new Option(LINEAGE_OPT, false, LINEAGE_OPT_DESCRIPTION);
group.addOption(discovery);
group.addOption(lineage);
Option pipeline = new Option(PIPELINE_OPT, true, PIPELINE_OPT_DESCRIPTION);
metadataOptions.addOptionGroup(group);
// Add discovery options
Option list = new Option(LIST_OPT, false, LIST_OPT_DESCRIPTION);
Option relations = new Option(RELATIONS_OPT, false, RELATIONS_OPT_DESCRIPTION);
metadataOptions.addOption(list);
metadataOptions.addOption(relations);
Option url = new Option(URL_OPTION, true, URL_OPTION_DESCRIPTION);
Option type = new Option(TYPE_OPT, true, TYPE_OPT_DESCRIPTION);
Option name = new Option(NAME_OPT, true, NAME_OPT_DESCRIPTION);
Option cluster = new Option(CLUSTER_OPT, true, CLUSTER_OPT_DESCRIPTION);
Option feed = new Option(FEED_OPT, true, FEED_OPT_DESCRIPTION);
Option process = new Option(PROCESS_OPT, true, PROCESS_OPT_DESCRIPTION);
Option numResults = new Option(NUM_RESULTS_OPT, true, NUM_RESULTS_OPT_DESCRIPTION);
// 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, VERTEX_CMD_DESCRIPTION);
Option vertices = new Option(VERTICES_CMD, false, VERTICES_CMD_DESCRIPTION);
Option vertexEdges = new Option(VERTEX_EDGES_CMD, false, VERTEX_EDGES_CMD_DESCRIPTION);
Option edges = new Option(EDGE_CMD, false, EDGE_CMD_DESCRIPTION);
Option id = new Option(ID_OPT, true, ID_OPT_DESCRIPTION);
Option key = new Option(KEY_OPT, true, KEY_OPT_DESCRIPTION);
Option value = new Option(VALUE_OPT, true, VALUE_OPT_DESCRIPTION);
Option direction = new Option(DIRECTION_OPT, true, DIRECTION_OPT_DESCRIPTION);
Option debug = new Option(DEBUG_OPTION, false, DEBUG_OPTION_DESCRIPTION);
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(DO_AS_OPT, true, DO_AS_DESCRIPTION);
metadataOptions.addOption(doAs);
return metadataOptions;
}
public void metadataCommand(CommandLine commandLine, FalconClient client) {
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/missing metadata command. Supported commands include "
+ "list, relations, lineage, vertex, vertices, edge, edges. "
+ "Please refer to Falcon CLI twiki for more details.");
}
OUT.get().println(result);
}
}