Search in sources :

Example 66 with BadRequestException

use of io.cdap.cdap.common.BadRequestException in project cdap by cdapio.

the class ProgramLifecycleHttpHandler method readScheduleDetailBody.

private ScheduleDetail readScheduleDetailBody(FullHttpRequest request, String scheduleName) throws BadRequestException, IOException {
    JsonElement json;
    try (Reader reader = new InputStreamReader(new ByteBufInputStream(request.content()), Charsets.UTF_8)) {
        // The schedule spec in the request body does not contain the program information
        json = DECODE_GSON.fromJson(reader, JsonElement.class);
    } catch (IOException e) {
        throw new IOException("Error reading request body", e);
    } catch (JsonSyntaxException e) {
        throw new BadRequestException("Request body is invalid json: " + e.getMessage());
    }
    if (!json.isJsonObject()) {
        throw new BadRequestException("Expected a json object in the request body but received " + GSON.toJson(json));
    }
    ScheduleDetail scheduleDetail;
    try {
        scheduleDetail = DECODE_GSON.fromJson(json, ScheduleDetail.class);
    } catch (JsonSyntaxException e) {
        throw new BadRequestException("Error parsing request body as a schedule specification: " + e.getMessage());
    }
    // If the schedule name is present in the request body, it should match the name in path params
    if (scheduleDetail.getName() != null && !scheduleName.equals(scheduleDetail.getName())) {
        throw new BadRequestException(String.format("Schedule name in the body of the request (%s) does not match the schedule name in the path parameter (%s)", scheduleDetail.getName(), scheduleName));
    }
    return scheduleDetail;
}
Also used : JsonSyntaxException(com.google.gson.JsonSyntaxException) InputStreamReader(java.io.InputStreamReader) JsonElement(com.google.gson.JsonElement) Reader(java.io.Reader) InputStreamReader(java.io.InputStreamReader) BadRequestException(io.cdap.cdap.common.BadRequestException) ByteBufInputStream(io.netty.buffer.ByteBufInputStream) IOException(java.io.IOException) ScheduleDetail(io.cdap.cdap.proto.ScheduleDetail)

Example 67 with BadRequestException

use of io.cdap.cdap.common.BadRequestException in project cdap by cdapio.

the class ProgramLifecycleHttpHandler method getProgramStatusSchedules.

/**
 * Get schedules containing {@link ProgramStatusTrigger} filtered by triggering program, and optionally by
 * triggering program statuses or schedule status
 *  @param triggerNamespaceId namespace of the triggering program in {@link ProgramStatusTrigger}
 * @param triggerAppName application name of the triggering program in {@link ProgramStatusTrigger}
 * @param triggerAppVersion application version of the triggering program in {@link ProgramStatusTrigger}
 * @param triggerProgramType program type of the triggering program in {@link ProgramStatusTrigger}
 * @param triggerProgramName program name of the triggering program in {@link ProgramStatusTrigger}
 * @param triggerProgramStatuses comma separated {@link ProgramStatus} in {@link ProgramStatusTrigger}.
 *                               Schedules with {@link ProgramStatusTrigger} triggered by none of the
 *                               {@link ProgramStatus} in triggerProgramStatuses will be filtered out.
 *                               If not specified, schedules will be returned regardless of triggering program status.
 * @param scheduleStatus status of the schedule. Can only be one of "SCHEDULED" or "SUSPENDED".
 *                       If specified, only schedules with matching status will be returned.
 */
