You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by mo...@apache.org on 2016/11/09 18:04:43 UTC
zeppelin git commit: [ZEPPELIN-1029] Add rest api for paragraph
config update
Repository: zeppelin
Updated Branches:
refs/heads/master dbd81bf85 -> 24187b0a7
[ZEPPELIN-1029] Add rest api for paragraph config update
### What is this PR for?
This PR adds new end point for updating paragraph configuration
### What type of PR is it?
Improvement | Documentation
### What is the Jira issue?
[ZEPPELIN-1029](https://issues.apache.org/jira/browse/ZEPPELIN-1029)
### How should this be tested?
Outline the steps to test the PR here.
### Questions:
* Does the licenses files need update? no
* Is there breaking changes for older versions? no
* Does this needs documentation? yes
Author: Mina Lee <mi...@apache.org>
Closes #1592 from minahlee/ZEPPELIN-1029 and squashes the following commits:
c8357ca [Mina Lee] Add rest api for paragraph config update
Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/24187b0a
Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/24187b0a
Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/24187b0a
Branch: refs/heads/master
Commit: 24187b0a7584b09b74cddd44440cac4b62f5cd86
Parents: dbd81bf
Author: Mina Lee <mi...@apache.org>
Authored: Thu Nov 3 22:28:25 2016 +0900
Committer: Lee moon soo <mo...@apache.org>
Committed: Wed Nov 9 10:04:32 2016 -0800
----------------------------------------------------------------------
docs/rest-api/rest-notebook.md | 127 ++++++++++++++++++-
.../apache/zeppelin/rest/NotebookRestApi.java | 33 +++++
.../rest/exception/BadRequestException.java | 47 +++++++
.../zeppelin/rest/NotebookRestApiTest.java | 27 +++-
4 files changed, 230 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/24187b0a/docs/rest-api/rest-notebook.md
----------------------------------------------------------------------
diff --git a/docs/rest-api/rest-notebook.md b/docs/rest-api/rest-notebook.md
index 46f2cd1..d8ae117 100644
--- a/docs/rest-api/rest-notebook.md
+++ b/docs/rest-api/rest-notebook.md
@@ -809,6 +809,127 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple
</table>
<br/>
+### Update paragraph configuration
+ <table class="table-configuration">
+ <col width="200">
+ <tr>
+ <td>Description</td>
+ <td>This ```PUT``` method update paragraph configuration using given id so that user can change paragraph setting such as graph type, show or hide editor/result and paragraph size, etc. You can update certain fields you want, for example you can update <code>colWidth</code> field only by sending request with payload <code>{"colWidth": 12.0}</code>.
+ </td>
+ </tr>
+ <tr>
+ <td>URL</td>
+ <td>```http://[zeppelin-server]:[zeppelin-port]/api/notebook/[noteId]/paragraph/[paragraphId]/config```</td>
+ </tr>
+ <tr>
+ <td>Success code</td>
+ <td>200</td>
+ </tr>
+ <tr>
+ <td>Bad Request code</td>
+ <td>400</td>
+ </tr>
+ <tr>
+ <td>Forbidden code</td>
+ <td>403</td>
+ </tr>
+ <tr>
+ <td>Not Found code</td>
+ <td>404</td>
+ </tr>
+ <tr>
+ <td>Fail code</td>
+ <td>500</td>
+ </tr>
+ <tr>
+ <td>sample JSON input</td>
+ <td><pre>
+{
+ "colWidth": 6.0,
+ "graph": {
+ "mode": "lineChart",
+ "height": 200.0,
+ "optionOpen": false,
+ "keys": [
+ {
+ "name": "age",
+ "index": 0.0,
+ "aggr": "sum"
+ }
+ ],
+ "values": [
+ {
+ "name": "value",
+ "index": 1.0,
+ "aggr": "sum"
+ }
+ ],
+ "groups": [],
+ "scatter": {}
+ },
+ "editorHide": true,
+ "editorMode": "ace/mode/markdown",
+ "tableHide": false
+}</pre></td>
+ </tr>
+ <tr>
+ <td>sample JSON response</td>
+ <td><pre>
+{
+ "status":"OK",
+ "message":"",
+ "body":{
+ "text":"%sql \nselect age, count(1) value\nfrom bank \nwhere age \u003c 30 \ngroup by age \norder by age",
+ "config":{
+ "colWidth":6.0,
+ "graph":{
+ "mode":"lineChart",
+ "height":200.0,
+ "optionOpen":false,
+ "keys":[
+ {
+ "name":"age",
+ "index":0.0,
+ "aggr":"sum"
+ }
+ ],
+ "values":[
+ {
+ "name":"value",
+ "index":1.0,
+ "aggr":"sum"
+ }
+ ],
+ "groups":[],
+ "scatter":{}
+ },
+ "tableHide":false,
+ "editorMode":"ace/mode/markdown",
+ "editorHide":true
+ },
+ "settings":{
+ "params":{},
+ "forms":{}
+ },
+ "apps":[],
+ "jobName":"paragraph_1423500782552_-1439281894",
+ "id":"20150210-015302_1492795503",
+ "result":{
+ "code":"SUCCESS",
+ "type":"TABLE",
+ "msg":"age\tvalue\n19\t4\n20\t3\n21\t7\n22\t9\n23\t20\n24\t24\n25\t44\n26\t77\n27\t94\n28\t103\n29\t97\n"
+ },
+ "dateCreated":"Feb 10, 2015 1:53:02 AM",
+ "dateStarted":"Jul 3, 2015 1:43:17 PM",
+ "dateFinished":"Jul 3, 2015 1:43:23 PM",
+ "status":"FINISHED",
+ "progressUpdateIntervalMs":500
+ }
+}</pre></td>
+ </tr>
+ </table>
+
+<br/>
### Move a paragraph to the specific index
<table class="table-configuration">
<col width="200">
@@ -835,7 +956,6 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple
</tr>
</table>
-
<br/>
### Delete a paragraph
<table class="table-configuration">
@@ -934,7 +1054,8 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple
<td> Fail code</td>
<td> 500 </td>
</tr>
- <td>sample JSON input</td>
+ <tr>
+ <td>sample JSON input</td>
<td><pre>
{
"paragraphs": [
@@ -961,6 +1082,7 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple
"config": {},
"info": {}
}</pre></td>
+ </tr>
<tr>
<td>sample JSON response</td>
<td><pre>
@@ -970,7 +1092,6 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple
"body": "2AZPHY918"
}</pre></td>
</tr>
- </tr>
</table>
<br />
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/24187b0a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java
index 52f7d11..1f03b64 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java
@@ -42,6 +42,7 @@ import org.apache.zeppelin.notebook.Note;
import org.apache.zeppelin.notebook.Notebook;
import org.apache.zeppelin.notebook.NotebookAuthorization;
import org.apache.zeppelin.notebook.Paragraph;
+import org.apache.zeppelin.rest.exception.BadRequestException;
import org.apache.zeppelin.rest.exception.NotFoundException;
import org.apache.zeppelin.rest.exception.ForbiddenException;
import org.apache.zeppelin.rest.message.CronRequest;
@@ -451,6 +452,38 @@ public class NotebookRestApi {
return new JsonResponse<>(Status.OK, "", p).build();
}
+ @PUT
+ @Path("{noteId}/paragraph/{paragraphId}/config")
+ @ZeppelinApi
+ public Response updateParagraphConfig(@PathParam("noteId") String noteId,
+ @PathParam("paragraphId") String paragraphId, String message) throws IOException {
+ String user = SecurityUtils.getPrincipal();
+ LOG.info("{} will update paragraph config {} {}", user, noteId, paragraphId);
+
+ Note note = notebook.getNote(noteId);
+ checkIfNoteIsNotNull(note);
+ checkIfUserCanWrite(noteId, "Insufficient privileges you cannot update this paragraph config");
+ Paragraph p = note.getParagraph(paragraphId);
+ checkIfParagraphIsNotNull(p);
+
+ Map<String, Object> newConfig = gson.fromJson(message, HashMap.class);
+ if (newConfig == null || newConfig.isEmpty()) {
+ LOG.warn("{} is trying to update paragraph {} of note {} with empty config",
+ user, paragraphId, noteId);
+ throw new BadRequestException("paragraph config cannot be empty");
+ }
+ Map<String, Object> origConfig = p.getConfig();
+ for (String key : newConfig.keySet()) {
+ origConfig.put(key, newConfig.get(key));
+ }
+
+ p.setConfig(origConfig);
+ AuthenticationInfo subject = new AuthenticationInfo(user);
+ note.persist(subject);
+
+ return new JsonResponse<>(Status.OK, "", p).build();
+ }
+
/**
* Move paragraph REST API
*
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/24187b0a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/BadRequestException.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/BadRequestException.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/BadRequestException.java
new file mode 100644
index 0000000..944cedc
--- /dev/null
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/BadRequestException.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zeppelin.rest.exception;
+
+import org.apache.zeppelin.utils.ExceptionUtils;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
+
+/**
+ * BadRequestException handler for WebApplicationException.
+ */
+public class BadRequestException extends WebApplicationException {
+
+ public BadRequestException() {
+ super(ExceptionUtils.jsonResponse(BAD_REQUEST));
+ }
+
+ private static Response badRequestJson(String message) {
+ return ExceptionUtils.jsonResponseContent(BAD_REQUEST, message);
+ }
+
+ public BadRequestException(Throwable cause, String message) {
+ super(cause, badRequestJson(message));
+ }
+
+ public BadRequestException(String message) {
+ super(badRequestJson(message));
+ }
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/24187b0a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java
index 15b6903..0fdb810 100644
--- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java
@@ -94,7 +94,7 @@ public class NotebookRestApiTest extends AbstractTestRestApi {
Note note2 = ZeppelinServer.notebook.createNote(anonymous);
// Set only writers
jsonRequest = "{\"readers\":[],\"owners\":[]," +
- "\"writers\":[\"admin-team\"]}";
+ "\"writers\":[\"admin-team\"]}";
put = httpPut("/notebook/" + note2.getId() + "/permissions/", jsonRequest);
assertThat("test update method:", put, isAllowed());
put.releaseConnection();
@@ -175,7 +175,32 @@ public class NotebookRestApiTest extends AbstractTestRestApi {
//cleanup
ZeppelinServer.notebook.removeNote(note1.getId(), anonymous);
ZeppelinServer.notebook.removeNote(clonedNoteId, anonymous);
+ }
+
+ @Test
+ public void testUpdateParagraphConfig() throws IOException {
+ Note note = ZeppelinServer.notebook.createNote(anonymous);
+ String noteId = note.getId();
+ Paragraph p = note.addParagraph();
+ assertNull(p.getConfig().get("colWidth"));
+ String paragraphId = p.getId();
+ String jsonRequest = "{\"colWidth\": 6.0}";
+
+ PutMethod put = httpPut("/notebook/" + noteId + "/paragraph/" + paragraphId +"/config", jsonRequest);
+ assertThat("test testUpdateParagraphConfig:", put, isAllowed());
+ Map<String, Object> resp = gson.fromJson(put.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {
+ }.getType());
+ Map<String, Object> respBody = (Map<String, Object>) resp.get("body");
+ Map<String, Object> config = (Map<String, Object>) respBody.get("config");
+ put.releaseConnection();
+
+ assertEquals(config.get("colWidth"), 6.0);
+ note = ZeppelinServer.notebook.getNote(noteId);
+ assertEquals(note.getParagraph(paragraphId).getConfig().get("colWidth"), 6.0);
+
+ //cleanup
+ ZeppelinServer.notebook.removeNote(noteId, anonymous);
}
@Test