Repository: zeppelin Updated Branches: refs/heads/master 051929db3 -> bba6ddd24
[ZEPPELIN-1268] As an enduser, I would like to embed paragraph and refresh the content of it in my custom UI ### What is this PR for? This pull request is to add the below options so when someone develops a custom UI it would ease them. 1. Add a new option "Get paragraph id" in the notebook UI 2. Add a new REST API to get the status of a single paragraph ### What type of PR is it? Improvement ### Todos * Need to update the REST APIs documentation http://zeppelin.apache.org/docs/0.7.0-SNAPSHOT/rest-api/rest-notebook.html#get-the-status-of-all-paragraphs ### What is the Jira issue? * https://issues.apache.org/jira/browse/ZEPPELIN-1268 ### How should this be tested? * Navigate to the notebook UI and a new option "Get paragraph id" will be shown for each paragraph and on clicking on it, the paragraph id would be alerted * The new REST API http://%5Bzeppelin-server%5D:%5Bzeppelin-port%5D/api/notebook/job/%5BnotebookId%5D/%5BparagraphId%5D could be accessed to get the status of a single paragraph. ### Screenshots (if appropriate) ### Questions: Author: Kavin Kumar <[email protected]> Author: Kavin <[email protected]> Closes #1262 from kavinkumarks/zeppelin-1268-custom-UI and squashes the following commits: 88a0627 [Kavin Kumar] Reverted UI code, added unit test for the new REST API and updated docs 4d11553 [Kavin] Changes to show new option to get paragraph id in notebook UI and new REST API to get status of a single paragraph Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/bba6ddd2 Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/bba6ddd2 Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/bba6ddd2 Branch: refs/heads/master Commit: bba6ddd2496d5f73354f2e5d510e2f989b93165f Parents: 051929d Author: Kavin Kumar <[email protected]> Authored: Fri Aug 5 01:21:01 2016 +0530 Committer: Jongyoul Lee <[email protected]> Committed: Thu Aug 18 14:50:11 2016 +0900 ---------------------------------------------------------------------- docs/rest-api/rest-notebook.md | 37 ++++++++++++++++++ .../apache/zeppelin/rest/NotebookRestApi.java | 29 ++++++++++++++ .../zeppelin/rest/NotebookRestApiTest.java | 22 +++++++++++ .../java/org/apache/zeppelin/notebook/Note.java | 40 ++++++++++++++------ 4 files changed, 116 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/bba6ddd2/docs/rest-api/rest-notebook.md ---------------------------------------------------------------------- diff --git a/docs/rest-api/rest-notebook.md b/docs/rest-api/rest-notebook.md index 1275740..fa96b6e 100644 --- a/docs/rest-api/rest-notebook.md +++ b/docs/rest-api/rest-notebook.md @@ -393,6 +393,43 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple </table> <br/> +### Get the status of a single paragraph + <table class="table-configuration"> + <col width="200"> + <tr> + <td>Description</td> + <td>This ```GET``` method gets the status of a single paragraph by the given notebook and paragraph id. + The body field of the returned JSON contains of the array that compose of the paragraph id, paragraph status, paragraph finish date, paragraph started date. + </td> + </tr> + <tr> + <td>URL</td> + <td>```http://[zeppelin-server]:[zeppelin-port]/api/notebook/job/[notebookId]/[paragraphId]```</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", + "body": { + "id":"20151121-212654\_766735423", + "status":"FINISHED", + "finished":"Tue Nov 24 14:21:40 KST 2015", + "started":"Tue Nov 24 14:21:39 KST 2015" + } +}</pre></td> + </tr> + </table> + +<br/> ### Run a paragraph <table class="table-configuration"> <col width="200"> http://git-wip-us.apache.org/repos/asf/zeppelin/blob/bba6ddd2/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 f33bef1..a724003 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 @@ -529,6 +529,35 @@ public class NotebookRestApi { } /** + * Get notebook paragraph job status REST API + * + * @param notebookId ID of Notebook + * @param paragraphId ID of Paragraph + * @return JSON with status.OK + * @throws IOException, IllegalArgumentException + */ + @GET + @Path("job/{notebookId}/{paragraphId}") + @ZeppelinApi + public Response getNoteParagraphJobStatus(@PathParam("notebookId") String notebookId, + @PathParam("paragraphId") String paragraphId) + throws IOException, IllegalArgumentException { + LOG.info("get notebook paragraph job status."); + Note note = notebook.getNote(notebookId); + if (note == null) { + return new JsonResponse<>(Status.NOT_FOUND, "note not found.").build(); + } + + Paragraph paragraph = note.getParagraph(paragraphId); + if (paragraph == null) { + return new JsonResponse<>(Status.NOT_FOUND, "paragraph not found.").build(); + } + + return new JsonResponse<>(Status.OK, null, note.generateSingleParagraphInfo(paragraphId)). + build(); + } + + /** * Run paragraph job REST API * * @param message - JSON with params if user wants to update dynamic form's value http://git-wip-us.apache.org/repos/asf/zeppelin/blob/bba6ddd2/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 94e7fa8..b06c7ca 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 @@ -122,6 +122,28 @@ public class NotebookRestApiTest extends AbstractTestRestApi { ZeppelinServer.notebook.removeNote(note2.getId(), null); } + + @Test + public void testGetNoteParagraphJobStatus() throws IOException { + Note note1 = ZeppelinServer.notebook.createNote(null); + note1.addParagraph(); + + String paragraphId = note1.getLastParagraph().getId(); + + GetMethod get = httpGet("/notebook/job/" + note1.getId() + "/" + paragraphId); + assertThat(get, isAllowed()); + Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() { + }.getType()); + Map<String, Set<String>> paragraphStatus = (Map<String, Set<String>>) resp.get("body"); + + // Check id and status have proper value + assertEquals(paragraphStatus.get("id"), paragraphId); + assertEquals(paragraphStatus.get("status"), "READY"); + + //cleanup + ZeppelinServer.notebook.removeNote(note1.getId(), null); + + } } http://git-wip-us.apache.org/repos/asf/zeppelin/blob/bba6ddd2/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java index 9106cf5..d9a3f96 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java @@ -411,24 +411,40 @@ public class Note implements Serializable, ParagraphJobListener { List<Map<String, String>> paragraphsInfo = new LinkedList<>(); synchronized (paragraphs) { for (Paragraph p : paragraphs) { - Map<String, String> info = new HashMap<>(); - info.put("id", p.getId()); - info.put("status", p.getStatus().toString()); - if (p.getDateStarted() != null) { - info.put("started", p.getDateStarted().toString()); - } - if (p.getDateFinished() != null) { - info.put("finished", p.getDateFinished().toString()); - } - if (p.getStatus().isRunning()) { - info.put("progress", String.valueOf(p.progress())); - } + Map<String, String> info = populatePragraphInfo(p); paragraphsInfo.add(info); } } return paragraphsInfo; } + public Map<String, String> generateSingleParagraphInfo(String paragraphId) { + synchronized (paragraphs) { + for (Paragraph p : paragraphs) { + if (p.getId().equals(paragraphId)) { + return populatePragraphInfo(p); + } + } + return new HashMap<>(); + } + } + + private Map<String, String> populatePragraphInfo(Paragraph p) { + Map<String, String> info = new HashMap<>(); + info.put("id", p.getId()); + info.put("status", p.getStatus().toString()); + if (p.getDateStarted() != null) { + info.put("started", p.getDateStarted().toString()); + } + if (p.getDateFinished() != null) { + info.put("finished", p.getDateFinished().toString()); + } + if (p.getStatus().isRunning()) { + info.put("progress", String.valueOf(p.progress())); + } + return info; + } + /** * Run all paragraphs sequentially. */