@GET
@Path("schedules/trigger-type/program-status")
public void getProgramStatusSchedules(HttpRequest request, HttpResponder responder, @QueryParam("trigger-namespace-id") String triggerNamespaceId, @QueryParam("trigger-app-name") String triggerAppName, @QueryParam("trigger-app-version") @DefaultValue(ApplicationId.DEFAULT_VERSION) String triggerAppVersion, @QueryParam("trigger-program-type") String triggerProgramType, @QueryParam("trigger-program-name") String triggerProgramName, @QueryParam("trigger-program-statuses") String triggerProgramStatuses, @QueryParam("schedule-status") String scheduleStatus) throws Exception {
    if (triggerNamespaceId == null) {
        throw new BadRequestException("Must specify trigger-namespace-id as a query param");
    }
    if (triggerAppName == null) {
        throw new BadRequestException("Must specify trigger-app-name as a query param");
    }
    if (triggerProgramType == null) {
        throw new BadRequestException("Must specify trigger-program-type as a query param");
    }
    if (triggerProgramName == null) {
        throw new BadRequestException("Must specify trigger-program-name as a query param");
    }
    ProgramType programType = getProgramType(triggerProgramType);
    ProgramScheduleStatus programScheduleStatus;
    try {
        programScheduleStatus = scheduleStatus == null ? null : ProgramScheduleStatus.valueOf(scheduleStatus);
    } catch (IllegalArgumentException e) {
        throw new BadRequestException(String.format("Invalid schedule status '%s'. Must be one of %s.", scheduleStatus, Joiner.on(',').join(ProgramScheduleStatus.values())), e);
    }
    ProgramId triggerProgramId = new NamespaceId(triggerNamespaceId).app(triggerAppName, triggerAppVersion).program(programType, triggerProgramName);
    Set<io.cdap.cdap.api.ProgramStatus> queryProgramStatuses = new HashSet<>();
    if (triggerProgramStatuses != null) {
        try {
            for (String status : triggerProgramStatuses.split(",")) {
                queryProgramStatuses.add(io.cdap.cdap.api.ProgramStatus.valueOf(status));
            }
        } catch (Exception e) {
            throw new BadRequestException(String.format("Unable to parse program statuses '%s'. Must be comma separated " + "valid ProgramStatus names such as COMPLETED, FAILED, KILLED.", triggerProgramStatuses), e);
        }
    } else {
        // Query for schedules with all the statuses if no query status is specified
        Collections.addAll(queryProgramStatuses, io.cdap.cdap.api.ProgramStatus.values());
    }
    List<ScheduleDetail> details = programScheduleService.findTriggeredBy(triggerProgramId, queryProgramStatuses).stream().filter(record -> programScheduleStatus == null || record.getMeta().getStatus().equals(programScheduleStatus)).map(ProgramScheduleRecord::toScheduleDetail).collect(Collectors.toList());
    responder.sendJson(HttpResponseStatus.OK, GSON.toJson(details, Schedulers.SCHEDULE_DETAILS_TYPE));
}
Also used : ProgramId(io.cdap.cdap.proto.id.ProgramId) UnauthorizedException(io.cdap.cdap.security.spi.authorization.UnauthorizedException) NamespaceNotFoundException(io.cdap.cdap.common.NamespaceNotFoundException) IOException(java.io.IOException) ConflictException(io.cdap.cdap.common.ConflictException) NotImplementedException(io.cdap.cdap.common.NotImplementedException) ServiceUnavailableException(io.cdap.cdap.common.ServiceUnavailableException) NotFoundException(io.cdap.cdap.common.NotFoundException) JsonSyntaxException(com.google.gson.JsonSyntaxException) SchedulerException(io.cdap.cdap.internal.app.runtime.schedule.SchedulerException) BadRequestException(io.cdap.cdap.common.BadRequestException) ProgramScheduleStatus(io.cdap.cdap.internal.app.runtime.schedule.ProgramScheduleStatus) BadRequestException(io.cdap.cdap.common.BadRequestException) ProgramType(io.cdap.cdap.proto.ProgramType) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) ScheduleDetail(io.cdap.cdap.proto.ScheduleDetail) ProgramStatus(io.cdap.cdap.proto.ProgramStatus) BatchProgramStatus(io.cdap.cdap.proto.BatchProgramStatus) HashSet(java.util.HashSet) Path(javax.ws.rs.Path) GET(javax.ws.rs.GET)

Example 68 with BadRequestException

