Repository: oozie
Updated Branches:
  refs/heads/master 4c28591b7 -> dc22c9022


OOZIE-1746 New API to fetch workflows corresponding to coordinator action 
reruns (mona)


Project: http://git-wip-us.apache.org/repos/asf/oozie/repo
Commit: http://git-wip-us.apache.org/repos/asf/oozie/commit/dc22c902
Tree: http://git-wip-us.apache.org/repos/asf/oozie/tree/dc22c902
Diff: http://git-wip-us.apache.org/repos/asf/oozie/diff/dc22c902

Branch: refs/heads/master
Commit: dc22c902250e1498f58710d4d516710e1f5f918d
Parents: 4c28591
Author: Mona Chitnis <[email protected]>
Authored: Wed Mar 26 08:23:35 2014 -0700
Committer: Mona Chitnis <[email protected]>
Committed: Wed Mar 26 08:23:35 2014 -0700

----------------------------------------------------------------------
 .../java/org/apache/oozie/cli/OozieCLI.java     | 33 +++++++-
 .../org/apache/oozie/client/OozieClient.java    | 31 +++++++-
 .../apache/oozie/client/rest/RestConstants.java |  2 +
 .../org/apache/oozie/CoordinatorEngine.java     | 15 ++++
 .../java/org/apache/oozie/WorkflowJobBean.java  |  6 +-
 .../executor/jpa/WorkflowJobQueryExecutor.java  | 15 +++-
 .../apache/oozie/servlet/BaseJobServlet.java    | 19 ++++-
 .../org/apache/oozie/servlet/V0JobServlet.java  |  6 ++
 .../org/apache/oozie/servlet/V1JobServlet.java  | 43 +++++++++-
 .../org/apache/oozie/servlet/V2JobServlet.java  |  7 ++
 .../jpa/TestWorkflowJobQueryExecutor.java       | 22 +++++-
 .../apache/oozie/servlet/TestV2JobServlet.java  | 29 +++++++
 docs/src/site/twiki/DG_CommandLineTool.twiki    | 27 ++++++-
 docs/src/site/twiki/WebServicesAPI.twiki        | 48 ++++++++++++
 release-log.txt                                 |  1 +
 webapp/src/main/webapp/oozie-console.css        |  3 +
 webapp/src/main/webapp/oozie-console.js         | 82 +++++++++++++++++++-
 17 files changed, 376 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/client/src/main/java/org/apache/oozie/cli/OozieCLI.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/oozie/cli/OozieCLI.java 
