PR #867: bundle persistence blacklist/whitelist configurable

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/03f254fd
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/03f254fd
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/03f254fd

Branch: refs/heads/master
Commit: 03f254fd2812580e343993afaddd69a630841d81
Parents: 5d13ebf
Author: Aled Sage <[email protected]>
Authored: Fri Oct 27 12:09:48 2017 +0100
Committer: Aled Sage <[email protected]>
Committed: Fri Oct 27 13:50:15 2017 +0100

----------------------------------------------------------------------
 .../core/mgmt/ha/OsgiArchiveInstaller.java      | 43 +++++++++-
 .../brooklyn/core/mgmt/ha/OsgiManager.java      |  4 +
 .../core/server/BrooklynServerConfig.java       | 13 +++
 .../core/mgmt/ha/OsgiArchiveInstallerTest.java  | 83 ++++++++++++++++++++
 .../core/mgmt/rebind/RebindTestFixture.java     | 13 ++-
 5 files changed, 150 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/03f254fd/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
index e3b91fa..e41ec74 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
@@ -31,15 +31,18 @@ import java.util.Map;
 import java.util.TreeMap;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
+import java.util.regex.Pattern;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.BrooklynVersion;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import 
org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult.ResultCode;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.server.BrooklynServerConfig;
 import org.apache.brooklyn.core.typereg.BasicBrooklynTypeRegistry;
 import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
@@ -64,9 +67,11 @@ import org.osgi.framework.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 
 // package-private so we can move this one if/when we move OsgiManager
