Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3645354
Rest Apis to export/import
ramdevarajan Jan 9, 2016
0e94dce
add documentation
ramdevarajan Jan 9, 2016
9b64a66
fixed alignments
ramdevarajan Jan 9, 2016
ecb8f1e
Formatting for google style
ramdevarajan Jan 9, 2016
6c19668
Changed http put to Http post for REST import
ramdevarajan Jan 11, 2016
7351f31
Moved export/import methods to Notebook.java
ramdevarajan Jan 11, 2016
db8b016
added note not found check for export
ramdevarajan Jan 11, 2016
b080d7d
Merge pull request #1 from apache/master
ramaswamydevarajan Jan 12, 2016
630664c
Merge pull request #2 from apache/master
ramaswamydevarajan Jan 13, 2016
ec14034
Merge pull request #3 from apache/master
ramaswamydevarajan Jan 13, 2016
db6a580
changed HTTP Put to POST in the docs
ramaswamydevarajan Jan 13, 2016
4be62f6
Merge branch 'master' of [email protected]:swakrish/incubator-zeppelin.git
ramaswamydevarajan Jan 13, 2016
e928c14
changed doc to make it http post
ramaswamydevarajan Jan 13, 2016
e282958
Changed websocket import to use common code
ramaswamydevarajan Jan 16, 2016
4cb69be
Merge pull request #4 from apache/master
ramaswamydevarajan Jan 16, 2016
270e17b
changed soureJSON to sourceJson
ramaswamydevarajan Jan 19, 2016
f8a992c
Merge branch 'master' of [email protected]:swakrish/incubator-zeppelin.git
ramaswamydevarajan Jan 19, 2016
f8bf1f3
Merge pull request #5 from apache/master
ramaswamydevarajan Jan 19, 2016
869b48f
logging the error
ramaswamydevarajan Jan 21, 2016
f5b0805
Merge branch 'master' of [email protected]:swakrish/incubator-zeppelin.git
ramaswamydevarajan Jan 21, 2016
042d9af
Merge pull request #6 from apache/master
ramaswamydevarajan Jan 21, 2016
83e7a6d
Merge pull request #7 from apache/master
ramaswamydevarajan Jan 22, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 110 additions & 1 deletion docs/rest-api/rest-notebook.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ limitations under the License.
<br />
### Notebook REST API list

Notebooks REST API supports the following operations: List, Create, Get, Delete, Clone, Run as detailed in the following table
Notebooks REST API supports the following operations: List, Create, Get, Delete, Clone, Run, Export, Import as detailed in the following table

<table class="table-configuration">
<col width="200">
Expand Down Expand Up @@ -773,3 +773,112 @@ limitations under the License.
</tr>
</table>



<table class="table-configuration">
<col width="200">
<tr>
<th>Export notebook</th>
<th></th>
</tr>
<tr>
<td>Description</td>
<td>This ```GET``` method exports a notebook by the given id and gernerates a JSON
</td>
</tr>
<tr>
<td>URL</td>
<td>```http://[zeppelin-server]:[zeppelin-port]/api/notebook/export/[notebookId]```</td>
</tr>
<tr>
<td>Success code</td>
<td>201</td>
</tr>
<tr>
<td> Fail code</td>
<td> 500 </td>
</tr>
<td> sample JSON response </td>
<td><pre>{
"paragraphs": [
{
"text": "%md This is my new paragraph in my new note",
"dateUpdated": "Jan 8, 2016 4:49:38 PM",
"config": {
"enabled": true
},
"settings": {
"params": {},
"forms": {}
},
"jobName": "paragraph_1452300578795_1196072540",
"id": "20160108-164938_1685162144",
"dateCreated": "Jan 8, 2016 4:49:38 PM",
"status": "READY",
"progressUpdateIntervalMs": 500
}
],
"name": "source note for export",
"id": "2B82H3RR1",
"angularObjects": {},
"config": {},
"info": {}
}</pre></td>
</tr>
</table>

