use of io.cdap.cdap.common.InvalidArtifactException in project cdap by caskdata.
the class DefaultArtifactRepository method validatePluginSet.
/**
* Validates the set of plugins for an artifact. Checks that the pair of plugin type and name are unique among
* all plugins in an artifact.
*
* @param plugins the set of plugins to validate
* @throws InvalidArtifactException if there is more than one class with the same type and name
*/
@VisibleForTesting
static void validatePluginSet(Set<PluginClass> plugins) throws InvalidArtifactException {
boolean isInvalid = false;
StringBuilder errMsg = new StringBuilder("Invalid plugins field.");
Set<ImmutablePair<String, String>> existingPlugins = new HashSet<>();
Set<ImmutablePair<String, String>> dupes = new HashSet<>();
for (PluginClass plugin : plugins) {
ImmutablePair<String, String> typeAndName = ImmutablePair.of(plugin.getType(), plugin.getName());
if (!existingPlugins.add(typeAndName) && !dupes.contains(typeAndName)) {
errMsg.append(" Only one plugin with type '");
errMsg.append(typeAndName.getFirst());
errMsg.append("' and name '");
errMsg.append(typeAndName.getSecond());
errMsg.append("' can be present.");
dupes.add(typeAndName);
isInvalid = true;
}
}
// "Invalid plugins. Only one plugin with type 'source' and name 'table' can be present."
if (isInvalid) {
throw new InvalidArtifactException(errMsg.toString());
}
}
use of io.cdap.cdap.common.InvalidArtifactException in project cdap by caskdata.
the class DefaultArtifactInspector method inspectPlugins.
/**
* Inspects the plugin file and extracts plugin classes information.
*/
private void inspectPlugins(ArtifactClasses.Builder builder, File artifactFile, io.cdap.cdap.proto.id.ArtifactId artifactId, PluginInstantiator pluginInstantiator, Set<PluginClass> additionalPlugins, List<MetadataMutation> mutations) throws IOException, InvalidArtifactException {
ArtifactId artifact = artifactId.toApiArtifactId();
PluginClassLoader pluginClassLoader = pluginInstantiator.getArtifactClassLoader(artifact);
inspectAdditionalPlugins(artifact, additionalPlugins, pluginClassLoader);
// See if there are export packages. Plugins should be in those packages
Set<String> exportPackages = getExportPackages(artifactFile);
if (exportPackages.isEmpty()) {
return;
}
try {
for (Class<?> cls : getPluginClasses(exportPackages, pluginClassLoader)) {
Plugin pluginAnnotation = cls.getAnnotation(Plugin.class);
if (pluginAnnotation == null) {
continue;
}
Map<String, PluginPropertyField> pluginProperties = Maps.newHashMap();
try {
String configField = getProperties(TypeToken.of(cls), pluginProperties);
String pluginName = getPluginName(cls);
PluginId pluginId = new PluginId(artifactId.getNamespace(), artifactId.getArtifact(), artifactId.getVersion(), pluginName, pluginAnnotation.type());
MetadataMutation mutation = getMetadataMutation(pluginId, cls);
if (mutation != null) {
mutations.add(mutation);
}
PluginClass pluginClass = PluginClass.builder().setName(pluginName).setType(pluginAnnotation.type()).setCategory(getPluginCategory(cls)).setClassName(cls.getName()).setConfigFieldName(configField).setProperties(pluginProperties).setRequirements(getArtifactRequirements(cls)).setDescription(getPluginDescription(cls)).build();
builder.addPlugin(pluginClass);
} catch (UnsupportedTypeException e) {
LOG.warn("Plugin configuration type not supported. Plugin ignored. {}", cls, e);
}
}
} catch (Throwable t) {
throw new InvalidArtifactException(String.format("Class could not be found while inspecting artifact for plugins. " + "Please check dependencies are available, and that the correct parent artifact was specified. " + "Error class: %s, message: %s.", t.getClass(), t.getMessage()), t);
}
}
use of io.cdap.cdap.common.InvalidArtifactException in project cdap by caskdata.
the class AppLifecycleHttpHandler method updateApp.
/**
* Updates an existing application.
*/
@POST
@Path("/apps/{app-id}/update")
@AuditPolicy(AuditDetail.REQUEST_BODY)
public void updateApp(FullHttpRequest request, HttpResponder responder, @PathParam("namespace-id") final String namespaceId, @PathParam("app-id") final String appName) throws NotFoundException, BadRequestException, AccessException, IOException {
ApplicationId appId = validateApplicationId(namespaceId, appName);
AppRequest appRequest;
try (Reader reader = new InputStreamReader(new ByteBufInputStream(request.content()), StandardCharsets.UTF_8)) {
appRequest = DECODE_GSON.fromJson(reader, AppRequest.class);
} catch (IOException e) {
LOG.error("Error reading request to update app {} in namespace {}.", appName, namespaceId, e);
throw new IOException("Error reading request body.");
} catch (JsonSyntaxException e) {
throw new BadRequestException("Request body is invalid json: " + e.getMessage());
}
try {
applicationLifecycleService.updateApp(appId, appRequest, createProgramTerminator());
responder.sendString(HttpResponseStatus.OK, "Update complete.");
} catch (InvalidArtifactException e) {
throw new BadRequestException(e.getMessage());
} catch (ConflictException e) {
responder.sendString(HttpResponseStatus.CONFLICT, e.getMessage());
} catch (NotFoundException | UnauthorizedException e) {
throw e;
} catch (Exception e) {
// this is the same behavior as deploy app pipeline, but this is bad behavior. Error handling needs improvement.
LOG.error("Deploy failure", e);
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
}
}
use of io.cdap.cdap.common.InvalidArtifactException in project cdap by caskdata.
the class AppLifecycleHttpHandler method deployApplication.
private BodyConsumer deployApplication(final HttpResponder responder, final NamespaceId namespace, final String appId, final String archiveName, final String configString, @Nullable final String ownerPrincipal, final boolean updateSchedules) throws IOException {
Id.Namespace idNamespace = Id.Namespace.fromEntityId(namespace);
Location namespaceHomeLocation = namespacePathLocator.get(namespace);
if (!namespaceHomeLocation.exists()) {
String msg = String.format("Home directory %s for namespace %s not found", namespaceHomeLocation, namespace.getNamespace());
LOG.error(msg);
responder.sendString(HttpResponseStatus.NOT_FOUND, msg);
return null;
}
if (archiveName == null || archiveName.isEmpty()) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, String.format("%s header not present. Please include the header and set its value to the jar name.", ARCHIVE_NAME_HEADER), new DefaultHttpHeaders().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE));
return null;
}
// TODO: (CDAP-3258) error handling needs to be refactored here, should be able just to throw the exception,
// but the caller catches all exceptions and responds with a 500
final Id.Artifact artifactId;
try {
artifactId = Id.Artifact.parse(idNamespace, archiveName);
} catch (IllegalArgumentException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
return null;
}
KerberosPrincipalId ownerPrincipalId = ownerPrincipal == null ? null : new KerberosPrincipalId(ownerPrincipal);
// Store uploaded content to a local temp file
String namespacesDir = configuration.get(Constants.Namespace.NAMESPACES_DIR);
File localDataDir = new File(configuration.get(Constants.CFG_LOCAL_DATA_DIR));
File namespaceBase = new File(localDataDir, namespacesDir);
File tempDir = new File(new File(namespaceBase, namespace.getNamespace()), configuration.get(Constants.AppFabric.TEMP_DIR)).getAbsoluteFile();
if (!DirUtils.mkdirs(tempDir)) {
throw new IOException("Could not create temporary directory at: " + tempDir);
}
final KerberosPrincipalId finalOwnerPrincipalId = ownerPrincipalId;
return new AbstractBodyConsumer(File.createTempFile("app-", ".jar", tempDir)) {
@Override
protected void onFinish(HttpResponder responder, File uploadedFile) {
try {
// deploy app
ApplicationWithPrograms app = applicationLifecycleService.deployAppAndArtifact(namespace, appId, artifactId, uploadedFile, configString, finalOwnerPrincipalId, createProgramTerminator(), updateSchedules);
LOG.info("Successfully deployed app {} in namespace {} from artifact {} with configuration {} and " + "principal {}", app.getApplicationId().getApplication(), namespace.getNamespace(), artifactId, configString, finalOwnerPrincipalId);
responder.sendString(HttpResponseStatus.OK, String.format("Successfully deployed app %s", app.getApplicationId().getApplication()));
} catch (InvalidArtifactException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
} catch (ArtifactAlreadyExistsException e) {
responder.sendString(HttpResponseStatus.CONFLICT, String.format("Artifact '%s' already exists. Please use the API that creates an application from an existing artifact. " + "If you are trying to replace the artifact, please delete it and then try again.", artifactId));
} catch (WriteConflictException e) {
// don't really expect this to happen. It means after multiple retries there were still write conflicts.
LOG.warn("Write conflict while trying to add artifact {}.", artifactId, e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Write conflict while adding artifact. This can happen if multiple requests to add " + "the same artifact occur simultaneously. Please try again.");
} catch (UnauthorizedException e) {
responder.sendString(HttpResponseStatus.FORBIDDEN, e.getMessage());
} catch (ConflictException e) {
responder.sendString(HttpResponseStatus.CONFLICT, e.getMessage());
} catch (Exception e) {
LOG.error("Deploy failure", e);
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
}
}
};
}
use of io.cdap.cdap.common.InvalidArtifactException in project cdap by caskdata.
the class SystemAppEnableExecutor method deploySystemApp.
private ApplicationWithPrograms deploySystemApp(Arguments arguments) throws Exception {
ApplicationId appId = arguments.getId();
ArtifactSummary artifactSummary = arguments.getArtifact();
KerberosPrincipalId ownerPrincipalId = arguments.getOwnerPrincipal() == null ? null : new KerberosPrincipalId(arguments.getOwnerPrincipal());
// if we don't null check, it gets serialized to "null"
String configString = arguments.getConfig() == null ? null : GSON.toJson(arguments.getConfig());
try {
return appLifecycleService.deployApp(appId.getParent(), appId.getApplication(), appId.getVersion(), artifactSummary, configString, x -> {
}, ownerPrincipalId, arguments.canUpdateSchedules(), false, Collections.emptyMap());
} catch (UnauthorizedException | InvalidArtifactException e) {
throw e;
} catch (DatasetManagementException e) {
if (e.getCause() instanceof UnauthorizedException) {
throw (UnauthorizedException) e.getCause();
} else {
throw new RetryableException(e);
}
} catch (Exception e) {
throw new RetryableException(e);
}
}
Aggregations