use of io.cdap.cdap.common.BadRequestException in project cdap by caskdata.
the class DefaultPreviewManager method stopPreview.
@Override
public void stopPreview(@Name("applicationId") ApplicationId applicationId) throws Exception {
accessEnforcer.enforce(applicationId, authenticationContext.getPrincipal(), ApplicationPermission.PREVIEW);
PreviewStatus status = getStatus(applicationId);
if (status.getStatus().isEndState()) {
throw new BadRequestException(String.format("Preview run cannot be stopped. It is already in %s state.", status.getStatus().name()));
}
if (status.getStatus() == PreviewStatus.Status.WAITING) {
previewStore.setPreviewStatus(applicationId, new PreviewStatus(PreviewStatus.Status.KILLED, status.getSubmitTime(), null, null, null));
return;
}
previewRunStopper.stop(applicationId);
}
use of io.cdap.cdap.common.BadRequestException in project cdap by caskdata.
the class DefaultNamespaceAdmin method create.
/**
* Creates a new namespace
*
* @param metadata the {@link NamespaceMeta} for the new namespace to be created
* @throws NamespaceAlreadyExistsException if the specified namespace already exists
*/
@Override
public synchronized void create(final NamespaceMeta metadata) throws Exception {
// TODO: CDAP-1427 - This should be transactional, but we don't support transactions on files yet
Preconditions.checkArgument(metadata != null, "Namespace metadata should not be null.");
NamespaceId namespace = metadata.getNamespaceId();
if (exists(namespace)) {
throw new NamespaceAlreadyExistsException(namespace);
}
// need to enforce on the principal id if impersonation is involved
String ownerPrincipal = metadata.getConfig().getPrincipal();
Principal requestingUser = authenticationContext.getPrincipal();
if (ownerPrincipal != null) {
accessEnforcer.enforce(new KerberosPrincipalId(ownerPrincipal), requestingUser, AccessPermission.SET_OWNER);
}
accessEnforcer.enforce(namespace, requestingUser, StandardPermission.CREATE);
// If this namespace has custom mapping then validate the given custom mapping
if (hasCustomMapping(metadata)) {
validateCustomMapping(metadata);
}
// check that the user has configured either both or none of the following configuration: principal and keytab URI
boolean hasValidKerberosConf = false;
if (metadata.getConfig() != null) {
String configuredPrincipal = metadata.getConfig().getPrincipal();
String configuredKeytabURI = metadata.getConfig().getKeytabURI();
if ((!Strings.isNullOrEmpty(configuredPrincipal) && Strings.isNullOrEmpty(configuredKeytabURI)) || (Strings.isNullOrEmpty(configuredPrincipal) && !Strings.isNullOrEmpty(configuredKeytabURI))) {
throw new BadRequestException(String.format("Either both or none of the following two configurations must be configured. " + "Configured principal: %s, Configured keytabURI: %s", configuredPrincipal, configuredKeytabURI));
}
hasValidKerberosConf = true;
}
// check that if explore as principal is explicitly set to false then user has kerberos configuration
if (!metadata.getConfig().isExploreAsPrincipal() && !hasValidKerberosConf) {
throw new BadRequestException(String.format("No kerberos principal or keytab-uri was provided while '%s' was set to true.", NamespaceConfig.EXPLORE_AS_PRINCIPAL));
}
// store the meta first in the namespace store because namespacedLocationFactory needs to look up location
// mapping from namespace config
nsStore.create(metadata);
try {
UserGroupInformation ugi;
if (NamespaceId.DEFAULT.equals(namespace)) {
ugi = UserGroupInformation.getCurrentUser();
} else {
ugi = impersonator.getUGI(namespace);
}
ImpersonationUtils.doAs(ugi, (Callable<Void>) () -> {
storageProviderNamespaceAdmin.get().create(metadata);
return null;
});
// if needed, run master environment specific logic
MasterEnvironment masterEnv = MasterEnvironments.getMasterEnvironment();
if (masterEnv != null) {
masterEnv.onNamespaceCreation(namespace.getNamespace(), metadata.getConfig().getConfigs());
}
} catch (Throwable t) {
LOG.error(String.format("Failed to create namespace '%s'", namespace.getNamespace()), t);
// failed to create namespace in underlying storage so delete the namespace meta stored in the store earlier
deleteNamespaceMeta(metadata.getNamespaceId());
throw new NamespaceCannotBeCreatedException(namespace, t);
}
emitNamespaceCountMetric();
LOG.info("Namespace {} created with meta {}", metadata.getNamespaceId(), metadata);
}
use of io.cdap.cdap.common.BadRequestException in project cdap by caskdata.
the class ArtifactHttpHandler method getArtifactProperties.
@POST
@Path("/namespaces/{namespace-id}/artifactproperties")
public void getArtifactProperties(FullHttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId, @QueryParam("order") @DefaultValue("DESC") String order) throws Exception {
NamespaceId namespace = validateAndGetNamespace(namespaceId);
ArtifactSortOrder sortOrder = ArtifactSortOrder.valueOf(order);
List<ArtifactPropertiesRequest> propertyRequests;
try (Reader reader = new InputStreamReader(new ByteBufInputStream(request.content()), StandardCharsets.UTF_8)) {
propertyRequests = GSON.fromJson(reader, BATCH_ARTIFACT_PROPERTIES_REQUEST);
} catch (JsonSyntaxException e) {
throw new BadRequestException("Unable to parse request: " + e.getMessage(), e);
}
List<ArtifactSummaryProperties> result = new ArrayList<>(propertyRequests.size());
for (ArtifactPropertiesRequest propertiesRequest : propertyRequests) {
NamespaceId requestNamespace = propertiesRequest.getScope() == ArtifactScope.SYSTEM ? NamespaceId.SYSTEM : namespace;
ArtifactRange range = new ArtifactRange(requestNamespace.getNamespace(), propertiesRequest.getName(), ArtifactVersionRange.parse(propertiesRequest.getVersion()));
List<ArtifactDetail> artifactDetails = artifactRepository.getArtifactDetails(range, 1, sortOrder);
for (ArtifactDetail artifactDetail : artifactDetails) {
Map<String, String> properties = artifactDetail.getMeta().getProperties();
Map<String, String> filteredProperties = new HashMap<>(propertiesRequest.getProperties().size());
for (String propertyKey : propertiesRequest.getProperties()) {
if (properties.containsKey(propertyKey)) {
filteredProperties.put(propertyKey, properties.get(propertyKey));
}
}
String artifactVersion = artifactDetail.getDescriptor().getArtifactId().getVersion().getVersion();
result.add(new ArtifactSummaryProperties(propertiesRequest.getName(), artifactVersion, propertiesRequest.getScope(), filteredProperties));
}
}
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(result, BATCH_ARTIFACT_PROPERTIES_RESPONSE));
}
use of io.cdap.cdap.common.BadRequestException in project cdap by caskdata.
the class ArtifactHttpHandler method addArtifact.
@POST
@Path("/namespaces/{namespace-id}/artifacts/{artifact-name}")
@AuditPolicy(AuditDetail.HEADERS)
public BodyConsumer addArtifact(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") final String namespaceId, @PathParam("artifact-name") final String artifactName, @HeaderParam(VERSION_HEADER) final String artifactVersion, @HeaderParam(EXTENDS_HEADER) final String parentArtifactsStr, @HeaderParam(PLUGINS_HEADER) String pluginClasses) throws NamespaceNotFoundException, BadRequestException {
final NamespaceId namespace = validateAndGetNamespace(namespaceId);
// that processes the last http chunk.
if (artifactVersion != null && !artifactVersion.isEmpty()) {
ArtifactId artifactId = validateAndGetArtifactId(namespace, artifactName, artifactVersion);
// If the artifact ID is available, use it to perform an authorization check.
contextAccessEnforcer.enforce(artifactId, StandardPermission.CREATE);
} else {
// If there is no version, we perform an enforceOnParent check in which the entityID is not needed.
contextAccessEnforcer.enforceOnParent(EntityType.ARTIFACT, namespace, StandardPermission.CREATE);
}
final Set<ArtifactRange> parentArtifacts = parseExtendsHeader(namespace, parentArtifactsStr);
final Set<PluginClass> additionalPluginClasses;
if (pluginClasses == null || pluginClasses.isEmpty()) {
additionalPluginClasses = ImmutableSet.of();
} else {
try {
additionalPluginClasses = GSON.fromJson(pluginClasses, PLUGINS_TYPE);
additionalPluginClasses.forEach(PluginClass::validate);
} catch (JsonParseException e) {
throw new BadRequestException(String.format("%s header '%s' is invalid.", PLUGINS_HEADER, pluginClasses), e);
} catch (IllegalArgumentException e) {
throw new BadRequestException(String.format("Invalid PluginClasses '%s'.", pluginClasses), e);
}
}
try {
// copy the artifact contents to local tmp directory
Files.createDirectories(tmpDir.toPath());
File destination = File.createTempFile("artifact-", ".jar", tmpDir);
return new AbstractBodyConsumer(destination) {
@Override
protected void onFinish(HttpResponder responder, File uploadedFile) {
try {
String version = (artifactVersion == null || artifactVersion.isEmpty()) ? getBundleVersion(uploadedFile) : artifactVersion;
ArtifactId artifactId = validateAndGetArtifactId(namespace, artifactName, version);
// add the artifact to the repo
artifactRepository.addArtifact(Id.Artifact.fromEntityId(artifactId), uploadedFile, parentArtifacts, additionalPluginClasses);
responder.sendString(HttpResponseStatus.OK, "Artifact added successfully");
} catch (ArtifactRangeNotFoundException e) {
responder.sendString(HttpResponseStatus.NOT_FOUND, e.getMessage());
} catch (ArtifactAlreadyExistsException e) {
responder.sendString(HttpResponseStatus.CONFLICT, e.getMessage());
} catch (WriteConflictException e) {
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Conflict while writing artifact, please try again.");
} catch (IOException e) {
LOG.error("Exception while trying to write artifact {}-{}-{}.", namespaceId, artifactName, artifactVersion, e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Error performing IO while writing artifact.");
} catch (BadRequestException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
} catch (UnauthorizedException e) {
responder.sendString(HttpResponseStatus.FORBIDDEN, e.getMessage());
} catch (Exception e) {
LOG.error("Error while writing artifact {}-{}-{}", namespaceId, artifactName, artifactVersion, e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Error while adding artifact.");
}
}
private String getBundleVersion(File file) throws BadRequestException, IOException {
try (JarFile jarFile = new JarFile(file)) {
Manifest manifest = jarFile.getManifest();
if (manifest == null) {
throw new BadRequestException("Unable to derive version from artifact because it does not contain a manifest. " + "Please package the jar with a manifest, or explicitly specify the artifact version.");
}
Attributes attributes = manifest.getMainAttributes();
String version = attributes == null ? null : attributes.getValue(ManifestFields.BUNDLE_VERSION);
if (version == null) {
throw new BadRequestException("Unable to derive version from artifact because manifest does not contain Bundle-Version attribute. " + "Please include Bundle-Version in the manifest, or explicitly specify the artifact version.");
}
return version;
} catch (ZipException e) {
throw new BadRequestException("Artifact is not in zip format. Please make sure it is a jar file.");
}
}
};
} catch (IOException e) {
LOG.error("Exception creating temp file to place artifact {} contents", artifactName, e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Server error creating temp file for artifact.");
return null;
}
}
use of io.cdap.cdap.common.BadRequestException in project cdap by caskdata.
the class ArtifactHttpHandler method parseExtendsHeader.
// find out if this artifact extends other artifacts. If so, there will be a header like
// 'Artifact-Extends: <name>[<lowerversion>,<upperversion>]/<name>[<lowerversion>,<upperversion>]:
// for example: 'Artifact-Extends: etl-batch[1.0.0,2.0.0]/etl-realtime[1.0.0:3.0.0]
private Set<ArtifactRange> parseExtendsHeader(NamespaceId namespace, String extendsHeader) throws BadRequestException {
Set<ArtifactRange> parentArtifacts = Sets.newHashSet();
if (extendsHeader != null && !extendsHeader.isEmpty()) {
for (String parent : Splitter.on('/').split(extendsHeader)) {
parent = parent.trim();
ArtifactRange range;
// try parsing it as a namespaced range like system:etl-batch[1.0.0,2.0.0)
try {
range = ArtifactRanges.parseArtifactRange(parent);
// only support extending an artifact that is in the same namespace, or system namespace
if (!NamespaceId.SYSTEM.getNamespace().equals(range.getNamespace()) && !namespace.getNamespace().equals(range.getNamespace())) {
throw new BadRequestException(String.format("Parent artifact %s must be in the same namespace or a system artifact.", parent));
}
} catch (InvalidArtifactRangeException e) {
// if this failed, try parsing as a non-namespaced range like etl-batch[1.0.0,2.0.0)
try {
range = ArtifactRanges.parseArtifactRange(namespace.getNamespace(), parent);
} catch (InvalidArtifactRangeException e1) {
throw new BadRequestException(String.format("Invalid artifact range %s: %s", parent, e1.getMessage()));
}
}
parentArtifacts.add(range);
}
}
return parentArtifacts;
}
Aggregations