Search in sources :

Example 96 with BadRequestException

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

the class ArtifactClient method deleteProperties.

/**
 * Delete all properties for an artifact. If no properties exist, this will be a no-op.
 *
 * @param artifactId the artifact to delete properties from
 * @throws BadRequestException if the request is invalid. For example, if the artifact name or version is invalid
 * @throws UnauthenticatedException if the request is not authorized successfully in the gateway server
 * @throws ArtifactNotFoundException if the artifact does not exist
 * @throws IOException if a network error occurred
 */
public void deleteProperties(ArtifactId artifactId) throws IOException, UnauthenticatedException, ArtifactNotFoundException, BadRequestException, UnauthorizedException {
    String path = String.format("artifacts/%s/versions/%s/properties", artifactId.getArtifact(), artifactId.getVersion());
    URL url = config.resolveNamespacedURLV3(artifactId.getParent(), path);
    HttpRequest.Builder requestBuilder = HttpRequest.delete(url);
    HttpRequest request = requestBuilder.build();
    HttpResponse response = restClient.execute(request, config.getAccessToken(), HttpURLConnection.HTTP_BAD_REQUEST, HttpURLConnection.HTTP_NOT_FOUND);
    int responseCode = response.getResponseCode();
    if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
        throw new ArtifactNotFoundException(artifactId);
    } else if (responseCode == HttpURLConnection.HTTP_BAD_REQUEST) {
        throw new BadRequestException(response.getResponseBodyAsString());
    }
}
Also used : HttpRequest(io.cdap.common.http.HttpRequest) HttpResponse(io.cdap.common.http.HttpResponse) BadRequestException(io.cdap.cdap.common.BadRequestException) ArtifactNotFoundException(io.cdap.cdap.common.ArtifactNotFoundException) URL(java.net.URL)

Example 97 with BadRequestException

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

the class ProgramLifecycleService method issueStop.

/**
 * Issues a command to stop the specified {@link RunId} of the specified {@link ProgramId} and returns a
 * {@link ListenableFuture} with the {@link ProgramRunId} for the runs that were stopped.
 * Clients can wait for completion of the {@link ListenableFuture}.
 *
 * @param programId the {@link ProgramId program} to issue a stop for
 * @param runId the runId of the program run to stop. If null, all runs of the program as returned by
 *              {@link ProgramRuntimeService} are stopped.
 * @return a list of {@link ListenableFuture} with the {@link ProgramRunId} that clients can wait on for stop
 *         to complete.
 * @throws NotFoundException if the app, program or run was not found
 * @throws BadRequestException if an attempt is made to stop a program that is either not running or
 *                             was started by a workflow
 * @throws UnauthorizedException if the user issuing the command is not authorized to stop the program. To stop a
 *                               program, a user requires {@link ApplicationPermission#EXECUTE} permission on
 *                               the program.
 */
