use of io.cdap.cdap.proto.id.NamespaceId in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method reEnableSuspendedSchedules.
/**
* Update schedules which were suspended between startTimeMillis and endTimeMillis
* @param startTimeMillis lower bound in millis of the update time for schedules (inclusive)
* @param endTimeMillis upper bound in millis of the update time for schedules (exclusive)
*/
@PUT
@Path("schedules/re-enable")
public void reEnableSuspendedSchedules(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId, @QueryParam("start-time-millis") long startTimeMillis, @QueryParam("end-time-millis") long endTimeMillis) throws Exception {
programScheduleService.reEnableSchedules(new NamespaceId(namespaceId), startTimeMillis, endTimeMillis);
responder.sendStatus(HttpResponseStatus.OK);
}
use of io.cdap.cdap.proto.id.NamespaceId in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method getStatuses.
/**
* Returns the status for 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"}]
* </code></pre>
* </p><p>
* The response will be an array of JsonObjects each of which will contain the three input parameters
* as well as 2 fields, "status" which maps to the status of the program and "statusCode" 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, "status": "RUNNING"},
* {"appId": "App1", "programType": "Mapreduce", "programId": "Mapreduce2", "statusCode": 200, "status": "STOPPED"}]
* </code></pre>
*/
@POST
@Path("/status")
@AuditPolicy(AuditDetail.REQUEST_BODY)
public void getStatuses(FullHttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId) throws Exception {
List<BatchProgram> batchPrograms = validateAndGetBatchInput(request, BATCH_PROGRAMS_TYPE);
List<ProgramId> programs = batchPrograms.stream().map(p -> new ProgramId(namespaceId, p.getAppId(), p.getProgramType(), p.getProgramId())).collect(Collectors.toList());
Map<ProgramId, ProgramStatus> statuses = lifecycleService.getProgramStatuses(programs);
List<BatchProgramStatus> result = new ArrayList<>(programs.size());
for (BatchProgram program : batchPrograms) {
ProgramId programId = new ProgramId(namespaceId, program.getAppId(), program.getProgramType(), program.getProgramId());
ProgramStatus status = statuses.get(programId);
if (status == null) {
result.add(new BatchProgramStatus(program, HttpResponseStatus.NOT_FOUND.code(), new NotFoundException(programId).getMessage(), null));
} else {
result.add(new BatchProgramStatus(program, HttpResponseStatus.OK.code(), null, status.name()));
}
}
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(result));
}
use of io.cdap.cdap.proto.id.NamespaceId in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method getPreviousScheduledRunTime.
/**
* Returns the previous runtime when the scheduled program ran.
*/
@GET
@Path("/apps/{app-name}/{program-type}/{program-name}/previousruntime")
public void getPreviousScheduledRunTime(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId, @PathParam("app-name") String appId, @PathParam("program-type") String type, @PathParam("program-name") String program) throws Exception {
ProgramType programType = getProgramType(type);
handleScheduleRunTime(responder, new NamespaceId(namespaceId).app(appId).program(programType, program), true);
}
use of io.cdap.cdap.proto.id.NamespaceId in project cdap by caskdata.
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));
}
use of io.cdap.cdap.proto.id.NamespaceId in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method getLatestRuns.
/**
* Returns the latest runs for all program runnables 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.
* <p>
* Example input:
* <pre><code>
* [{"appId": "App1", "programType": "Service", "programId": "Service1"},
* {"appId": "App1", "programType": "Workflow", "programId": "testWorkflow"},
* {"appId": "App2", "programType": "Workflow", "programId": "DataPipelineWorkflow"}]
* </code></pre>
* </p><p>
* </p><p>
* The response will be an array of JsonObjects each of which will contain the three input parameters
* as well as 2 fields, "runs" which is a list of the latest run records and "statusCode" 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, workflow in app1 does not exist),
* then all JsonObjects for which the parameters have a valid status will have the count 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 workflow in App1 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, "runs": [...]},
* {"appId": "App1", "programType": "Workflow", "programId": "testWorkflow", "statusCode": 404,
* "error": "Program 'testWorkflow' is not found"},
* {"appId": "App2", "programType": "Workflow", "programId": "DataPipelineWorkflow", "runnableId": "Flowlet1",
* "statusCode": 200, "runs": [...]}]
* </code></pre>
*/
@POST
@Path("/runs")
public void getLatestRuns(FullHttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId) throws Exception {
List<BatchProgram> programs = validateAndGetBatchInput(request, BATCH_PROGRAMS_TYPE);
List<ProgramId> programIds = programs.stream().map(batchProgram -> new ProgramId(namespaceId, batchProgram.getAppId(), batchProgram.getProgramType(), batchProgram.getProgramId())).collect(Collectors.toList());
List<BatchProgramHistory> response = new ArrayList<>(programs.size());
List<ProgramHistory> result = lifecycleService.getRunRecords(programIds, ProgramRunStatus.ALL, 0, Long.MAX_VALUE, 1);
for (ProgramHistory programHistory : result) {
ProgramId programId = programHistory.getProgramId();
Exception exception = programHistory.getException();
BatchProgram batchProgram = new BatchProgram(programId.getApplication(), programId.getType(), programId.getProgram());
if (exception == null) {
response.add(new BatchProgramHistory(batchProgram, HttpResponseStatus.OK.code(), null, programHistory.getRuns()));
} else if (exception instanceof NotFoundException) {
response.add(new BatchProgramHistory(batchProgram, HttpResponseStatus.NOT_FOUND.code(), exception.getMessage(), Collections.emptyList()));
} else if (exception instanceof UnauthorizedException) {
response.add(new BatchProgramHistory(batchProgram, HttpResponseStatus.FORBIDDEN.code(), exception.getMessage(), Collections.emptyList()));
} else {
response.add(new BatchProgramHistory(batchProgram, HttpResponseStatus.INTERNAL_SERVER_ERROR.code(), exception.getMessage(), Collections.emptyList()));
}
}
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(response));
}
Aggregations