WIP: add parsing for execution state

This commit is contained in:
Greg Schueler 2014-01-18 10:17:27 -08:00
parent d29d2067d0
commit cbdb5c818e
19 changed files with 1074 additions and 0 deletions

View file

@ -0,0 +1,47 @@
package org.rundeck.api.domain;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* $INTERFACE is ... User: greg Date: 1/17/14 Time: 11:26 AM
*/
public class BaseState {
private Date startTime;
private Date endTime;
private Date updateTime;
private RundeckWFExecState executionState;
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public RundeckWFExecState getExecutionState() {
return executionState;
}
public void setExecutionState(RundeckWFExecState executionState) {
this.executionState = executionState;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

View file

@ -0,0 +1,38 @@
package org.rundeck.api.domain;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* $INTERFACE is ... User: greg Date: 1/16/14 Time: 5:41 PM
*/
public class RundeckExecutionState extends WorkflowState{
private long executionId;
private Set<RundeckNodeIdentity> allNodes;
private Map<String, List<WorkflowStepContextState>> nodeStates;
public Set<RundeckNodeIdentity> getAllNodes() {
return allNodes;
}
public void setAllNodes(Set<RundeckNodeIdentity> allNodes) {
this.allNodes = allNodes;
}
public Map<String, List<WorkflowStepContextState>> getNodeStates() {
return nodeStates;
}
public void setNodeStates(Map<String, List<WorkflowStepContextState>> nodeStates) {
this.nodeStates = nodeStates;
}
public long getExecutionId() {
return executionId;
}
public void setExecutionId(long executionId) {
this.executionId = executionId;
}
}

View file

@ -0,0 +1,43 @@
package org.rundeck.api.domain;
/**
* $INTERFACE is ... User: greg Date: 1/17/14 Time: 11:27 AM
*/
public enum RundeckWFExecState {
/**
* Waiting to start running
*/
WAITING,
/**
* Currently running
*/
RUNNING,
/**
* Running error handler
*/
RUNNING_HANDLER,
/**
* Finished running successfully
*/
SUCCEEDED,
/**
* Finished with a failure
*/
FAILED,
/**
* Execution was aborted
*/
ABORTED,
/**
* Partial success for some nodes
*/
NODE_PARTIAL_SUCCEEDED,
/**
* Mixed states among nodes
*/
NODE_MIXED,
/**
* After waiting the execution did not start
*/
NOT_STARTED,;
}

View file

@ -0,0 +1,40 @@
package org.rundeck.api.domain;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* $INTERFACE is ... User: greg Date: 1/16/14 Time: 5:44 PM
*/
public class WorkflowState extends BaseState{
private int stepCount;
private Set<RundeckNodeIdentity> targetNodes;
private List<WorkflowStepState> steps;
public int getStepCount() {
return stepCount;
}
public void setStepCount(int stepCount) {
this.stepCount = stepCount;
}
public Set<RundeckNodeIdentity> getTargetNodes() {
return targetNodes;
}
public void setTargetNodes(Set<RundeckNodeIdentity> targetNodes) {
this.targetNodes = targetNodes;
}
public List<WorkflowStepState> getSteps() {
return steps;
}
public void setSteps(List<WorkflowStepState> steps) {
this.steps = steps;
}
}

View file

@ -0,0 +1,25 @@
package org.rundeck.api.domain;
/**
* A state for a particular step
*/
public class WorkflowStepContextState extends BaseState {
private String stepContextId;
private String stepNum;
public String getStepContextId() {
return stepContextId;
}
public void setStepContextId(String stepContextId) {
this.stepContextId = stepContextId;
}
public String getStepNum() {
return stepNum;
}
public void setStepNum(String stepNum) {
this.stepNum = stepNum;
}
}

View file

@ -0,0 +1,37 @@
package org.rundeck.api.domain;
import java.util.List;
import java.util.Map;
/**
* $INTERFACE is ... User: greg Date: 1/17/14 Time: 12:03 PM
*/
public class WorkflowStepState extends WorkflowStepContextState {
private boolean nodeStep;
private WorkflowState subWorkflow;
private Map<String, WorkflowStepContextState> nodeStates;
public boolean isNodeStep() {
return nodeStep;
}
public void setNodeStep(boolean nodeStep) {
this.nodeStep = nodeStep;
}
public WorkflowState getSubWorkflow() {
return subWorkflow;
}
public void setSubWorkflow(WorkflowState subWorkflow) {
this.subWorkflow = subWorkflow;
}
public Map<String, WorkflowStepContextState> getNodeStates() {
return nodeStates;
}
public void setNodeStates(Map<String, WorkflowStepContextState> nodeStates) {
this.nodeStates = nodeStates;
}
}

View file

@ -0,0 +1,42 @@
package org.rundeck.api.parser;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Node;
import org.rundeck.api.domain.BaseState;
import org.rundeck.api.domain.RundeckWFExecState;
/**
* $INTERFACE is ... User: greg Date: 1/17/14 Time: 12:19 PM
*/
public class BaseStateParser implements XmlNodeParser<BaseState> {
public static void parseBaseState(Node targetNode, BaseState state) {
state.setEndTime(WorkflowStateParser.parseDate(StringUtils.trimToNull(targetNode.valueOf("endTime"))));
state.setStartTime(WorkflowStateParser.parseDate(StringUtils.trimToNull(targetNode.valueOf("startTime"))));
state.setUpdateTime(WorkflowStateParser.parseDate(StringUtils.trimToNull(targetNode.valueOf("updateTime"))));
try {
state.setExecutionState(RundeckWFExecState.valueOf(StringUtils.upperCase(targetNode.valueOf
("executionState"))));
} catch (IllegalArgumentException e) {
state.setExecutionState(null);
}
}
private String xpath;
public BaseStateParser() {
}
public BaseStateParser(String xpath) {
this.xpath = xpath;
}
@Override
public BaseState parseXmlNode(Node node) {
Node targetNode = xpath != null ? node.selectSingleNode(xpath) : node;
BaseState baseState = new BaseState();
parseBaseState(targetNode, baseState);
return baseState;
}
}

View file

@ -0,0 +1,60 @@
package org.rundeck.api.parser;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Node;
import org.rundeck.api.domain.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
/**
* $INTERFACE is ... User: greg Date: 1/16/14 Time: 5:42 PM
*/
public class ExecutionStateParser implements XmlNodeParser<RundeckExecutionState> {
private String xpath;
public ExecutionStateParser() {
super();
}
/**
* @param xpath of the execution element if it is not the root node
*/
public ExecutionStateParser(String xpath) {
this();
this.xpath = xpath;
}
@Override
public RundeckExecutionState parseXmlNode(Node node) {
Node targetNode = xpath != null ? node.selectSingleNode(xpath) : node;
RundeckExecutionState rundeckExecutionState = new RundeckExecutionState();
rundeckExecutionState.setExecutionId(Long.valueOf(targetNode.valueOf("@id")));
WorkflowStateParser.parseWorkflowState(targetNode, rundeckExecutionState);
final List<RundeckNode> rundeckNodes =
new ListParser<RundeckNode>(new NodeParser(), "allNodes/nodes/node").parseXmlNode(targetNode);
rundeckExecutionState.setAllNodes(new HashSet<RundeckNodeIdentity>(rundeckNodes));
//node states
HashMap<String, List<WorkflowStepContextState>> nodeStates = new HashMap<String, List<WorkflowStepContextState>>();
for (Object o : targetNode.selectNodes("nodes/node")) {
final Node nodeStateNode = (Node) o;
final String nodeName = StringUtils.trimToNull(nodeStateNode.valueOf("@name"));
if (null != nodeName) {
ListParser<WorkflowStepContextState> workflowStepStateListParser
= new ListParser<WorkflowStepContextState>(new IndexedWorkflowStepStateParser(rundeckExecutionState, nodeName)
, "steps/step");
nodeStates.put(nodeName, workflowStepStateListParser.parseXmlNode(nodeStateNode));
}
}
rundeckExecutionState.setNodeStates(nodeStates);
return rundeckExecutionState;
}
}

View file

@ -0,0 +1,61 @@
package org.rundeck.api.parser;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Node;
import org.rundeck.api.domain.WorkflowState;
import org.rundeck.api.domain.WorkflowStepContextState;
import org.rundeck.api.domain.WorkflowStepState;
/**
* Returns a WorkflowStepContextState by looking up the given Rundeck node's state in the workflow, using the step
* context path of the "stepctx" element of the selected DOM node.
*/
public class IndexedWorkflowStepStateParser implements XmlNodeParser<WorkflowStepContextState> {
private final WorkflowState workflowState;
private String rundeckNodeName;
@Override
public WorkflowStepContextState parseXmlNode(final Node node) {
//look for workflow step state based on node name and stepctx found on the node
final String stepctx = StringUtils.trimToNull(node.valueOf("stepctx"));
final WorkflowStepState foundStep = lookupContext(stepctx, workflowState);
//look up node state for this node
if (null != foundStep
&& null != foundStep.getNodeStates()
&& null != foundStep.getNodeStates().get(rundeckNodeName)) {
return foundStep.getNodeStates().get(rundeckNodeName);
}
return null;
}
/**
* look up the workflow step state for the step context, from the root workflow
*
* @param stepctx
* @param initial
*
* @return
*/
public static WorkflowStepState lookupContext(final String stepctx, final WorkflowState initial) {
final String[] parts = stepctx.split("/");
//descend workflow steps to find correct step
WorkflowState current = initial;
WorkflowStepState currentStep = null;
for (int i = 0; i < parts.length; i++) {
final String part = parts[i];
final WorkflowStepState workflowStepState = current.getSteps().get(Integer.parseInt(part) - 1);
currentStep = workflowStepState;
if (i < parts.length - 1) {
current = currentStep.getSubWorkflow();
}
}
return currentStep;
}
public IndexedWorkflowStepStateParser(final WorkflowState workflowState, final String rundeckNodeName) {
this.workflowState = workflowState;
this.rundeckNodeName = rundeckNodeName;
}
}

View file

@ -0,0 +1,83 @@
package org.rundeck.api.parser;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Node;
import org.rundeck.api.domain.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* $INTERFACE is ... User: greg Date: 1/16/14 Time: 5:44 PM
*/
public class WorkflowStateParser implements XmlNodeParser<WorkflowState> {
private String xpath;
public WorkflowStateParser() {
}
public WorkflowStateParser(String xpath) {
this();
this.xpath = xpath;
}
private static final ThreadLocal<DateFormat> w3cDateFormat = new ThreadLocal<DateFormat>() {
protected DateFormat initialValue() {
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
return fmt;
}
};
public static Date parseDate(String s) {
if (null == s) {
return null;
}
try {
Date parse = w3cDateFormat.get().parse(s);
return parse;
} catch (ParseException e) {
return null;
}
}
private static int integerValue(final String value, final int defValue) {
int parseMax = defValue;
try {
parseMax = null != value ? Integer.parseInt(value) : defValue;
} catch (NumberFormatException e) {
}
return parseMax;
}
@Override
public WorkflowState parseXmlNode(Node node) {
Node targetNode = xpath != null ? node.selectSingleNode(xpath) : node;
WorkflowState state = new WorkflowState();
parseWorkflowState(targetNode, state);
return state;
}
/**
* Parse the workflow state components from the given dom node
* @param targetNode
* @param state
*/
public static void parseWorkflowState(Node targetNode, WorkflowState state) {
BaseStateParser.parseBaseState(targetNode, state);
state.setStepCount(integerValue(StringUtils.trimToNull(targetNode.valueOf("stepCount")), 0));
final List<RundeckNode> rundeckNodes =
new ListParser<RundeckNode>(new NodeParser(), "targetNodes/nodes/node").parseXmlNode(targetNode);
state.setTargetNodes(new HashSet<RundeckNodeIdentity>(rundeckNodes));
//steps
state.setSteps(new ListParser<WorkflowStepState>(new WorkflowStepStateParser(),
"steps/step").parseXmlNode(targetNode));
}
}

View file

@ -0,0 +1,27 @@
package org.rundeck.api.parser;
import org.dom4j.Node;
import org.rundeck.api.domain.WorkflowStepContextState;
import org.rundeck.api.domain.WorkflowStepState;
/**
* $INTERFACE is ... User: greg Date: 1/17/14 Time: 12:39 PM
*/
public class WorkflowStepContextStateParser implements XmlNodeParser<WorkflowStepContextState> {
WorkflowStepContextState inherit;
public WorkflowStepContextStateParser(WorkflowStepContextState inherit) {
this.inherit = inherit;
}
@Override
public WorkflowStepContextState parseXmlNode(Node node) {
WorkflowStepContextState workflowStepState = new WorkflowStepContextState();
if(null!=inherit) {
workflowStepState.setStepNum(inherit.getStepNum());
workflowStepState.setStepContextId(inherit.getStepContextId());
}
BaseStateParser.parseBaseState(node, workflowStepState);
return workflowStepState;
}
}

View file

@ -0,0 +1,51 @@
package org.rundeck.api.parser;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Node;
import org.rundeck.api.domain.BaseState;
import org.rundeck.api.domain.WorkflowStepContextState;
import org.rundeck.api.domain.WorkflowStepState;
import java.util.HashMap;
/**
* $INTERFACE is ... User: greg Date: 1/17/14 Time: 12:09 PM
*/
public class WorkflowStepStateParser implements XmlNodeParser<WorkflowStepState> {
private String xpath;
public WorkflowStepStateParser(final String xpath) {
this.xpath = xpath;
}
public WorkflowStepStateParser() {
}
@Override
public WorkflowStepState parseXmlNode(final Node node) {
final Node targetNode = xpath != null ? node.selectSingleNode(xpath) : node;
final WorkflowStepState state = new WorkflowStepState();
BaseStateParser.parseBaseState(targetNode, state);
state.setStepContextId(StringUtils.trimToNull(targetNode.valueOf("@stepctx")));
state.setStepNum(StringUtils.trimToNull(targetNode.valueOf("@id")));
state.setNodeStep(Boolean.valueOf(StringUtils.trimToNull(targetNode.valueOf("nodeStep"))));
if (Boolean.valueOf(StringUtils.trimToNull(targetNode.valueOf("hasSubworkflow")))) {
//parse sub workflow
state.setSubWorkflow(new WorkflowStateParser("workflow").parseXmlNode(targetNode));
}
if (Boolean.valueOf(StringUtils.trimToNull(targetNode.valueOf("nodeStep")))) {
//node states
final HashMap<String, WorkflowStepContextState> nodeStates = new HashMap<String, WorkflowStepContextState>();
for (final Object o : targetNode.selectNodes("nodeStates/nodeState")) {
final Node nodeStateNode = (Node) o;
final String nodeName = StringUtils.trimToNull(nodeStateNode.valueOf("@name"));
if (null != nodeName) {
nodeStates.put(nodeName, new WorkflowStepContextStateParser(state).parseXmlNode(nodeStateNode));
}
}
state.setNodeStates(nodeStates);
}
return state;
}
}

View file

@ -0,0 +1,40 @@
package org.rundeck.api.parser;
import junit.framework.Assert;
import org.dom4j.Document;
import org.junit.Test;
import org.rundeck.api.domain.BaseState;
import org.rundeck.api.domain.RundeckWFExecState;
import java.io.InputStream;
import java.util.Date;
/**
* $INTERFACE is ... User: greg Date: 1/18/14 Time: 8:33 AM
*/
public class BaseStateParserTest {
@Test
public void testBase1(){
InputStream input = getClass().getResourceAsStream("execution-state1.xml");
Document document = ParserHelper.loadDocument(input);
BaseState baseState = new BaseState();
BaseStateParser.parseBaseState(document.selectSingleNode("/result/executionState"), baseState);
Assert.assertEquals(1390066160000L, baseState.getEndTime().getTime());
Assert.assertEquals(1390066159000L, baseState.getStartTime().getTime());
Assert.assertEquals(1390066160000L, baseState.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.SUCCEEDED, baseState.getExecutionState());
}
@Test
public void testBase2(){
InputStream input = getClass().getResourceAsStream("execution-state1.xml");
Document document = ParserHelper.loadDocument(input);
BaseState baseState = new BaseState();
BaseStateParser.parseBaseState(document.selectSingleNode("/result/executionState/steps/step[1]"), baseState);
Assert.assertEquals(1390066159000L, baseState.getStartTime().getTime());
Assert.assertEquals(1390066160000L, baseState.getEndTime().getTime());
Assert.assertEquals(1390066160000L, baseState.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.SUCCEEDED, baseState.getExecutionState());
}
}

View file

@ -0,0 +1,43 @@
package org.rundeck.api.parser;
import junit.framework.Assert;
import org.dom4j.Document;
import org.junit.Test;
import org.rundeck.api.domain.RundeckExecutionState;
import org.rundeck.api.domain.RundeckNodeIdentity;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
/**
* $INTERFACE is ... User: greg Date: 1/16/14 Time: 5:42 PM
*/
public class ExecutionStateParserTest {
@Test
public void testBasic(){
InputStream input = getClass().getResourceAsStream("execution-state1.xml");
Document document = ParserHelper.loadDocument(input);
RundeckExecutionState execution = new ExecutionStateParser("/result/executionState").parseXmlNode
(document);
Assert.assertEquals(149L, execution.getExecutionId());
HashSet<String> expectedTargetNodes = new HashSet<String>(Arrays.asList(
"node-111.qa.subgroup.mycompany.com",
"node-14.qa.subgroup.mycompany.com",
"node-6.qa.subgroup.mycompany.com"
));
Assert.assertEquals(3, execution.getAllNodes().size());
for (RundeckNodeIdentity rundeckNodeIdentity : execution.getAllNodes()) {
Assert.assertTrue(expectedTargetNodes.contains(rundeckNodeIdentity.getName()));
}
Assert.assertEquals(3,execution.getNodeStates().size());
for (String s : execution.getNodeStates().keySet()) {
Assert.assertTrue(expectedTargetNodes.contains(s));
}
}
}

View file

@ -0,0 +1,73 @@
package org.rundeck.api.parser;
import junit.framework.Assert;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.junit.Test;
import org.rundeck.api.domain.WorkflowState;
import org.rundeck.api.domain.WorkflowStepContextState;
import org.rundeck.api.domain.WorkflowStepState;
import java.util.Arrays;
import java.util.HashMap;
/**
* $INTERFACE is ... User: greg Date: 1/18/14 Time: 9:57 AM
*/
public class IndexedWorkflowStepStateParserTest {
@Test
public void testLookupContextSimple1(){
WorkflowState workflowState = new WorkflowState();
WorkflowStepState step1 = new WorkflowStepState();
workflowState.setSteps(Arrays.asList(step1));
WorkflowStepState stepState = IndexedWorkflowStepStateParser.lookupContext("1", workflowState);
Assert.assertEquals(step1,stepState);
}
@Test
public void testLookupContextSimple2(){
WorkflowState workflowState = new WorkflowState();
WorkflowStepState step1 = new WorkflowStepState();
WorkflowStepState step2 = new WorkflowStepState();
workflowState.setSteps(Arrays.asList(step1,step2));
WorkflowStepState stepState = IndexedWorkflowStepStateParser.lookupContext("2", workflowState);
Assert.assertEquals(step2,stepState);
}
@Test
public void testLookupContextDescend1(){
WorkflowState workflowState = new WorkflowState();
WorkflowStepState step1 = new WorkflowStepState();
WorkflowStepState step2 = new WorkflowStepState();
WorkflowState sub1 = new WorkflowState();
step2.setSubWorkflow(sub1);
workflowState.setSteps(Arrays.asList(step1,step2));
WorkflowStepState step21 = new WorkflowStepState();
sub1.setSteps(Arrays.asList(step21));
WorkflowStepState stepState = IndexedWorkflowStepStateParser.lookupContext("2/1", workflowState);
Assert.assertEquals(step21,stepState);
}
@Test
public void testParse1() throws DocumentException {
WorkflowState workflowState = new WorkflowState();
WorkflowStepState step1 = new WorkflowStepState();
WorkflowStepState step2 = new WorkflowStepState();
WorkflowState sub1 = new WorkflowState();
step2.setSubWorkflow(sub1);
workflowState.setSteps(Arrays.asList(step1,step2));
WorkflowStepState step21 = new WorkflowStepState();
sub1.setSteps(Arrays.asList(step21));
HashMap<String, WorkflowStepContextState> nodeStates = new HashMap<String, WorkflowStepContextState>();
WorkflowStepContextState nodeState1 = new WorkflowStepContextState();
nodeStates.put("dignan", nodeState1);
step21.setNodeStates(nodeStates);
Document document = DocumentHelper.parseText("<stepctx>2/1</stepctx>");
WorkflowStepContextState result = new IndexedWorkflowStepStateParser(workflowState,"dignan").parseXmlNode(document);
Assert.assertEquals(nodeState1,result);
}
}

View file

@ -0,0 +1,65 @@
package org.rundeck.api.parser;
import junit.framework.Assert;
import org.dom4j.Document;
import org.junit.Test;
import org.rundeck.api.domain.*;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
/**
* $INTERFACE is ... User: greg Date: 1/16/14 Time: 5:47 PM
*/
public class WorkflowStateParserTest {
@Test
public void parseBasic(){
InputStream input = getClass().getResourceAsStream("execution-state1.xml");
Document document = ParserHelper.loadDocument(input);
WorkflowState execution = new WorkflowStateParser("result/executionState").parseXmlNode(document);
Assert.assertEquals(1390066159000L, execution.getStartTime().getTime());
Assert.assertEquals(1390066160000L, execution.getEndTime().getTime());
Assert.assertEquals(1390066160000L, execution.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.SUCCEEDED, execution.getExecutionState());
Assert.assertEquals(1, execution.getStepCount());
Assert.assertEquals(3, execution.getTargetNodes().size());
HashSet<String> expectedTargetNodes = new HashSet<String>(Arrays.asList(
"node-111.qa.subgroup.mycompany.com",
"node-14.qa.subgroup.mycompany.com",
"node-6.qa.subgroup.mycompany.com"
));
for (RundeckNodeIdentity rundeckNodeIdentity : execution.getTargetNodes()) {
Assert.assertTrue(expectedTargetNodes.contains(rundeckNodeIdentity.getName()));
}
//
Assert.assertEquals(1,execution.getSteps().size());
WorkflowStepState step1 = execution.getSteps().get(0);
}
@Test
public void parse(){
InputStream input = getClass().getResourceAsStream("execution-state2.xml");
Document document = ParserHelper.loadDocument(input);
WorkflowState execution = new WorkflowStateParser("result/executionState").parseXmlNode(document);
Assert.assertEquals(1390066061000L, execution.getStartTime().getTime());
Assert.assertEquals(null, execution.getEndTime());
Assert.assertEquals(1390066067000L, execution.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.RUNNING, execution.getExecutionState());
Assert.assertEquals(2, execution.getStepCount());
Assert.assertEquals(1, execution.getTargetNodes().size());
HashSet<String> expectedTargetNodes = new HashSet<String>(Arrays.asList(
"dignan"
));
for (RundeckNodeIdentity rundeckNodeIdentity : execution.getTargetNodes()) {
Assert.assertTrue(expectedTargetNodes.contains(rundeckNodeIdentity.getName()));
}
//
Assert.assertEquals(2,execution.getSteps().size());
WorkflowStepState step1 = execution.getSteps().get(0);
}
}

View file

@ -0,0 +1,122 @@
package org.rundeck.api.parser;
import junit.framework.Assert;
import org.dom4j.Document;
import org.junit.Test;
import org.rundeck.api.domain.*;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
/**
* $INTERFACE is ... User: greg Date: 1/18/14 Time: 9:00 AM
*/
public class WorkflowStepStateParserTest {
@Test
public void testParse1() {
InputStream input = getClass().getResourceAsStream("execution-state1.xml");
Document document = ParserHelper.loadDocument(input);
WorkflowStepState stepState = new WorkflowStepStateParser().parseXmlNode(document.selectSingleNode
("/result/executionState/steps/step[1]"));
Assert.assertNotNull(stepState);
Assert.assertEquals(true, stepState.isNodeStep());
Assert.assertEquals(null, stepState.getSubWorkflow());
Assert.assertNotNull(stepState.getNodeStates());
Assert.assertEquals("1", stepState.getStepContextId());
Assert.assertEquals("1", stepState.getStepNum());
Assert.assertEquals(1390066159000L, stepState.getStartTime().getTime());
Assert.assertEquals(1390066160000L, stepState.getEndTime().getTime());
Assert.assertEquals(1390066160000L, stepState.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.SUCCEEDED, stepState.getExecutionState());
HashSet<String> expectedTargetNodes = new HashSet<String>(Arrays.asList(
"node-111.qa.subgroup.mycompany.com",
"node-14.qa.subgroup.mycompany.com",
"node-6.qa.subgroup.mycompany.com"
));
int i = 0;
for (String s : stepState.getNodeStates().keySet()) {
Assert.assertTrue(expectedTargetNodes.contains(s));
WorkflowStepContextState workflowStepContextState = stepState.getNodeStates().get(s);
Assert.assertEquals("1", workflowStepContextState.getStepContextId());
Assert.assertEquals("1", workflowStepContextState.getStepNum());
Assert.assertEquals(1390066159000L + (i * 1000), workflowStepContextState.getStartTime().getTime());
Assert.assertEquals(1390066159000L + (i * 1000), workflowStepContextState.getEndTime().getTime());
Assert.assertEquals(1390066159000L + (i * 1000), workflowStepContextState.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.SUCCEEDED, workflowStepContextState.getExecutionState());
i++;
}
}
@Test
public void testParseRunning1() {
InputStream input = getClass().getResourceAsStream("execution-state2.xml");
Document document = ParserHelper.loadDocument(input);
WorkflowStepState stepState = new WorkflowStepStateParser().parseXmlNode(document.selectSingleNode
("/result/executionState/steps/step[1]"));
Assert.assertNotNull(stepState);
Assert.assertEquals(true, stepState.isNodeStep());
Assert.assertEquals(null, stepState.getSubWorkflow());
Assert.assertEquals("1", stepState.getStepContextId());
Assert.assertEquals("1", stepState.getStepNum());
Assert.assertNotNull(stepState.getNodeStates());
Assert.assertEquals(1390066061000L, stepState.getStartTime().getTime());
Assert.assertEquals(1390066066000L, stepState.getEndTime().getTime());
Assert.assertEquals(1390066061000L, stepState.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.SUCCEEDED, stepState.getExecutionState());
HashSet<String> expectedTargetNodes = new HashSet<String>(Arrays.asList(
"dignan"
));
WorkflowStepContextState workflowStepContextState = stepState.getNodeStates().get("dignan");
Assert.assertEquals("1", workflowStepContextState.getStepContextId());
Assert.assertEquals("1", workflowStepContextState.getStepNum());
Assert.assertEquals(1390066061000L, workflowStepContextState.getStartTime().getTime());
Assert.assertEquals(1390066066000L, workflowStepContextState.getEndTime().getTime());
Assert.assertEquals(1390066066000L, workflowStepContextState.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.SUCCEEDED, workflowStepContextState.getExecutionState());
}
@Test
public void testParseRunning2() {
InputStream input = getClass().getResourceAsStream("execution-state2.xml");
Document document = ParserHelper.loadDocument(input);
WorkflowStepState stepState = new WorkflowStepStateParser().parseXmlNode(document.selectSingleNode
("/result/executionState/steps/step[2]"));
Assert.assertNotNull(stepState);
Assert.assertEquals(false, stepState.isNodeStep());
Assert.assertNotNull(stepState.getSubWorkflow());
Assert.assertNull(stepState.getNodeStates());
Assert.assertEquals("2", stepState.getStepContextId());
Assert.assertEquals("2",stepState.getStepNum());
Assert.assertEquals(1390066066000L, stepState.getStartTime().getTime());
Assert.assertNull(stepState.getEndTime());
Assert.assertEquals(1390066066000L, stepState.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.RUNNING, stepState.getExecutionState());
//sub workflow
WorkflowState subWorkflow = stepState.getSubWorkflow();
Assert.assertEquals(1,subWorkflow.getSteps().size());
Assert.assertEquals(1,subWorkflow.getTargetNodes().size());
WorkflowStepState stepState1 = subWorkflow.getSteps().get(0);
Assert.assertEquals(true, stepState1.isNodeStep());
Assert.assertNull(stepState1.getSubWorkflow());
Assert.assertNotNull(stepState1.getNodeStates());
Assert.assertEquals("2/1", stepState1.getStepContextId());
Assert.assertEquals("1", stepState1.getStepNum());
Assert.assertEquals(1390066067000L, stepState1.getStartTime().getTime());
Assert.assertNull(stepState1.getEndTime());
Assert.assertEquals(1390066067000L, stepState1.getUpdateTime().getTime());
Assert.assertEquals(RundeckWFExecState.RUNNING, stepState1.getExecutionState());
}
}

View file

@ -0,0 +1,81 @@
<result success="true" apiversion="10">
<executionState id="149">
<executionId>149</executionId>
<serverNode>dignan</serverNode>
<executionState>SUCCEEDED</executionState>
<completed>true</completed>
<targetNodes>
<nodes>
<node name="node-111.qa.subgroup.mycompany.com"/>
<node name="node-14.qa.subgroup.mycompany.com"/>
<node name="node-6.qa.subgroup.mycompany.com"/>
</nodes>
</targetNodes>
<allNodes>
<nodes>
<node name="node-111.qa.subgroup.mycompany.com"/>
<node name="node-14.qa.subgroup.mycompany.com"/>
<node name="node-6.qa.subgroup.mycompany.com"/>
</nodes>
</allNodes>
<stepCount>1</stepCount>
<updateTime>2014-01-18T17:29:20Z</updateTime>
<startTime>2014-01-18T17:29:19Z</startTime>
<endTime>2014-01-18T17:29:20Z</endTime>
<steps>
<step stepctx="1" id="1">
<nodeStep>true</nodeStep>
<executionState>SUCCEEDED</executionState>
<startTime>2014-01-18T17:29:19Z</startTime>
<updateTime>2014-01-18T17:29:20Z</updateTime>
<endTime>2014-01-18T17:29:20Z</endTime>
<nodeStates>
<nodeState name="node-111.qa.subgroup.mycompany.com">
<executionState>SUCCEEDED</executionState>
<startTime>2014-01-18T17:29:19Z</startTime>
<updateTime>2014-01-18T17:29:19Z</updateTime>
<endTime>2014-01-18T17:29:19Z</endTime>
</nodeState>
<nodeState name="node-6.qa.subgroup.mycompany.com">
<executionState>SUCCEEDED</executionState>
<startTime>2014-01-18T17:29:20Z</startTime>
<updateTime>2014-01-18T17:29:20Z</updateTime>
<endTime>2014-01-18T17:29:20Z</endTime>
</nodeState>
<nodeState name="node-14.qa.subgroup.mycompany.com">
<executionState>SUCCEEDED</executionState>
<startTime>2014-01-18T17:29:21Z</startTime>
<updateTime>2014-01-18T17:29:21Z</updateTime>
<endTime>2014-01-18T17:29:21Z</endTime>
</nodeState>
</nodeStates>
</step>
</steps>
<nodes>
<node name="node-111.qa.subgroup.mycompany.com">
<steps>
<step>
<stepctx>1</stepctx>
<executionState>SUCCEEDED</executionState>
</step>
</steps>
</node>
<node name="node-6.qa.subgroup.mycompany.com">
<steps>
<step>
<stepctx>1</stepctx>
<executionState>SUCCEEDED</executionState>
</step>
</steps>
</node>
<node name="node-14.qa.subgroup.mycompany.com">
<steps>
<step>
<stepctx>1</stepctx>
<executionState>SUCCEEDED</executionState>
</step>
</steps>
</node>
</nodes>
</executionState>
</result>

View file

@ -0,0 +1,96 @@
<result success="true" apiversion="10">
<executionState id="148">
<executionId>148</executionId>
<serverNode>dignan</serverNode>
<executionState>RUNNING</executionState>
<completed>false</completed>
<targetNodes>
<nodes>
<node name="dignan"/>
</nodes>
</targetNodes>
<allNodes>
<nodes>
<node name="dignan"/>
</nodes>
</allNodes>
<stepCount>2</stepCount>
<updateTime>2014-01-18T17:27:47Z</updateTime>
<startTime>2014-01-18T17:27:41Z</startTime>
<endTime/>
<steps>
<step stepctx="1" id="1">
<nodeStep>true</nodeStep>
<executionState>SUCCEEDED</executionState>
<startTime>2014-01-18T17:27:41Z</startTime>
<updateTime>2014-01-18T17:27:41Z</updateTime>
<endTime>2014-01-18T17:27:46Z</endTime>
<nodeStates>
<nodeState name="dignan">
<executionState>SUCCEEDED</executionState>
<startTime>2014-01-18T17:27:41Z</startTime>
<updateTime>2014-01-18T17:27:46Z</updateTime>
<endTime>2014-01-18T17:27:46Z</endTime>
</nodeState>
</nodeStates>
</step>
<step stepctx="2" id="2">
<hasSubworkflow>true</hasSubworkflow>
<workflow>
<executionState>RUNNING</executionState>
<completed>false</completed>
<targetNodes>
<nodes>
<node name="dignan"/>
</nodes>
</targetNodes>
<allNodes>
<nodes>
<node name="dignan"/>
</nodes>
</allNodes>
<stepCount>1</stepCount>
<updateTime>2014-01-18T17:27:47Z</updateTime>
<startTime>2014-01-18T17:27:47Z</startTime>
<endTime/>
<steps>
<step stepctx="2/1" id="1">
<nodeStep>true</nodeStep>
<executionState>RUNNING</executionState>
<startTime>2014-01-18T17:27:47Z</startTime>
<updateTime>2014-01-18T17:27:47Z</updateTime>
<endTime/>
<nodeStates>
<nodeState name="dignan">
<executionState>RUNNING</executionState>
<startTime>2014-01-18T17:27:47Z</startTime>
<updateTime>2014-01-18T17:27:47Z</updateTime>
<endTime/>
</nodeState>
</nodeStates>
</step>
</steps>
</workflow>
<nodeStep>false</nodeStep>
<executionState>RUNNING</executionState>
<startTime>2014-01-18T17:27:46Z</startTime>
<updateTime>2014-01-18T17:27:46Z</updateTime>
<endTime/>
</step>
</steps>
<nodes>
<node name="dignan">
<steps>
<step>
<stepctx>1</stepctx>
<executionState>SUCCEEDED</executionState>
</step>
<step>
<stepctx>2/1</stepctx>
<executionState>RUNNING</executionState>
</step>
</steps>
</node>
</nodes>
</executionState>
</result>