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);
}
}
}
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);
}
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);
}
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();
}
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));
}
Aggregations