mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
ZEPPELIN-509 Introduce a new REST API: get notebook information
* Added REST API version of "get notebook information" based on websocket implementation * Added unit test to test this feature * Added description of "get notebook information" to rest-notebook.md
This commit is contained in:
parent
42100550f3
commit
f63c4fd118
3 changed files with 328 additions and 1 deletions
|
|
@ -33,7 +33,7 @@ limitations under the License.
|
|||
<br />
|
||||
### Notebook REST API list
|
||||
|
||||
Notebooks REST API supports the following operations: List, Create, Delete & Clone as detailed in the following table
|
||||
Notebooks REST API supports the following operations: List, Create, Get, Delete, Clone, Run as detailed in the following table
|
||||
|
||||
<table class="table-configuration">
|
||||
<col width="200">
|
||||
|
|
@ -101,6 +101,288 @@ limitations under the License.
|
|||
</tr>
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
|
||||
<table class="table-configuration">
|
||||
<col width="200">
|
||||
<tr>
|
||||
<th>Get notebook</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>This ```GET``` method retrieves an existing notebook's information using the given id.
|
||||
The body field of the returned JSON contain information about paragraphs in the notebook.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>URL</td>
|
||||
<td>```http://[zeppelin-server]:[zeppelin-port]/api/notebook/[notebookId]```</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Success code</td>
|
||||
<td>200</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Fail code</td>
|
||||
<td> 500 </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> sample JSON response </td>
|
||||
<td><pre>
|
||||
{
|
||||
"status": "OK",
|
||||
"message": "",
|
||||
"body": {
|
||||
"paragraphs": [
|
||||
{
|
||||
"title": "Load data into table",
|
||||
"text": "import org.apache.commons.io.IOUtils\nimport java.net.URL\nimport java.nio.charset.Charset\n\n// Zeppelin creates and injects sc (SparkContext) and sqlContext (HiveContext or SqlContext)\n// So you don't need create them manually\n\n// load bank data\nval bankText = sc.parallelize(\n IOUtils.toString(\n new URL(\"https://s3.amazonaws.com/apache-zeppelin/tutorial/bank/bank.csv\"),\n Charset.forName(\"utf8\")).split(\"\n\"))\n\ncase class Bank(age: Integer, job: String, marital: String, education: String, balance: Integer)\n\nval bank = bankText.map(s => s.split(\";\")).filter(s => s(0) != \"\"age\"\").map(\n s => Bank(s(0).toInt, \n s(1).replaceAll(\"\"\", \"\"),\n s(2).replaceAll(\"\"\", \"\"),\n s(3).replaceAll(\"\"\", \"\"),\n s(5).replaceAll(\"\"\", \"\").toInt\n )\n).toDF()\nbank.registerTempTable(\"bank\")",
|
||||
"config": {
|
||||
"colWidth": 12,
|
||||
"graph": {
|
||||
"mode": "table",
|
||||
"height": 300,
|
||||
"optionOpen": false,
|
||||
"keys": [],
|
||||
"values": [],
|
||||
"groups": [],
|
||||
"scatter": {}
|
||||
},
|
||||
"title": true
|
||||
},
|
||||
"settings": {
|
||||
"params": {},
|
||||
"forms": {}
|
||||
},
|
||||
"jobName": "paragraph_1423500779206_-1502780787",
|
||||
"id": "20150210-015259_1403135953",
|
||||
"result": {
|
||||
"code": "SUCCESS",
|
||||
"type": "TEXT",
|
||||
"msg": "import org.apache.commons.io.IOUtils\nimport java.net.URL\nimport java.nio.charset.Charset\nbankText: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[32] at parallelize at <console>:65\ndefined class Bank\nbank: org.apache.spark.sql.DataFrame = [age: int, job: string, marital: string, education: string, balance: int]\n"
|
||||
},
|
||||
"dateCreated": "Feb 10, 2015 1:52:59 AM",
|
||||
"dateStarted": "Jul 3, 2015 1:43:40 PM",
|
||||
"dateFinished": "Jul 3, 2015 1:43:45 PM",
|
||||
"status": "FINISHED",
|
||||
"progressUpdateIntervalMs": 500
|
||||
},
|
||||
{
|
||||
"text": "%sql \nselect age, count(1) value\nfrom bank \nwhere age < 30 \ngroup by age \norder by age",
|
||||
"config": {
|
||||
"colWidth": 4,
|
||||
"graph": {
|
||||
"mode": "multiBarChart",
|
||||
"height": 300,
|
||||
"optionOpen": false,
|
||||
"keys": [
|
||||
{
|
||||
"name": "age",
|
||||
"index": 0,
|
||||
"aggr": "sum"
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"name": "value",
|
||||
"index": 1,
|
||||
"aggr": "sum"
|
||||
}
|
||||
],
|
||||
"groups": [],
|
||||
"scatter": {
|
||||
"xAxis": {
|
||||
"name": "age",
|
||||
"index": 0,
|
||||
"aggr": "sum"
|
||||
},
|
||||
"yAxis": {
|
||||
"name": "value",
|
||||
"index": 1,
|
||||
"aggr": "sum"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"params": {},
|
||||
"forms": {}
|
||||
},
|
||||
"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
|
||||
},
|
||||
{
|
||||
"text": "%sql \nselect age, count(1) value \nfrom bank \nwhere age < ${maxAge=30} \ngroup by age \norder by age",
|
||||
"config": {
|
||||
"colWidth": 4,
|
||||
"graph": {
|
||||
"mode": "multiBarChart",
|
||||
"height": 300,
|
||||
"optionOpen": false,
|
||||
"keys": [
|
||||
{
|
||||
"name": "age",
|
||||
"index": 0,
|
||||
"aggr": "sum"
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"name": "value",
|
||||
"index": 1,
|
||||
"aggr": "sum"
|
||||
}
|
||||
],
|
||||
"groups": [],
|
||||
"scatter": {
|
||||
"xAxis": {
|
||||
"name": "age",
|
||||
"index": 0,
|
||||
"aggr": "sum"
|
||||
},
|
||||
"yAxis": {
|
||||
"name": "value",
|
||||
"index": 1,
|
||||
"aggr": "sum"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"params": {
|
||||
"maxAge": "35"
|
||||
},
|
||||
"forms": {
|
||||
"maxAge": {
|
||||
"name": "maxAge",
|
||||
"defaultValue": "30",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"jobName": "paragraph_1423720444030_-1424110477",
|
||||
"id": "20150212-145404_867439529",
|
||||
"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\n30\t150\n31\t199\n32\t224\n33\t186\n34\t231\n"
|
||||
},
|
||||
"dateCreated": "Feb 12, 2015 2:54:04 PM",
|
||||
"dateStarted": "Jul 3, 2015 1:43:28 PM",
|
||||
"dateFinished": "Jul 3, 2015 1:43:29 PM",
|
||||
"status": "FINISHED",
|
||||
"progressUpdateIntervalMs": 500
|
||||
},
|
||||
{
|
||||
"text": "%sql \nselect age, count(1) value \nfrom bank \nwhere marital=\"${marital=single,single|divorced|married}\" \ngroup by age \norder by age",
|
||||
"config": {
|
||||
"colWidth": 4,
|
||||
"graph": {
|
||||
"mode": "multiBarChart",
|
||||
"height": 300,
|
||||
"optionOpen": false,
|
||||
"keys": [
|
||||
{
|
||||
"name": "age",
|
||||
"index": 0,
|
||||
"aggr": "sum"
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"name": "value",
|
||||
"index": 1,
|
||||
"aggr": "sum"
|
||||
}
|
||||
],
|
||||
"groups": [],
|
||||
"scatter": {
|
||||
"xAxis": {
|
||||
"name": "age",
|
||||
"index": 0,
|
||||
"aggr": "sum"
|
||||
},
|
||||
"yAxis": {
|
||||
"name": "value",
|
||||
"index": 1,
|
||||
"aggr": "sum"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"params": {
|
||||
"marital": "single"
|
||||
},
|
||||
"forms": {
|
||||
"marital": {
|
||||
"name": "marital",
|
||||
"defaultValue": "single",
|
||||
"options": [
|
||||
{
|
||||
"value": "single"
|
||||
},
|
||||
{
|
||||
"value": "divorced"
|
||||
},
|
||||
{
|
||||
"value": "married"
|
||||
}
|
||||
],
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"jobName": "paragraph_1423836262027_-210588283",
|
||||
"id": "20150213-230422_1600658137",
|
||||
"result": {
|
||||
"code": "SUCCESS",
|
||||
"type": "TABLE",
|
||||
"msg": "age\tvalue\n19\t4\n20\t3\n21\t7\n22\t9\n23\t17\n24\t13\n25\t33\n26\t56\n27\t64\n28\t78\n29\t56\n30\t92\n31\t86\n32\t105\n33\t61\n34\t75\n35\t46\n36\t50\n37\t43\n38\t44\n39\t30\n40\t25\n41\t19\n42\t23\n43\t21\n44\t20\n45\t15\n46\t14\n47\t12\n48\t12\n49\t11\n50\t8\n51\t6\n52\t9\n53\t4\n55\t3\n56\t3\n57\t2\n58\t7\n59\t2\n60\t5\n66\t2\n69\t1\n"
|
||||
},
|
||||
"dateCreated": "Feb 13, 2015 11:04:22 PM",
|
||||
"dateStarted": "Jul 3, 2015 1:43:33 PM",
|
||||
"dateFinished": "Jul 3, 2015 1:43:34 PM",
|
||||
"status": "FINISHED",
|
||||
"progressUpdateIntervalMs": 500
|
||||
},
|
||||
{
|
||||
"config": {},
|
||||
"settings": {
|
||||
"params": {},
|
||||
"forms": {}
|
||||
},
|
||||
"jobName": "paragraph_1435955447812_-158639899",
|
||||
"id": "20150703-133047_853701097",
|
||||
"dateCreated": "Jul 3, 2015 1:30:47 PM",
|
||||
"status": "READY",
|
||||
"progressUpdateIntervalMs": 500
|
||||
}
|
||||
],
|
||||
"name": "Zeppelin Tutorial",
|
||||
"id": "2A94M5J1Z",
|
||||
"angularObjects": {},
|
||||
"config": {
|
||||
"looknfeel": "default"
|
||||
},
|
||||
"info": {}
|
||||
}
|
||||
}
|
||||
</pre></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
|
||||
<table class="table-configuration">
|
||||
|
|
|
|||
|
|
@ -125,6 +125,17 @@ public class NotebookRestApi {
|
|||
return new JsonResponse(Status.OK, "", notesInfo ).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{notebookId}")
|
||||
public Response getNotebook(@PathParam("notebookId") String notebookId) throws IOException {
|
||||
Note note = notebook.getNote(notebookId);
|
||||
if (note == null) {
|
||||
return new JsonResponse(Status.NOT_FOUND, "note not found.").build();
|
||||
}
|
||||
|
||||
return new JsonResponse(Status.OK, "", note).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new note REST API
|
||||
* @param message - JSON with new note name
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import org.apache.zeppelin.interpreter.InterpreterSetting;
|
|||
import org.apache.zeppelin.notebook.Note;
|
||||
import org.apache.zeppelin.notebook.Paragraph;
|
||||
import org.apache.zeppelin.scheduler.Job.Status;
|
||||
import org.apache.zeppelin.server.JsonResponse;
|
||||
import org.apache.zeppelin.server.ZeppelinServer;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
|
@ -190,6 +191,39 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
ZeppelinServer.notebook.removeNote(note.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNotebookInfo() throws IOException {
|
||||
LOG.info("testGetNotebookInfo");
|
||||
// Create note to get info
|
||||
Note note = ZeppelinServer.notebook.createNote();
|
||||
assertNotNull("can't create new note", note);
|
||||
note.setName("note");
|
||||
Paragraph paragraph = note.addParagraph();
|
||||
Map config = paragraph.getConfig();
|
||||
config.put("enabled", true);
|
||||
paragraph.setConfig(config);
|
||||
String paragraphText = "%md This is my new paragraph in my new note";
|
||||
paragraph.setText(paragraphText);
|
||||
note.persist();
|
||||
|
||||
String sourceNoteID = note.getId();
|
||||
GetMethod get = httpGet("/notebook/" + sourceNoteID);
|
||||
LOG.info("testGetNotebookInfo \n" + get.getResponseBodyAsString());
|
||||
assertThat("test notebook get method:", get, isAllowed());
|
||||
|
||||
Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {
|
||||
}.getType());
|
||||
|
||||
assertNotNull(resp);
|
||||
assertEquals("OK", resp.get("status"));
|
||||
|
||||
Map<String, Object> body = (Map<String, Object>) resp.get("body");
|
||||
List<Map<String, Object>> paragraphs = (List<Map<String, Object>>) body.get("paragraphs");
|
||||
|
||||
assertTrue(paragraphs.size() > 0);
|
||||
assertEquals(paragraphText, paragraphs.get(0).get("text"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotebookCreateWithName() throws IOException {
|
||||
String noteName = "Test note name";
|
||||
|
|
|
|||
Loading…
Reference in a new issue