This is an automated email from the ASF dual-hosted git repository.

zjffdu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new cb6fa56  [ZEPPELIN-4903]. Add property to zeppelin-site to filter 
unnecessary interpreters
cb6fa56 is described below

commit cb6fa5682c529f2a8e29d39231ec57ae89cbd107
Author: Jeff Zhang <zjf...@apache.org>
AuthorDate: Tue Jun 23 11:09:45 2020 +0800

    [ZEPPELIN-4903]. Add property to zeppelin-site to filter unnecessary 
interpreters
    
    ### What is this PR for?
    This PR introduce 2 properties `zeppelin.interpreter.include` and 
`zeppelin.interpreter.exclude`. User can use these properties to filter out the 
interpreters that he would like to use. Without this PR, user have to manually 
delete corresponding interpreter folders or rebuild zeppelin.
    
    ### What type of PR is it?
    [ Improvement]
    
    ### Todos
    * [ ] - Task
    
    ### What is the Jira issue?
    * https://issues.apache.org/jira/browse/ZEPPELIN-4903
    
    ### How should this be tested?
    * CI pass
    
    ### Screenshots (if appropriate)
    
    ### Questions:
    * Does the licenses files need update? No
    * Is there breaking changes for older versions? No
    * Does this needs documentation? No
    
    Author: Jeff Zhang <zjf...@apache.org>
    
    Closes #3819 from zjffdu/ZEPPELIN-4903 and squashes the following commits:
    
    62a9fcf1e [Jeff Zhang] [ZEPPELIN-4903]. Add property to zeppelin-site to 
filter unnecessary interpreters
---
 conf/zeppelin-site.xml.template                    | 12 +++++
 docs/usage/interpreter/overview.md                 |  6 +++
 .../zeppelin/conf/ZeppelinConfiguration.java       |  3 ++
 .../interpreter/InterpreterSettingManager.java     | 53 ++++++++++++++++++----
 .../interpreter/InterpreterSettingManagerTest.java | 50 ++++++++++++++++++++
 5 files changed, 115 insertions(+), 9 deletions(-)

diff --git a/conf/zeppelin-site.xml.template b/conf/zeppelin-site.xml.template
index be99433..8a47b79 100755
--- a/conf/zeppelin-site.xml.template
+++ b/conf/zeppelin-site.xml.template
@@ -62,6 +62,18 @@
 </property>
 
 <property>
+  <name>zeppelin.interpreter.include</name>
+  <value></value>
+  <description>All the inteprreters that you would like to include. You can 
only specify either 'zeppelin.interpreter.include' or 
'zeppelin.interpreter.exclude'. Specifying them together is not 
allowed.</description>
+</property>
+
+<property>
+  <name>zeppelin.interpreter.exclude</name>
+  <value></value>
+  <description>All the inteprreters that you would like to exclude. You can 
only specify either 'zeppelin.interpreter.include' or 
'zeppelin.interpreter.exclude'. Specifying them together is not 
allowed.</description>
+</property>
+
+<property>
   <name>zeppelin.notebook.homescreen</name>
   <value></value>
   <description>id of notebook to be displayed in homescreen. ex) 2A94M5J1Z 
Empty value displays default home screen</description>
diff --git a/docs/usage/interpreter/overview.md 
b/docs/usage/interpreter/overview.md
index b1bbf60..7584abf 100644
--- a/docs/usage/interpreter/overview.md
+++ b/docs/usage/interpreter/overview.md
@@ -167,3 +167,9 @@ Here's one screenshot of how one running paragraph of flink 
interpreter works.
 
 
 <img 
src="{{BASE_PATH}}/assets/themes/zeppelin/img/docs-img/flink_recovery.gif" 
width="800px">
+
+## Choose Interpreters
+
+By default, Zeppelin will register and display all the interpreters under 
folder `$ZEPPELIN_HOME/interpreters`.
+But you can configure property `zeppelin.interpreter.include` to specify what 
interpreters you want to include or `zeppelin.interpreter.exclude` to specify 
what interpreters you want to exclude.
+Only one of them can be specified, you can not specify them together.
diff --git 
a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
 
