You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by gu...@apache.org on 2020/06/29 00:28:46 UTC

[pulsar-manager] branch master updated: Bundle BKVM.org - BookKeeper Visual Manager 1.2.0 (#300)

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

guangning pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-manager.git


The following commit(s) were added to refs/heads/master by this push:
     new 6975804  Bundle BKVM.org - BookKeeper Visual Manager 1.2.0 (#300)
6975804 is described below

commit 697580489ba55603ae383c83d793aa7800d2d0a5
Author: Enrico Olivelli <eo...@gmail.com>
AuthorDate: Mon Jun 29 02:28:36 2020 +0200

    Bundle BKVM.org - BookKeeper Visual Manager 1.2.0 (#300)
    
    * Deploy BKVM.org - BookKeeper Visual Manager
    - add dependency to bkvn.org war
    - make explicit a few dependencies
    - start bkvm.org on backend service at path http://localhost:8080/bkvm
    - create example bkvm.conf file
    
    * Use BKVM 1.2.0
    
    Co-authored-by: Enrico Olivelli <eo...@apache.org>
    Co-authored-by: Enrico Olivelli <en...@diennea.com>
---
 README.md                                          |   2 +-
 build.gradle                                       |  14 ++
 gradle.properties                                  |   3 +
 .../pulsar/manager/EmbeddedTomcatCustomizer.java   | 162 +++++++++++++++++++++
 .../manager/interceptor/WebAppConfigurer.java      |   5 +-
 src/main/resources/application.properties          |   2 +-
 src/main/resources/bkvm.conf                       |  29 ++++
 7 files changed, 214 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 6fadff7..261a5cd 100644
--- a/README.md
+++ b/README.md
@@ -164,7 +164,7 @@ If you are deploying Pulsar Manager 0.1.0 using the released container, you can
 If you are deploying Pulsar Manager using the latest code, you can create a super-user using the following command. Then you can use the super user credentials to log in the Pulsar Manager UI.
 
     ```$xslt
-    curl 
+    curl \
         -H "Content-Type: application/json" \
         -X PUT http://backend-service:7750/pulsar-manager/users/superuser \
         -d '{"name": "admin", "password": "apachepulsar", "description": "test", "email": "username@test.org"}'
diff --git a/build.gradle b/build.gradle
index 017a109..a6a1389 100644
--- a/build.gradle
+++ b/build.gradle
@@ -82,6 +82,7 @@ distributions {
     main {
         contents {
             from 'src/main/resources/application.properties'
+            from 'src/main/resources/bkvm.conf'
         }
     }
 }
@@ -123,6 +124,19 @@ dependencies {
     compile group: 'io.springfox', name: 'springfox-swagger-ui', version: swaggeruiVersion
     compile group: 'org.apache.pulsar', name: 'pulsar-broker', version: brokerVersion
     compile group: 'commons-validator', name: 'commons-validator', version: commonsValidatorVersion
+    compile (group: 'org.bkvm', name: 'bkvm', version: bkvmVersion, ext: 'war', classifier:'war-no-libs') {
+        exclude group: 'org.slf4j', module: 'slf4j-jdk14'
+        exclude group: 'org.herddb', module: '*'
+    }
+    compile (group: 'org.bkvm', name: 'bkvm', version: bkvmVersion, classifier:'classes') {
+        exclude group: 'org.slf4j', module: 'slf4j-jdk14'
+        exclude group: 'org.herddb', module: '*'
+    }
+    compile (group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: tomcatVersion)
+    compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet', version: jerseyVersion
+    compile group: 'org.glassfish.jersey.core', name: 'jersey-client', version: jerseyVersion
+    compile group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: jerseyVersion
+    compile group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: jerseyVersion
     compileOnly group: 'org.projectlombok', name: 'lombok', version: lombokVersion
     compileOnly group: 'org.springframework.boot', name: 'spring-boot-devtools', version: springBootVersion
     testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion
diff --git a/gradle.properties b/gradle.properties
index 75a726b..5679029 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -20,3 +20,6 @@ postgresqlVersion=42.2.5
 herddbVersion=0.16.1
 brokerVersion=2.4.1
 commonsValidatorVersion=1.6
+bkvmVersion=1.2.0
+tomcatVersion=8.5.31
+jerseyVersion=2.26
diff --git a/src/main/java/org/apache/pulsar/manager/EmbeddedTomcatCustomizer.java b/src/main/java/org/apache/pulsar/manager/EmbeddedTomcatCustomizer.java
new file mode 100644
index 0000000..e262c97
--- /dev/null
+++ b/src/main/java/org/apache/pulsar/manager/EmbeddedTomcatCustomizer.java
@@ -0,0 +1,162 @@
+/**
+ * Licensed 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.pulsar.manager;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import javax.servlet.ServletException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.catalina.Context;
+import org.apache.catalina.loader.WebappLoader;
+import org.apache.catalina.startup.Tomcat;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+/**
+ * Customize Tomcat Service
+ */
+@Component
+@Slf4j
+public class EmbeddedTomcatCustomizer implements
+        WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
+
+    @Override
+    public void customize(ConfigurableServletWebServerFactory factory) {
+        log.info("Starting Tomcat Customizer");
+    }
+
+    @Bean
+    public ServletWebServerFactory servletContainer() {
+        log.info("Starting servletContainer");
+        return new TomcatServletWebServerFactory() {
+            @Override
+            protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
+                try {
+                    log.info("Catalina base is " + tomcat.getServer().getCatalinaBase().getAbsolutePath());
+                    File lib = new File("lib").getAbsoluteFile();
+                    if (lib.isDirectory()) {
+                        File bkvmWar = searchWar(lib, "bkvm", ".war");
+                        if (bkvmWar != null) {
+                            File configFile = new File("bkvm.conf");
+                            log.info("looking for BKVM configuration file at " + configFile.getAbsolutePath());
+                            if (configFile.isFile()) {
+                                Properties props = new Properties();
+                                try (FileReader reader = new FileReader(configFile)) {
+                                    props.load(reader);
+                                }
+                                boolean bkvmEnabled = Boolean.parseBoolean(props.getProperty("bkvm.enabled", "false"));
+                                log.info("Read bkvm.enabled = {}", bkvmEnabled);
+                                if (bkvmEnabled) {
+                                    System.setProperty("bookkeeper.visual.manager.config.path", configFile.getAbsolutePath());
+                                    File file = new File(tomcat.getServer().getCatalinaBase(), "/webapps");
+                                    log.info("Tomcat Webapps directory is " + file.getAbsolutePath());
+                                    file.mkdirs();
+                                    File bkvmDirectory = new File(file, "bkvm");
+                                    log.info("Deploying BKVM to " + bkvmDirectory.getAbsolutePath());
+                                    unZip(bkvmWar, bkvmDirectory);
+                                    Context context = tomcat.addWebapp("/bkvm", bkvmDirectory.getAbsolutePath());
+                                    WebappLoader loader = new WebappLoader(Thread.currentThread().getContextClassLoader());
+                                    context.setLoader(loader);
+                                }
+                            }
+                        }
+                    }
+                    return super.getTomcatWebServer(tomcat);
+                } catch (IOException | ServletException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+
+        };
+    }
+
+    private static File searchWar(File directory, String prefix, String ext) throws IOException {
+        log.info("looking for " + prefix + " into " + directory.getAbsolutePath());
+        Path path = directory.toPath();
+        try (DirectoryStream<Path> list = Files.newDirectoryStream(path);) {
+            for (Path o : list) {
+                if (o.getFileName().toString().startsWith(prefix) && o.getFileName().toString().endsWith(ext)) {
+                    return o.toFile();
+                }
+
+            }
+        }
+        log.info("Cannot find any file whose name starts with " + prefix + " into " + directory.getAbsolutePath());
+        return null;
+    }
+
+    public static List<File> unZip(File war, File outDir) throws IOException {
+        log.info("Unzipping " + war.getAbsolutePath() + " to " + outDir);
+        try (ZipInputStream zipStream = new ZipInputStream(new FileInputStream(war), StandardCharsets.UTF_8);) {
+            ZipEntry entry = zipStream.getNextEntry();
+            List<File> listFiles = new ArrayList<>();
+            while (entry != null) {
+                if (entry.isDirectory()) {
+                    entry = zipStream.getNextEntry();
+                    continue;
+                }
+
+                String normalized = entry.getName();
+                File outFile = new File(outDir, normalized);
+                File parentDir = outFile.getParentFile();
+                if (parentDir != null && !parentDir.isDirectory()) {
+                    Files.createDirectories(parentDir.toPath());
+                }
+
+                listFiles.add(outFile);
+                try (FileOutputStream out = new FileOutputStream(outFile);
+                        BufferedOutputStream oo = new BufferedOutputStream(out)) {
+                    copyStream(zipStream, oo);
+                }
+                entry = zipStream.getNextEntry();
+
+            }
+            return listFiles;
+        } catch (IllegalArgumentException ex) {
+            throw new IOException(ex);
+        }
+
+    }
+
+    private static long copyStream(InputStream input, OutputStream output) throws IOException {
+        long count = 0;
+        int n = 0;
+        byte[] buffer = new byte[64 * 1024];
+        while (-1 != (n = input.read(buffer))) {
+            output.write(buffer, 0, n);
+            count += n;
+        }
+        return count;
+    }
+}
diff --git a/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java b/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
index 3f5ac4b..0c97479 100644
--- a/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
+++ b/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
@@ -39,7 +39,10 @@ public class WebAppConfigurer implements WebMvcConfigurer {
                 // static front-end resources
                 .excludePathPatterns("/ui")
                 .excludePathPatterns("/static")
-                .excludePathPatterns("/error");
+                .excludePathPatterns("/error")
+                // BKVM
+                .excludePathPatterns("/bkvm")
+                ;
     }
 
     @Override
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index bdfd655..9305e60 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -13,7 +13,7 @@
 #
 
 spring.cloud.refresh.refreshable=none
-server.port=7750
+server.port=8080
 
 # configuration log
 logging.path=
diff --git a/src/main/resources/bkvm.conf b/src/main/resources/bkvm.conf
new file mode 100644
index 0000000..8fe0de7
--- /dev/null
+++ b/src/main/resources/bkvm.conf
@@ -0,0 +1,29 @@
+#
+# Licensed 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.
+#
+
+# Change this to true in order to start BKVM
+bkvm.enabled=false
+
+# BookKeeper Connection
+# Default value zk+null://127.0.0.1:2181/ledgers works for Pulsar Standalone
+metadataServiceUri=zk+null://127.0.0.1:2181/ledgers
+
+# HerdDB database connection, not to be changed if you are running embedded HerdDB in Pulsar Manager
+# If you are using PostGRE SQL you will have to change this configuration
+# We want to use the HerdDB database started by PulsarManager itself, by default BKVM wants to start its one database
+jdbc.url=jdbc:herddb:localhost:7000?server.mode=standalone&server.start=false
+jdbc.startDatabase=false
+server.mode=standalone
+server.start=false
+