Repository: zeppelin
Updated Branches:
  refs/heads/master 86bc9332e -> 96d78ee57


[ZEPPELIN-2714] Soft-code Spark UI button visualization

### What is this PR for?
When "spark.ui.enabled" property is set to "false" we should not show the Spark 
UI button.
We keep the same behaviour when this property does not exist or when it exists 
and it's set to true.

### What type of PR is it?
[ Improvement]

### What is the Jira issue?
* https://issues.apache.org/jira/browse/ZEPPELIN-2714

### How should this be tested?
1. Open Zeppelin, go to Interpreter > Spark
1. Click spark ui > msg: "No spark application running"
1. Go to a paragraph, run "sc.parallelize(1 to 100).count()", check "SPARK JOB" 
button
1. Go to Interpreter > Spark > Set "spark.ui.enabled" to "false"
1. Rerun paragraph > "SPARK JOB" button not visible
1. Go to Interpreter > Spark > "spark ui" button not visible
Also, test with "spark.ui.enabled"="true" and other workflow combinations

### Questions:
* Does the licenses files need update? N
* Is there breaking changes for older versions? N
* Does this needs documentation? N

Author: Nelson Costa <nelson.cost...@gmail.com>

Closes #2456 from necosta/zeppelin2714 and squashes the following commits:

278a23e [Nelson Costa] [ZEPPELIN-2714] Fixed broken unit-test
edf29cc [Nelson Costa] [ZEPPELIN-2714] Minor final fix
294dea8 [Nelson Costa] [ZEPPELIN-2714] Improvements to change request
a85864c [Nelson Costa] [ZEPPELIN-2714] Soft-code Spark UI button visualization


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

Branch: refs/heads/master
Commit: 96d78ee57b5340b2441a1b8fd866d327d998913b
Parents: 86bc933
Author: Nelson Costa <nelson.cost...@gmail.com>
Authored: Thu Jul 6 15:04:04 2017 +0100
Committer: Felix Cheung <felixche...@apache.org>
Committed: Sun Jul 9 00:43:54 2017 -0700

----------------------------------------------------------------------
 docs/usage/rest_api/interpreter.md              | 23 ++++++++++++
 .../apache/zeppelin/spark/SparkInterpreter.java | 37 ++++++++++++-------
 .../zeppelin/rest/InterpreterRestApi.java       | 23 ++++--------
 .../zeppelin/rest/InterpreterRestApiTest.java   | 39 +++++++++++++++++---
 .../app/interpreter/interpreter.controller.js   | 13 +++++--
 5 files changed, 96 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/96d78ee5/docs/usage/rest_api/interpreter.md
----------------------------------------------------------------------
diff --git a/docs/usage/rest_api/interpreter.md 
b/docs/usage/rest_api/interpreter.md
index 4869866..23a7c66 100644
--- a/docs/usage/rest_api/interpreter.md
+++ b/docs/usage/rest_api/interpreter.md
@@ -604,3 +604,26 @@ The role of registered interpreters, settings and 
interpreters group are describ
     </td>        
   </table>  
   
+<br/>
+### Get interpreter settings metadata info
+
+  <table class="table-configuration">
+    <col width="200">
+    <tr>
+      <td>Description</td>
+      <td>This ```GET``` method returns interpreter settings metadata info. 
</td>
+    </tr>
+    <tr>
+      <td>URL</td>
+      
<td>```http://[zeppelin-server]:[zeppelin-port]/api/interpreter/metadata/[setting
 ID]```</td>
