/*
* Copyright © 2015 Cask Data, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package co.cask.cdap.cli.command.artifact;
import co.cask.cdap.cli.ArgumentName;
import co.cask.cdap.cli.CLIConfig;
import co.cask.cdap.cli.util.AbstractAuthCommand;
import co.cask.cdap.cli.util.FilePathResolver;
import co.cask.cdap.client.ArtifactClient;
import co.cask.cdap.common.conf.ArtifactConfig;
import co.cask.cdap.common.conf.ArtifactConfigReader;
import co.cask.cdap.proto.Id;
import co.cask.common.cli.Arguments;
import com.google.common.io.Files;
import com.google.inject.Inject;
import java.io.File;
import java.io.PrintStream;
import java.util.Map;
/**
* Loads an artifact into CDAP.
*/
public class LoadArtifactCommand extends AbstractAuthCommand {
private final ArtifactClient artifactClient;
private final FilePathResolver resolver;
private final ArtifactConfigReader configReader;
@Inject
public LoadArtifactCommand(ArtifactClient artifactClient, CLIConfig cliConfig, FilePathResolver resolver) {
super(cliConfig);
this.artifactClient = artifactClient;
this.resolver = resolver;
this.configReader = new ArtifactConfigReader();
}
@Override
public void perform(Arguments arguments, PrintStream output) throws Exception {
File artifactFile = resolver.resolvePathToFile(arguments.get(ArgumentName.LOCAL_FILE_PATH.toString()));
String name = arguments.getOptional(ArgumentName.ARTIFACT_NAME.toString());
String version = arguments.getOptional(ArgumentName.ARTIFACT_VERSION.toString());
Id.Artifact artifactId;
if (name == null && version != null) {
throw new IllegalArgumentException("If a version is specified, name must also be specified.");
} else if (name != null && version == null) {
throw new IllegalArgumentException("If a name is specified, a version must also be specified.");
} else if (name == null) {
artifactId = Id.Artifact.parse(cliConfig.getCurrentNamespace(), artifactFile.getName());
} else {
artifactId = Id.Artifact.from(cliConfig.getCurrentNamespace(), name, version);
}
String configPath = arguments.getOptional(ArgumentName.ARTIFACT_CONFIG_FILE.toString());
if (configPath == null) {
artifactClient.add(artifactId.getNamespace(), artifactId.getName(), Files.newInputStreamSupplier(artifactFile),
artifactId.getVersion().getVersion());
} else {
File configFile = resolver.resolvePathToFile(configPath);
ArtifactConfig artifactConfig = configReader.read(artifactId.getNamespace(), configFile);
artifactClient.add(artifactId.getNamespace(), artifactId.getName(), Files.newInputStreamSupplier(artifactFile),
artifactId.getVersion().getVersion(), artifactConfig.getParents(), artifactConfig.getPlugins());
Map<String, String> properties = artifactConfig.getProperties();
if (properties != null && !properties.isEmpty()) {
artifactClient.writeProperties(artifactId, properties);
}
}
output.printf("Successfully added artifact with name '%s'\n", artifactId.getName());
}
@Override
public String getPattern() {
return String.format("load artifact <%s> [config-file <%s>] [name <%s>] [version <%s>]",
ArgumentName.LOCAL_FILE_PATH, ArgumentName.ARTIFACT_CONFIG_FILE,
ArgumentName.ARTIFACT_NAME, ArgumentName.ARTIFACT_VERSION);
}
@Override
public String getDescription() {
return "Loads an artifact into CDAP. If the artifact name and version are not both given, " +
"they will be derived from the filename of the artifact. " +
"File names are expected to be of the form '<name>-<version>.jar'. " +
"If the artifact contains plugins that extend another artifact, or if it contains " +
"third-party plugins, a config file must be provided. " +
"The config file must contain a JSON object that specifies the parent artifacts " +
"and any third-party plugins in the JAR. " +
"For example, if there is a config file with these contents:\n" +
" {\n" +
" \"parents\":[ \"app1[1.0.0,2.0.0)\", \"app2[1.2.0,1.3.0] ],\n" +
" \"plugins\":[\n" +
" { \"type\": \"jdbc\",\n" +
" \"name\": \"mysql\",\n" +
" \"className\": \"com.mysql.jdbc.Driver\"\n" +
" }\n" +
" ],\n" +
" \"properties\":{\n" +
" \"prop1\": \"val1\"\n" +
" }\n" +
" }\n" +
"This config specifies that the artifact contains one JDBC third-party plugin that should be " +
"available to the 'app1' artifact (versions 1.0.0 inclusive to 2.0.0 exclusive) and 'app2' artifact " +
"(versions 1.2.0 inclusive to 1.3.0 inclusive). The config may also include a 'properties' field specifying " +
"properties for the artifact.";
}
}