use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class ProgramLifecycleHttpHandlerTest method testAddSchedule.
private void testAddSchedule(String scheduleName) throws Exception {
String partitionScheduleName = scheduleName + "Partition";
String orScheduleName = scheduleName + "Or";
ProtoTrigger.TimeTrigger protoTime = new ProtoTrigger.TimeTrigger("0 * * * ?");
ProtoTrigger.PartitionTrigger protoPartition = new ProtoTrigger.PartitionTrigger(NamespaceId.DEFAULT.dataset("data"), 5);
ProtoTrigger.OrTrigger protoOr = ProtoTrigger.or(protoTime, protoPartition);
String description = "Something";
ScheduleProgramInfo programInfo = new ScheduleProgramInfo(SchedulableProgramType.WORKFLOW, AppWithSchedule.WORKFLOW_NAME);
ImmutableMap<String, String> properties = ImmutableMap.of("a", "b", "c", "d");
TimeTrigger timeTrigger = new TimeTrigger("0 * * * ?");
ScheduleDetail timeDetail = new ScheduleDetail(TEST_NAMESPACE1, AppWithSchedule.NAME, ApplicationId.DEFAULT_VERSION, scheduleName, description, programInfo, properties, timeTrigger, Collections.<Constraint>emptyList(), Schedulers.JOB_QUEUE_TIMEOUT_MILLIS, null);
PartitionTrigger partitionTrigger = new PartitionTrigger(protoPartition.getDataset(), protoPartition.getNumPartitions());
ScheduleDetail expectedPartitionDetail = new ScheduleDetail(TEST_NAMESPACE1, AppWithSchedule.NAME, ApplicationId.DEFAULT_VERSION, partitionScheduleName, description, programInfo, properties, partitionTrigger, Collections.<Constraint>emptyList(), Schedulers.JOB_QUEUE_TIMEOUT_MILLIS, null);
ScheduleDetail requestPartitionDetail = new ScheduleDetail(TEST_NAMESPACE1, AppWithSchedule.NAME, ApplicationId.DEFAULT_VERSION, partitionScheduleName, description, programInfo, properties, protoPartition, Collections.<Constraint>emptyList(), Schedulers.JOB_QUEUE_TIMEOUT_MILLIS, null);
ScheduleDetail expectedOrDetail = new ScheduleDetail(TEST_NAMESPACE1, AppWithSchedule.NAME, ApplicationId.DEFAULT_VERSION, orScheduleName, description, programInfo, properties, new OrTrigger(timeTrigger, partitionTrigger), Collections.<Constraint>emptyList(), Schedulers.JOB_QUEUE_TIMEOUT_MILLIS, null);
ScheduleDetail requestOrDetail = new ScheduleDetail(TEST_NAMESPACE1, AppWithSchedule.NAME, ApplicationId.DEFAULT_VERSION, orScheduleName, description, programInfo, properties, protoOr, Collections.<Constraint>emptyList(), Schedulers.JOB_QUEUE_TIMEOUT_MILLIS, null);
// trying to add the schedule with different name in path param than schedule spec should fail
HttpResponse response = addSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, "differentName", timeDetail);
Assert.assertEquals(HttpResponseStatus.BAD_REQUEST.code(), response.getStatusLine().getStatusCode());
// adding a schedule to a non-existing app should fail
response = addSchedule(TEST_NAMESPACE1, "nonExistingApp", null, scheduleName, timeDetail);
Assert.assertEquals(HttpResponseStatus.NOT_FOUND.code(), response.getStatusLine().getStatusCode());
// adding a schedule to invalid type of program type should fail
ScheduleDetail invalidScheduleDetail = new ScheduleDetail(scheduleName, "Something", new ScheduleProgramInfo(SchedulableProgramType.MAPREDUCE, AppWithSchedule.MAPREDUCE), properties, protoTime, ImmutableList.<Constraint>of(), TimeUnit.MINUTES.toMillis(1));
response = addSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, scheduleName, invalidScheduleDetail);
Assert.assertEquals(HttpResponseStatus.BAD_REQUEST.code(), response.getStatusLine().getStatusCode());
// adding a schedule for a program that does not exist
ScheduleDetail nonExistingDetail = new ScheduleDetail(TEST_NAMESPACE1, AppWithSchedule.NAME, ApplicationId.DEFAULT_VERSION, scheduleName, description, new ScheduleProgramInfo(SchedulableProgramType.MAPREDUCE, "nope"), properties, timeTrigger, Collections.<Constraint>emptyList(), Schedulers.JOB_QUEUE_TIMEOUT_MILLIS, null);
response = addSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, scheduleName, nonExistingDetail);
Assert.assertEquals(HttpResponseStatus.NOT_FOUND.code(), response.getStatusLine().getStatusCode());
// test adding a schedule
response = addSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, scheduleName, timeDetail);
Assert.assertEquals(HttpResponseStatus.OK.code(), response.getStatusLine().getStatusCode());
response = addSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, partitionScheduleName, requestPartitionDetail);
Assert.assertEquals(HttpResponseStatus.OK.code(), response.getStatusLine().getStatusCode());
response = addSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, orScheduleName, requestOrDetail);
Assert.assertEquals(HttpResponseStatus.OK.code(), response.getStatusLine().getStatusCode());
List<ScheduleDetail> schedules = getSchedules(TEST_NAMESPACE1, AppWithSchedule.NAME, AppWithSchedule.WORKFLOW_NAME);
Assert.assertEquals(4, schedules.size());
Assert.assertEquals(timeDetail, schedules.get(1));
Assert.assertEquals(expectedOrDetail, schedules.get(2));
Assert.assertEquals(expectedPartitionDetail, schedules.get(3));
List<ScheduleDetail> schedulesForApp = listSchedules(TEST_NAMESPACE1, AppWithSchedule.NAME, null);
Assert.assertEquals(schedules, schedulesForApp);
// trying to add ScheduleDetail of the same schedule again should fail with AlreadyExistsException
response = addSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, scheduleName, timeDetail);
Assert.assertEquals(HttpResponseStatus.CONFLICT.code(), response.getStatusLine().getStatusCode());
// although we should be able to add schedule to a different version of the app
response = addSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, VERSION2, scheduleName, timeDetail);
Assert.assertEquals(HttpResponseStatus.OK.code(), response.getStatusLine().getStatusCode());
// this should not have affected the schedules of the default version
List<ScheduleDetail> scheds = getSchedules(TEST_NAMESPACE1, AppWithSchedule.NAME, AppWithSchedule.WORKFLOW_NAME);
Assert.assertEquals(schedules, scheds);
// there should be two schedules now for version 2
List<ScheduleDetail> schedules2 = getSchedules(TEST_NAMESPACE1, AppWithSchedule.NAME, VERSION2, AppWithSchedule.WORKFLOW_NAME);
Assert.assertEquals(2, schedules2.size());
Assert.assertEquals(timeDetail, schedules2.get(1));
List<ScheduleDetail> schedulesForApp2 = listSchedules(TEST_NAMESPACE1, AppWithSchedule.NAME, VERSION2);
Assert.assertEquals(schedules2, schedulesForApp2);
// Add a schedule with no schedule name in spec
ScheduleDetail detail2 = new ScheduleDetail(TEST_NAMESPACE1, AppWithSchedule.NAME, VERSION2, null, "Something 2", programInfo, properties, new TimeTrigger("0 * * * ?"), Collections.<Constraint>emptyList(), TimeUnit.HOURS.toMillis(6), null);
response = addSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, VERSION2, "schedule-100", detail2);
Assert.assertEquals(HttpResponseStatus.OK.code(), response.getStatusLine().getStatusCode());
ScheduleDetail detail100 = getSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, VERSION2, "schedule-100");
Assert.assertEquals("schedule-100", detail100.getName());
Assert.assertEquals(detail2.getTimeoutMillis(), detail100.getTimeoutMillis());
}
use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class ScheduleClientTestRun method testScheduleChanges.
@Test
public void testScheduleChanges() throws Exception {
File appJar = createAppJarFile(FakeApp.class);
// deploy the app with time schedule
FakeApp.AppConfig config = new FakeApp.AppConfig(true, null, null);
appClient.deploy(namespace, appJar, config);
// now there should be one schedule
List<ScheduleDetail> list = scheduleClient.listSchedules(workflow);
Assert.assertEquals(1, list.size());
// test updating the schedule cron
config = new FakeApp.AppConfig(true, FakeApp.TIME_SCHEDULE_NAME, "0 2 1 1 *");
appClient.deploy(namespace, appJar, config);
list = scheduleClient.listSchedules(workflow);
Assert.assertEquals(1, list.size());
ProtoTrigger.TimeTrigger trigger = (ProtoTrigger.TimeTrigger) list.get(0).getTrigger();
Assert.assertEquals("0 2 1 1 *", trigger.getCronExpression());
// re-deploy the app without time schedule
config = new FakeApp.AppConfig(false, null, null);
appClient.deploy(namespace, appJar, config);
// now there should be no schedule
list = scheduleClient.listSchedules(workflow);
Assert.assertEquals(0, list.size());
}
use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class AppFabricClient method getProgramSchedules.
public List<ScheduleDetail> getProgramSchedules(String namespace, String app, String workflow) throws NotFoundException {
MockResponder responder = new MockResponder();
String uri = String.format("%s/apps/%s/workflows/%s/schedules", getNamespacePath(namespace), app, workflow);
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri);
try {
workflowHttpHandler.getWorkflowSchedules(request, responder, namespace, app, workflow, null, null, null);
} catch (Exception e) {
// cannot happen
throw Throwables.propagate(e);
}
List<ScheduleDetail> schedules = responder.decodeResponseContent(SCHEDULE_DETAILS_TYPE, GSON);
verifyResponse(HttpResponseStatus.OK, responder.getStatus(), "Getting workflow schedules failed");
return schedules;
}
use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class ListWorkflowSchedulesCommand method perform.
@Override
public void perform(Arguments arguments, PrintStream output) throws Exception {
String[] programIdParts = arguments.get(ElementType.WORKFLOW.getArgumentName().toString()).split("\\.");
if (programIdParts.length < 2) {
throw new CommandInputError(this);
}
final String appId = programIdParts[0];
String workflowName = programIdParts[1];
WorkflowId workflowId = cliConfig.getCurrentNamespace().app(appId).workflow(workflowName);
List<ScheduleDetail> list = scheduleClient.listSchedules(workflowId);
Table table = Table.builder().setHeader("application", "program", "program type", "name", "description", "trigger", "timeoutMillis", "properties").setRows(list, new RowMaker<ScheduleDetail>() {
@Override
public List<?> makeRow(ScheduleDetail object) {
return Lists.newArrayList(appId, object.getProgram().getProgramName(), object.getProgram().getProgramType().name(), object.getName(), object.getDescription(), object.getTrigger(), object.getTimeoutMillis(), GSON.toJson(object.getProperties()));
}
}).build();
cliConfig.getTableRenderer().render(cliConfig, output, table);
}
use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method doGetSchedules.
protected void doGetSchedules(HttpResponder responder, ApplicationId applicationId, @Nullable String workflow, @Nullable String triggerTypeStr, @Nullable String statusStr) throws Exception {
ApplicationSpecification appSpec = store.getApplication(applicationId);
if (appSpec == null) {
throw new NotFoundException(applicationId);
}
ProgramScheduleStatus status;
try {
status = statusStr == null ? null : ProgramScheduleStatus.valueOf(statusStr);
} catch (IllegalArgumentException e) {
throw new BadRequestException(String.format("Invalid schedule status '%s'. Must be one of %s.", statusStr, Joiner.on(',').join(ProgramScheduleStatus.values())), e);
}
ProtoTrigger.Type triggerType;
try {
triggerType = triggerTypeStr == null ? null : ProtoTrigger.Type.valueOfCategoryName(triggerTypeStr);
} catch (IllegalArgumentException e) {
throw new BadRequestException(e.getMessage(), e);
}
Predicate<ProgramScheduleRecord> predicate = record -> true;
if (status != null) {
predicate = predicate.and(record -> record.getMeta().getStatus().equals(status));
}
if (triggerType != null) {
predicate = predicate.and(record -> record.getSchedule().getTrigger().getType().equals(triggerType));
}
Collection<ProgramScheduleRecord> schedules;
if (workflow != null) {
WorkflowId workflowId = applicationId.workflow(workflow);
if (appSpec.getWorkflows().get(workflow) == null) {
throw new NotFoundException(workflowId);
}
schedules = programScheduleService.list(workflowId, predicate);
} else {
schedules = programScheduleService.list(applicationId, predicate);
}
List<ScheduleDetail> details = schedules.stream().map(ProgramScheduleRecord::toScheduleDetail).collect(Collectors.toList());
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(details, Schedulers.SCHEDULE_DETAILS_TYPE));
}
Aggregations