From 8dcf02c0cf0458957e1eaefd00a9127ad878d388 Mon Sep 17 00:00:00 2001 From: Jungtaek Lim Date: Wed, 16 Dec 2015 17:12:40 +0900 Subject: [PATCH] ZEPPELIN-507 Expand "run paragraph" of REST API to specify params * Modified "run paragraph" to specify params * which means we want to update dynamic form's value * Added unit test to test this feature * Updated rest-notebook.md to reflect new json request --- docs/rest-api/rest-notebook.md | 12 +++++ .../apache/zeppelin/rest/NotebookRestApi.java | 34 ++++++++++---- .../RunParagraphWithParametersRequest.java | 35 ++++++++++++++ .../zeppelin/rest/ZeppelinRestApiTest.java | 47 ++++++++++++++++++- 4 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/RunParagraphWithParametersRequest.java diff --git a/docs/rest-api/rest-notebook.md b/docs/rest-api/rest-notebook.md index 1bb0e531c8..c7c0043e0c 100644 --- a/docs/rest-api/rest-notebook.md +++ b/docs/rest-api/rest-notebook.md @@ -290,6 +290,18 @@ limitations under the License. Fail code 500 + + sample JSON input (optional, only needed when if you want to update dynamic form's value) +
+{
+  "name": "name of new notebook",
+  "params": {
+    "formLabel1": "value1",
+    "formLabel2": "value2"
+  }
+}
+      
+ sample JSON response
{"status":"OK"}
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 b3f912ed2c..77900b7127 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 @@ -26,14 +26,13 @@ import javax.ws.rs.*; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +import org.apache.commons.lang3.StringUtils; +import org.apache.zeppelin.display.Input; import org.apache.zeppelin.interpreter.InterpreterSetting; import org.apache.zeppelin.notebook.Note; import org.apache.zeppelin.notebook.Notebook; import org.apache.zeppelin.notebook.Paragraph; -import org.apache.zeppelin.rest.message.CronRequest; -import org.apache.zeppelin.rest.message.InterpreterSettingListForNoteBind; -import org.apache.zeppelin.rest.message.NewInterpreterSettingRequest; -import org.apache.zeppelin.rest.message.NewNotebookRequest; +import org.apache.zeppelin.rest.message.*; import org.apache.zeppelin.server.JsonResponse; import org.apache.zeppelin.server.ZeppelinServer; import org.apache.zeppelin.socket.NotebookServer; @@ -255,26 +254,41 @@ public class NotebookRestApi { /** * Run paragraph job REST API - * @param + * @param message - JSON with params if user wants to update dynamic form's value + * null, empty string, empty json if user doesn't want to update * @return JSON with status.OK * @throws IOException, IllegalArgumentException */ @POST @Path("job/{notebookId}/{paragraphId}") public Response runParagraph(@PathParam("notebookId") String notebookId, - @PathParam("paragraphId") String paragraphId) throws + @PathParam("paragraphId") String paragraphId, + String message) throws IOException, IllegalArgumentException { - logger.info("run paragraph job {} {} ", notebookId, paragraphId); + logger.info("run paragraph job {} {} {}", notebookId, paragraphId, message); + Note note = notebook.getNote(notebookId); if (note == null) { return new JsonResponse(Status.NOT_FOUND, "note not found.").build(); } - - if (note.getParagraph(paragraphId) == null) { + + Paragraph paragraph = note.getParagraph(paragraphId); + if (paragraph == null) { return new JsonResponse(Status.NOT_FOUND, "paragraph not found.").build(); } - note.run(paragraphId); + // handle params if presented + if (!StringUtils.isEmpty(message)) { + RunParagraphWithParametersRequest request = gson.fromJson(message, + RunParagraphWithParametersRequest.class); + Map paramsForUpdating = request.getParams(); + if (paramsForUpdating != null) { + paragraph.settings.getParams().putAll(paramsForUpdating); + note.persist(); + } + } + + note.run(paragraph.getId()); return new JsonResponse(Status.OK).build(); } diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/RunParagraphWithParametersRequest.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/RunParagraphWithParametersRequest.java new file mode 100644 index 0000000000..7d8095f113 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/RunParagraphWithParametersRequest.java @@ -0,0 +1,35 @@ +/* + * 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.message; + +import java.util.Map; + +/** + * RunParagraphWithParametersRequest rest api request message + */ +public class RunParagraphWithParametersRequest { + Map params; + + public RunParagraphWithParametersRequest() { + + } + + public Map getParams() { + return params; + } +} diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java index 0a58fb06c7..a7c733889e 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java @@ -362,7 +362,52 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi { //cleanup ZeppelinServer.notebook.removeNote(note.getId()); } - + + @Test + public void testRunParagraphWithParams() throws IOException, InterruptedException { + LOG.info("testRunParagraphWithParams"); + // Create note to run test. + Note note = ZeppelinServer.notebook.createNote(); + assertNotNull("can't create new note", note); + note.setName("note for run test"); + Paragraph paragraph = note.addParagraph(); + + Map config = paragraph.getConfig(); + config.put("enabled", true); + paragraph.setConfig(config); + + paragraph.setText("%spark\nval param = z.input(\"param\").toString\nprintln(param)"); + note.persist(); + String noteID = note.getId(); + + note.runAll(); + // wait until job is finished or timeout. + int timeout = 1; + while (!paragraph.isTerminated()) { + Thread.sleep(1000); + if (timeout++ > 30) { + LOG.info("testRunParagraphWithParams timeout job."); + break; + } + } + + // Call Run paragraph REST API + PostMethod postParagraph = httpPost("/notebook/job/" + noteID + "/" + paragraph.getId(), + "{\"params\": {\"param\": \"hello\", \"param2\": \"world\"}}"); + assertThat("test paragraph run:", postParagraph, isAllowed()); + postParagraph.releaseConnection(); + Thread.sleep(1000); + + Note retrNote = ZeppelinServer.notebook.getNote(noteID); + Paragraph retrParagraph = retrNote.getParagraph(paragraph.getId()); + Map params = retrParagraph.settings.getParams(); + assertEquals("hello", params.get("param")); + assertEquals("world", params.get("param2")); + + //cleanup + ZeppelinServer.notebook.removeNote(note.getId()); + } + @Test public void testCronJobs() throws InterruptedException, IOException{ // create a note and a paragraph