use of io.cdap.cdap.common.BadRequestException in project cdap by cdapio.

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;
    }
}
Also used : ArtifactRangeNotFoundException(io.cdap.cdap.common.ArtifactRangeNotFoundException) HttpResponder(io.cdap.http.HttpResponder) ArtifactId(io.cdap.cdap.proto.id.ArtifactId) ArtifactRange(io.cdap.cdap.api.artifact.ArtifactRange) Attributes(java.util.jar.Attributes) ZipException(java.util.zip.ZipException) IOException(java.io.IOException) JsonParseException(com.google.gson.JsonParseException) JarFile(java.util.jar.JarFile) Manifest(java.util.jar.Manifest) ArtifactRangeNotFoundException(io.cdap.cdap.common.ArtifactRangeNotFoundException) ZipException(java.util.zip.ZipException) ArtifactAlreadyExistsException(io.cdap.cdap.common.ArtifactAlreadyExistsException) JsonParseException(com.google.gson.JsonParseException) InvalidArtifactRangeException(io.cdap.cdap.api.artifact.InvalidArtifactRangeException) UnauthorizedException(io.cdap.cdap.security.spi.authorization.UnauthorizedException) NamespaceNotFoundException(io.cdap.cdap.common.NamespaceNotFoundException) PluginNotExistsException(io.cdap.cdap.internal.app.runtime.plugin.PluginNotExistsException) WriteConflictException(io.cdap.cdap.internal.app.runtime.artifact.WriteConflictException) CapabilityNotAvailableException(io.cdap.cdap.internal.capability.CapabilityNotAvailableException) JsonSyntaxException(com.google.gson.JsonSyntaxException) IOException(java.io.IOException) BadRequestException(io.cdap.cdap.common.BadRequestException) ArtifactNotFoundException(io.cdap.cdap.common.ArtifactNotFoundException) ArtifactAlreadyExistsException(io.cdap.cdap.common.ArtifactAlreadyExistsException) AbstractBodyConsumer(io.cdap.cdap.common.http.AbstractBodyConsumer) WriteConflictException(io.cdap.cdap.internal.app.runtime.artifact.WriteConflictException) UnauthorizedException(io.cdap.cdap.security.spi.authorization.UnauthorizedException) BadRequestException(io.cdap.cdap.common.BadRequestException) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) PluginClass(io.cdap.cdap.api.plugin.PluginClass) JarFile(java.util.jar.JarFile) File(java.io.File) Path(javax.ws.rs.Path) AuditPolicy(io.cdap.cdap.common.security.AuditPolicy) POST(javax.ws.rs.POST)

Example 69 with BadRequestException

use of io.cdap.cdap.common.BadRequestException in project cdap by cdapio.

the class ImpersonationHandler method getCredentials.

@POST
@Path("/credentials")
public void getCredentials(FullHttpRequest request, HttpResponder responder) throws Exception {
    String requestContent = request.content().toString(StandardCharsets.UTF_8);
    if (requestContent == null) {
        throw new BadRequestException("Request body is empty.");
    }
    ImpersonationRequest impersonationRequest = GSON.fromJson(requestContent, ImpersonationRequest.class);
    LOG.debug("Fetching credentials for {}", impersonationRequest);
    UGIWithPrincipal ugiWithPrincipal;
    try {
        ugiWithPrincipal = ugiProvider.getConfiguredUGI(impersonationRequest);
    } catch (AccessException e) {
        throw new ServiceException(e, HttpResponseStatus.INTERNAL_SERVER_ERROR);
    }
    Credentials credentials = ImpersonationUtils.doAs(ugiWithPrincipal.getUGI(), new Callable<Credentials>() {

        @Override
        public Credentials call() throws Exception {
            return tokenSecureStoreRenewer.createCredentials();
        }
    });
    // example: hdfs:///cdap/credentials
    Location credentialsDir = locationFactory.create("credentials");
    if (credentialsDir.isDirectory() || credentialsDir.mkdirs() || credentialsDir.isDirectory()) {
        // the getTempFile() doesn't create the file within the directory that you call it on. It simply appends the path
        // without a separator, which is why we manually append the "tmp"
        // example: hdfs:///cdap/credentials/tmp.5960fe60-6fd8-4f3e-8e92-3fb6d4726006.credentials
        Location credentialsFile = credentialsDir.append("tmp").getTempFile(".credentials");
        // 600 is owner-only READ_WRITE
        try (DataOutputStream os = new DataOutputStream(new BufferedOutputStream(credentialsFile.getOutputStream("600")))) {
            credentials.writeTokenStorageToStream(os);
        }
        LOG.debug("Wrote credentials for user {} to {}", ugiWithPrincipal.getPrincipal(), credentialsFile);
        PrincipalCredentials principalCredentials = new PrincipalCredentials(ugiWithPrincipal.getPrincipal(), credentialsFile.toURI().toString());
        responder.sendJson(HttpResponseStatus.OK, GSON.toJson(principalCredentials));
    } else {
        throw new IllegalStateException("Unable to create credentials directory.");
    }
}
Also used : PrincipalCredentials(io.cdap.cdap.security.impersonation.PrincipalCredentials) UGIWithPrincipal(io.cdap.cdap.security.impersonation.UGIWithPrincipal) DataOutputStream(java.io.DataOutputStream) AccessException(io.cdap.cdap.api.security.AccessException) ServiceException(io.cdap.cdap.common.ServiceException) IOException(java.io.IOException) BadRequestException(io.cdap.cdap.common.BadRequestException) AccessException(io.cdap.cdap.api.security.AccessException) ServiceException(io.cdap.cdap.common.ServiceException) ImpersonationRequest(io.cdap.cdap.security.impersonation.ImpersonationRequest) BadRequestException(io.cdap.cdap.common.BadRequestException) BufferedOutputStream(java.io.BufferedOutputStream) Credentials(org.apache.hadoop.security.Credentials) PrincipalCredentials(io.cdap.cdap.security.impersonation.PrincipalCredentials) Location(org.apache.twill.filesystem.Location) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST)