b/client/src/main/java/org/apache/oozie/cli/OozieCLI.java
index a6203c6..6dc4a3b 100644
--- a/client/src/main/java/org/apache/oozie/cli/OozieCLI.java
+++ b/client/src/main/java/org/apache/oozie/cli/OozieCLI.java
@@ -152,6 +152,8 @@ public class OozieCLI {
 
     public static final String AVAILABLE_SERVERS_OPTION = "servers";
 
+    public static final String ALL_WORKFLOWS_FOR_COORD_ACTION = "allruns";
+
     private static final String[] OOZIE_HELP = {
             "the env variable '" + ENV_OOZIE_URL + "' is used as default value 
for the '-" + OOZIE_OPTION + "' option",
             "the env variable '" + ENV_OOZIE_TIME_ZONE + "' is used as default 
value for the '-" + TIME_ZONE_OPTION + "' option",
@@ -303,6 +305,8 @@ public class OozieCLI {
                 "do not clean up output-events of the coordiantor rerun 
actions (requires -rerun)");
         Option property = 
OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription(
                 "set/override value for given property").create("D");
+        Option getAllWorkflows = new Option(ALL_WORKFLOWS_FOR_COORD_ACTION, 
false,
+                "Get workflow jobs corresponding to a coordinator action 
including all the reruns");
 
         Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates 
as the specified user");
 
@@ -339,6 +343,7 @@ public class OozieCLI {
         jobOptions.addOption(rerun_coord);
         jobOptions.addOption(rerun_refresh);
         jobOptions.addOption(rerun_nocleanup);
+        jobOptions.addOption(getAllWorkflows);
         jobOptions.addOptionGroup(actions);
         addAuthOptions(jobOptions);
         return jobOptions;
@@ -968,11 +973,16 @@ public class OozieCLI {
                             options.contains(VERBOSE_OPTION));
                 }
                 else if (optionValue.contains("-C@")) {
-                    String filter = commandLine.getOptionValue(FILTER_OPTION);
-                    if (filter != null) {
-                        throw new OozieCLIException("Filter option is not 
supported for a Coordinator action");
+                    if (options.contains(ALL_WORKFLOWS_FOR_COORD_ACTION)) {
+                        
printWfsForCoordAction(wc.getWfsForCoordAction(optionValue), timeZoneId);
+                    }
+                    else {
+                        String filter = 
commandLine.getOptionValue(FILTER_OPTION);
+                        if (filter != null) {
+                            throw new OozieCLIException("Filter option is not 
supported for a Coordinator action");
+                        }
+                        printCoordAction(wc.getCoordActionInfo(optionValue), 
timeZoneId);
                     }
-                    printCoordAction(wc.getCoordActionInfo(optionValue), 
timeZoneId);
                 }
                 else if (optionValue.contains("-W@")) {
                     String filter = commandLine.getOptionValue(FILTER_OPTION);
@@ -1582,6 +1592,21 @@ public class OozieCLI {
         }
     }
 
+    void printWfsForCoordAction(List<WorkflowJob> jobs, String timeZoneId) 
throws IOException {
+        if (jobs != null && jobs.size() > 0) {
+            System.out.println(String.format("%-41s%-10s%-24s%-24s", "Job ID", 
"Status", "Started", "Ended"));
+            System.out.println(RULER);
+
+            for (WorkflowJob job : jobs) {
+                System.out
+                        .println(String.format("%-41s%-10s%-24s%-24s", 
maskIfNull(job.getId()), job.getStatus(),
+                                maskDate(job.getStartTime(), timeZoneId, 
false),
+                                maskDate(job.getEndTime(), timeZoneId, 
false)));
+                System.out.println(RULER);
+            }
+        }
+    }
+
     private String maskIfNull(String value) {
         if (value != null && value.length() > 0) {
             return value;

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/client/src/main/java/org/apache/oozie/client/OozieClient.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/oozie/client/OozieClient.java 
b/client/src/main/java/org/apache/oozie/client/OozieClient.java
index b0a85fd..6164447 100644
--- a/client/src/main/java/org/apache/oozie/client/OozieClient.java
+++ b/client/src/main/java/org/apache/oozie/client/OozieClient.java
@@ -741,7 +741,6 @@ public class OozieClient {
         }
     }
 
-
     private class JMSInfo extends ClientCallable<JMSConnectionInfo> {
 
         JMSInfo() {
@@ -1031,6 +1030,32 @@ public class OozieClient {
         }
     }
 
+    private class WfsForCoordAction extends ClientCallable<List<WorkflowJob>> {
+
+        WfsForCoordAction(String coordActionId) {
+            super("GET", RestConstants.JOB, notEmpty(coordActionId, 
"coordActionId"), prepareParams(
+                    RestConstants.JOB_SHOW_PARAM, 
RestConstants.ALL_WORKFLOWS_FOR_COORD_ACTION));
+        }
+
+        @Override
+        protected List<WorkflowJob> call(HttpURLConnection conn) throws 
IOException, OozieClientException {
+            if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
+                Reader reader = new InputStreamReader(conn.getInputStream());
+                JSONObject json = (JSONObject) JSONValue.parse(reader);
+                JSONArray workflows = (JSONArray) 
json.get(JsonTags.WORKFLOWS_JOBS);
+                if (workflows == null) {
+                    workflows = new JSONArray();
+                }
+                return JsonToBean.createWorkflowJobList(workflows);
+            }
+            else {
+                handleError(conn);
+            }
+            return null;
+        }
+    }
+
+
     private class BundleJobInfo extends ClientCallable<BundleJob> {
 
         BundleJobInfo(String jobId) {
@@ -1108,6 +1133,10 @@ public class OozieClient {
         return new CoordJobInfo(jobId, filter, start, len).call();
     }
 
+    public List<WorkflowJob> getWfsForCoordAction(String coordActionId) throws 
OozieClientException {
+        return new WfsForCoordAction(coordActionId).call();
+    }
+
     /**
      * Get the info of a coordinator action.
      *

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/client/src/main/java/org/apache/oozie/client/rest/RestConstants.java
----------------------------------------------------------------------
diff --git 
a/client/src/main/java/org/apache/oozie/client/rest/RestConstants.java 
b/client/src/main/java/org/apache/oozie/client/rest/RestConstants.java
index 0466ffe..a7fe06e 100644
--- a/client/src/main/java/org/apache/oozie/client/rest/RestConstants.java
+++ b/client/src/main/java/org/apache/oozie/client/rest/RestConstants.java
@@ -168,4 +168,6 @@ public interface RestConstants {
 
     public static final String ALL_SERVER_REQUEST = "allservers";
 
+    public static final String ALL_WORKFLOWS_FOR_COORD_ACTION = "allruns";
+
 }

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/CoordinatorEngine.java 
b/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
index 315a330..3f10024 100644
--- a/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
+++ b/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
@@ -50,6 +50,9 @@ import org.apache.oozie.command.coord.CoordRerunXCommand;
 import org.apache.oozie.command.coord.CoordResumeXCommand;
 import org.apache.oozie.command.coord.CoordSubmitXCommand;
 import org.apache.oozie.command.coord.CoordSuspendXCommand;
+import org.apache.oozie.executor.jpa.JPAExecutorException;
+import org.apache.oozie.executor.jpa.WorkflowJobQueryExecutor;
+import org.apache.oozie.executor.jpa.WorkflowJobQueryExecutor.WorkflowJobQuery;
 import org.apache.oozie.service.DagXLogInfoService;
 import org.apache.oozie.service.Services;
 import org.apache.oozie.service.XLogStreamingService;
@@ -682,4 +685,16 @@ public class CoordinatorEngine extends BaseEngine {
         }
         return map;
     }
+
+    public List<WorkflowJobBean> getReruns(String coordActionId) throws 
CoordinatorEngineException {
+        List<WorkflowJobBean> wfBeans;
+        try {
+            wfBeans = 
WorkflowJobQueryExecutor.getInstance().getList(WorkflowJobQuery.GET_WORKFLOWS_PARENT_COORD_RERUN,
+                    coordActionId);
+        }
+        catch (JPAExecutorException e) {
+            throw new CoordinatorEngineException(e);
+        }
+        return wfBeans;
+    }
 }

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/core/src/main/java/org/apache/oozie/WorkflowJobBean.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/WorkflowJobBean.java 
b/core/src/main/java/org/apache/oozie/WorkflowJobBean.java
index 3194995..8a731f4 100644
--- a/core/src/main/java/org/apache/oozie/WorkflowJobBean.java
+++ b/core/src/main/java/org/apache/oozie/WorkflowJobBean.java
@@ -124,8 +124,10 @@ import org.json.simple.JSONObject;
 
     @NamedQuery(name = "GET_WORKFLOW_FOR_USER", query = "select w.user from 
WorkflowJobBean w where w.id = :id"),
 
-    @NamedQuery(name = "GET_WORKFLOW_STATUS", query = "select w.statusStr from 
WorkflowJobBean w where w.id = :id")
-        })
+    @NamedQuery(name = "GET_WORKFLOW_STATUS", query = "select w.statusStr from 
WorkflowJobBean w where w.id = :id"),
+
+    @NamedQuery(name = "GET_WORKFLOWS_PARENT_COORD_RERUN", query = "select 
w.id, w.statusStr, w.startTimestamp, w.endTimestamp "
+            + "from WorkflowJobBean w where w.parentId = :parentId order by 
w.createdTimestamp")})
 @Table(name = "WF_JOBS")
 public class WorkflowJobBean implements Writable, WorkflowJob, JsonBean {
 

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowJobQueryExecutor.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowJobQueryExecutor.java
 
b/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowJobQueryExecutor.java
index e60e009..e7d42e9 100644
--- 
a/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowJobQueryExecutor.java
+++ 
b/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowJobQueryExecutor.java
@@ -20,6 +20,7 @@ package org.apache.oozie.executor.jpa;
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.List;
+
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
 
@@ -56,7 +57,8 @@ public class WorkflowJobQueryExecutor extends 
QueryExecutor<WorkflowJobBean, Wor
         GET_WORKFLOW_DEFINITION,
         GET_WORKFLOW_KILL,
         GET_WORKFLOW_RESUME,
-        GET_WORKFLOW_STATUS
+        GET_WORKFLOW_STATUS,
+        GET_WORKFLOWS_PARENT_COORD_RERUN
     };
 
     private static WorkflowJobQueryExecutor instance = new 
WorkflowJobQueryExecutor();
@@ -178,6 +180,9 @@ public class WorkflowJobQueryExecutor extends 
QueryExecutor<WorkflowJobBean, Wor
             case GET_WORKFLOW_STATUS:
                 query.setParameter("id", parameters[0]);
                 break;
+            case GET_WORKFLOWS_PARENT_COORD_RERUN:
+                query.setParameter("parentId", parameters[0]);
+                break;
             default:
                 throw new JPAExecutorException(ErrorCode.E0603, "QueryExecutor 
cannot set parameters for "
                         + namedQuery.name());
@@ -300,6 +305,14 @@ public class WorkflowJobQueryExecutor extends 
QueryExecutor<WorkflowJobBean, Wor
                 bean.setId((String) parameters[0]);
                 bean.setStatusStr((String) ret);
                 break;
+            case GET_WORKFLOWS_PARENT_COORD_RERUN:
+                bean = new WorkflowJobBean();
+                arr = (Object[]) ret;
+                bean.setId((String) arr[0]);
+                bean.setStatusStr((String) arr[1]);
+                bean.setStartTime(DateUtils.toDate((Timestamp) arr[2]));
+                bean.setEndTime(DateUtils.toDate((Timestamp) arr[3]));
+                break;
             default:
                 throw new JPAExecutorException(ErrorCode.E0603, "QueryExecutor 
cannot construct job bean for "
                         + namedQuery.name());

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/core/src/main/java/org/apache/oozie/servlet/BaseJobServlet.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/servlet/BaseJobServlet.java 
b/core/src/main/java/org/apache/oozie/servlet/BaseJobServlet.java
index 31e9d2f..aa43e68 100644
--- a/core/src/main/java/org/apache/oozie/servlet/BaseJobServlet.java
+++ b/core/src/main/java/org/apache/oozie/servlet/BaseJobServlet.java
@@ -242,7 +242,12 @@ public abstract class BaseJobServlet extends 
JsonRestServlet {
             startCron();
             sendJsonResponse(response, HttpServletResponse.SC_OK, job, 
timeZoneId);
         }
-
+        else if (show.equals(RestConstants.ALL_WORKFLOWS_FOR_COORD_ACTION)) {
+            stopCron();
+            JSONObject json = getJobsByParentId(request, response);
+            startCron();
+            sendJsonResponse(response, HttpServletResponse.SC_OK, json);
+        }
         else if (show.equals(RestConstants.JOB_SHOW_JMS_TOPIC)) {
             stopCron();
             String jmsTopicName = getJMSTopicName(request, response);
@@ -399,4 +404,16 @@ public abstract class BaseJobServlet extends 
JsonRestServlet {
      */
     abstract String getJMSTopicName(HttpServletRequest request, 
HttpServletResponse response)
             throws XServletException, IOException;
+
+    /**
+     * abstract method to get workflow job ids from the parent id
+     * i.e. coordinator action
+     * @param request
+     * @param response
+     * @return comma-separated list of workflow job ids
+     * @throws XServletException
+     * @throws IOException
+     */
+    abstract JSONObject getJobsByParentId(HttpServletRequest request, 
HttpServletResponse response)
+            throws XServletException, IOException;
 }

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/core/src/main/java/org/apache/oozie/servlet/V0JobServlet.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/servlet/V0JobServlet.java 
b/core/src/main/java/org/apache/oozie/servlet/V0JobServlet.java
index d080d3c..443ab6d 100644
--- a/core/src/main/java/org/apache/oozie/servlet/V0JobServlet.java
+++ b/core/src/main/java/org/apache/oozie/servlet/V0JobServlet.java
@@ -208,4 +208,10 @@ public class V0JobServlet extends BaseJobServlet {
             IOException {
         throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, 
ErrorCode.E0306);
     }
+
+    @Override
+    protected JSONObject getJobsByParentId(HttpServletRequest request, 
HttpServletResponse response) throws XServletException,
+            IOException {
+        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, 
ErrorCode.E0302, "Not supported in v0");
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/core/src/main/java/org/apache/oozie/servlet/V1JobServlet.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/servlet/V1JobServlet.java 
b/core/src/main/java/org/apache/oozie/servlet/V1JobServlet.java
index 2ef351e..ac399e9 100644
--- a/core/src/main/java/org/apache/oozie/servlet/V1JobServlet.java
+++ b/core/src/main/java/org/apache/oozie/servlet/V1JobServlet.java
@@ -35,10 +35,11 @@ import org.apache.oozie.service.BundleEngineService;
 import org.apache.oozie.service.CoordinatorEngineService;
 import org.apache.oozie.service.DagEngineService;
 import org.apache.oozie.service.Services;
+import org.apache.oozie.service.UUIDService;
 import org.apache.oozie.util.GraphGenerator;
 import org.apache.oozie.util.XLog;
+import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
-import org.xml.sax.SAXException;
 
 
 @SuppressWarnings("serial")
@@ -1031,4 +1032,44 @@ public class V1JobServlet extends BaseJobServlet {
         throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, 
ErrorCode.E0302, "Not supported in v1");
     }
 
+    @Override
+    protected JSONObject getJobsByParentId(HttpServletRequest request, 
HttpServletResponse response)
+            throws XServletException, IOException {
+        JSONObject json = new JSONObject();
+        CoordinatorEngine coordEngine = 
Services.get().get(CoordinatorEngineService.class)
+                .getCoordinatorEngine(getUser(request));
+        String coordActionId;
+        String type = 
request.getParameter(RestConstants.JOB_COORD_RANGE_TYPE_PARAM);
+        String scope = 
request.getParameter(RestConstants.JOB_COORD_SCOPE_PARAM);
+        // for getting allruns for coordinator action - 2 alternate endpoints
+        if (type != null && type.equals(RestConstants.JOB_COORD_SCOPE_ACTION) 
&& scope != null) {
+            // endpoint - 
oozie/v2/coord-job-id?type=action&scope=action-num&show=allruns
+            String jobId = getResourceName(request);
+            coordActionId = 
Services.get().get(UUIDService.class).generateChildId(jobId, scope);
+        }
+        else {
+            // endpoint - oozie/v2/coord-action-id?show=allruns
+            coordActionId = getResourceName(request);
+        }
+        try {
+            List<WorkflowJobBean> wfs = coordEngine.getReruns(coordActionId);
+            JSONArray array = new JSONArray();
+            if (wfs != null) {
+                for (WorkflowJobBean wf : wfs) {
+                    JSONObject json1 = new JSONObject();
+                    json1.put(JsonTags.WORKFLOW_ID, wf.getId());
+                    json1.put(JsonTags.WORKFLOW_STATUS, 
wf.getStatus().toString());
+                    json1.put(JsonTags.WORKFLOW_START_TIME, 
JsonUtils.formatDateRfc822(wf.getStartTime(), "GMT"));
+                    json1.put(JsonTags.WORKFLOW_ACTION_END_TIME, 
JsonUtils.formatDateRfc822(wf.getEndTime(), "GMT"));
+                    array.add(json1);
+                }
+            }
+            json.put(JsonTags.WORKFLOWS_JOBS, array);
+            return json;
+        }
+        catch (CoordinatorEngineException ex) {
+            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, 
ex);
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/core/src/main/java/org/apache/oozie/servlet/V2JobServlet.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/servlet/V2JobServlet.java 
b/core/src/main/java/org/apache/oozie/servlet/V2JobServlet.java
index 72265c8..2d26599 100644
--- a/core/src/main/java/org/apache/oozie/servlet/V2JobServlet.java
+++ b/core/src/main/java/org/apache/oozie/servlet/V2JobServlet.java
@@ -27,6 +27,7 @@ import org.apache.oozie.DagEngineException;
 import org.apache.oozie.client.rest.JsonBean;
 import org.apache.oozie.service.DagEngineService;
 import org.apache.oozie.service.Services;
+import org.json.simple.JSONObject;
 
 @SuppressWarnings("serial")
 public class V2JobServlet extends V1JobServlet {
@@ -68,4 +69,10 @@ public class V2JobServlet extends V1JobServlet {
         }
         return topicName;
     }
+
+    @Override
+    protected JSONObject getJobsByParentId(HttpServletRequest request, 
HttpServletResponse response)
+            throws XServletException, IOException {
+        return super.getJobsByParentId(request, response);
+    }
 }

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/core/src/test/java/org/apache/oozie/executor/jpa/TestWorkflowJobQueryExecutor.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/oozie/executor/jpa/TestWorkflowJobQueryExecutor.java
 
b/core/src/test/java/org/apache/oozie/executor/jpa/TestWorkflowJobQueryExecutor.java
index 63e3b16..9e0f03b 100644
--- 
a/core/src/test/java/org/apache/oozie/executor/jpa/TestWorkflowJobQueryExecutor.java
+++ 
b/core/src/test/java/org/apache/oozie/executor/jpa/TestWorkflowJobQueryExecutor.java
@@ -19,11 +19,17 @@ package org.apache.oozie.executor.jpa;
 
 import java.nio.ByteBuffer;
 import java.util.Date;
+import java.util.List;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
 
+import org.apache.oozie.CoordinatorActionBean;
+import org.apache.oozie.CoordinatorEngine;
+import org.apache.oozie.CoordinatorJobBean;
 import org.apache.oozie.WorkflowJobBean;
+import org.apache.oozie.client.CoordinatorAction;
+import org.apache.oozie.client.CoordinatorJob;
 import org.apache.oozie.client.WorkflowJob;
 import org.apache.oozie.executor.jpa.WorkflowJobQueryExecutor.WorkflowJobQuery;
 import org.apache.oozie.service.JPAService;
@@ -309,6 +315,20 @@ public class TestWorkflowJobQueryExecutor extends 
XDataTestCase {
     }
 
     public void testGetList() throws Exception {
-        // TODO
+        // GET_WORKFLOWS_PARENT_COORD_RERUN
+        CoordinatorJobBean coordJob = 
addRecordToCoordJobTable(CoordinatorJob.Status.SUCCEEDED, null, null, false,
+                false, 1);
+        WorkflowJobBean wfJob1 = 
addRecordToWfJobTable(WorkflowJob.Status.SUCCEEDED, 
WorkflowInstance.Status.SUCCEEDED,
+                coordJob.getId() + "@2");
+        CoordinatorActionBean coordAction1 = 
addRecordToCoordActionTable(coordJob.getId(), 2,
+                CoordinatorAction.Status.SUCCEEDED, "coord-action-get.xml", 
wfJob1.getId(), "SUCCEEDED", 0);
+        // second wf after rerunning coord action, having same parent id
+        WorkflowJobBean wfJob2 = 
addRecordToWfJobTable(WorkflowJob.Status.SUCCEEDED, 
WorkflowInstance.Status.SUCCEEDED,
+                coordJob.getId() + "@2");
+        final CoordinatorEngine ce = new CoordinatorEngine(getTestUser());
+        List<WorkflowJobBean> wfsForRerun = ce.getReruns(coordAction1.getId());
+        assertEquals(2, wfsForRerun.size());
+        assertEquals(wfJob1.getId(), wfsForRerun.get(0).getId());
+        assertEquals(wfJob2.getId(), wfsForRerun.get(1).getId());
     }
 }

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/core/src/test/java/org/apache/oozie/servlet/TestV2JobServlet.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/oozie/servlet/TestV2JobServlet.java 
b/core/src/test/java/org/apache/oozie/servlet/TestV2JobServlet.java
index 6f5a172..aa5442c 100644
--- a/core/src/test/java/org/apache/oozie/servlet/TestV2JobServlet.java
+++ b/core/src/test/java/org/apache/oozie/servlet/TestV2JobServlet.java
@@ -118,4 +118,33 @@ public class TestV2JobServlet extends DagServletTestCase {
             }
         });
     }
+
+    public void testGetCoordActionReruns() throws Exception {
+        runTest("/v2/job/*", V1JobServlet.class, IS_SECURITY_ENABLED, new 
Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+
+                MockDagEngineService.reset();
+                Map<String, String> params = new HashMap<String, String>();
+                params.put(RestConstants.JOB_SHOW_PARAM, 
RestConstants.ALL_WORKFLOWS_FOR_COORD_ACTION);
+
+                // url - oozie/v2/coord-action-id?show=allruns
+                URL url = createURL(MockCoordinatorEngineService.ACTION_ID + 
1, params);
+                HttpURLConnection conn = (HttpURLConnection) 
url.openConnection();
+                conn.setRequestMethod("GET");
+                assertEquals(HttpServletResponse.SC_OK, 
conn.getResponseCode());
+
+                MockDagEngineService.reset();
+                params.put(RestConstants.JOB_COORD_RANGE_TYPE_PARAM, 
RestConstants.JOB_COORD_SCOPE_ACTION);
+                params.put(RestConstants.JOB_COORD_SCOPE_PARAM, "2");
+
+                // url - 
oozie/v2/coord-job-id?type=action&scope=action-num&show=allruns
+                url = createURL(MockCoordinatorEngineService.JOB_ID + 2, 
params);
+                conn = (HttpURLConnection) url.openConnection();
+                conn.setRequestMethod("GET");
+                assertEquals(HttpServletResponse.SC_OK, 
conn.getResponseCode());
+                return null;
+            }
+        });
+    }
 }

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/docs/src/site/twiki/DG_CommandLineTool.twiki
----------------------------------------------------------------------
diff --git a/docs/src/site/twiki/DG_CommandLineTool.twiki 
b/docs/src/site/twiki/DG_CommandLineTool.twiki
index c13b78a..ee4c7d9 100644
--- a/docs/src/site/twiki/DG_CommandLineTool.twiki
+++ b/docs/src/site/twiki/DG_CommandLineTool.twiki
@@ -28,6 +28,8 @@ usage:
 .
       oozie job <OPTIONS> : job operations
                 -action <arg>         coordinator rerun/kill on action ids 
(requires -rerun/-kill); coordinator log retrieval on action ids (requires -log)
+                -allruns              Get workflow jobs corresponding to a 
coordinator action
+                                      including all the reruns
                 -auth <arg>           select authentication type 
[SIMPLE|KERBEROS]
                 -change <arg>         change a coordinator/bundle job
                 -config <arg>         job configuration file '.xml' or 
'.properties'
@@ -413,7 +415,7 @@ The =rerun= option reruns coordinator actions belonging to 
specified coordinator
 After the command is executed the rerun coordiator action will be in =WAITING= 
status.
 
 
----+++ Checking the Status of a Workflow, Coordinator or Bundle Job or a 
Coordinator Action
+---+++ Checking the Information and Status of a Workflow, Coordinator or 
Bundle Job or a Coordinator Action
 
 Example:
 
@@ -482,6 +484,29 @@ The two fields External Stats and External ChildIDs 
display the action statistic
 
 Note that the user can turn on/off External Stats by specifying the property 
_oozie.action.external.stats.write_ as _true_ or _false_ in workflow.xml. By 
default, it is set to false (not to collect External Stats). External ChildIDs 
will always be stored.
 
+---+++ Listing all the Workflows for a Coordinator Action
+
+A coordinator action kicks off different workflows for its original run and 
all subsequent reruns.
+Getting a list of those workflow ids is a useful tool to keep track of your 
actions' runs and
+to go debug the workflow job logs if required. Along with ids, it also lists 
their statuses,
+and start and end times for quick reference.
+
+This is achieved by using the Coordinator Action info command and specifying a 
flag *=allruns=*
+along with the =info= command.
+
+<verbatim>
+$ oozie job -info 0000001-111219170928042-oozie-joe-C@1 -allruns -oozie 
http://localhost:11000/oozie
+.
+Job ID                                   Status    Started                 
Ended
+.----------------------------------------------------------------------------------------------------
+0000001-140324163709596-oozie-joe-W     SUCCEEDED 2014-03-24 23:40 GMT    
2014-03-24 23:40 GMT
+.----------------------------------------------------------------------------------------------------
+0000000-140324164318985-oozie-joe-W     SUCCEEDED 2014-03-24 23:44 GMT    
2014-03-24 23:44 GMT
+.----------------------------------------------------------------------------------------------------
+0000001-140324164318985-oozie-joe-W     SUCCEEDED 2014-03-24 23:44 GMT    
2014-03-24 23:44 GMT
+.----------------------------------------------------------------------------------------------------
+</verbatim>
+
 ---+++ Checking the xml definition of a Workflow, Coordinator or Bundle Job
 
 Example:

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/docs/src/site/twiki/WebServicesAPI.twiki
----------------------------------------------------------------------
diff --git a/docs/src/site/twiki/WebServicesAPI.twiki 
b/docs/src/site/twiki/WebServicesAPI.twiki
index 4b20075..37c0bc0 100644
--- a/docs/src/site/twiki/WebServicesAPI.twiki
+++ b/docs/src/site/twiki/WebServicesAPI.twiki
@@ -1167,6 +1167,54 @@ Content-Type: application/json;charset=UTF-8
 }
 </verbatim>
 
