Search in sources :

Example 21 with ProgramController

use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.

the class AbstractInMemoryProgramRunner method startAll.

/**
   * Starts all instances of a Program component.
   * @param program The program to run
   * @param options options for the program
   * @param runId The runId
   * @param numInstances number of component instances to start
   */
protected final ProgramController startAll(Program program, ProgramOptions options, RunId runId, int numInstances) {
    Table<String, Integer, ProgramController> components = HashBasedTable.create();
    try {
        for (int instanceId = 0; instanceId < numInstances; instanceId++) {
            ProgramOptions componentOptions = createComponentOptions(program.getName(), instanceId, numInstances, runId, options);
            ProgramController controller = createProgramRunner().run(program, componentOptions);
            components.put(program.getName(), instanceId, controller);
        }
        return new InMemoryProgramController(components, program, options, runId);
    } catch (Throwable t) {
        LOG.error("Failed to start all program instances", t);
        try {
            // Need to stop all started components
            Futures.successfulAsList(Iterables.transform(components.values(), new Function<ProgramController, ListenableFuture<?>>() {

                @Override
                public ListenableFuture<?> apply(ProgramController controller) {
                    return controller.stop();
                }
            })).get();
            throw Throwables.propagate(t);
        } catch (Exception e) {
            LOG.error("Failed to stop all program instances upon startup failure.", e);
            throw Throwables.propagate(e);
        }
    }
}
Also used : Function(com.google.common.base.Function) ProgramController(co.cask.cdap.app.runtime.ProgramController) AbstractProgramController(co.cask.cdap.internal.app.runtime.AbstractProgramController) SimpleProgramOptions(co.cask.cdap.internal.app.runtime.SimpleProgramOptions) ProgramOptions(co.cask.cdap.app.runtime.ProgramOptions)

Example 22 with ProgramController

use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.

the class ProgramLifecycleHttpHandler method startPrograms.

/**
   * Starts all programs that are passed into the data. The data is an array of JSON objects
   * where each object must contain the following three elements: appId, programType, and programId
   * (flow name, service name, etc.). In additional, each object can contain an optional runtimeargs element,
   * which is a map of arguments to start the program with.
   * <p>
   * Example input:
   * <pre><code>
   * [{"appId": "App1", "programType": "Service", "programId": "Service1"},
   * {"appId": "App1", "programType": "Mapreduce", "programId": "MapReduce2", "runtimeargs":{"arg1":"val1"}},
   * {"appId": "App2", "programType": "Flow", "programId": "Flow1"}]
   * </code></pre>
   * </p><p>
   * The response will be an array of JsonObjects each of which will contain the three input parameters
   * as well as a "statusCode" field which maps to the status code for the data in that JsonObjects.
   * </p><p>
   * If an error occurs in the input (for the example above, App2 does not exist), then all JsonObjects for which the
   * parameters have a valid status will have the status field but all JsonObjects for which the parameters do not have
   * a valid status will have an error message and statusCode.
   * </p><p>
   * For example, if there is no App2 in the data above, then the response would be 200 OK with following possible data:
   * </p>
   * <pre><code>
   * [{"appId": "App1", "programType": "Service", "programId": "Service1", "statusCode": 200},
   * {"appId": "App1", "programType": "Mapreduce", "programId": "Mapreduce2", "statusCode": 200},
   * {"appId":"App2", "programType":"Flow", "programId":"Flow1", "statusCode":404, "error": "App: App2 not found"}]
   * </code></pre>
   */