public List<ListenableFuture<ProgramRunId>> issueStop(ProgramId programId, @Nullable String runId) throws Exception {
    accessEnforcer.enforce(programId, authenticationContext.getPrincipal(), ApplicationPermission.EXECUTE);
    // See if the program is running as per the runtime service
    Map<RunId, RuntimeInfo> runtimeInfos = findRuntimeInfo(programId, runId);
    Map<ProgramRunId, RunRecordDetail> activeRunRecords = getActiveRuns(programId, runId);
    if (runtimeInfos.isEmpty() && activeRunRecords.isEmpty()) {
        // Error out if no run information from runtime service and from run record
        Store.ensureProgramExists(programId, store.getApplication(programId.getParent()));
        throw new BadRequestException(String.format("Program '%s' is not running.", programId));
    }
    // Stop the running program based on a combination of runtime info and run record
    // It's possible that some of them are not yet available from the runtimeService due to timing
    // differences between the run record was created vs being added to runtimeService
    // So we retry in a loop for up to 3 seconds max to cater for those cases
    Set<String> pendingStops = Stream.concat(runtimeInfos.keySet().stream().map(RunId::getId), activeRunRecords.keySet().stream().map(ProgramRunId::getRun)).collect(Collectors.toSet());
    List<ListenableFuture<ProgramRunId>> futures = new ArrayList<>();
    Stopwatch stopwatch = new Stopwatch().start();
    Set<ProgramRunId> cancelledProvisionRuns = new HashSet<>();
    while (!pendingStops.isEmpty() && stopwatch.elapsedTime(TimeUnit.SECONDS) < 3L) {
        Iterator<String> iterator = pendingStops.iterator();
        while (iterator.hasNext()) {
            ProgramRunId activeRunId = programId.run(iterator.next());
            RunRecordDetail runRecord = activeRunRecords.get(activeRunId);
            if (runRecord == null) {
                runRecord = store.getRun(activeRunId);
            }
            // Check if the program is actually started from workflow and the workflow is running
            if (runRecord != null && runRecord.getProperties().containsKey("workflowrunid") && runRecord.getStatus().equals(ProgramRunStatus.RUNNING)) {
                String workflowRunId = runRecord.getProperties().get("workflowrunid");
                throw new BadRequestException(String.format("Cannot stop the program '%s' started by the Workflow " + "run '%s'. Please stop the Workflow.", activeRunId, workflowRunId));
            }
            RuntimeInfo runtimeInfo = runtimeService.lookup(programId, RunIds.fromString(activeRunId.getRun()));
            // if there is a runtimeInfo, the run is in the 'starting' state or later
            if (runtimeInfo != null) {
                ListenableFuture<ProgramController> future = runtimeInfo.getController().stop();
                futures.add(Futures.transform(future, ProgramController::getProgramRunId));
                iterator.remove();
                // if it was in this set, it means we cancelled a task, but it had already sent a PROVISIONED message
                // by the time we cancelled it. We then waited for it to show up in the runtime service and got here.
                // We added a future for this run in the lines above, but we don't want to add another duplicate future
                // at the end of this loop, so remove this run from the cancelled provision runs.
                cancelledProvisionRuns.remove(activeRunId);
            } else {
                // if there is no runtimeInfo, the run could be in the provisioning state.
                Optional<ProvisioningTaskInfo> cancelledInfo = provisioningService.cancelProvisionTask(activeRunId);
                cancelledInfo.ifPresent(taskInfo -> {
                    cancelledProvisionRuns.add(activeRunId);
                    // This state check is to handle a race condition where we cancel the provision task, but not in time
                    // to prevent it from sending the PROVISIONED notification.
                    // If the notification was sent, but not yet consumed, we are *not* done stopping the run.
                    // We have to wait for the notification to be consumed, which will start the run, and place the controller
                    // in the runtimeService. The next time we loop, we can find it in the runtimeService and tell it to stop.
                    // If the notification was not sent, then we *are* done stopping the run.
                    // Therefore, if the state is CREATED, we don't remove it from the iterator so that the run will get
                    // checked again in the next loop, when we may get the controller from the runtimeService to stop it.
                    // No other task states have this race condition, as the PROVISIONED notification is only sent
                    // after the state transitions to CREATED. Therefore it is safe to remove the runId from the iterator,
                    // as we know we are done stopping it.
                    ProvisioningOp.Status taskState = taskInfo.getProvisioningOp().getStatus();
                    if (taskState != ProvisioningOp.Status.CREATED) {
                        iterator.remove();
                    }
                });
            }
        }
        if (!pendingStops.isEmpty()) {
            // If not able to stop all of them, it means there were some runs that didn't have a runtime info and
            // didn't have a provisioning task. This can happen if the run was already finished, or the run transitioned
            // from the provisioning state to the starting state during this stop operation.
            // We'll get the active runs again and filter it by the pending stops. Stop will be retried for those.
            Set<String> finalPendingStops = pendingStops;
            activeRunRecords = getActiveRuns(programId, runId).entrySet().stream().filter(e -> finalPendingStops.contains(e.getKey().getRun())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
            pendingStops = activeRunRecords.keySet().stream().map(ProgramRunId::getRun).collect(Collectors.toSet());
            if (!pendingStops.isEmpty()) {
                TimeUnit.MILLISECONDS.sleep(200);
            }
        }
    }
    for (ProgramRunId cancelledProvisionRun : cancelledProvisionRuns) {
        SettableFuture<ProgramRunId> future = SettableFuture.create();
        future.set(cancelledProvisionRun);
        futures.add(future);
    }
    return futures;
}
Also used : ProgramController(io.cdap.cdap.app.runtime.ProgramController) RuntimeInfo(io.cdap.cdap.app.runtime.ProgramRuntimeService.RuntimeInfo) RunRecordDetail(io.cdap.cdap.internal.app.store.RunRecordDetail) ArrayList(java.util.ArrayList) Stopwatch(com.google.common.base.Stopwatch) ProvisioningTaskInfo(io.cdap.cdap.internal.provision.ProvisioningTaskInfo) LogEntry(org.apache.twill.api.logging.LogEntry) BadRequestException(io.cdap.cdap.common.BadRequestException) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) ProvisioningOp(io.cdap.cdap.internal.provision.ProvisioningOp) RunId(org.apache.twill.api.RunId) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 98 with BadRequestException

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