@@ -74,6 +79,10 @@ class OsgiArchiveInstaller {
 
     private static final Logger log = 
LoggerFactory.getLogger(OsgiArchiveInstaller.class);
     
+    public static final ConfigKey<String> 
PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX = 
BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX;
+    
+    public static final ConfigKey<String> 
PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX = 
BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX;
+    
     final private OsgiManager osgiManager;
     private ManagedBundle suppliedKnownBundleMetadata;
     private InputStream zipIn;
@@ -93,6 +102,8 @@ class OsgiArchiveInstaller {
     private ManagedBundle inferredMetadata;
     private final boolean inputStreamSupplied;
     
+    private volatile Predicate<ManagedBundle> 
blacklistBundlePersistencePredicate;
+    
     OsgiArchiveInstaller(OsgiManager osgiManager, ManagedBundle 
knownBundleMetadata, InputStream zipIn) {
         this.osgiManager = osgiManager;
         this.suppliedKnownBundleMetadata = knownBundleMetadata;
@@ -121,7 +132,7 @@ class OsgiArchiveInstaller {
     }
 
     private ManagementContextInternal mgmt() {
-        return (ManagementContextInternal) osgiManager.mgmt;
+        return (ManagementContextInternal) osgiManager.getManagementContext();
     }
     
     private synchronized void init() {
@@ -681,15 +692,39 @@ class OsgiArchiveInstaller {
         }
     }
     
-    private static boolean isBlacklistedForPersistence(ManagedBundle 
managedBundle) {
-        // Specifically, we treat as "managed bundles" (to extract their 
catalog.bom) the contents of:
+    @VisibleForTesting
+    boolean isBlacklistedForPersistence(ManagedBundle managedBundle) {
+        // We treat as "managed bundles" (to extract their catalog.bom) the 
contents of:
         //   - org.apache.brooklyn.core
         //   - org.apache.brooklyn.policy
         //   - org.apache.brooklyn.test-framework
         //   - org.apache.brooklyn.software-*
         //   - org.apache.brooklyn.library-catalog
         //   - org.apache.brooklyn.karaf-init (not sure why this one could end 
up in persisted state!)
-        return 
managedBundle.getSymbolicName().startsWith("org.apache.brooklyn.");
+        // We don't want to persist the entire brooklyn distro! Therefore 
default is to blacklist those.
+        
+        if (blacklistBundlePersistencePredicate == null) {
+            String whitelistRegex = 
mgmt().getConfig().getConfig(PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX);
+            String blacklistRegex = 
mgmt().getConfig().getConfig(PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX);
+            
+            final Pattern whitelistPattern = (whitelistRegex != null) ? 
Pattern.compile(whitelistRegex) : null;
+            final Pattern blacklistPattern = (blacklistRegex != null) ? 
Pattern.compile(blacklistRegex) : null;
+
+            blacklistBundlePersistencePredicate = new 
Predicate<ManagedBundle>() {
+                @Override public boolean apply(ManagedBundle input) {
+                    String bundleName = input.getSymbolicName();
+                    if (whitelistPattern != null && 
whitelistPattern.matcher(bundleName).matches()) {
+                        return false;
+                    }
+                    if (blacklistPattern != null && 
blacklistPattern.matcher(bundleName).matches()) {
+                        return true;
+                    }
+                    return false;
+                }
+            };
+        }
+        
+        return blacklistBundlePersistencePredicate.apply(managedBundle);
     }
     
     private static List<Bundle> findBundlesByVersion(OsgiManager osgiManager, 
ManagedBundle desired) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/03f254fd/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index e7bd75e..e3c0e82 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -344,6 +344,10 @@ public class OsgiManager {
         return Maybe.absent();
     }
     
+    ManagementContext getManagementContext() {
+        return mgmt;
+    }
+    
     /**
      * Clears all record of the managed bundles (use with care!).
      * 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/03f254fd/core/src/main/java/org/apache/brooklyn/core/server/BrooklynServerConfig.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/server/BrooklynServerConfig.java 
b/core/src/main/java/org/apache/brooklyn/core/server/BrooklynServerConfig.java
index 530095d..9bcd409 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/server/BrooklynServerConfig.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/server/BrooklynServerConfig.java
@@ -131,6 +131,19 @@ public class BrooklynServerConfig {
     public static final ConfigKey<Boolean> OSGI_CACHE_CLEAN = 
ConfigKeys.newBooleanConfigKey("brooklyn.osgi.cache.clean",
         "Whether to delete the OSGi directory before and after use; if unset, 
it will delete if the node ID forms part of the cache dir path (which by 
default it does) to avoid file leaks");
 
+    public static final ConfigKey<String> 
PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX = ConfigKeys.newStringConfigKey(
+            "brooklyn.persistence.bundle.whitelist",
+            "Regex for bundle symbolic names explicitly allowed to be 
persisted (taking precedence over blacklist); "
+                    + "managed bundles will by default be peristed if not 
blacklisted; "
+                    + "they do not need to be explicitly whitelisted.",
+            null);
+    
+    public static final ConfigKey<String> 
PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX = ConfigKeys.newStringConfigKey(
+            "brooklyn.persistence.bundle.blacklist",
+            "Regex for bundle symbolic names explicitly excluded from 
persistence (but whitelist takes precedence); "
+                    + "if not explicitly blacklisted, managed bundles will by 
default be peristed",
+            "org\\.apache\\.brooklyn\\..*");
+
     /** @see BrooklynServerPaths#getMgmtBaseDir(ManagementContext) */
     public static String getMgmtBaseDir(ManagementContext mgmt) {
         return BrooklynServerPaths.getMgmtBaseDir(mgmt);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/03f254fd/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstallerTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstallerTest.java
 
b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstallerTest.java
new file mode 100644
index 0000000..3a86a3d
--- /dev/null
+++ 
b/core/src/test/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstallerTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.brooklyn.core.mgmt.ha;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.typereg.ManagedBundle;
+import org.apache.brooklyn.core.server.BrooklynServerConfig;
+import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
+import org.apache.brooklyn.util.osgi.VersionedName;
+import org.mockito.Mockito;
+import org.testng.annotations.Test;
+
+public class OsgiArchiveInstallerTest extends BrooklynMgmtUnitTestSupport {
+
+    // The tests here will so far not need an actual OSGi Framework! Therefore 
we're using the simple
+    // BrooklynMgmtUnitTestSupport, which does not expose `useOsgi` or 
`osgiReuse`
+    
+    @Test
+    public void testBlacklistPersistingOrgApacheBrooklyn() throws Exception {
+        OsgiManager osgiManager = newMockOsgiManager(mgmt);
+        OsgiArchiveInstaller installer = new OsgiArchiveInstaller(osgiManager, 
Mockito.mock(ManagedBundle.class), new ByteArrayInputStream(new byte[0]));
+        
+        
assertTrue(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.core",
 "1.0.0")));
+        
assertTrue(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.mybundle",
 "1.0.0")));
+        
assertFalse(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.different",
 "1.0.0")));