@POST
@Path("/start")
@AuditPolicy({ AuditDetail.REQUEST_BODY, AuditDetail.RESPONSE_BODY })
public void startPrograms(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId) throws Exception {
    List<BatchProgramStart> programs = validateAndGetBatchInput(request, BATCH_STARTS_TYPE);
    List<BatchProgramResult> output = new ArrayList<>(programs.size());
    for (BatchProgramStart program : programs) {
        ProgramId programId = new ProgramId(namespaceId, program.getAppId(), program.getProgramType(), program.getProgramId());
        try {
            ProgramController programController = lifecycleService.start(programId, program.getRuntimeargs(), false);
            output.add(new BatchProgramResult(program, HttpResponseStatus.OK.getCode(), null, programController.getRunId().getId()));
        } catch (NotFoundException e) {
            output.add(new BatchProgramResult(program, HttpResponseStatus.NOT_FOUND.getCode(), e.getMessage()));
        } catch (BadRequestException e) {
            output.add(new BatchProgramResult(program, HttpResponseStatus.BAD_REQUEST.getCode(), e.getMessage()));
        } catch (ConflictException e) {
            output.add(new BatchProgramResult(program, HttpResponseStatus.CONFLICT.getCode(), e.getMessage()));
        }
    }
    responder.sendJson(HttpResponseStatus.OK, output);
}
Also used : ProgramController(co.cask.cdap.app.runtime.ProgramController) ConflictException(co.cask.cdap.common.ConflictException) ArrayList(java.util.ArrayList) BatchProgramResult(co.cask.cdap.proto.BatchProgramResult) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException) NotFoundException(co.cask.cdap.common.NotFoundException) BadRequestException(co.cask.cdap.common.BadRequestException) BatchProgramStart(co.cask.cdap.proto.BatchProgramStart) ProgramId(co.cask.cdap.proto.id.ProgramId) Path(javax.ws.rs.Path) AuditPolicy(co.cask.cdap.common.security.AuditPolicy) POST(javax.ws.rs.POST)

Example 23 with ProgramController

use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.

the class ProgramLifecycleHttpHandler method stopPrograms.

/**
   * Stops all programs that are passed into the data. The data is an array of JSON objects
   * where each object must contain the following three elements: appId, programType, and programId
   * (flow name, service name, etc.).
   * <p>
   * Example input:
   * <pre><code>
   * [{"appId": "App1", "programType": "Service", "programId": "Service1"},
   * {"appId": "App1", "programType": "Mapreduce", "programId": "MapReduce2"},
   * {"appId": "App2", "programType": "Flow", "programId": "Flow1"}]
   * </code></pre>
   * </p><p>
   * The response will be an array of JsonObjects each of which will contain the three input parameters
   * as well as a "statusCode" field which maps to the status code for the data in that JsonObjects.
   * </p><p>
   * If an error occurs in the input (for the example above, App2 does not exist), then all JsonObjects for which the
   * parameters have a valid status will have the status field but all JsonObjects for which the parameters do not have
   * a valid status will have an error message and statusCode.
   * </p><p>
   * For example, if there is no App2 in the data above, then the response would be 200 OK with following possible data:
   * </p>
   * <pre><code>
   * [{"appId": "App1", "programType": "Service", "programId": "Service1", "statusCode": 200},
   * {"appId": "App1", "programType": "Mapreduce", "programId": "Mapreduce2", "statusCode": 200},
   * {"appId":"App2", "programType":"Flow", "programId":"Flow1", "statusCode":404, "error": "App: App2 not found"}]
   * </code></pre>
   */
