zeppelin-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m...@apache.org
Subject zeppelin git commit: [ZEPPELIN-1684] Add GET /interpreter/setting/id REST API
Date Sun, 20 Nov 2016 16:02:21 GMT
Repository: zeppelin
Updated Branches:
  refs/heads/master c507c59b6 -> e33be2525


[ZEPPELIN-1684] Add GET /interpreter/setting/id REST API

### What is this PR for?

Due to the lack of this missing API, some front-end code retrieve all settings. This is inefficient.
We can modify those codes by adding this API.

Also, i refactored the whole `InterpreterRestApiTest`

### What type of PR is it?
[Feature | Documentation | Refactoring]

### What is the Jira issue?
[ZEPPELIN-1684](https://issues.apache.org/jira/browse/ZEPPELIN-1684)

### How should this be tested?

You can run unit test `InterpreterRestApiTest`

### Screenshots (if appropriate)

Updated doc screenshots

<img width="900" alt="new_api_doc" src="https://cloud.githubusercontent.com/assets/4968473/20423419/74eeb2a0-adb3-11e6-9a69-58e33457d514.png">

### Questions:
* Does the licenses files need update? - NO
* Is there breaking changes for older versions? - NO
* Does this needs documentation? - YES, but done.

Author: 1ambda <1amb4a@gmail.com>

Closes #1655 from 1ambda/feat/create-interpreter-get-api and squashes the following commits:

89ff7fd [1ambda] style: Apply zeppelin checkstyle xml
c901287 [1ambda] docs: Add new api to rest-interpreter.html
2641a73 [1ambda] refactor: InterpreterRestApiTest
e63c80e [1ambda] refactor: testSettingsCRUD
9bc24fd [1ambda] feat: Add /interpreter/setting/id API and test


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

Branch: refs/heads/master
Commit: e33be2525679982a5eae4cb61e7ec267262effdf
Parents: c507c59
Author: 1ambda <1amb4a@gmail.com>
Authored: Fri Nov 18 22:51:52 2016 +0900
Committer: Lee moon soo <moon@apache.org>
Committed: Sun Nov 20 08:02:12 2016 -0800

----------------------------------------------------------------------
 docs/rest-api/rest-interpreter.md               |  59 ++++++++++
 .../zeppelin/rest/InterpreterRestApi.java       |  25 +++-
 .../zeppelin/rest/InterpreterRestApiTest.java   | 117 ++++++++++++-------
 3 files changed, 155 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/e33be252/docs/rest-api/rest-interpreter.md
----------------------------------------------------------------------
diff --git a/docs/rest-api/rest-interpreter.md b/docs/rest-api/rest-interpreter.md
index 4f85e69..277d365 100644
--- a/docs/rest-api/rest-interpreter.md
+++ b/docs/rest-api/rest-interpreter.md
@@ -178,6 +178,65 @@ The role of registered interpreters, settings and interpreters group
are describ
       </td>
     </tr>
   </table>
+  
+<br/>
+### Get a registered interpreter setting by the setting id 
+
+  <table class="table-configuration">
+    <col width="200">
+    <tr>
+      <td>Description</td>
+      <td>This ```GET``` method returns a registered interpreter setting on the server.</td>
+    </tr>
+    <tr>
+      <td>URL</td>
+      <td>```http://[zeppelin-server]:[zeppelin-port]/api/interpreter/setting/[setting
ID]```</td>
+    </tr>
+    <tr>
+      <td>Success code</td>
+      <td>200</td>
+    </tr>
+    <tr>
+      <td>Fail code</td>
+      <td>
+          400 if such interpreter setting id does not exist <br/>
+          500 for any other errors
+      </td>
+    </tr>
+    <tr>
+      <td>Sample JSON response</td>
+      <td>
+        <pre>
+{
+  "status": "OK",
+  "message": "",
+  "body": {
+    "id": "2AYW25ANY",
+    "name": "Markdown setting name",
+    "group": "md",
+    "properties": {
+      "propname": "propvalue"
+    },
+    "interpreterGroup": [
+      {
+        "class": "org.apache.zeppelin.markdown.Markdown",
+        "name": "md"
+      }
+    ],
+    "dependencies": [
+      {
+        "groupArtifactVersion": "groupId:artifactId:version",
+        "exclusions": [
+          "groupId:artifactId"
+        ]
+      }
+    ]
+  }
+}
+        </pre>
+      </td>
+    </tr>
+  </table>
 
 <br/>
 ### Create a new interpreter setting  

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/e33be252/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 cb50a8a..90a58ac 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
@@ -81,6 +81,27 @@ public class InterpreterRestApi {
   }
 
   /**
+   * Get a setting
+   */
+  @GET
+  @Path("setting/{settingId}")
+  @ZeppelinApi
+  public Response getSetting(@PathParam("settingId") String settingId) {
+    try {
+      InterpreterSetting setting = interpreterFactory.get(settingId);
+      if (setting == null) {
+        return new JsonResponse<>(Status.NOT_FOUND).build();
+      } else {
+        return new JsonResponse<>(Status.OK, "", setting).build();
+      }
+    } catch (NullPointerException e) {
+      logger.error("Exception in InterpreterRestApi while creating ", e);
+      return new JsonResponse<>(Status.INTERNAL_SERVER_ERROR, e.getMessage(),
+          ExceptionUtils.getStackTrace(e)).build();
+    }
+  }
+
+  /**
    * Add new interpreter setting
    *
    * @param message NewInterpreterSettingRequest
@@ -209,7 +230,7 @@ public class InterpreterRestApi {
     try {
       Repository request = gson.fromJson(message, Repository.class);
       interpreterFactory.addRepository(request.getId(), request.getUrl(), request.isSnapshot(),
-        request.getAuthentication(), request.getProxy());
+          request.getAuthentication(), request.getProxy());
       logger.info("New repository {} added", request.getId());
     } catch (Exception e) {
       logger.error("Exception in InterpreterRestApi while adding repository ", e);
@@ -225,7 +246,7 @@ public class InterpreterRestApi {
   @GET
   @Path("getmetainfos/{settingId}")
   public Response getMetaInfo(@Context HttpServletRequest req,
-      @PathParam("settingId") String settingId) {
+                              @PathParam("settingId") String settingId) {
     String propName = req.getParameter("propName");
     if (propName == null) {
       return new JsonResponse<>(Status.BAD_REQUEST).build();

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/e33be252/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 ada6c07..8db6650 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
@@ -18,9 +18,11 @@
 package org.apache.zeppelin.rest;
 
 import java.io.IOException;
-import java.util.List;
 import java.util.Map;
 
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
 import org.apache.commons.httpclient.methods.DeleteMethod;
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.methods.PostMethod;
@@ -40,7 +42,6 @@ import org.junit.Test;
 import org.junit.runners.MethodSorters;
 
 import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
 
 import static org.junit.Assert.*;
 
@@ -71,13 +72,12 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
   public void getAvailableInterpreters() throws IOException {
     // when
     GetMethod get = httpGet("/interpreter");
+    JsonObject body = getBodyFieldFromResponse(get.getResponseBodyAsString());
 
     // then
     assertThat(get, isAllowed());
-    Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), new TypeToken<Map<String,
Object>>() {
-    }.getType());
-    Map<String, Object> body = (Map<String, Object>) resp.get("body");
-    assertEquals(ZeppelinServer.notebook.getInterpreterFactory().getAvailableInterpreterSettings().size(),
body.size());
+    assertEquals(ZeppelinServer.notebook.getInterpreterFactory().getAvailableInterpreterSettings().size(),
+        body.entrySet().size());
     get.releaseConnection();
   }
 
@@ -85,45 +85,63 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
   public void getSettings() throws IOException {
     // when
     GetMethod get = httpGet("/interpreter/setting");
-
     // then
-    Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), new TypeToken<Map<String,
Object>>() {
-    }.getType());
     assertThat(get, isAllowed());
+    // DO NOT REMOVE: implies that body is properly parsed as an array
+    JsonArray body = getArrayBodyFieldFromResponse(get.getResponseBodyAsString());
+    get.releaseConnection();
+  }
+
+  @Test
+  public void testGetNonExistInterpreterSetting() throws IOException {
+    // when
+    String nonExistInterpreterSettingId = "apache_.zeppelin_1s_.aw3some$";
+    GetMethod get = httpGet("/interpreter/setting/" + nonExistInterpreterSettingId);
+
+    // then
+    assertThat("Test get method:", get, isNotFound());
     get.releaseConnection();
   }
 
   @Test
   public void testSettingsCRUD() throws IOException {
-    // Call Create Setting REST API
-    String jsonRequest = "{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"propvalue\"},"
+
+    // when: call create setting API
+    String rawRequest = "{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"propvalue\"},"
+
         "\"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}],"
+
         "\"dependencies\":[]," +
         "\"option\": { \"remote\": true, \"session\": false }}";
-    PostMethod post = httpPost("/interpreter/setting/", jsonRequest);
+    JsonObject jsonRequest = gson.fromJson(rawRequest, JsonElement.class).getAsJsonObject();
+    PostMethod post = httpPost("/interpreter/setting/", jsonRequest.toString());
+    String postResponse = post.getResponseBodyAsString();
     LOG.info("testSettingCRUD create response\n" + post.getResponseBodyAsString());
+    InterpreterSetting created = convertResponseToInterpreterSetting(postResponse);
+    String newSettingId = created.getId();
+    // then : call create setting API
     assertThat("test create method:", post, isCreated());
-
-    Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), new TypeToken<Map<String,
Object>>() {
-    }.getType());
-    Map<String, Object> body = (Map<String, Object>) resp.get("body");
-    //extract id from body string {id=2AWMQDNX7, name=md2, group=md,
-    String newSettingId = body.toString().split(",")[0].split("=")[1];
     post.releaseConnection();
 
-    // Call Update Setting REST API
-    jsonRequest = "{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"Otherpropvalue\"},"
+
-        "\"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}],"
+
-        "\"dependencies\":[]," +
-        "\"option\": { \"remote\": true, \"session\": false }}";
-    PutMethod put = httpPut("/interpreter/setting/" + newSettingId, jsonRequest);
+    // when: call read setting API
+    GetMethod get = httpGet("/interpreter/setting/" + newSettingId);
+    String getResponse = get.getResponseBodyAsString();
+    LOG.info("testSettingCRUD get response\n" + getResponse);
+    InterpreterSetting previouslyCreated = convertResponseToInterpreterSetting(getResponse);
+    // then : read Setting API
+    assertThat("Test get method:", get, isAllowed());
+    assertEquals(newSettingId, previouslyCreated.getId());
+    get.releaseConnection();
+
+    // when: call update setting API
+    jsonRequest.getAsJsonObject("properties").addProperty("propname2", "this is new prop");
+    PutMethod put = httpPut("/interpreter/setting/" + newSettingId, jsonRequest.toString());
     LOG.info("testSettingCRUD update response\n" + put.getResponseBodyAsString());
+    // then: call update setting API
     assertThat("test update method:", put, isAllowed());
     put.releaseConnection();
 
-    // Call Delete Setting REST API
+    // when: call delete setting API
     DeleteMethod delete = httpDelete("/interpreter/setting/" + newSettingId);
     LOG.info("testSettingCRUD delete response\n" + delete.getResponseBodyAsString());
+    // then: call delete setting API
     assertThat("Test delete method:", delete, isAllowed());
     delete.releaseConnection();
   }
@@ -139,33 +157,29 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
 
   @Test
   public void testInterpreterAutoBinding() throws IOException {
-    // create note
+    // when
     Note note = ZeppelinServer.notebook.createNote(anonymous);
-
-    // check interpreter is binded
     GetMethod get = httpGet("/notebook/interpreter/bind/" + note.getId());
     assertThat(get, isAllowed());
     get.addRequestHeader("Origin", "http://localhost");
-    Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), new TypeToken<Map<String,
Object>>() {
-    }.getType());
-    List<Map<String, String>> body = (List<Map<String, String>>)
resp.get("body");
-    assertTrue(0 < body.size());
+    JsonArray body = getArrayBodyFieldFromResponse(get.getResponseBodyAsString());
 
+    // then: check interpreter is binded
+    assertTrue(0 < body.size());
     get.releaseConnection();
-    //cleanup
     ZeppelinServer.notebook.removeNote(note.getId(), anonymous);
   }
 
   @Test
   public void testInterpreterRestart() throws IOException, InterruptedException {
-    // create new note
+    // when: create new note
     Note note = ZeppelinServer.notebook.createNote(anonymous);
     note.addParagraph();
     Paragraph p = note.getLastParagraph();
     Map config = p.getConfig();
     config.put("enabled", true);
 
-    // run markdown paragraph
+    // when: run markdown paragraph
     p.setConfig(config);
     p.setText("%md markdown");
     p.setAuthenticationInfo(anonymous);
@@ -175,10 +189,10 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
     }
     assertEquals(p.getResult().message(), getSimulatedMarkdownResult("markdown"));
 
-    // restart interpreter
+    // when: restart interpreter
     for (InterpreterSetting setting : ZeppelinServer.notebook.getInterpreterFactory().getInterpreterSettings(note.getId()))
{
       if (setting.getName().equals("md")) {
-        // Call Restart Interpreter REST API
+        // call restart interpreter API
         PutMethod put = httpPut("/interpreter/setting/restart/" + setting.getId(), "");
         assertThat("test interpreter restart:", put, isAllowed());
         put.releaseConnection();
@@ -186,7 +200,7 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
       }
     }
 
-    // run markdown paragraph, again
+    // when: run markdown paragraph, again
     p = note.addParagraph();
     p.setConfig(config);
     p.setText("%md markdown restarted");
@@ -195,21 +209,22 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
     while (p.getStatus() != Status.FINISHED) {
       Thread.sleep(100);
     }
+
+    // then
     assertEquals(p.getResult().message(), getSimulatedMarkdownResult("markdown restarted"));
-    //cleanup
     ZeppelinServer.notebook.removeNote(note.getId(), anonymous);
   }
 
   @Test
   public void testRestartInterpreterPerNote() throws IOException, InterruptedException {
-    // create new note
+    // when: create new note
     Note note = ZeppelinServer.notebook.createNote(anonymous);
     note.addParagraph();
     Paragraph p = note.getLastParagraph();
     Map config = p.getConfig();
     config.put("enabled", true);
 
-    // run markdown paragraph.
+    // when: run markdown paragraph.
     p.setConfig(config);
     p.setText("%md markdown");
     p.setAuthenticationInfo(anonymous);
@@ -219,7 +234,7 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
     }
     assertEquals(p.getResult().message(), getSimulatedMarkdownResult("markdown"));
 
-    // get md interpreter
+    // when: get md interpreter
     InterpreterSetting mdIntpSetting = null;
     for (InterpreterSetting setting : ZeppelinServer.notebook.getInterpreterFactory().getInterpreterSettings(note.getId()))
{
       if (setting.getName().equals("md")) {
@@ -260,7 +275,7 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
 
   @Test
   public void testAddDeleteRepository() throws IOException {
-    // Call create repository REST API
+    // Call create repository API
     String repoId = "securecentral";
     String jsonRequest = "{\"id\":\"" + repoId +
         "\",\"url\":\"https://repo1.maven.org/maven2\",\"snapshot\":\"false\"}";
@@ -269,12 +284,26 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
     assertThat("Test create method:", post, isCreated());
     post.releaseConnection();
 
-    // Call delete repository REST API
+    // Call delete repository API
     DeleteMethod delete = httpDelete("/interpreter/repository/" + repoId);
     assertThat("Test delete method:", delete, isAllowed());
     delete.releaseConnection();
   }
 
+  public JsonObject getBodyFieldFromResponse(String rawResponse) {
+    JsonObject response = gson.fromJson(rawResponse, JsonElement.class).getAsJsonObject();
+    return response.getAsJsonObject("body");
+  }
+
+  public JsonArray getArrayBodyFieldFromResponse(String rawResponse) {
+    JsonObject response = gson.fromJson(rawResponse, JsonElement.class).getAsJsonObject();
+    return response.getAsJsonArray("body");
+  }
+
+  public InterpreterSetting convertResponseToInterpreterSetting(String rawResponse) {
+    return gson.fromJson(getBodyFieldFromResponse(rawResponse), InterpreterSetting.class);
+  }
+
   public static String getSimulatedMarkdownResult(String markdown) {
     return String.format("<div class=\"markdown-body\">\n<p>%s</p>\n</div>",
markdown);
   }


Mime
View raw message