Example 70 with BadRequestException

use of io.cdap.cdap.common.BadRequestException in project cdap by cdapio.

the class MonitorHandler method setServiceInstance.

/**
 * Sets the number of instances of CDAP Services
 */
@Path("/system/services/{service-name}/instances")
@PUT
@AuditPolicy(AuditDetail.REQUEST_BODY)
public void setServiceInstance(FullHttpRequest request, HttpResponder responder, @PathParam("service-name") final String serviceName) throws Exception {
    if (!serviceManagementMap.containsKey(serviceName)) {
        throw new NotFoundException(String.format("Invalid service name %s", serviceName));
    }
    SystemServiceId systemServiceId = new SystemServiceId(serviceName);
    contextAccessEnforcer.enforce(systemServiceId, StandardPermission.UPDATE);
    MasterServiceManager serviceManager = serviceManagementMap.get(serviceName);
    int instances = getInstances(request);
    if (!serviceManager.isServiceEnabled()) {
        throw new ForbiddenException(String.format("Service %s is not enabled", serviceName));
    }
    int currentInstances = getSystemServiceInstanceCount(serviceName);
    if (instances < serviceManager.getMinInstances() || instances > serviceManager.getMaxInstances()) {
        String response = String.format("Instance count should be between [%s,%s]", serviceManager.getMinInstances(), serviceManager.getMaxInstances());
        throw new BadRequestException(response);
    } else if (instances == currentInstances) {
        responder.sendStatus(HttpResponseStatus.OK);
        return;
    }
    serviceStore.setServiceInstance(serviceName, instances);
    if (serviceManager.setInstances(instances)) {
        responder.sendStatus(HttpResponseStatus.OK);
    } else {
        throw new BadRequestException("Operation did not succeed");
    }
}
Also used : SystemServiceId(io.cdap.cdap.proto.id.SystemServiceId) ForbiddenException(io.cdap.cdap.common.ForbiddenException) MasterServiceManager(io.cdap.cdap.common.twill.MasterServiceManager) NotFoundException(io.cdap.cdap.common.NotFoundException) BadRequestException(io.cdap.cdap.common.BadRequestException) Path(javax.ws.rs.Path) AuditPolicy(io.cdap.cdap.common.security.AuditPolicy) PUT(javax.ws.rs.PUT)

Aggregations

BadRequestException (io.cdap.cdap.common.BadRequestException)188 Path (javax.ws.rs.Path)68 NamespaceId (io.cdap.cdap.proto.id.NamespaceId)54 IOException (java.io.IOException)46 JsonSyntaxException (com.google.gson.JsonSyntaxException)44 NotFoundException (io.cdap.cdap.common.NotFoundException)42 ApplicationId (io.cdap.cdap.proto.id.ApplicationId)42 POST (javax.ws.rs.POST)42 HttpResponse (io.cdap.common.http.HttpResponse)36 ByteBufInputStream (io.netty.buffer.ByteBufInputStream)34 URL (java.net.URL)34 ProgramType (io.cdap.cdap.proto.ProgramType)30 InputStreamReader (java.io.InputStreamReader)28 Reader (java.io.Reader)28 ArrayList (java.util.ArrayList)28 AuditPolicy (io.cdap.cdap.common.security.AuditPolicy)26 ProgramId (io.cdap.cdap.proto.id.ProgramId)26 ServiceUnavailableException (io.cdap.cdap.common.ServiceUnavailableException)24 GET (javax.ws.rs.GET)24 ProgramRunId (io.cdap.cdap.proto.id.ProgramRunId)22