@POST
@Path("/stop")
@AuditPolicy({ AuditDetail.REQUEST_BODY, AuditDetail.RESPONSE_BODY })
public void stopPrograms(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId) throws Exception {
    List<BatchProgram> programs = validateAndGetBatchInput(request, BATCH_PROGRAMS_TYPE);
    List<ListenableFuture<BatchProgramResult>> issuedStops = new ArrayList<>(programs.size());
    for (final BatchProgram program : programs) {
        ProgramId programId = new ProgramId(namespaceId, program.getAppId(), program.getProgramType(), program.getProgramId());
        try {
            List<ListenableFuture<ProgramController>> stops = lifecycleService.issueStop(programId, null);
            for (ListenableFuture<ProgramController> stop : stops) {
                ListenableFuture<BatchProgramResult> issuedStop = Futures.transform(stop, new Function<ProgramController, BatchProgramResult>() {

                    @Override
                    public BatchProgramResult apply(ProgramController input) {
                        return new BatchProgramResult(program, HttpResponseStatus.OK.getCode(), null, input.getRunId().getId());
                    }
                });
                issuedStops.add(issuedStop);
            }
        } catch (NotFoundException e) {
            issuedStops.add(Futures.immediateFuture(new BatchProgramResult(program, HttpResponseStatus.NOT_FOUND.getCode(), e.getMessage())));
        } catch (BadRequestException e) {
            issuedStops.add(Futures.immediateFuture(new BatchProgramResult(program, HttpResponseStatus.BAD_REQUEST.getCode(), e.getMessage())));
        }
    }
    List<BatchProgramResult> output = new ArrayList<>(programs.size());
    // need to keep this index in case there is an exception getting the future, since we won't have the program
    // information in that scenario
    int i = 0;
    for (ListenableFuture<BatchProgramResult> issuedStop : issuedStops) {
        try {
            output.add(issuedStop.get());
        } catch (Throwable t) {
            LOG.warn(t.getMessage(), t);
            output.add(new BatchProgramResult(programs.get(i), HttpResponseStatus.INTERNAL_SERVER_ERROR.getCode(), t.getMessage()));
        }
        i++;
    }
    responder.sendJson(HttpResponseStatus.OK, output);
}
Also used : ProgramController(co.cask.cdap.app.runtime.ProgramController) ArrayList(java.util.ArrayList) BatchProgramResult(co.cask.cdap.proto.BatchProgramResult) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException) NotFoundException(co.cask.cdap.common.NotFoundException) ProgramId(co.cask.cdap.proto.id.ProgramId) Constraint(co.cask.cdap.internal.schedule.constraint.Constraint) ProtoConstraint(co.cask.cdap.proto.ProtoConstraint) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) BadRequestException(co.cask.cdap.common.BadRequestException) BatchProgram(co.cask.cdap.proto.BatchProgram) Path(javax.ws.rs.Path) AuditPolicy(co.cask.cdap.common.security.AuditPolicy) POST(javax.ws.rs.POST)

Example 24 with ProgramController

use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.

the class WorkflowTest method testWorkflow.