+*Getting all the Workflows corresponding to a Coordinator Action:*
+
+A coordinator action kicks off different workflows for its original run and 
all subsequent reruns.
+Getting a list of those workflow ids is a useful tool to keep track of your 
actions' runs and
+to go debug the workflow job logs if required. Along with ids, it also lists 
their statuses,
+and start and end times for quick reference.
+
+Both v1 and v2 API are supported. v0 is not supported.
+
+<verbatim>
+GET /oozie/v2/job/0000001-111219170928042-oozie-joe-C@1?show=allruns
+</verbatim>
+
+*Response*
+
+<verbatim>
+HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+.
+{"workflows":[
+    {
+        "startTime":"Mon, 24 Mar 2014 23:40:53 GMT",
+        "id":"0000001-140324163709596-oozie-chit-W",
+        "status":"SUCCEEDED",
+        "endTime":"Mon, 24 Mar 2014 23:40:54 GMT"
+    },
+    {
+        "startTime":"Mon, 24 Mar 2014 23:44:01 GMT",
+        "id":"0000000-140324164318985-oozie-chit-W",
+        "status":"SUCCEEDED",
+        "endTime":"Mon, 24 Mar 2014 23:44:01 GMT"
+    },
+    {
+        "startTime":"Mon, 24 Mar 2014 23:44:24 GMT",
+        "id":"0000001-140324164318985-oozie-chit-W",
+        "status":"SUCCEEDED",
+        "endTime":"Mon, 24 Mar 2014 23:44:24 GMT"
+    }
+]}
+</verbatim>
+
+An alternate API is also available for the same output. With this API, one can 
pass the coordinator *JOB* Id
+followed by query params - type=action and scope=<action-number>. One single 
action number can be passed at a time.
+
+<verbatim>
+GET 
/oozie/v2/job/0000001-111219170928042-oozie-joe-C?show=allruns&type=action&scope=1
+</verbatim>
+
 ---++++ Job Application Definition
 
 A HTTP GET request retrieves the workflow or a coordinator job definition file.

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index 0fbdde5..3e5279b 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -1,5 +1,6 @@
 -- Oozie 4.1.0 release (trunk - unreleased)
 
