Add rest api for paragraph config update

This commit is contained in:
Mina Lee 2016-11-03 22:28:25 +09:00
parent cb175032a2
commit c8357ca58e
4 changed files with 230 additions and 4 deletions

View file

@ -808,6 +808,127 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple
</tr>
</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">
@ -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 />

View file

@ -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
*

View file

@ -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));
}
}

View file

@ -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