azkaban-uncached

Merge pull request #85 from davidzchen/bootstrap_ui Grab

12/19/2013 11:23:52 PM

Details

diff --git a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
index 6099b5c..bee757e 100644
--- a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
+++ b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
@@ -30,6 +30,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.HashSet;
 import java.util.Set;
 
 import javax.servlet.ServletConfig;
@@ -196,6 +197,11 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 			if (handleAjaxPermission(project, user, Type.READ, ret)) {
 				ajaxFetchFlow(project, ret, req, resp);
 			}
+    }
+		else if (ajaxName.equals("fetchflowdetails")) {
+			if (handleAjaxPermission(project, user, Type.READ, ret)) {
+				ajaxFetchFlowDetails(project, ret, req);
+			}
 		}
 		else if (ajaxName.equals("fetchflowgraph")) {
 			if (handleAjaxPermission(project, user, Type.READ, ret)) {
@@ -302,7 +308,38 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 		
 		ret.put("logData", eventData);
 	}
+
+  private List<String> getFlowJobTypes(Flow flow) {
+    Set<String> jobTypeSet = new HashSet<String>();
+    for (Node node : flow.getNodes()) {
+      jobTypeSet.add(node.getType());
+    }
+    List<String> jobTypes = new ArrayList<String>();
+    jobTypes.addAll(jobTypeSet);
+    return jobTypes;
+  }
 	
+	private void ajaxFetchFlowDetails(Project project, 
+      HashMap<String, Object> ret, HttpServletRequest req) 
+      throws ServletException {
+		String projectName = getParam(req, "project");
+		String flowName = getParam(req, "flow");
+
+		Flow flow = null;
+		try {
+      flow = project.getFlow(flowName);
+      if (flow == null) {
+        ret.put("error", "Flow " + flowName + " not found.");
+        return;
+      }
+
+      ret.put("jobTypes", getFlowJobTypes(flow));
+		}
+		catch (AccessControlException e) {
+			ret.put("error", e.getMessage());
+		}
+  }
+
 	private void ajaxFetchFlowExecutions(Project project, HashMap<String, Object> ret, HttpServletRequest req) throws ServletException {
 		String flowId = getParam(req, "flow");
 		int from = Integer.valueOf(getParam(req, "start"));
@@ -918,88 +955,88 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 		Flow flow = null;
 		try {
 			project = projectManager.getProject(projectName);
-			
 			if (project == null) {
 				page.add("errorMsg", "Project " + projectName + " not found.");
+        page.render();
+        return;
 			}
-			else {
-				if (!hasPermission(project, user, Type.READ)) {
-					throw new AccessControlException( "No permission to view project " + projectName + ".");
-				}
-				
-				page.add("project", project);
-				
-				flow = project.getFlow(flowName);
-				if (flow == null) {
-					page.add("errorMsg", "Flow " + flowName + " not found.");
-				}
-				else {
-					page.add("flowid", flow.getId());
-					Node node = flow.getNode(jobName);
-					if (node == null) {
-						page.add("errorMsg", "Job " + jobName + " not found.");
-					}
-					else {
-						Props prop = projectManager.getProperties(project, node.getJobSource());
-						Props overrideProp = projectManager.getJobOverrideProperty(project, jobName);
-						if (overrideProp == null) {
-							overrideProp = new Props();
-						}
-						Props comboProp = new Props(prop);
-						for (String key : overrideProp.getKeySet()) {
-							comboProp.put(key, overrideProp.get(key));
-						}
-						page.add("jobid", node.getId());
-						page.add("jobtype", node.getType());
-						
-						ArrayList<String> dependencies = new ArrayList<String>();
-						Set<Edge> inEdges = flow.getInEdges(node.getId());
-						if (inEdges != null) {
-							for (Edge dependency: inEdges) {
-								dependencies.add(dependency.getSourceId());
-							}
-						}
-						if (!dependencies.isEmpty()) {
-							page.add("dependencies", dependencies);
-						}
-						
-						ArrayList<String> dependents = new ArrayList<String>();
-						Set<Edge> outEdges = flow.getOutEdges(node.getId());
-						if (outEdges != null) {
-							for (Edge dependent: outEdges) {
-								dependents.add(dependent.getTargetId());
-							}
-						}
-						if (!dependents.isEmpty()) {
-							page.add("dependents", dependents);
-						}
-						
-						// Resolve property dependencies
-						ArrayList<String> source = new ArrayList<String>(); 
-						String nodeSource = node.getPropsSource();
-						if (nodeSource != null) {
-							source.add(nodeSource);
-							FlowProps parent = flow.getFlowProps(nodeSource);
-							while (parent.getInheritedSource() != null) {
-								source.add(parent.getInheritedSource());
-								parent = flow.getFlowProps(parent.getInheritedSource()); 
-							}
-						}
-						if (!source.isEmpty()) {
-							page.add("properties", source);
-						}
-						
-						ArrayList<Pair<String,String>> parameters = new ArrayList<Pair<String, String>>();
-						// Parameter
-						for (String key : comboProp.getKeySet()) {
-							String value = comboProp.get(key);
-							parameters.add(new Pair<String,String>(key, value));
-						}
-						
-						page.add("parameters", parameters);
-					}
-				}
-			}
+      if (!hasPermission(project, user, Type.READ)) {
+        throw new AccessControlException( "No permission to view project " + projectName + ".");
+      }
+      
+      page.add("project", project);
+      flow = project.getFlow(flowName);
+      if (flow == null) {
+        page.add("errorMsg", "Flow " + flowName + " not found.");
+        page.render();
+        return;
+      }
+
+      page.add("flowid", flow.getId());
+      Node node = flow.getNode(jobName);
+      if (node == null) {
+        page.add("errorMsg", "Job " + jobName + " not found.");
+        page.render();
+        return;
+      }
+
+      Props prop = projectManager.getProperties(project, node.getJobSource());
+      Props overrideProp = projectManager.getJobOverrideProperty(project, jobName);
+      if (overrideProp == null) {
+        overrideProp = new Props();
+      }
+      Props comboProp = new Props(prop);
+      for (String key : overrideProp.getKeySet()) {
+        comboProp.put(key, overrideProp.get(key));
+      }
+      page.add("jobid", node.getId());
+      page.add("jobtype", node.getType());
+      
+      ArrayList<String> dependencies = new ArrayList<String>();
+      Set<Edge> inEdges = flow.getInEdges(node.getId());
+      if (inEdges != null) {
+        for (Edge dependency: inEdges) {
+          dependencies.add(dependency.getSourceId());
+        }
+      }
+      if (!dependencies.isEmpty()) {
+        page.add("dependencies", dependencies);
+      }
+      
+      ArrayList<String> dependents = new ArrayList<String>();
+      Set<Edge> outEdges = flow.getOutEdges(node.getId());
+      if (outEdges != null) {
+        for (Edge dependent: outEdges) {
+          dependents.add(dependent.getTargetId());
+        }
+      }
+      if (!dependents.isEmpty()) {
+        page.add("dependents", dependents);
+      }
+      
+      // Resolve property dependencies
+      ArrayList<String> source = new ArrayList<String>(); 
+      String nodeSource = node.getPropsSource();
+      if (nodeSource != null) {
+        source.add(nodeSource);
+        FlowProps parent = flow.getFlowProps(nodeSource);
+        while (parent.getInheritedSource() != null) {
+          source.add(parent.getInheritedSource());
+          parent = flow.getFlowProps(parent.getInheritedSource()); 
+        }
+      }
+      if (!source.isEmpty()) {
+        page.add("properties", source);
+      }
+      
+      ArrayList<Pair<String,String>> parameters = new ArrayList<Pair<String, String>>();
+      // Parameter
+      for (String key : comboProp.getKeySet()) {
+        String value = comboProp.get(key);
+        parameters.add(new Pair<String,String>(key, value));
+      }
+      
+      page.add("parameters", parameters);
 		}
 		catch (AccessControlException e) {
 			page.add("errorMsg", e.getMessage());
@@ -1007,7 +1044,6 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 		catch (ProjectManagerException e) {
 			page.add("errorMsg", e.getMessage());
 		}
-		
 		page.render();
 	}
 	
@@ -1023,67 +1059,65 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 		Flow flow = null;
 		try {
 			project = projectManager.getProject(projectName);
-			
 			if (project == null) {
 				page.add("errorMsg", "Project " + projectName + " not found.");
+        page.render();
+        return;
 			}
-			else {
-				if (!hasPermission(project,user,Type.READ)) {
-					throw new AccessControlException( "No permission to view project " + projectName + ".");
-				}
-				
-				page.add("project", project);
-				
-				flow = project.getFlow(flowName);
-				if (flow == null) {
-					page.add("errorMsg", "Flow " + flowName + " not found.");
-				}
-				else {
-					page.add("flowid", flow.getId());
-					Node node = flow.getNode(jobName);
-					
-					if (node == null) {
-						page.add("errorMsg", "Job " + jobName + " not found.");
-					}
-					else {
-						Props prop = projectManager.getProperties(project, propSource);
-						
-						page.add("property", propSource);
-						
-						page.add("jobid", node.getId());
-						
-						// Resolve property dependencies
-						ArrayList<String> inheritProps = new ArrayList<String>(); 
-						FlowProps parent = flow.getFlowProps(propSource);
-						while(parent.getInheritedSource() != null) {
-							inheritProps.add(parent.getInheritedSource());
-							parent = flow.getFlowProps(parent.getInheritedSource()); 
-						}
-						if(!inheritProps.isEmpty()) {
-							page.add("inheritedproperties", inheritProps);
-						}
-						
-						ArrayList<String> dependingProps = new ArrayList<String>(); 
-						FlowProps child = flow.getFlowProps(flow.getNode(jobName).getPropsSource());
-						while(!child.getSource().equals(propSource)) {
-							dependingProps.add(child.getSource());
-							child = flow.getFlowProps(child.getInheritedSource()); 
-						}
-						if(!dependingProps.isEmpty()) {
-							page.add("dependingproperties", dependingProps);
-						}
-						
-						ArrayList<Pair<String,String>> parameters = new ArrayList<Pair<String, String>>();
-						// Parameter
-						for (String key : prop.getKeySet()) {
-							String value = prop.get(key);
-							parameters.add(new Pair<String,String>(key, value));
-						}
-						
-						page.add("parameters", parameters);
-					}
-				}
-			}
+
+      if (!hasPermission(project,user,Type.READ)) {
+        throw new AccessControlException( "No permission to view project " + projectName + ".");
+      }
+      page.add("project", project);
+      
+      flow = project.getFlow(flowName);
+      if (flow == null) {
+        page.add("errorMsg", "Flow " + flowName + " not found.");
+        page.render();
+        return;
+      }
+
+      page.add("flowid", flow.getId());
+      Node node = flow.getNode(jobName);
+      if (node == null) {
+        page.add("errorMsg", "Job " + jobName + " not found.");
+        page.render();
+        return;
+      }
+
+      Props prop = projectManager.getProperties(project, propSource);
+      page.add("property", propSource);
+      page.add("jobid", node.getId());
+      
+      // Resolve property dependencies
+      ArrayList<String> inheritProps = new ArrayList<String>(); 
+      FlowProps parent = flow.getFlowProps(propSource);
+      while (parent.getInheritedSource() != null) {
+        inheritProps.add(parent.getInheritedSource());
+        parent = flow.getFlowProps(parent.getInheritedSource()); 
+      }
+      if (!inheritProps.isEmpty()) {
+        page.add("inheritedproperties", inheritProps);
+      }
+      
+      ArrayList<String> dependingProps = new ArrayList<String>(); 
+      FlowProps child = flow.getFlowProps(flow.getNode(jobName).getPropsSource());
+      while (!child.getSource().equals(propSource)) {
+        dependingProps.add(child.getSource());
+        child = flow.getFlowProps(child.getInheritedSource()); 
+      }
+      if (!dependingProps.isEmpty()) {
+        page.add("dependingproperties", dependingProps);
+      }
+      
+      ArrayList<Pair<String,String>> parameters = new ArrayList<Pair<String, String>>();
+      // Parameter
+      for (String key : prop.getKeySet()) {
+        String value = prop.get(key);
+        parameters.add(new Pair<String,String>(key, value));
+      }
+      
+      page.add("parameters", parameters);
 		}
 		catch (AccessControlException e) {
 			page.add("errorMsg", e.getMessage());
@@ -1104,24 +1138,23 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 		Flow flow = null;
 		try {
 			project = projectManager.getProject(projectName);
-			
 			if (project == null) {
 				page.add("errorMsg", "Project " + projectName + " not found.");
+        page.render();
+        return;
 			}
-			else {
-				if (!hasPermission(project, user, Type.READ)) {
-					throw new AccessControlException( "No permission Project " + projectName + ".");
-				}
-				
-				page.add("project", project);
-				
-				flow = project.getFlow(flowName);
-				if (flow == null) {
-					page.add("errorMsg", "Flow " + flowName + " not found.");
-				}
-				
-				page.add("flowid", flow.getId());
-			}
+
+      if (!hasPermission(project, user, Type.READ)) {
+        throw new AccessControlException( "No permission Project " + projectName + ".");
+      }
+      
+      page.add("project", project);
+      flow = project.getFlow(flowName);
+      if (flow == null) {
+        page.add("errorMsg", "Flow " + flowName + " not found.");
+      }
+      
+      page.add("flowid", flow.getId());
 		}
 		catch (AccessControlException e) {
 			page.add("errorMsg", e.getMessage());
diff --git a/src/java/azkaban/webapp/servlet/velocity/style.vm b/src/java/azkaban/webapp/servlet/velocity/style.vm
index 6f65f36..73df059 100644
--- a/src/java/azkaban/webapp/servlet/velocity/style.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/style.vm
@@ -21,7 +21,18 @@
     <!-- Bootstrap core CSS -->
     <link href="/css/bootstrap.css" rel="stylesheet">
     <link href="/css/bootstrap-fileinput.css" rel="stylesheet">
-    <link href="/css/bootstrap-azkaban.css" rel="stylesheet">
+		<link href="/css/bootstrap-azkaban.css" rel="stylesheet">
+		<style type="text/css">
+			.navbar-enviro .navbar-enviro-name {
+				color: ${azkaban_color};
+			}
+			.navbar-inverse {
+				border-top: 5px solid ${azkaban_color};
+			}
+			.navbar-inverse .navbar-nav > .active >a {
+				border-bottom: 1px solid ${azkaban_color};
+			}
+		</style>
 
     <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
     <!--[if lt IE 9]>
diff --git a/src/tl/flowsummary.tl b/src/tl/flowsummary.tl
index 7e42852..e1227ad 100644
--- a/src/tl/flowsummary.tl
+++ b/src/tl/flowsummary.tl
@@ -2,16 +2,16 @@
           <table class="table table-striped table-bordered table-condensed table-hover">
             <tbody>
               <tr>
-                <td class="flow-summary-key">Workflow name</td>
-                <td class="flow-summary-value">{general.flowId}</td>
+                <td class="flow-summary-key">Flow name</td>
+                <td class="flow-summary-value">{flowName}</td>
                 <td class="flow-summary-key">Project name</td>
-                <td class="flow-summary-value">{general.projectName}</td>
+                <td class="flow-summary-value">{projectName}</td>
               </tr>
               <tr>
-                <td class="flow-summary-key">Workflow Hadoop User Name</td>
-                <td class="flow-summary-value">{general.user}</td>
+                <td class="flow-summary-key">Run As</td>
+                <td class="flow-summary-value">{user}</td>
                 <td class="flow-summary-key">Job Types Used</td>
-                <td class="flow-summary-value">{general.apis}</td>
+                <td class="flow-summary-value">{#jobTypes}{.} {/jobTypes}</td>
               </tr>
             </tbody>
           </table>
diff --git a/src/web/js/azkaban.flow.view.js b/src/web/js/azkaban.flow.view.js
index 897f09b..55d26c4 100644
--- a/src/web/js/azkaban.flow.view.js
+++ b/src/web/js/azkaban.flow.view.js
@@ -299,36 +299,34 @@ azkaban.SummaryView = Backbone.View.extend({
 	
 	initialize: function(settings) {
 		console.log("summaryView initialize");
-		var general = {
-			projectName: projectName,
-			flowId: flowId
-		};
-    /*var schedule = {
-			scheduleId: "0",
-			submitUser: "azkaban",
-			firstSchedTime: "1",
-			nextExecTime: "2",
-			period: "3",
-		};
-    var lastRun = {
-			maxMapSlots: 3,
-			maxReduceSlots: 9999,
-			totalMapSlots: 3,
-			totalReduceSlots: 9999,
-			numJobs: 3,
-			longestTaskTime: 1111
-		};*/
-		var lastRun = null;
 
 		this.model.bind('change:view', this.handleChangeView, this);
 		this.model.bind('render', this.render, this);
 		
-		this.model.set({'general': general});
-		this.fetchSchedule();
+		this.fetchDetails();
+    this.fetchSchedule();
 		this.fetchLastRun();
 		this.model.trigger('render');
 	},
 
+  fetchDetails: function() {
+    var requestURL = contextURL + "/manager";
+    var requestData = {
+      'ajax': 'fetchflowdetails',
+      'project': projectName,
+      'flow': flowId
+    };
+		var model = this.model;
+    var successHandler = function(data) {
+      console.log(data);
+      model.set({
+        'jobTypes': data.jobTypes
+      });
+      model.trigger('render');
+    };
+    $.get(requestURL, requestData, successHandler, 'json');
+  },
+
 	fetchSchedule: function() {
 		var requestURL = contextURL + "/schedule"
 		var requestData = {
@@ -338,10 +336,8 @@ azkaban.SummaryView = Backbone.View.extend({
 		};
 		var model = this.model;
 		var successHandler = function(data) {
-			if (data.schedule != null) {
-				model.set({'schedule': data.schedule});
-				model.trigger('render');
-			}
+      model.set({'schedule': data.schedule});
+      model.trigger('render');
 		};
 		$.get(requestURL, requestData, successHandler, 'json');
 	},
@@ -357,7 +353,9 @@ azkaban.SummaryView = Backbone.View.extend({
 	render: function(evt) {
 		console.log("summaryView render");
 		var data = {
+      projectName: projectName,
 			flowName: flowId,
+      jobTypes: this.model.get('jobTypes'),
 			general: this.model.get('general'),
 			schedule: this.model.get('schedule'),
 			lastRun: this.model.get('lastRun')