+OOZIE-1746 New API to fetch workflows corresponding to coordinator action 
reruns (mona)
 OOZIE-1713 Avoid creating dummy input file for each launcher job (puru via 
rohini)
 OOZIE-1701 TestXTestCase#testWaitFor and TestXTestCase#testBaseDir have the 
errors (omaliuvanchuk via rohini)
 OOZIE-1751 Default authentication type using env variable for oozie CLI (puru 
via rohini)

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/webapp/src/main/webapp/oozie-console.css
----------------------------------------------------------------------
diff --git a/webapp/src/main/webapp/oozie-console.css 
b/webapp/src/main/webapp/oozie-console.css
index 0473fe3..307b7da 100644
--- a/webapp/src/main/webapp/oozie-console.css
+++ b/webapp/src/main/webapp/oozie-console.css
@@ -28,3 +28,6 @@
     top:auto;
     vertical-align:top;
 }
+.spaces{
+    padding-right: 15px;
+}

http://git-wip-us.apache.org/repos/asf/oozie/blob/dc22c902/webapp/src/main/webapp/oozie-console.js
----------------------------------------------------------------------
diff --git a/webapp/src/main/webapp/oozie-console.js 
b/webapp/src/main/webapp/oozie-console.js
index 2742485..6ac21a3 100644
--- a/webapp/src/main/webapp/oozie-console.js
+++ b/webapp/src/main/webapp/oozie-console.js
@@ -1199,6 +1199,78 @@ function coordJobDetailsPopup(response, request) {
              */
         }
     }