the class ProgramLifecycleService method findRuntimeInfo.

private Map<RunId, ProgramRuntimeService.RuntimeInfo> findRuntimeInfo(ProgramId programId, @Nullable String runId) throws BadRequestException {
    if (runId != null) {
        RunId run;
        try {
            run = RunIds.fromString(runId);
        } catch (IllegalArgumentException e) {
            throw new BadRequestException("Error parsing run-id.", e);
        }
        ProgramRuntimeService.RuntimeInfo runtimeInfo = runtimeService.lookup(programId, run);
        return runtimeInfo == null ? Collections.emptyMap() : Collections.singletonMap(run, runtimeInfo);
    }
    return new HashMap<>(runtimeService.list(programId));
}
Also used : HashMap(java.util.HashMap) BadRequestException(io.cdap.cdap.common.BadRequestException) RuntimeInfo(io.cdap.cdap.app.runtime.ProgramRuntimeService.RuntimeInfo) RunId(org.apache.twill.api.RunId) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) ProgramRuntimeService(io.cdap.cdap.app.runtime.ProgramRuntimeService)

Example 99 with BadRequestException

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

the class ApplicationClientTestRun method testAppUpdate.

@Test
public void testAppUpdate() throws Exception {
    String artifactName = "cfg-programs";
    ArtifactId artifactIdV1 = NamespaceId.DEFAULT.artifact(artifactName, "1.0.0");
    ArtifactId artifactIdV2 = NamespaceId.DEFAULT.artifact(artifactName, "2.0.0");
    ApplicationId appId = NamespaceId.DEFAULT.app("ProgramsApp");
    artifactClient.add(NamespaceId.DEFAULT, artifactName, () -> Files.newInputStream(createAppJarFile(ConfigurableProgramsApp.class).toPath()), "1.0.0");
    artifactClient.add(NamespaceId.DEFAULT, artifactName, () -> Files.newInputStream(createAppJarFile(ConfigurableProgramsApp2.class).toPath()), "2.0.0");
    try {
        // deploy the app with just the worker
        ConfigurableProgramsApp.Programs conf = new ConfigurableProgramsApp.Programs("worker1", null, "dataset1");
        AppRequest<ConfigurableProgramsApp.Programs> request = new AppRequest<>(new ArtifactSummary(artifactIdV1.getArtifact(), artifactIdV1.getVersion()), conf);
        appClient.deploy(appId, request);
        // should only have the worker
        Assert.assertTrue(appClient.listPrograms(appId, ProgramType.SERVICE).isEmpty());
        Assert.assertEquals(1, appClient.listPrograms(appId, ProgramType.WORKER).size());
        // update to use just the service
        conf = new ConfigurableProgramsApp.Programs(null, "service", "dataset1");
        request = new AppRequest<>(new ArtifactSummary(artifactIdV1.getArtifact(), artifactIdV1.getVersion()), conf);
        appClient.update(appId, request);
        // should only have the service
        Assert.assertTrue(appClient.listPrograms(appId, ProgramType.WORKER).isEmpty());
        Assert.assertEquals(1, appClient.listPrograms(appId, ProgramType.SERVICE).size());
        // check nonexistent app is not found
        try {
            appClient.update(NamespaceId.DEFAULT.app("ghost"), request);
            Assert.fail();
        } catch (NotFoundException e) {
        // expected
        }
        // check different artifact name is invalid
        request = new AppRequest<>(new ArtifactSummary("ghost", artifactIdV1.getVersion()), conf);
        try {
            appClient.update(appId, request);
            Assert.fail();
        } catch (BadRequestException e) {
        // expected
        }
        // check nonexistent artifact is not found
        request = new AppRequest<>(new ArtifactSummary(artifactIdV1.getArtifact(), "0.0.1"), conf);
        try {
            appClient.update(appId, request);
            Assert.fail();
        } catch (NotFoundException e) {
        // expected
        }
        // update artifact version. This version uses a different app class with that can add a workflow
        ConfigurableProgramsApp2.Programs conf2 = new ConfigurableProgramsApp2.Programs(null, null, "workflow1", "dataset1");
        AppRequest<ConfigurableProgramsApp2.Programs> request2 = new AppRequest<>(new ArtifactSummary(artifactIdV2.getArtifact(), artifactIdV2.getVersion()), conf2);
        appClient.update(appId, request2);
        // should only have a single workflow
        Assert.assertTrue(appClient.listPrograms(appId, ProgramType.WORKER).isEmpty());
        Assert.assertTrue(appClient.listPrograms(appId, ProgramType.SERVICE).isEmpty());
        Assert.assertEquals(1, appClient.listPrograms(appId, ProgramType.WORKFLOW).size());
    } finally {
        appClient.delete(appId);
        appClient.waitForDeleted(appId, 30, TimeUnit.SECONDS);
        artifactClient.delete(artifactIdV1);
        artifactClient.delete(artifactIdV2);
    }
}
Also used : ArtifactId(io.cdap.cdap.proto.id.ArtifactId) ConfigurableProgramsApp(io.cdap.cdap.client.app.ConfigurableProgramsApp) DatasetNotFoundException(io.cdap.cdap.common.DatasetNotFoundException) DatasetModuleNotFoundException(io.cdap.cdap.common.DatasetModuleNotFoundException) NotFoundException(io.cdap.cdap.common.NotFoundException) AppRequest(io.cdap.cdap.proto.artifact.AppRequest) ConfigurableProgramsApp2(io.cdap.cdap.client.app.ConfigurableProgramsApp2) ArtifactSummary(io.cdap.cdap.api.artifact.ArtifactSummary) BadRequestException(io.cdap.cdap.common.BadRequestException) ApplicationId(io.cdap.cdap.proto.id.ApplicationId) Test(org.junit.Test)

Example 100 with BadRequestException

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

the class AbstractMetadataClient method makeRequest.

private HttpResponse makeRequest(String path, HttpMethod httpMethod, @Nullable String body) throws IOException, UnauthenticatedException, BadRequestException, UnauthorizedException {
    URL url = resolve(path);
    HttpRequest.Builder builder = HttpRequest.builder(httpMethod, url);
    if (body != null) {
        builder.withBody(body);
    }
    HttpResponse response = execute(builder.build(), HttpURLConnection.HTTP_BAD_REQUEST, HttpURLConnection.HTTP_NOT_FOUND);
    if (response.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST) {
        throw new BadRequestException(response.getResponseBodyAsString());
    }
    return response;
}
Also used : HttpRequest(io.cdap.common.http.HttpRequest) HttpResponse(io.cdap.common.http.HttpResponse) BadRequestException(io.cdap.cdap.common.BadRequestException) URL(java.net.URL)

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