<table class="table-configuration">
<col width="200">
<tr>
<th>Export notebook</th>
<th></th>
</tr>
<tr>
<td>Description</td>
<td>This ```POST``` method imports a notebook from the notebook JSON input
</td>
</tr>
<tr>
<td>URL</td>
<td>```http://[zeppelin-server]:[zeppelin-port]/api/notebook/import```</td>
</tr>
<tr>
<td>Success code</td>
<td>201</td>
</tr>
<tr>
<td> Fail code</td>
<td> 500 </td>
</tr>
<td> sample JSON input </td>
<td><pre>{
"paragraphs": [
{
"text": "%md This is my new paragraph in my new note",
"dateUpdated": "Jan 8, 2016 4:49:38 PM",
"config": {
"enabled": true
},
"settings": {
"params": {},
"forms": {}
},
"jobName": "paragraph_1452300578795_1196072540",
"id": "20160108-164938_1685162144",
"dateCreated": "Jan 8, 2016 4:49:38 PM",
"status": "READY",
"progressUpdateIntervalMs": 500
}
],
"name": "source note for export",
"id": "2B82H3RR1",
"angularObjects": {},
"config": {},
"info": {}
}</pre></td>
<tr>
<td> sample JSON response </td>
<td><pre>"status": "CREATED","message": "","body": "2AZPHY918"}</pre></td>
</tr>
</tr>
</table>
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;
import java.io.StringReader;
/**
* Rest api endpoint for the noteBook.
*/
Expand Down Expand Up @@ -146,6 +148,34 @@ public Response getNotebook(@PathParam("notebookId") String notebookId) throws I
return new JsonResponse<>(Status.OK, "", note).build();
}

/**
* export note REST API
*
* @param
* @return note JSON with status.OK
* @throws IOException
*/
@GET
@Path("export/{id}")
public Response exportNoteBook(@PathParam("id") String noteId) throws IOException {
String exportJson = notebook.exportNote(noteId);
return new JsonResponse(Status.OK, "", exportJson).build();
}

/**
* import new note REST API
*
* @param req - notebook Json
* @return JSON with new note ID
* @throws IOException
*/
@POST
@Path("import")
public Response importNotebook(String req) throws IOException {
Note newNote = notebook.importNote(req, null);
return new JsonResponse<>(Status.CREATED, "", newNote.getId()).build();
}