+
+    var rerunActionText = new Ext.form.Label({
+        text : 'Enter Coordinator Action number : ',
+        ctCls: 'spaces'
+    });
+    var rerunActionTextBox = new Ext.form.TextField({
+        fieldLabel: 'RerunAction',
+        name: 'RerunAction',
+        width: 150,
+        value: ''
+    });
+    var store = new Ext.data.JsonStore({
+        baseParams: {
+            scope: 0,
+        },
+        root: 'workflows',
+        fields: ['id', 'status', 'startTime', 'endTime'],
+        proxy: new Ext.data.HttpProxy({
+            url: getOozieBase() + 'job/' + coordJobId + 
'?show=allruns&type=action',
+            timeout: 300000
+        })
+    });
+    store.proxy.conn.method = "GET";
+
+    var rerunsUnit = new Ext.grid.GridPanel({
+        autoScroll: true,
+        height: 200,
+        autoRender: true,
+        store: store,
+        columns: [new Ext.grid.RowNumberer(), {
+            header: 'Workflow Id',
+            dataIndex: 'id',
+            id: 'id',
+            width: 240
+        },{
+            header: 'Workflow Status',
+            dataIndex: 'status',
+            id: 'status',
+            width: 200
+        },{
+            header: 'Started',
+            dataIndex: 'startTime',
+            id: 'startTime',
+            width: 240
+        },{
+            header: 'Ended',
+            dataIndex: 'endTime',
+            id: 'endTime',
+            width: 240
+        }],
+        listeners: {
+            cellclick: function (rerunsUnit, rowIndex, colIndex) {
+                var obj = store.getAt(rowIndex);
+                jobDetailsGridWindow(obj.data.id);
+            },
+        },
+        frame: false
+    });
+    function populateReruns(coordActionId) {
+        var actionNum = rerunActionTextBox.getValue();
+        store.baseParams.scope = actionNum;
+        store.reload();
+    }
+    var getRerunsButton = new Ext.Button({
+        text: 'Get Workflows',
+        ctCls: 'x-btn-over',
+        ctCls: 'spaces',
+        handler: function() {
+            populateReruns(rerunsUnit);
+        }
+    });
+
     var jobDetailsTab = new Ext.TabPanel({
         activeTab: 0,
         autoHeight: true,
@@ -1225,7 +1297,12 @@ function coordJobDetailsPopup(response, request) {
            items: jobLogArea,
            tbar: [
                    actionsText,actionsTextBox, getLogButton]
-          }]
+       },{
+           title: 'Coord Action Reruns',
+           items: rerunsUnit,
+           tbar: [
+               rerunActionText, rerunActionTextBox, getRerunsButton]
+       }]
 });
 
     jobDetailsTab.addListener("tabchange", function(panel, selectedTab) {
@@ -1236,6 +1313,9 @@ function coordJobDetailsPopup(response, request) {
         else if (selectedTab.title == 'Coord Job Definition') {
             fetchDefinition(coordJobId);
         }
+        else if (selectedTab.title == 'Coord Action Reruns') {
+            rerunsUnit.setVisible(true);
+        }
         coord_jobs_grid.setVisible(false);
     });
     var win = new Ext.Window({

Reply via email to