@Test(timeout = 120 * 1000L)
public void testWorkflow() throws Exception {
    final ApplicationWithPrograms app = AppFabricTestHelper.deployApplicationWithManager(WorkflowApp.class, TEMP_FOLDER_SUPPLIER);
    final Injector injector = AppFabricTestHelper.getInjector();
    final ProgramDescriptor programDescriptor = Iterators.filter(app.getPrograms().iterator(), input -> input.getProgramId().getType() == ProgramType.WORKFLOW).next();
    String inputPath = createInput();
    String outputPath = new File(tmpFolder.newFolder(), "output").getAbsolutePath();
    BasicArguments userArgs = new BasicArguments(ImmutableMap.of("inputPath", inputPath, "outputPath", outputPath));
    final SettableFuture<String> completion = SettableFuture.create();
    final ProgramController controller = AppFabricTestHelper.submit(app, programDescriptor.getSpecification().getClassName(), userArgs, TEMP_FOLDER_SUPPLIER);
    controller.addListener(new AbstractListener() {

        @Override
        public void init(ProgramController.State currentState, @Nullable Throwable cause) {
            LOG.info("Starting");
            long nowSecs = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
            setStartAndRunning(injector.getInstance(Store.class), controller.getProgramRunId().getParent(), controller.getProgramRunId().getRun(), nowSecs);
        }

        @Override
        public void completed() {
            LOG.info("Completed");
            completion.set("Completed");
        }

        @Override
        public void error(Throwable cause) {
            LOG.info("Error", cause);
            completion.setException(cause);
        }
    }, Threads.SAME_THREAD_EXECUTOR);
    completion.get();
}
Also used : ProgramDescriptor(co.cask.cdap.app.program.ProgramDescriptor) ProgramController(co.cask.cdap.app.runtime.ProgramController) Supplier(com.google.common.base.Supplier) LoggerFactory(org.slf4j.LoggerFactory) SettableFuture(com.google.common.util.concurrent.SettableFuture) Iterators(com.google.common.collect.Iterators) ProgramType(co.cask.cdap.proto.ProgramType) WorkflowApp(co.cask.cdap.WorkflowApp) Store(co.cask.cdap.app.store.Store) ProgramId(co.cask.cdap.proto.id.ProgramId) MissingMapReduceWorkflowApp(co.cask.cdap.MissingMapReduceWorkflowApp) ClassRule(org.junit.ClassRule) Nullable(javax.annotation.Nullable) Threads(org.apache.twill.common.Threads) NonUniqueProgramsInWorkflowWithForkApp(co.cask.cdap.NonUniqueProgramsInWorkflowWithForkApp) AbstractListener(co.cask.cdap.internal.app.runtime.AbstractListener) Logger(org.slf4j.Logger) OneActionWorkflowApp(co.cask.cdap.OneActionWorkflowApp) ImmutableMap(com.google.common.collect.ImmutableMap) BufferedWriter(java.io.BufferedWriter) FileWriter(java.io.FileWriter) Throwables(com.google.common.base.Throwables) Test(org.junit.Test) IOException(java.io.IOException) Category(org.junit.experimental.categories.Category) File(java.io.File) NonUniqueProgramsInWorkflowApp(co.cask.cdap.NonUniqueProgramsInWorkflowApp) ApplicationWithPrograms(co.cask.cdap.internal.app.deploy.pipeline.ApplicationWithPrograms) Injector(com.google.inject.Injector) TimeUnit(java.util.concurrent.TimeUnit) BasicArguments(co.cask.cdap.internal.app.runtime.BasicArguments) ScheduleAppWithMissingWorkflow(co.cask.cdap.ScheduleAppWithMissingWorkflow) XSlowTests(co.cask.cdap.test.XSlowTests) AppWithAnonymousWorkflow(co.cask.cdap.AppWithAnonymousWorkflow) AppFabricTestHelper(co.cask.cdap.internal.AppFabricTestHelper) MissingSparkWorkflowApp(co.cask.cdap.MissingSparkWorkflowApp) Assert(org.junit.Assert) WorkflowSchedulesWithSameNameApp(co.cask.cdap.WorkflowSchedulesWithSameNameApp) TemporaryFolder(org.junit.rules.TemporaryFolder) ProgramController(co.cask.cdap.app.runtime.ProgramController) ApplicationWithPrograms(co.cask.cdap.internal.app.deploy.pipeline.ApplicationWithPrograms) Injector(com.google.inject.Injector) AbstractListener(co.cask.cdap.internal.app.runtime.AbstractListener) ProgramDescriptor(co.cask.cdap.app.program.ProgramDescriptor) BasicArguments(co.cask.cdap.internal.app.runtime.BasicArguments) File(java.io.File) Test(org.junit.Test)

Example 25 with ProgramController

use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.

the class ProgramLifecycleHttpHandler method startPrograms.

/**
 * Starts all programs that are passed into the data. The data is an array of JSON objects
 * where each object must contain the following three elements: appId, programType, and programId
 * (flow name, service name, etc.). In additional, each object can contain an optional runtimeargs element,
 * which is a map of arguments to start the program with.
 * <p>
 * Example input:
 * <pre><code>
 * [{"appId": "App1", "programType": "Service", "programId": "Service1"},
 * {"appId": "App1", "programType": "Mapreduce", "programId": "MapReduce2", "runtimeargs":{"arg1":"val1"}},
 * {"appId": "App2", "programType": "Flow", "programId": "Flow1"}]
 * </code></pre>
 * </p><p>
 * The response will be an array of JsonObjects each of which will contain the three input parameters
 * as well as a "statusCode" field which maps to the status code for the data in that JsonObjects.
 * </p><p>
 * If an error occurs in the input (for the example above, App2 does not exist), then all JsonObjects for which the
 * parameters have a valid status will have the status field but all JsonObjects for which the parameters do not have
 * a valid status will have an error message and statusCode.
 * </p><p>
 * For example, if there is no App2 in the data above, then the response would be 200 OK with following possible data:
 * </p>
 * <pre><code>
 * [{"appId": "App1", "programType": "Service", "programId": "Service1", "statusCode": 200},
 * {"appId": "App1", "programType": "Mapreduce", "programId": "Mapreduce2", "statusCode": 200},
 * {"appId":"App2", "programType":"Flow", "programId":"Flow1", "statusCode":404, "error": "App: App2 not found"}]
 * </code></pre>
 */
