Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
language: java
jdk:
- openjdk8
install: true
script: mvn package -DskipTests=false -Dmaven.javadoc.skip=true -B -V
cache:
directories:
- $HOME/.m2
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM openjdk:8u151-jre-alpine

ENV KRONOS_VERSION 3.0.0
ENV KRONOS_VERSION 3.1.0
ENV KRONOS_HOME /home/kronos-${KRONOS_VERSION}
ENV MODE all

Expand Down
2 changes: 1 addition & 1 deletion api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<artifactId>kronos</artifactId>
<groupId>com.cognitree</groupId>
<version>3.0.0</version>
<version>3.1.0</version>
</parent>

<modelVersion>4.0.0</modelVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public Response getAllJobs(@ApiParam(value = "job status", allowMultiple = true)
@DefaultValue(DEFAULT_DAYS) @QueryParam("date_range") int numberOfDays,
@HeaderParam("namespace") String namespace) throws ServiceException, ValidationException {
logger.info("Received request to get all jobs under namespace {} with param status in {}, date range {}, " +
"from {}, to {}", namespace, statuses, numberOfDays, createdAfter, createdBefore, namespace);
"from {}, to {}", namespace, statuses, numberOfDays, createdAfter, createdBefore);
if (namespace == null || namespace.isEmpty()) {
return Response.status(BAD_REQUEST).entity("missing namespace header").build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -133,7 +134,19 @@ public Response getJob(@ApiParam(value = "workflow name", required = true)
logger.error("No job exists with id {}", jobId);
return Response.status(NOT_FOUND).build();
}
final List<Task> tasks = JobService.getService().getTasks(job);
final List<Task> tasks = JobService.getService().getTasks(job).stream()
.sorted((task1, task2) -> {
int diff = task1.getStatus().getOrder() - task2.getStatus().getOrder();
if (diff == 0){
if (task1.getCompletedAt() != null && task2.getCompletedAt() != null){
return task1.getCompletedAt().compareTo(task2.getCompletedAt());
}else {
return task1.getCreatedAt().compareTo(task2.getCreatedAt());
}
}else {
return diff;
}
}).collect(Collectors.toList());
return Response.status(OK).entity(JobResponse.create(job, tasks)).build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public Response updateWorkflowTrigger(@ApiParam(value = "workflow name", require
@HeaderParam("namespace") String namespace)
throws ServiceException, ValidationException, SchedulerException {
logger.info("Received request to update workflow trigger {} for workflow {} under namespace {} set enable to {}",
triggerName, workflowName, namespace);
triggerName, workflowName, namespace, enable);
if (namespace == null || namespace.isEmpty()) {
return Response.status(BAD_REQUEST).entity("missing namespace header").build();
}
Expand Down
2 changes: 1 addition & 1 deletion app/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<artifactId>kronos</artifactId>
<groupId>com.cognitree</groupId>
<version>3.0.0</version>
<version>3.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
20 changes: 0 additions & 20 deletions app/src/main/conf/log4j.properties

This file was deleted.

16 changes: 16 additions & 0 deletions app/src/main/conf/log4j2.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name = Log4j2Config
#The level of internal Log4j events that should be logged to the console
status = error
#The minimum amount of time, in seconds, that must elapse before the file configuration is checked for changes.
#Any changes to the configuration file during runtime will come into effect.
monitorInterval = 10

appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %5p [%t] (%F:%L) - %m%n
appender.console.immediateFlush=true

rootLogger.level = INFO
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,103 @@ public void testGetJobTasksFailedDueToHandler() throws Exception {
}
}

@Test
public void testConditionSuccessJob() throws Exception {
final WorkflowTrigger workflowTrigger = scheduleWorkflow(CONDITION_WORKFLOW_TEMPLATE_SUCCESS_YAML);

waitForJobsToTriggerAndComplete(workflowTrigger);

JobService jobService = JobService.getService();
final List<Job> workflowOneJobs = jobService.get(workflowTrigger.getNamespace(), workflowTrigger.getWorkflow(),
workflowTrigger.getName(), 0, System.currentTimeMillis());
Assert.assertEquals(1, workflowOneJobs.size());

final Job job = workflowOneJobs.get(0);
final List<Task> tasks = jobService.getTasks(job);
Assert.assertEquals(3, tasks.size());
for (Task task : tasks) {
switch (task.getName()) {
case "taskOne":
case "taskTwo":
case "taskThree":
Assert.assertEquals(Task.Status.SUCCESSFUL, task.getStatus());
Assert.assertTrue(MockSuccessTaskHandler.isHandled(task.getIdentity()));
Assert.assertEquals(0, task.getRetryCount());
break;
default:
Assert.fail();
}
}
}

@Test
public void testLastConditionFailsJob() throws Exception {
final WorkflowTrigger workflowTrigger = scheduleWorkflow(CONDITION_WORKFLOW_TEMPLATE_FAILURE_LASTCONDITION_YAML);

waitForJobsToTriggerAndComplete(workflowTrigger);

JobService jobService = JobService.getService();
final List<Job> workflowOneJobs = jobService.get(workflowTrigger.getNamespace(), workflowTrigger.getWorkflow(),
workflowTrigger.getName(), 0, System.currentTimeMillis());
Assert.assertEquals(1, workflowOneJobs.size());

final Job job = workflowOneJobs.get(0);
final List<Task> tasks = jobService.getTasks(job);
Assert.assertEquals(3, tasks.size());
for (Task task : tasks) {
switch (task.getName()) {
case "taskOne":
case "taskTwo":
Assert.assertEquals(Task.Status.SUCCESSFUL, task.getStatus());
Assert.assertTrue(MockSuccessTaskHandler.isHandled(task.getIdentity()));
break;
case "taskThree":
Assert.assertEquals(SKIPPED, task.getStatus());
Assert.assertEquals(Messages.TASK_SKIPPED_CONDITION_FAILS, task.getStatusMessage());
Assert.assertEquals(0, task.getRetryCount());
break;
default:
Assert.fail();
}
}
}

@Test
public void testSecondConditionFails() throws Exception {
final WorkflowTrigger workflowTrigger = scheduleWorkflow(CONDITION_WORKFLOW_TEMPLATE_FAILURE_SECONDCONDITION_YAML);

waitForJobsToTriggerAndComplete(workflowTrigger);

JobService jobService = JobService.getService();
final List<Job> workflowOneJobs = jobService.get(workflowTrigger.getNamespace(), workflowTrigger.getWorkflow(),
workflowTrigger.getName(), 0, System.currentTimeMillis());
Assert.assertEquals(1, workflowOneJobs.size());

final Job job = workflowOneJobs.get(0);
final List<Task> tasks = jobService.getTasks(job);
Assert.assertEquals(3, tasks.size());
for (Task task : tasks) {
switch (task.getName()) {
case "taskOne":
Assert.assertEquals(Task.Status.SUCCESSFUL, task.getStatus());
Assert.assertTrue(MockSuccessTaskHandler.isHandled(task.getIdentity()));
break;
case "taskTwo":
Assert.assertEquals(SKIPPED, task.getStatus());
Assert.assertEquals(Messages.TASK_SKIPPED_CONDITION_FAILS, task.getStatusMessage());
Assert.assertEquals(0, task.getRetryCount());
break;
case "taskThree":
Assert.assertEquals(SKIPPED, task.getStatus());
Assert.assertEquals(Messages.SKIPPED_DEPENDEE_TASK_MESSAGE, task.getStatusMessage());
Assert.assertEquals(0, task.getRetryCount());
break;
default:
Assert.fail();
}
}
}

@Test(expected = ValidationException.class)
public void testAbortJobNotFound() throws Exception {
final WorkflowTrigger workflowTrigger = scheduleWorkflow(WORKFLOW_TEMPLATE_YAML);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ public class ServiceTest {
protected static final String WORKFLOW_TEMPLATE_WITH_TASK_CONTEXT_YAML = "workflows/workflow-template-with-task-context.yaml";
protected static final String WORKFLOW_TEMPLATE_WITH_PROPERTIES_YAML = "workflows/workflow-template-with-properties.yaml";
protected static final String WORKFLOW_TEMPLATE_WITH_DUPLICATE_POLICY_YAML = "workflows/workflow-template-with-duplicate-policy.yaml";
protected static final String WORKFLOW_TEMPLATE_FAILED_PARALLEL_BRANCH_YAML = "workflows/workflow-template-failed-parallel-branch.yaml";

protected static final String CONDITION_WORKFLOW_TEMPLATE_SUCCESS_YAML = "workflows/condition-workflow-template-success.yaml";
protected static final String CONDITION_WORKFLOW_TEMPLATE_FAILURE_LASTCONDITION_YAML = "workflows/condition-workflow-template-failure-last-task.yaml";
protected static final String CONDITION_WORKFLOW_TEMPLATE_FAILURE_SECONDCONDITION_YAML = "workflows/condition-workflow-template-failure-second-task";
protected static final String CONDITION_WORKFLOW_TEMPLATE_FAILED_PARALLEL_BRANCH_YAML = "workflows/condition-workflow-template-failed-parallel-branch.yaml";

private static final ObjectMapper MAPPER = new ObjectMapper(new YAMLFactory());
private static final List<Namespace> EXISTING_NAMESPACE = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@
import java.util.List;
import java.util.UUID;

import static com.cognitree.kronos.TestUtil.scheduleWorkflow;
import static com.cognitree.kronos.TestUtil.waitForJobsToTriggerAndComplete;
import static com.cognitree.kronos.TestUtil.waitForTaskToBeRunning;
import static com.cognitree.kronos.TestUtil.waitForTriggerToComplete;
import static com.cognitree.kronos.TestUtil.*;

public class TaskServiceTest extends ServiceTest {

Expand Down Expand Up @@ -155,6 +152,38 @@ public void testAbortTasks() throws Exception {
}
}

@Test
public void testFailedBranchTasks() throws Exception {
final WorkflowTrigger workflowTrigger = scheduleWorkflow(WORKFLOW_TEMPLATE_FAILED_PARALLEL_BRANCH_YAML);

waitForJobsToTriggerAndComplete(workflowTrigger);
TaskService taskService = TaskService.getService();
List<Task> tasks = taskService.get(workflowTrigger.getNamespace());
for (Task task : tasks) {
if (task.getName().equals("B") || task.getName().equals("C")) {
Assert.assertNotEquals(Task.Status.SUCCESSFUL, task.getStatus());
} else {
Assert.assertEquals(Task.Status.SUCCESSFUL, task.getStatus());
}
}
}

@Test
public void testConditionFailedBranchTasks() throws Exception {
final WorkflowTrigger workflowTrigger = scheduleWorkflow(CONDITION_WORKFLOW_TEMPLATE_FAILED_PARALLEL_BRANCH_YAML);

waitForJobsToTriggerAndComplete(workflowTrigger);
TaskService taskService = TaskService.getService();
List<Task> tasks = taskService.get(workflowTrigger.getNamespace());
for (Task task : tasks) {
if (task.getName().equals("B") || task.getName().equals("C")) {
Assert.assertNotEquals(Task.Status.SUCCESSFUL, task.getStatus());
} else {
Assert.assertEquals(Task.Status.SUCCESSFUL, task.getStatus());
}
}
}

@Test
public void testDeleteTask() throws Exception {
final WorkflowTrigger workflowTrigger = scheduleWorkflow(WORKFLOW_TEMPLATE_YAML);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
tasks:
- name: A
type: typeSuccess
properties:
keyA: valA
keyB: valB
- name: B
type: typeSuccess
properties:
keyA: valA
keyB: valB
condition: 2==3
dependsOn:
- A
- name: C
type: typeSuccess
properties:
keyA: valA
keyB: valB
dependsOn:
- B
- name: D
type: typeSuccess
properties:
keyA: valA
keyB: valB
dependsOn:
- A
- name: E
type: typeSuccess
properties:
keyA: valA
keyB: valB
dependsOn:
- D
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# name and namespace is set as part of test case
description: Workflow with condition only last conditions fails
tasks:
- name: taskOne
type: typeSuccess
properties:
keyA: valA
keyB: valB
- name: taskTwo
type: typeSuccess
dependsOn:
- taskOne
condition: taskOne.get("valOne") == 1234 && taskOne.get("valTwo") == 'abcd'
properties:
keyA: valA
keyB: valB
- name: taskThree
type: typeSuccess
dependsOn:
- taskTwo
- taskOne
condition: taskOne.get("valOne") + taskTwo.get("valOne") == 0 || taskOne.get("valTwo") != taskTwo.get("valTwo")
properties:
keyA: valA
keyB: valB
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# name and namespace is set as part of test case
description: Workflow with conditions with three tasks out of which only second condition fails.
tasks:
- name: taskOne
type: typeSuccess
properties:
keyA: valA
keyB: valB
- name: taskTwo
type: typeSuccess
dependsOn:
- taskOne
condition: taskOne.get("valOne") == 1234 && taskOne.get("valTwo") != 'abcd'
properties:
keyA: valA
keyB: valB
- name: taskThree
type: typeSuccess
dependsOn:
- taskTwo
- taskOne
condition: taskOne.get("valOne") + taskTwo.get("valOne") == 2468 || taskOne.get("valTwo") == taskTwo.get("valTwo")
properties:
keyA: valA
keyB: valB
Loading