+    </tr>
+    <tr>
+      <td>Success code</td>
+      <td>200</td>
+    </tr>
+    <tr>
+      <td>Fail code</td>
+      <td> 500 </td>
+    </tr>
+  </table>
+  
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/96d78ee5/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
----------------------------------------------------------------------
diff --git 
a/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java 
b/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
index c170e4e..dd1fa11 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
@@ -184,11 +184,14 @@ public class SparkInterpreter extends Interpreter {
         super.onJobStart(jobStart);
         int jobId = jobStart.jobId();
         String jobGroupId = 
jobStart.properties().getProperty("spark.jobGroup.id");
+        String uiEnabled = 
jobStart.properties().getProperty("spark.ui.enabled");
         String jobUrl = getJobUrl(jobId);
         String noteId = Utils.getNoteId(jobGroupId);
         String paragraphId = Utils.getParagraphId(jobGroupId);
-
-        if (jobUrl != null && noteId != null && paragraphId != null) {
+        // Button visible if Spark UI property not set, set as invalid boolean 
or true
+        java.lang.Boolean showSparkUI =
+                uiEnabled == null || 
!uiEnabled.trim().toLowerCase().equals("false");
+        if (showSparkUI && jobUrl != null) {
           RemoteEventClientWrapper eventClient = 
BaseZeppelinContext.getEventClient();
           Map<String, String> infos = new java.util.HashMap<>();
           infos.put("jobUrl", jobUrl);
@@ -1040,21 +1043,29 @@ public class SparkInterpreter extends Interpreter {
   }
 
   public void populateSparkWebUrl(InterpreterContext ctx) {
-    if (sparkUrl == null) {
-      sparkUrl = getSparkUIUrl();
-      Map<String, String> infos = new java.util.HashMap<>();
-      if (sparkUrl != null) {
-        infos.put("url", sparkUrl);
-        if (ctx != null && ctx.getClient() != null) {
-          logger.info("Sending metainfos to Zeppelin server: {}", 
infos.toString());
-          getZeppelinContext().setEventClient(ctx.getClient());
-          ctx.getClient().onMetaInfosReceived(infos);
-        }
+    sparkUrl = getSparkUIUrl();
+    Map<String, String> infos = new java.util.HashMap<>();
+    infos.put("url", sparkUrl);
+    String uiEnabledProp = property.getProperty("spark.ui.enabled", "true");
+    java.lang.Boolean uiEnabled = java.lang.Boolean.parseBoolean(
+            uiEnabledProp.trim());
+    if (!uiEnabled) {
+      infos.put("message", "Spark UI disabled");
+    } else {
+      if (StringUtils.isNotBlank(sparkUrl)) {
+        infos.put("message", "Spark UI enabled");
+      } else {
+        infos.put("message", "No spark url defined");
       }
     }
+    if (ctx != null && ctx.getClient() != null) {
+      logger.info("Sending metadata to Zeppelin server: {}", infos.toString());
+      getZeppelinContext().setEventClient(ctx.getClient());
+      ctx.getClient().onMetaInfosReceived(infos);
+    }
   }
 
-  public List<File> currentClassPath() {
+  private List<File> currentClassPath() {
     List<File> paths = 
classPath(Thread.currentThread().getContextClassLoader());
     String[] cps = 
System.getProperty("java.class.path").split(File.pathSeparator);
     if (cps != null) {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/96d78ee5/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java
 
b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java
index 17c4027..cd0210e 100644
--- 
a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java
+++ 
b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java
@@ -246,28 +246,19 @@ public class InterpreterRestApi {
   }
 
   /**
-   * get the metainfo property value
+   * get metadata values
    */
   @GET
-  @Path("getmetainfos/{settingId}")
+  @Path("metadata/{settingId}")
+  @ZeppelinApi
   public Response getMetaInfo(@Context HttpServletRequest req,
       @PathParam("settingId") String settingId) {
-    String propName = req.getParameter("propName");
-    if (propName == null) {
-      return new JsonResponse<>(Status.BAD_REQUEST).build();
-    }
-    String propValue = null;
     InterpreterSetting interpreterSetting = 
interpreterSettingManager.get(settingId);
-    Map<String, String> infos = interpreterSetting.getInfos();
-    if (infos != null) {
-      propValue = infos.get(propName);
+    if (interpreterSetting == null) {
+      return new JsonResponse<>(Status.NOT_FOUND).build();
     }
-    Map<String, String> respMap = new HashMap<>();
-    respMap.put(propName, propValue);
-    logger.debug("Get meta info");
-    logger.debug("Interpretersetting Id: {}, property Name:{}, property value: 
{}", settingId,
-        propName, propValue);
-    return new JsonResponse<>(Status.OK, respMap).build();
+    Map<String, String> infos = interpreterSetting.getInfos();
+    return new JsonResponse<>(Status.OK, "metadata", infos).build();
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/96d78ee5/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
index 5333385..28541bd 100644
--- 
a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
@@ -54,8 +54,8 @@ import static org.hamcrest.MatcherAssert.assertThat;
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class InterpreterRestApiTest extends AbstractTestRestApi {
-  Gson gson = new Gson();
-  AuthenticationInfo anonymous;
+  private Gson gson = new Gson();
+  private AuthenticationInfo anonymous;
 
   @BeforeClass
   public static void init() throws Exception {
@@ -365,21 +365,48 @@ public class InterpreterRestApiTest extends 
AbstractTestRestApi {
     delete.releaseConnection();
   }
 
-  public JsonObject getBodyFieldFromResponse(String rawResponse) {
+  @Test
+  public void testGetMetadataInfo() throws IOException {
+    String jsonRequest = "{\"name\":\"spark\",\"group\":\"spark\"," +
+            "\"properties\":{\"propname\": {\"value\": \"propvalue\", 
\"name\": \"propname\", \"type\": \"textarea\"}}," +
+            
"\"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}],"
 +
+            "\"dependencies\":[]," +
+            "\"option\": { \"remote\": true, \"session\": false }}";
+    PostMethod post = httpPost("/interpreter/setting/", jsonRequest);
+    InterpreterSetting created = 
convertResponseToInterpreterSetting(post.getResponseBodyAsString());
+    String settingId = created.getId();
+    Map<String, String> infos = new java.util.HashMap<>();
+    infos.put("key1", "value1");
+    infos.put("key2", "value2");
+    
ZeppelinServer.notebook.getInterpreterSettingManager().get(settingId).setInfos(infos);
+    GetMethod get = httpGet("/interpreter/metadata/" + settingId);
+    assertThat(get, isAllowed());
+    JsonObject body = getBodyFieldFromResponse(get.getResponseBodyAsString());
+    assertEquals(body.entrySet().size(), infos.size());
+    java.util.Map.Entry<String, JsonElement> item = 
body.entrySet().iterator().next();
+    if (item.getKey().equals("key1")) {
+      assertEquals(item.getValue().getAsString(), "value1");
+    } else {
+      assertEquals(item.getValue().getAsString(), "value2");
+    }
+    get.releaseConnection();
+  }
+
+  private JsonObject getBodyFieldFromResponse(String rawResponse) {
     JsonObject response = gson.fromJson(rawResponse, 
JsonElement.class).getAsJsonObject();
     return response.getAsJsonObject("body");
   }
 
-  public JsonArray getArrayBodyFieldFromResponse(String rawResponse) {
+  private JsonArray getArrayBodyFieldFromResponse(String rawResponse) {
     JsonObject response = gson.fromJson(rawResponse, 
JsonElement.class).getAsJsonObject();
     return response.getAsJsonArray("body");
   }
 
-  public InterpreterSetting convertResponseToInterpreterSetting(String 
rawResponse) {
+  private InterpreterSetting convertResponseToInterpreterSetting(String 
rawResponse) {
     return gson.fromJson(getBodyFieldFromResponse(rawResponse), 
InterpreterSetting.class);
   }
 
-  public static String getSimulatedMarkdownResult(String markdown) {
+  private static String getSimulatedMarkdownResult(String markdown) {
     return String.format("<div class=\"markdown-body\">\n<p>%s</p>\n</div>", 
markdown);
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/96d78ee5/zeppelin-web/src/app/interpreter/interpreter.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/interpreter/interpreter.controller.js 
b/zeppelin-web/src/app/interpreter/interpreter.controller.js
index e75740f..dc3619e 100644
--- a/zeppelin-web/src/app/interpreter/interpreter.controller.js
+++ b/zeppelin-web/src/app/interpreter/interpreter.controller.js
@@ -754,16 +754,21 @@ function InterpreterCtrl($rootScope, $scope, $http, 
baseUrlSrv, ngToast, $timeou
   }
 
   $scope.showSparkUI = function (settingId) {
-    $http.get(baseUrlSrv.getRestApiBase() + '/interpreter/getmetainfos/' + 
settingId + '?propName=url')
+    $http.get(baseUrlSrv.getRestApiBase() + '/interpreter/metadata/' + 
settingId)
       .success(function (data, status, headers, config) {
-        let url = data.body.url
-        if (!url) {
+        if (data.body === undefined) {
           BootstrapDialog.alert({
             message: 'No spark application running'
           })
           return
         }
-        window.open(url, '_blank')
+        if (data.body.url) {
+          window.open(data.body.url, '_blank')
+        } else {
+          BootstrapDialog.alert({
+            message: data.body.message
+          })
+        }
       }).error(function (data, status, headers, config) {
         console.log('Error %o %o', status, data.message)
       })

Reply via email to