b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
index dcb8619..7331a50 100644
--- 
a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
+++ 
b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
@@ -919,6 +919,9 @@ public class ZeppelinConfiguration extends XMLConfiguration 
{
     ZEPPELIN_INTERPRETER_MAX_POOL_SIZE("zeppelin.interpreter.max.poolsize", 
10),
     ZEPPELIN_INTERPRETER_GROUP_DEFAULT("zeppelin.interpreter.group.default", 
"spark"),
     ZEPPELIN_INTERPRETER_OUTPUT_LIMIT("zeppelin.interpreter.output.limit", 
1024 * 100),
+    ZEPPELIN_INTERPRETER_INCLUDES("zeppelin.interpreter.include", ""),
+    ZEPPELIN_INTERPRETER_EXCLUDES("zeppelin.interpreter.exclude", ""),
+
     ZEPPELIN_ENCODING("zeppelin.encoding", "UTF-8"),
     ZEPPELIN_NOTEBOOK_DIR("zeppelin.notebook.dir", "notebook"),
 
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSettingManager.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSettingManager.java
index 8b6a890..558d4b1 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSettingManager.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSettingManager.java
@@ -26,6 +26,7 @@ import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.reflect.TypeToken;
 
+import java.util.Arrays;
 import java.util.LinkedHashMap;
 import java.util.Set;
 import java.util.regex.Matcher;
@@ -80,7 +81,6 @@ import java.lang.reflect.Type;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
-import java.nio.file.DirectoryStream.Filter;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -141,6 +141,8 @@ public class InterpreterSettingManager implements 
NoteEventListener, ClusterEven
   private ConfigStorage configStorage;
   private RemoteInterpreterEventServer interpreterEventServer;
   private Map<String, String> jupyterKernelLanguageMap = new HashMap<>();
+  private List<String> includesInterpreters;
+  private List<String> excludesInterpreters;
 
   @Inject
   public InterpreterSettingManager(ZeppelinConfiguration zeppelinConfiguration,
@@ -243,13 +245,18 @@ public class InterpreterSettingManager implements 
NoteEventListener, ClusterEven
       for (InterpreterSetting interpreterSettingTemplate : 
interpreterSettingTemplates.values()) {
         InterpreterSetting interpreterSetting = new 
InterpreterSetting(interpreterSettingTemplate);
         initInterpreterSetting(interpreterSetting);
-        interpreterSettings.put(interpreterSetting.getId(), 
interpreterSetting);
+        if (shouldRegister(interpreterSetting.getGroup())) {
+          interpreterSettings.put(interpreterSetting.getId(), 
interpreterSetting);
+        }
       }
       return;
     }
 
     //TODO(zjffdu) still ugly (should move all to InterpreterInfoSaving)
     for (InterpreterSetting savedInterpreterSetting : 
infoSaving.interpreterSettings.values()) {
+      if (!shouldRegister(savedInterpreterSetting.getGroup())) {
+        break;
+      }
       
savedInterpreterSetting.setProperties(InterpreterSetting.convertInterpreterProperties(
           savedInterpreterSetting.getProperties()
       ));
@@ -322,15 +329,44 @@ public class InterpreterSettingManager implements 
NoteEventListener, ClusterEven
   }
 
   private void init() throws IOException {
+    this.includesInterpreters =
+            
Arrays.asList(conf.getString(ConfVars.ZEPPELIN_INTERPRETER_INCLUDES).split(","))
+                    .stream()
+                    .filter(t -> !t.isEmpty())
+                    .collect(Collectors.toList());
+    this.excludesInterpreters =
+            
Arrays.asList(conf.getString(ConfVars.ZEPPELIN_INTERPRETER_EXCLUDES).split(","))
+                    .stream()
+                    .filter(t -> !t.isEmpty())
+                    .collect(Collectors.toList());
+    if (!includesInterpreters.isEmpty() && !excludesInterpreters.isEmpty()) {
+      throw new IOException(String.format("%s and %s can not be specified 
together, only one can be set.",
+              ConfVars.ZEPPELIN_INTERPRETER_INCLUDES.getVarName(),
+              ConfVars.ZEPPELIN_INTERPRETER_EXCLUDES.getVarName()));
+    }
     loadJupyterKernelLanguageMap();
     loadInterpreterSettingFromDefaultDir(true);
     loadFromFile();
     saveToFile();
 
-    // must init Recovery after init of InterpreterSettingManagaer
+    // must init Recovery after init of InterpreterSettingManager
     recoveryStorage.init();
   }
 
+  /**
+   * We should only register interpreterSetting when
+   * 1. No setting in 'zeppelin.interpreter.include' and 
'zeppelin.interpreter.exclude'
+   * 2. It is specified in 'zeppelin.interpreter.include'
+   * 3. It is not specified in 'zeppelin.interpreter.exclude'
+   * @param group
+   * @return
+   */
+  private boolean shouldRegister(String group) {
+    return (includesInterpreters.isEmpty() && excludesInterpreters.isEmpty()) 
||
+    (!includesInterpreters.isEmpty() && includesInterpreters.contains(group)) 
||
+            (!excludesInterpreters.isEmpty() && 
!excludesInterpreters.contains(group));
+  }
+
   private void loadJupyterKernelLanguageMap() throws IOException {
     String kernels = 
conf.getString(ConfVars.ZEPPELIN_INTERPRETER_JUPYTER_KERNELS);
     for (String kernel : kernels.split(",")) {
@@ -351,12 +387,11 @@ public class InterpreterSettingManager implements 
NoteEventListener, ClusterEven
     ClassLoader cl = Thread.currentThread().getContextClassLoader();
     if (Files.exists(interpreterDirPath)) {
       for (Path interpreterDir : Files
-          .newDirectoryStream(interpreterDirPath, new Filter<Path>() {
-            @Override
-            public boolean accept(Path entry) throws IOException {
-              return Files.exists(entry) && Files.isDirectory(entry);
-            }
-          })) {
+          .newDirectoryStream(interpreterDirPath,
+                  entry -> Files.exists(entry)
+                          && Files.isDirectory(entry)
+                          && shouldRegister(entry.toFile().getName()))) {
+
         String interpreterDirString = interpreterDir.toString();
         /**
          * Register interpreter by the following ordering
diff --git 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterSettingManagerTest.java
 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterSettingManagerTest.java
index e18ac0b..d8a61a3 100644
--- 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterSettingManagerTest.java
+++ 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterSettingManagerTest.java
@@ -276,4 +276,54 @@ public class InterpreterSettingManagerTest extends 
AbstractInterpreterTest {
     assertEquals(1, interpreterSetting.getAllInterpreterGroups().size());
     assertEquals(1, 
interpreterSetting.getAllInterpreterGroups().get(0).getSessionNum());
   }
+
+  @Test
+  public void testInterpreterInclude() throws Exception {
+    try {
+      
System.setProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_INTERPRETER_INCLUDES.getVarName(),
 "mock1");
+      setUp();
+
+      assertEquals(1, interpreterSettingManager.get().size());
+      assertEquals("mock1", interpreterSettingManager.get().get(0).getGroup());
+    } finally {
+      
System.clearProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_INTERPRETER_INCLUDES.getVarName());
+    }
+  }
+
+  @Test
+  public void testInterpreterExclude() throws Exception {
+    try {
+      
System.setProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_INTERPRETER_EXCLUDES.getVarName(),
+              "test,config_test,mock_resource_pool");
+      setUp();
+
+      assertEquals(2, interpreterSettingManager.get().size());
+      assertNotNull(interpreterSettingManager.getByName("mock1"));
+      assertNotNull(interpreterSettingManager.getByName("mock2"));
+    } finally {
+      
System.clearProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_INTERPRETER_EXCLUDES.getVarName());
+    }
+  }
+
+  @Test
+  public void testInterpreterIncludeExcludeTogether() throws Exception {
+    try {
+      
System.setProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_INTERPRETER_INCLUDES.getVarName(),
+              "test,");
+      
System.setProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_INTERPRETER_EXCLUDES.getVarName(),
+              "config_test,mock_resource_pool");
+
+      try {
+        setUp();
+        fail("Should not able to create InterpreterSettingManager");
+      } catch (Exception e) {
+        e.printStackTrace();
+        assertEquals("zeppelin.interpreter.include and 
zeppelin.interpreter.exclude can not be specified together, only one can be 
set.",
+                e.getMessage());
+      }
+    } finally {
+      
System.clearProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_INTERPRETER_INCLUDES.getVarName());
+      
System.clearProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_INTERPRETER_EXCLUDES.getVarName());
+    }
+  }
 }

Reply via email to