/**
* Create new note REST API
* @param message - JSON with new note name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,56 +494,15 @@ private void cloneNote(NotebookSocket conn, Notebook notebook, Message fromMessa

protected Note importNote(NotebookSocket conn, Notebook notebook, Message fromMessage)
throws IOException {

Note note = notebook.createNote();
Note note = null;
if (fromMessage != null) {
String noteName = (String) ((Map) fromMessage.get("notebook")).get("name");
if (noteName == null || noteName.isEmpty()) {
noteName = "Note " + note.getId();
}
note.setName(noteName);
ArrayList<Map> paragraphs = ((Map<String, ArrayList>) fromMessage.get("notebook"))
.get("paragraphs");
if (paragraphs.size() > 0) {
for (Map paragraph : paragraphs) {
try {
Paragraph p = note.addParagraph();
String text = (String) paragraph.get("text");
p.setText(text);
p.setTitle((String) paragraph.get("title"));
Map<String, Object> params = (Map<String, Object>) ((Map) paragraph
.get("settings")).get("params");
Map<String, Input> forms = (Map<String, Input>) ((Map) paragraph
.get("settings")).get("forms");
if (params != null) {
p.settings.setParams(params);
}
if (forms != null) {
p.settings.setForms(forms);
}
Map<String, Object> result = (Map) paragraph.get("result");
if (result != null) {
InterpreterResult.Code code = InterpreterResult.Code
.valueOf((String) result.get("code"));
InterpreterResult.Type type = InterpreterResult.Type
.valueOf((String) result.get("type"));
String msg = (String) result.get("msg");
p.setReturn(new InterpreterResult(code, type, msg), null);
}

Map<String, Object> config = (Map<String, Object>) paragraph
.get("config");
p.setConfig(config);
} catch (Exception e) {
LOG.error("Exception while setting parameter in paragraph", e);
}
}
}
String noteJson = gson.toJson(fromMessage.get("notebook"));
note = notebook.importNote(noteJson, noteName);
note.persist();
broadcastNote(note);
broadcastNoteList();
}

note.persist();
broadcastNote(note);
broadcastNoteList();
return note;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,87 @@ public void testDeleteNoteBadId() throws IOException {
}


@Test
public void testExportNotebook() throws IOException {
LOG.info("testExportNotebook");
Note note = ZeppelinServer.notebook.createNote();
assertNotNull("can't create new note", note);
note.setName("source note for export");
Paragraph paragraph = note.addParagraph();
Map config = paragraph.getConfig();
config.put("enabled", true);
paragraph.setConfig(config);
paragraph.setText("%md This is my new paragraph in my new note");
note.persist();
String sourceNoteID = note.getId();
// Call export Notebook REST API
GetMethod get = httpGet("/notebook/export/" + sourceNoteID);
LOG.info("testNotebookExport \n" + get.getResponseBodyAsString());
assertThat("test notebook export method:", get, isAllowed());

Map<String, Object> resp =
gson.fromJson(get.getResponseBodyAsString(),
new TypeToken<Map<String, Object>>() {}.getType());

String exportJSON = (String) resp.get("body");
assertNotNull("Can not find new notejson", exportJSON);
LOG.info("export JSON:=" + exportJSON);
ZeppelinServer.notebook.removeNote(sourceNoteID);
get.releaseConnection();

}

@Test
public void testImportNotebook() throws IOException {
Map<String, Object> resp;
String noteName = "source note for import";
LOG.info("testImortNotebook");
// create test notebook
Note note = ZeppelinServer.notebook.createNote();
assertNotNull("can't create new note", note);
note.setName(noteName);
Paragraph paragraph = note.addParagraph();
Map config = paragraph.getConfig();
config.put("enabled", true);
paragraph.setConfig(config);
paragraph.setText("%md This is my new paragraph in my new note");
note.persist();
String sourceNoteID = note.getId();
// get note content as JSON
String oldJson = getNoteContent(sourceNoteID);
// call notebook post
PostMethod importPost = httpPost("/notebook/import/", oldJson);
assertThat(importPost, isCreated());
resp =
gson.fromJson(importPost.getResponseBodyAsString(),
new TypeToken<Map<String, Object>>() {}.getType());
String importId = (String) resp.get("body");

assertNotNull("Did not get back a notebook id in body", importId);
Note newNote = ZeppelinServer.notebook.getNote(importId);
assertEquals("Compare note names", noteName, newNote.getName());
assertEquals("Compare paragraphs count", note.getParagraphs().size(), newNote.getParagraphs()
.size());
// cleanup
ZeppelinServer.notebook.removeNote(note.getId());
ZeppelinServer.notebook.removeNote(newNote.getId());
importPost.releaseConnection();
}

private String getNoteContent(String id) throws IOException {
GetMethod get = httpGet("/notebook/export/" + id);
assertThat(get, isAllowed());
get.addRequestHeader("Origin", "http://localhost");
Map<String, Object> resp =
gson.fromJson(get.getResponseBodyAsString(),
new TypeToken<Map<String, Object>>() {}.getType());
assertEquals(200, get.getStatusCode());
String body = resp.get("body").toString();
// System.out.println("Body is " + body);
get.releaseConnection();
return body;
}

private void testDeleteNotebook(String notebookId) throws IOException {

DeleteMethod delete = httpDelete(("/notebook/" + notebookId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.zeppelin.notebook;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
Expand Down Expand Up @@ -54,6 +55,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;
/**
* Collection of Notes.
*/
Expand Down Expand Up @@ -150,6 +154,58 @@ public Note createNote(List<String> interpreterIds) throws IOException {
note.persist();
return note;
}

/**
* Export existing note.
* @param noteId - the note ID to clone
* @return Note JSON
* @throws IOException, IllegalArgumentException
*/
public String exportNote(String noteId) throws IOException, IllegalArgumentException {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setPrettyPrinting();
Gson gson = gsonBuilder.create();
Note note = getNote(noteId);
if (note == null) {
throw new IllegalArgumentException(noteId + " not found");
}
return gson.toJson(note);
}

/**
* import JSON as a new note.
* @param sourceJson - the note JSON to import
* @param noteName - the name of the new note
* @return notebook ID
* @throws IOException
*/
public Note importNote(String sourceJson, String noteName) throws IOException {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setPrettyPrinting();
Gson gson = gsonBuilder.create();
JsonReader reader = new JsonReader(new StringReader(sourceJson));
reader.setLenient(true);
Note newNote;
try {
Note oldNote = gson.fromJson(reader, Note.class);
newNote = createNote();
if (noteName != null)
newNote.setName(noteName);
else
newNote.setName(oldNote.getName());
List<Paragraph> paragraphs = oldNote.getParagraphs();
for (Paragraph p : paragraphs) {
newNote.addCloneParagraph(p);
}

newNote.persist();
} catch (IOException e) {
logger.error(e.toString(), e);
throw e;
}

return newNote;
}

/**
* Clone existing note.
Expand Down