@POST
@Path("/start")
@AuditPolicy({ AuditDetail.REQUEST_BODY, AuditDetail.RESPONSE_BODY })
public void startPrograms(FullHttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId) throws Exception {
    List<BatchProgramStart> programs = validateAndGetBatchInput(request, BATCH_STARTS_TYPE);
    List<BatchProgramResult> output = new ArrayList<>(programs.size());
    for (BatchProgramStart program : programs) {
        ProgramId programId = new ProgramId(namespaceId, program.getAppId(), program.getProgramType(), program.getProgramId());
        try {
            ProgramController programController = lifecycleService.start(programId, program.getRuntimeargs(), false);
            output.add(new BatchProgramResult(program, HttpResponseStatus.OK.code(), null, programController.getRunId().getId()));
        } catch (NotFoundException e) {
            output.add(new BatchProgramResult(program, HttpResponseStatus.NOT_FOUND.code(), e.getMessage()));
        } catch (BadRequestException e) {
            output.add(new BatchProgramResult(program, HttpResponseStatus.BAD_REQUEST.code(), e.getMessage()));
        } catch (ConflictException e) {
            output.add(new BatchProgramResult(program, HttpResponseStatus.CONFLICT.code(), e.getMessage()));
        }
    }
    responder.sendJson(HttpResponseStatus.OK, GSON.toJson(output));
}
Also used : ProgramController(co.cask.cdap.app.runtime.ProgramController) ConflictException(co.cask.cdap.common.ConflictException) BatchProgramResult(co.cask.cdap.proto.BatchProgramResult) ArrayList(java.util.ArrayList) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException) NotFoundException(co.cask.cdap.common.NotFoundException) BadRequestException(co.cask.cdap.common.BadRequestException) BatchProgramStart(co.cask.cdap.proto.BatchProgramStart) ProgramId(co.cask.cdap.proto.id.ProgramId) Path(javax.ws.rs.Path) AuditPolicy(co.cask.cdap.common.security.AuditPolicy) POST(javax.ws.rs.POST)

Aggregations

ProgramController (co.cask.cdap.app.runtime.ProgramController)37 ProgramId (co.cask.cdap.proto.id.ProgramId)13 IOException (java.io.IOException)10 Test (org.junit.Test)10 ProgramDescriptor (co.cask.cdap.app.program.ProgramDescriptor)9 ApplicationWithPrograms (co.cask.cdap.internal.app.deploy.pipeline.ApplicationWithPrograms)9 ProgramType (co.cask.cdap.proto.ProgramType)9 RunId (org.apache.twill.api.RunId)9 BasicArguments (co.cask.cdap.internal.app.runtime.BasicArguments)8 ApplicationSpecification (co.cask.cdap.api.app.ApplicationSpecification)7 AbstractListener (co.cask.cdap.internal.app.runtime.AbstractListener)7 NotFoundException (co.cask.cdap.common.NotFoundException)6 AbstractProgramController (co.cask.cdap.internal.app.runtime.AbstractProgramController)6 ExecutionException (java.util.concurrent.ExecutionException)6 ProgramOptions (co.cask.cdap.app.runtime.ProgramOptions)5 ArrayList (java.util.ArrayList)5 ProgramRuntimeService (co.cask.cdap.app.runtime.ProgramRuntimeService)4 BadRequestException (co.cask.cdap.common.BadRequestException)4 ConflictException (co.cask.cdap.common.ConflictException)4 NamespaceNotFoundException (co.cask.cdap.common.NamespaceNotFoundException)4