+    }
+
+    @Test
+    public void testWhitelistPersistingBundle() throws Exception {
+        
mgmt.getBrooklynProperties().put(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX,
 "org\\.apache\\.brooklyn\\.mywhitelistedbundle");
+        OsgiManager osgiManager = newMockOsgiManager(mgmt);
+        OsgiArchiveInstaller installer = new OsgiArchiveInstaller(osgiManager, 
Mockito.mock(ManagedBundle.class), new ByteArrayInputStream(new byte[0]));
+        
+        
assertTrue(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.core",
 "1.0.0")));
+        
assertFalse(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.mywhitelistedbundle",
 "1.0.0")));
+    }
+
+    @Test
+    public void testCustomBlacklistPersistingBundle() throws Exception {
+        
mgmt.getBrooklynProperties().put(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_BLACKLIST_REGEX,
 "org\\.example\\.myblacklistprefix.*");
+        OsgiManager osgiManager = newMockOsgiManager(mgmt);
+        OsgiArchiveInstaller installer = new OsgiArchiveInstaller(osgiManager, 
Mockito.mock(ManagedBundle.class), new ByteArrayInputStream(new byte[0]));
+        
+        
assertTrue(installer.isBlacklistedForPersistence(newMockManagedBundle("org.example.myblacklistprefix.mysuffix",
 "1.0.0")));
+        
assertFalse(installer.isBlacklistedForPersistence(newMockManagedBundle("org.apache.brooklyn.core",
 "1.0.0")));
+    }
+
+    public OsgiManager newMockOsgiManager(ManagementContext mgmt) throws 
Exception {
+        OsgiManager result = Mockito.mock(OsgiManager.class);
+        Mockito.when(result.getManagementContext()).thenReturn(mgmt);
+        return result;
+    }
+    
+    private ManagedBundle newMockManagedBundle(String symbolicName, String 
version) {
+        VersionedName versioneName = new VersionedName(symbolicName, version);
+        ManagedBundle result = Mockito.mock(ManagedBundle.class);
+        Mockito.when(result.getSymbolicName()).thenReturn(symbolicName);
+        
Mockito.when(result.getOsgiVersionString()).thenReturn(versioneName.getOsgiVersionString());
+        Mockito.when(result.getVersionedName()).thenReturn(versioneName);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/03f254fd/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
 
b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
index efe7d28..b80d857 100644
--- 
a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
+++ 
b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
@@ -39,8 +39,10 @@ import 
org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import 
org.apache.brooklyn.core.mgmt.persist.BrooklynMementoPersisterToObjectStore;
 import org.apache.brooklyn.core.mgmt.persist.FileBasedObjectStore;
 import org.apache.brooklyn.core.mgmt.persist.PersistMode;
+import org.apache.brooklyn.core.server.BrooklynServerConfig;
 import org.apache.brooklyn.util.core.task.BasicExecutionManager;
 import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.util.osgi.OsgiTestResources;
 import org.apache.brooklyn.util.repeat.Repeater;
 import org.apache.brooklyn.util.text.Identifiers;
 import org.apache.brooklyn.util.time.Duration;
@@ -82,11 +84,18 @@ public abstract class RebindTestFixture<T extends 
StartableApplication> {
     }
 
     protected BrooklynProperties createBrooklynProperties() {
+        BrooklynProperties result;
         if (useLiveManagementContext()) {
-            return BrooklynProperties.Factory.newDefault();
+            result = BrooklynProperties.Factory.newDefault();
         } else {
-            return BrooklynProperties.Factory.newEmpty();
+            result = BrooklynProperties.Factory.newEmpty();
         }
+        // By default, will not persist "org.apache.brooklyn.*" bundles; 
therefore explicitly whitelist 
+        // such things commonly used in tests.
+        String whitelistRegex = 
OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL 
+                + "|" + 
OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SYMBOLIC_NAME_FULL;
+        
result.put(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX, 
whitelistRegex);
+        return result;
     }
 
     /** @return A started management context */

Reply via email to