This is an automated email from the ASF dual-hosted git repository. heneveld pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit 9a58578db159fb3a45e3051b349c3afddd938311 Author: Alex Heneveld <a...@cloudsoft.io> AuthorDate: Thu Mar 28 21:55:03 2024 +0000 store whether a bundle comes from the initial catalog, and don't persist those change previous commit so that we don't exclude persisting of things from URL's, but we do exclude persisting of things from the catalog by default. we needed to persist things from URL's because we might manually install bundle A with libraries B, and we need to persist a record that those libraries B are installed and persisted, because if we remove A, we don't remove B, but if we haven't persisted a record of B, then B is removed after rebind. we could record an XML record without storing the JAR, but that is more work; and it makes more sense that things in the catalog we expect to be defined in the catalog; if you want to keep those on a restart, they need to stay in the catalog (or have upgrade instructions in catalog), or be installed manually prior to restarting, if you want to remove it from the catalog while it is in use, installing manually causes things to be persisted even if they are already in the catalog. --- .../catalog/internal/BasicBrooklynCatalog.java | 69 ++++++++---- .../core/catalog/internal/CatalogBundleLoader.java | 3 + .../catalog/internal/CatalogInitialization.java | 2 +- .../core/catalog/internal/CatalogUtils.java | 6 +- .../mgmt/ha/BrooklynBomOsgiArchiveInstaller.java | 81 +++++++++----- .../apache/brooklyn/core/mgmt/ha/OsgiManager.java | 11 ++ .../BrooklynMementoPersisterToObjectStore.java | 4 +- .../brooklyn/core/server/BrooklynServerConfig.java | 8 +- .../brooklyn/core/typereg/BasicManagedBundle.java | 35 ++++-- .../BrooklynBomYamlCatalogBundleResolver.java | 2 +- .../typereg/BrooklynCatalogBundleResolver.java | 8 ++ .../BrooklynLauncherRebindCatalogOsgiTest.java | 121 ++++++++++++++------- 12 files changed, 243 insertions(+), 107 deletions(-) diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java index e3a9208bf0..7fafe0db71 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java @@ -18,12 +18,9 @@ */ package org.apache.brooklyn.core.catalog.internal; -import com.google.common.base.*; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.reflect.TypeToken; -import java.io.*; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -36,13 +33,27 @@ import java.util.Set; import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.common.reflect.TypeToken; import org.apache.brooklyn.api.catalog.BrooklynCatalog; import org.apache.brooklyn.api.catalog.CatalogItem; import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle; import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType; import org.apache.brooklyn.api.entity.Application; import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; -import org.apache.brooklyn.api.location.LocationSpec; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; import org.apache.brooklyn.api.objs.BrooklynObject; @@ -63,11 +74,19 @@ import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult; import org.apache.brooklyn.core.mgmt.ha.OsgiManager; import org.apache.brooklyn.core.mgmt.internal.CampYamlParser; import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; -import org.apache.brooklyn.core.typereg.*; +import org.apache.brooklyn.core.typereg.BasicBrooklynTypeRegistry; +import org.apache.brooklyn.core.typereg.BasicManagedBundle; +import org.apache.brooklyn.core.typereg.BasicRegisteredType; +import org.apache.brooklyn.core.typereg.BasicTypeImplementationPlan; +import org.apache.brooklyn.core.typereg.BrooklynBomYamlCatalogBundleResolver; +import org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer; +import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts; +import org.apache.brooklyn.core.typereg.RegisteredTypeNaming; +import org.apache.brooklyn.core.typereg.RegisteredTypes; +import org.apache.brooklyn.core.typereg.UnsupportedTypePlanException; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.collections.MutableSet; -import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.ResourceUtils; import org.apache.brooklyn.util.core.flags.BrooklynTypeNameResolution.BrooklynTypeNameResolver; import org.apache.brooklyn.util.core.flags.TypeCoercions; @@ -95,14 +114,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; -import com.google.common.annotations.Beta; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Collections2; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; /* TODO the complex tree-structured catalogs are only useful when we are relying on those separate catalog classloaders * to isolate classpaths. with osgi everything is just put into the "manual additions" catalog. Deprecate/remove this. */ @@ -684,7 +697,8 @@ public class BasicBrooklynCatalog implements BrooklynCatalog { // `libraries` is supported in some places as a legacy syntax; it should always be `brooklyn.libraries` for new apps List<?> librariesAddedHereNames = MutableList.copyOf(getFirstAs(itemMetadataWithoutItemDef, List.class, "brooklyn.libraries", "libraries").orNull()); Collection<CatalogBundle> librariesAddedHereBundles = CatalogItemDtoAbstract.parseLibraries(librariesAddedHereNames); - + boolean fromInitialCatalog = containingBundle instanceof BasicManagedBundle && Boolean.TRUE.equals( ((BasicManagedBundle)containingBundle).getFromInitialCatalog() ); + MutableSet<Object> librariesCombinedNames = MutableSet.of(); if (!isNoBundleOrSimpleWrappingBundle(mgmt, containingBundle)) { // ensure containing bundle is declared, first, for search purposes @@ -700,7 +714,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog { // TODO this may take a while if downloading; ideally the REST call would be async // but this load is required for resolving YAML in this BOM (and if java-scanning); // need to think through how we expect dependencies to be installed - CatalogUtils.installLibraries(mgmt, librariesAddedHereBundles); + CatalogUtils.installLibraries(mgmt, librariesAddedHereBundles, true, fromInitialCatalog); // use resolved bundles librariesAddedHereBundles = resolveWherePossible(mgmt, librariesAddedHereBundles); @@ -1810,10 +1824,14 @@ public class BasicBrooklynCatalog implements BrooklynCatalog { @Override public List<? extends CatalogItem<?,?>> addItems(String yaml, boolean validate, boolean forceUpdate) { + return addItems(yaml, validate, forceUpdate, false); + } + + public List<? extends CatalogItem<?,?>> addItems(String yaml, boolean validate, boolean forceUpdate, boolean fromCatalog) { Maybe<OsgiManager> osgiManager = ((ManagementContextInternal)mgmt).getOsgiManager(); if (osgiManager.isPresent() && AUTO_WRAP_CATALOG_YAML_AS_BUNDLE) { // wrap in a bundle to be managed; need to get bundle and version from yaml - OsgiBundleInstallationResult result = addItemsOsgi(yaml, forceUpdate, osgiManager.get()); + OsgiBundleInstallationResult result = addItemsOsgi(yaml, forceUpdate, osgiManager.get(), fromCatalog); // above will have done validation and supertypes recorded return toLegacyCatalogItems(result.getTypesInstalled()); @@ -1831,7 +1849,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog { Maybe<OsgiManager> osgiManager = ((ManagementContextInternal)mgmt).getOsgiManager(); if (osgiManager.isPresent() && AUTO_WRAP_CATALOG_YAML_AS_BUNDLE) { // wrap in a bundle to be managed; need to get bundle and version from yaml - return addItemsOsgi(yaml, forceUpdate, osgiManager.get()); + return addItemsOsgi(yaml, forceUpdate, osgiManager.get(), false); // if all items pertaining to an older anonymous catalog.bom bundle have been overridden // we delete those later; see list of wrapper bundles kept in OsgiManager @@ -1847,7 +1865,10 @@ public class BasicBrooklynCatalog implements BrooklynCatalog { } protected OsgiBundleInstallationResult addItemsOsgi(String yaml, boolean forceUpdate, OsgiManager osgiManager) { - return osgiManager.install(InputStreamSource.of("addItemsOsgi supplied yaml", yaml.getBytes()), BrooklynBomYamlCatalogBundleResolver.FORMAT, forceUpdate).get(); + return addItemsOsgi(yaml, forceUpdate, osgiManager, false); + } + protected OsgiBundleInstallationResult addItemsOsgi(String yaml, boolean forceUpdate, OsgiManager osgiManager, boolean fromCatalog) { + return osgiManager.install(InputStreamSource.of("addItemsOsgi supplied yaml", yaml.getBytes()), BrooklynBomYamlCatalogBundleResolver.FORMAT, forceUpdate, !fromCatalog, fromCatalog).get(); } @SuppressWarnings("deprecation") @@ -1913,7 +1934,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog { Maybe<OsgiManager> osgiManager = ((ManagementContextInternal)mgmt).getOsgiManager(); if (osgiManager.isPresent() && AUTO_WRAP_CATALOG_YAML_AS_BUNDLE) { // wrap in a bundle to be managed; need to get bundle and version from yaml - return addItemsOsgi(catalogYaml, forceUpdate, osgiManager.get()).getTypesInstalled(); + return addItemsOsgi(catalogYaml, forceUpdate, osgiManager.get(), false).getTypesInstalled(); // above will have done validation and supertypes recorded } @@ -2271,7 +2292,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog { log.debug("Adding manual catalog item to "+mgmt+": "+item); checkNotNull(item, "item"); //don't activate bundles; only intended for legacy tests where that might not work - CatalogUtils.installLibraries(mgmt, item.getLibraries(), false); + CatalogUtils.installLibraries(mgmt, item.getLibraries(), false, false); if (manualAdditionsCatalog==null) loadManualAdditionsCatalog(); manualAdditionsCatalog.addEntry(getAbstractCatalogItem(item)); } diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleLoader.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleLoader.java index 88e160aa98..5eaaf1d9c3 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleLoader.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleLoader.java @@ -27,11 +27,14 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import javax.annotation.Nullable; + import org.apache.brooklyn.api.catalog.CatalogItem; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.typereg.ManagedBundle; import org.apache.brooklyn.api.typereg.RegisteredType; import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.core.typereg.BasicManagedBundle; import org.apache.brooklyn.core.typereg.RegisteredTypePredicates; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableSet; diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java index 5050977767..75dcb0bd5d 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java @@ -491,7 +491,7 @@ public class CatalogInitialization implements ManagementContextInjectable { String contents = new ResourceUtils(this).getResourceAsString(catalogUrl); catalog.reset(MutableList.<CatalogItem<?,?>>of()); - Object result = catalog.addItems(contents); + Object result = catalog.addItems(contents, true, false, true); log.debug("Loaded initial catalog from {}: {}", catalogUrl, result); diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java index c4aaa9185e..fa2b90fdd1 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java @@ -171,6 +171,8 @@ public class CatalogUtils { /** As {@link #installLibraries(ManagementContext, Collection)} but letting caller suppress the deferred start/install * (for use in tests where bundles' BOMs aren't resolvable). */ public static void installLibraries(ManagementContext managementContext, @Nullable Collection<CatalogBundle> libraries, boolean startBundlesAndInstallToBrooklyn) { + } + public static void installLibraries(ManagementContext managementContext, @Nullable Collection<CatalogBundle> libraries, boolean startBundlesAndInstallToBrooklyn, boolean fromInitialCatalog) { if (libraries == null) return; ManagementContextInternal mgmt = (ManagementContextInternal) managementContext; @@ -186,7 +188,9 @@ public class CatalogUtils { Stopwatch timer = Stopwatch.createStarted(); List<OsgiBundleInstallationResult> results = MutableList.of(); for (CatalogBundle bundle : libraries) { - ReferenceWithError<OsgiBundleInstallationResult> result = osgi.get().installDeferredStart(BasicManagedBundle.of(bundle), null, true); + BasicManagedBundle mb = (BasicManagedBundle) BasicManagedBundle.of(bundle); + if (fromInitialCatalog) mb.setFromInitialCatalog(true); + ReferenceWithError<OsgiBundleInstallationResult> result = osgi.get().installDeferredStart(mb, null, true); if (log.isDebugEnabled()) { logDebugOrTraceIfRebinding(log, "Installation of library "+bundle+": "+result); } diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java index cf47f230eb..011abd316b 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java @@ -27,8 +27,6 @@ import com.google.common.collect.Iterables; import java.io.*; import java.net.URL; import java.util.*; -import java.util.function.BiConsumer; -import java.util.function.Predicate; import java.util.function.Supplier; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -37,8 +35,6 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.annotation.Nullable; import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.api.mgmt.rebind.ChangeListener; -import org.apache.brooklyn.api.objs.BrooklynObject; import org.apache.brooklyn.api.typereg.ManagedBundle; import org.apache.brooklyn.api.typereg.RegisteredType; import org.apache.brooklyn.core.BrooklynVersion; @@ -301,10 +297,12 @@ public class BrooklynBomOsgiArchiveInstaller { throw new IllegalArgumentException("No input stream available and no URL could be found: no way to install " + suppliedKnownBundleMetadata); } + boolean shouldReplaceExistingBundle = force || replacingInitialCatalogBundle(suppliedKnownBundleMetadata, existingBrooklynInstalledBundle.orNull()); + if (zipIn != null) { // found input stream for existing osgi bundle - } else if (existingBrooklynInstalledBundle.isAbsent() || force) { + } else if (existingBrooklynInstalledBundle.isAbsent() || shouldReplaceExistingBundle) { // reload String url = suppliedKnownBundleMetadata.getUrl(); if (url == null) { @@ -375,6 +373,19 @@ public class BrooklynBomOsgiArchiveInstaller { return prepareInstallResult; } + private static boolean replacingInitialCatalogBundle(ManagedBundle suppliedKnownBundleMetadata, @Nullable ManagedBundle existingBrooklynInstalledBundle) { + boolean shouldReplaceExistingBundle = false; + if (existingBrooklynInstalledBundle instanceof BasicManagedBundle && suppliedKnownBundleMetadata instanceof BasicManagedBundle) { + if (Boolean.TRUE.equals(((BasicManagedBundle)existingBrooklynInstalledBundle).getFromInitialCatalog())) { + if (!Boolean.TRUE.equals(((BasicManagedBundle) suppliedKnownBundleMetadata).getFromInitialCatalog())) { + // we should replace if we are manually installing an identical bundle, so it is persisted + shouldReplaceExistingBundle = true; + } + } + } + return shouldReplaceExistingBundle; + } + private void discoverManifestFromCatalogBom(boolean isCatalogBomRequired) { discoveredManifest = new BundleMaker(mgmt()).getManifest(zipFile.getFile()); @@ -514,35 +525,49 @@ public class BrooklynBomOsgiArchiveInstaller { result.bundle = osgiManager.getFramework().getBundleContext().getBundle(result.getMetadata().getOsgiUniqueUrl()); // Check if exactly this bundle is already installed + boolean replacingInitialCatalogBundleWithMatchingChecksums = false; if (result.bundle != null && checksumsMatch(result.getMetadata(), inferredMetadata)) { - // e.g. repeatedly installing the same bundle - log.trace("Bundle "+inferredMetadata+" matches already installed managed bundle "+result.getMetadata() - +"; install is no-op"); - result.setIgnoringAlreadyInstalled(); - return ReferenceWithError.newInstanceWithoutError(result); - + if (replacingInitialCatalogBundle(inferredMetadata, result.getMetadata())) { + replacingInitialCatalogBundleWithMatchingChecksums = true; + // mark it not from initial catalog (but leave it as not deletable) + ((BasicManagedBundle) result.getMetadata()).setFromInitialCatalog(false); + } else { + // e.g. repeatedly installing the same bundle + log.trace("Bundle " + inferredMetadata + " matches already installed managed bundle " + result.getMetadata() + + "; install is no-op"); + result.setIgnoringAlreadyInstalled(); + return ReferenceWithError.newInstanceWithoutError(result); + } } List<Bundle> matchingVsnBundles = findBundlesBySymbolicNameAndVersion(osgiManager, inferredMetadata); - - List<Bundle> sameContentBundles = matchingVsnBundles.stream().filter(b -> isBundleSameOsgiUrlOrSameContents(b, inferredMetadata, zipFile.getFile())).collect(Collectors.toList()); - if (!sameContentBundles.isEmpty()) { - // e.g. happens if pre-installed bundle is brought under management, and then add it again via a mvn-style url. - // We wouldn't know the checksum from the pre-installed bundle, the osgi locations might be different, - // but the contents are the same - log.trace("Bundle "+inferredMetadata+" matches metadata of managed bundle "+result.getMetadata() - +" (but not OSGi bundle location "+result.getMetadata().getOsgiUniqueUrl()+"), " - + "and identified as equivalent to installed OSGi bundle; ; install is no-op"); - result.setIgnoringAlreadyInstalled(); - result.bundle = sameContentBundles.iterator().next(); - return ReferenceWithError.newInstanceWithoutError(result); + if (!replacingInitialCatalogBundleWithMatchingChecksums) { + List<Bundle> sameContentBundles = matchingVsnBundles.stream().filter(b -> isBundleSameOsgiUrlOrSameContents(b, inferredMetadata, zipFile.getFile())).collect(Collectors.toList()); + if (!sameContentBundles.isEmpty()) { + // e.g. happens if pre-installed bundle is brought under management, and then add it again via a mvn-style url. + // We wouldn't know the checksum from the pre-installed bundle, the osgi locations might be different, + // but the contents are the same + log.trace("Bundle " + inferredMetadata + " matches metadata of managed bundle " + result.getMetadata() + + " (but not OSGi bundle location " + result.getMetadata().getOsgiUniqueUrl() + "), " + + "and identified as equivalent to installed OSGi bundle; ; install is no-op"); + result.setIgnoringAlreadyInstalled(); + result.bundle = sameContentBundles.iterator().next(); + return ReferenceWithError.newInstanceWithoutError(result); + } } - if (canUpdate()) { - if (result.bundle == null && !matchingVsnBundles.isEmpty()) { - // if we are updating a snapshot bundle or forcing, and somehow we did not manage to preserve the original OSGi location - log.info("Updating existing brooklyn-managed bundle "+result+" with "+inferredMetadata+" with different OSGi location and different contents"); - result.bundle = matchingVsnBundles.iterator().next(); + if (replacingInitialCatalogBundleWithMatchingChecksums || canUpdate()) { + if (result.bundle == null) { + if (replacingInitialCatalogBundleWithMatchingChecksums) { + log.info("Updating existing brooklyn-managed bundle " + result + " with " + inferredMetadata + ", same contents, but post-initial-catalog installation means it must be persisted"); + result.bundle = matchingVsnBundles.iterator().next(); + } else if (!matchingVsnBundles.isEmpty()) { + // if we are updating a snapshot bundle or forcing, and somehow we did not manage to preserve the original OSGi location + log.info("Updating existing brooklyn-managed bundle " + result + " with " + inferredMetadata + " with different OSGi location and different contents"); + result.bundle = matchingVsnBundles.iterator().next(); + } else { + // will set updating=false and warn below + } } if (result.getBundle() == null) { 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 4455028291..c6b1e23be7 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 @@ -59,6 +59,7 @@ import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult.ResultCode; import org.apache.brooklyn.core.server.BrooklynServerConfig; import org.apache.brooklyn.core.server.BrooklynServerPaths; +import org.apache.brooklyn.core.typereg.BasicManagedBundle; import org.apache.brooklyn.core.typereg.BrooklynBomBundleCatalogBundleResolver; import org.apache.brooklyn.core.typereg.BrooklynCatalogBundleResolver.BundleInstallationOptions; import org.apache.brooklyn.core.typereg.BrooklynCatalogBundleResolvers; @@ -110,6 +111,7 @@ public class OsgiManager { public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX = BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX; public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_URL_EXCLUDE_REGEX = BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_URL_EXCLUDE_REGEX; public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX = BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX; + public static final ConfigKey<Boolean> PERSIST_MANAGED_BUNDLES_FROM_INITIAL_CATALOG = BrooklynServerConfig.PERSIST_MANAGED_BUNDLES_FROM_INITIAL_CATALOG; /* see `Osgis` class for info on starting framework etc */ @@ -471,10 +473,14 @@ public class OsgiManager { return install(input, format, force, null); } public ReferenceWithError<OsgiBundleInstallationResult> install(Supplier<InputStream> input, String format, boolean force, Boolean deleteable) { + return install(input, format, force, deleteable, false); + } + public ReferenceWithError<OsgiBundleInstallationResult> install(Supplier<InputStream> input, String format, boolean force, Boolean deleteable, Boolean fromInitialCatalog) { BundleInstallationOptions options = new BundleInstallationOptions(); options.setFormat(format); options.setForceUpdateOfNonSnapshots(force); options.setDeleteable(deleteable); + options.setFromInitialCatalog(fromInitialCatalog); return BrooklynCatalogBundleResolvers.install(getManagementContext(), input, options); } @@ -898,6 +904,11 @@ public class OsgiManager { // But we don't want to persist the entire brooklyn distro! Therefore default is to exclude those from persistence. // Similarly for anything installed via mvn or classpath. + if (managedBundle instanceof BasicManagedBundle && Boolean.TRUE.equals(((BasicManagedBundle)managedBundle).getFromInitialCatalog())) { + Boolean persistInitialCatalogBundles = mgmt.getConfig().getConfig(PERSIST_MANAGED_BUNDLES_FROM_INITIAL_CATALOG); + if (Boolean.FALSE.equals(persistInitialCatalogBundles)) return true; + } + if (bundlePersistenceExclusionFilterCache == null) { String regexSymnameInclude = mgmt.getConfig().getConfig(PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX); String regexSymnameIncludeLegacy = mgmt.getConfig().getConfig(BrooklynServerConfig.PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX); diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java index ed769ad390..00603ae7d7 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java @@ -826,7 +826,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer // someone else persisted this (race) return; } - if (!isBundleOmittedFromPersistence(mb)) { + if (!isBundleExcludedFromPersistence(mb)) { persist(type.getSubPathName(), type, id + ".jar", com.google.common.io.Files.asByteSource( ((ManagementContextInternal) mgmt).getOsgiManager().get().getBundleFile(mb)), exceptionHandler); } @@ -837,7 +837,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer } } - private boolean isBundleOmittedFromPersistence(ManagedBundle mb) { + private boolean isBundleExcludedFromPersistence(ManagedBundle mb) { return ((ManagementContextInternal)mgmt).getOsgiManager().get().isExcludedFromPersistence(mb); } 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 7ecfdc386c..d4c853eefc 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 @@ -146,7 +146,7 @@ public class BrooklynServerConfig { public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_URL_EXCLUDE_REGEX = ConfigKeys.newStringConfigKey( "brooklyn.persistence.bundle.exclude.url.regex", "Regex for bundle URLs explicitly excluded from persistence, unless symbolic name is in explicit include list", - "(mvn|classpath):.*"); + null); public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_EXCLUDE_REGEX = ConfigKeys.newStringConfigKey( "brooklyn.persistence.bundle.exclude.symbolicName.regex", @@ -154,6 +154,12 @@ public class BrooklynServerConfig { + "if not explicitly excluded by this or the URL exclusion, managed bundles will by default be peristed", "org\\.apache\\.brooklyn\\..*"); + public static final ConfigKey<Boolean> PERSIST_MANAGED_BUNDLES_FROM_INITIAL_CATALOG = ConfigKeys.newBooleanConfigKey( + "brooklyn.persistence.bundle.initialCatalog", + "Whether bundles installed by the startup catalog file(s) are persisted; " + + "historically defaulted to true, but now not as it was wasteful, but can be overridden here", + false); + @Deprecated /** @deprecated in favour of {@link #PERSIST_MANAGED_BUNDLE_SYMBOLIC_NAME_INCLUDE_REGEX} */ public static final ConfigKey<String> PERSIST_MANAGED_BUNDLE_WHITELIST_REGEX = ConfigKeys.newStringConfigKey( "brooklyn.persistence.bundle.whitelist", diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java index e053daaaba..fb02b28c49 100644 --- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java +++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java @@ -47,10 +47,12 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage private String format; private String url; private Credentials credentials; + private Boolean fromInitialCatalog; /** pretty much redundant as it is put in the delta if changed, and included even if not needed when full checkpoint requested */ private transient boolean persistenceNeeded = false; + /** Creates an empty one, with an ID, expecting other fields will be populated. */ public BasicManagedBundle() {} @@ -65,14 +67,17 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage /** @deprecated since 1.1 use larger constructor */ @Deprecated public BasicManagedBundle(String name, String version, String url, String format, Credentials credentials, @Nullable String checksum) { - init(name, version, url, format, credentials, checksum, null); + init(name, version, url, format, credentials, checksum, null, null); } public BasicManagedBundle(String name, String version, String url, String format, Credentials credentials, @Nullable String checksum, @Nullable Boolean deleteable) { - init(name, version, url, format, credentials, checksum, deleteable); + init(name, version, url, format, credentials, checksum, deleteable, null); + } + public BasicManagedBundle(String name, String version, String url, String format, Credentials credentials, @Nullable String checksum, @Nullable Boolean deleteable, @Nullable Boolean fromInitialCatalog) { + init(name, version, url, format, credentials, checksum, deleteable, fromInitialCatalog); } - private void init(String name, String version, String url, String format, Credentials credentials, @Nullable String checksum, @Nullable Boolean deleteable) { + private void init(String name, String version, String url, String format, Credentials credentials, @Nullable String checksum, @Nullable Boolean deleteable, @Nullable Boolean fromInitialCatalog) { if (name == null && version == null) { Preconditions.checkNotNull(url, "Either a URL or both name and version are required"); } else { @@ -86,18 +91,20 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage this.credentials = credentials; this.checksum = checksum; this.deleteable = deleteable; + this.fromInitialCatalog = fromInitialCatalog; } - private BasicManagedBundle(String id, String name, String version, String url, String format, Credentials credentials, @Nullable String checksum, @Nullable Boolean deleteable) { + private BasicManagedBundle(String id, String name, String version, String url, String format, Credentials credentials, @Nullable String checksum, @Nullable Boolean deleteable, @Nullable Boolean fromInitialCatalog) { super(id); - init(name, version, url, format, credentials, checksum, deleteable); + init(name, version, url, format, credentials, checksum, deleteable, fromInitialCatalog); } /** used when updating a persisted bundle, we want to use the coords (ID and OSGI unique URL) of the second with the checksum of the former; * the other fields should be the same between the two but if in doubt use the first argument */ public static BasicManagedBundle copyFirstWithCoordsOfSecond(ManagedBundle update, ManagedBundle oldOneForCoordinates) { - BasicManagedBundle result = new BasicManagedBundle(oldOneForCoordinates.getId(), update.getSymbolicName(), update.getSuppliedVersionString(), update.getUrl(), update.getFormat(), update.getUrlCredential(), update.getChecksum(), update.getDeleteable()); + BasicManagedBundle result = new BasicManagedBundle(oldOneForCoordinates.getId(), update.getSymbolicName(), update.getSuppliedVersionString(), update.getUrl(), update.getFormat(), update.getUrlCredential(), update.getChecksum(), update.getDeleteable(), + update instanceof BasicManagedBundle ? ((BasicManagedBundle)update).getFromInitialCatalog() : null); result.tags().addTags(update.tags().getTags()); // we have secondary logic which should accept a change in the OSGi unique URL, // but more efficient if we use the original URL @@ -110,6 +117,9 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage return symbolicName != null && version != null; } + public void setDeleteable(Boolean deleteable) { + this.deleteable = deleteable; + } @Override public Boolean getDeleteable() { return deleteable; @@ -271,7 +281,7 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage throw new UnsupportedOperationException(); } - public static ManagedBundle of(CatalogBundle bundle) { + public static ManagedBundle of(OsgiBundleWithUrl bundle) { String checksum = (bundle instanceof ManagedBundle) ? ((ManagedBundle)bundle).getChecksum() : null; return new BasicManagedBundle( bundle.getSymbolicName(), @@ -280,7 +290,8 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage null, bundle.getUrlCredential(), checksum, - bundle instanceof ManagedBundle ? ((ManagedBundle)bundle).getDeleteable() : null); + bundle.getDeleteable(), + (bundle instanceof BasicManagedBundle ? ((BasicManagedBundle)bundle).getFromInitialCatalog() : null)); } public void setPersistenceNeeded(boolean val) { @@ -290,5 +301,11 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage return persistenceNeeded; } - + + public Boolean getFromInitialCatalog() { + return fromInitialCatalog; + } + public void setFromInitialCatalog(Boolean fromInitialCatalog) { + this.fromInitialCatalog = fromInitialCatalog; + } } diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynBomYamlCatalogBundleResolver.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynBomYamlCatalogBundleResolver.java index aeb726f05b..faa51f875c 100644 --- a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynBomYamlCatalogBundleResolver.java +++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynBomYamlCatalogBundleResolver.java @@ -130,7 +130,7 @@ public class BrooklynBomYamlCatalogBundleResolver extends AbstractCatalogBundleR BasicManagedBundle basicManagedBundle = new BasicManagedBundle(vn.getSymbolicName(), vn.getVersionString(), null, BrooklynBomBundleCatalogBundleResolver.FORMAT, - null, null, options.getDeleteable()); + null, null, options.getDeleteable(), options.getFromInitialCatalog()); // if the submitted blueprint contains tags, we set them on the bundle, so they can be picked up and used to tag the plan. if( cm.containsKey("tags") && cm.get("tags") instanceof Iterable) { basicManagedBundle.tags().addTags((Iterable<?>)cm.get("tags")); diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynCatalogBundleResolver.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynCatalogBundleResolver.java index 5ee5286191..2c33f70c54 100644 --- a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynCatalogBundleResolver.java +++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynCatalogBundleResolver.java @@ -100,6 +100,7 @@ public interface BrooklynCatalogBundleResolver extends ManagementContextInjectab protected boolean start = true; protected boolean loadCatalogBom = true; protected Boolean deleteable = null; + protected Boolean fromInitialCatalog = null; protected ManagedBundle knownBundleMetadata = null; public void setFormat(String format) { @@ -163,6 +164,13 @@ public interface BrooklynCatalogBundleResolver extends ManagementContextInjectab public void setDeleteable(Boolean deleteable) { this.deleteable = deleteable; } + + public Boolean getFromInitialCatalog() { + return fromInitialCatalog; + } + public void setFromInitialCatalog(Boolean fromInitialCatalog) { + this.fromInitialCatalog = fromInitialCatalog; + } } } diff --git a/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogOsgiTest.java b/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogOsgiTest.java index 255d95a417..d16aa61a4a 100644 --- a/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogOsgiTest.java +++ b/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogOsgiTest.java @@ -18,6 +18,8 @@ */ package org.apache.brooklyn.launcher; +import org.apache.brooklyn.core.entity.BrooklynConfigKeys; +import org.apache.brooklyn.core.server.BrooklynServerConfig; import org.apache.brooklyn.util.stream.InputStreamSource; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -322,7 +324,8 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo // Should bring it under brooklyn-management (without re-installing it). startT1(newLauncherForTests(initialBomFile.getAbsolutePath())); - // Launch brooklyn again (because will have persisted both those bundles) + alsoPersistBundlesInstalledToCatalog(); + // Launch brooklyn again (because with the above, it will have persisted both those bundles) startT2(newLauncherForTests(CATALOG_EMPTY_INITIAL)); launcherT2.terminate(); @@ -333,12 +336,12 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo runInstallPreexistingBundleViaInitialBomBrooklynLibrariesReference(false); } - // Aled thought we supported version ranges in 'brooklyn.libraries', but doesn't work here. - // Alex confirms nope, not supported there yet (2017-10). - @Test(groups="Broken") - public void testInstallPreexistingBundleViaInitialBomBrooklynLibrariesReferenceWithVersionRange() throws Exception { - runInstallPreexistingBundleViaInitialBomBrooklynLibrariesReference(true); - } +// // Aled thought we supported version ranges in 'brooklyn.libraries', but doesn't work here. +// // Alex confirms nope, not supported there yet (2017-10). +// @Test(groups="Broken") +// public void testInstallPreexistingBundleViaInitialBomBrooklynLibrariesReferenceWithVersionRange() throws Exception { +// runInstallPreexistingBundleViaInitialBomBrooklynLibrariesReference(true); +// } protected void runInstallPreexistingBundleViaInitialBomBrooklynLibrariesReference(boolean useVersionRange) throws Exception { Set<VersionedName> bundleItems = ImmutableSet.of(VersionedName.fromString("one:1.0.0")); @@ -368,6 +371,7 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo // Should bring it under brooklyn-management (without re-installing it). startT1(newLauncherForTests(initialBomFile.getAbsolutePath())); + alsoPersistBundlesInstalledToCatalog(); // Launch brooklyn again (because will have persisted both those bundles) startT2(newLauncherForTests(CATALOG_EMPTY_INITIAL)); launcherT2.terminate(); @@ -479,6 +483,7 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo } }; startT1(newLauncherForTests(initialBomFileV1.getAbsolutePath())); + alsoPersistBundlesInstalledToCatalog(); startT2(newLauncherForTests(initialBomFileV2.getAbsolutePath())); assertManagedBundle(launcherLast, bundleNameV2, bundleItems); promoteT2IfStandby(); @@ -519,6 +524,7 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo } }; startT1(newLauncherForTests(initialBomFileV1.getAbsolutePath())); + alsoPersistBundlesInstalledToCatalog(); startT2(newLauncherForTests(initialBomFileV2.getAbsolutePath())); promoteT2IfStandby(); } @@ -608,6 +614,7 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo // First launcher should persist the bundle startT1(newLauncherForTests(initialBomFile.getAbsolutePath())); String bundlePersistenceId1 = findManagedBundle(launcherT1, bundleName).getId(); + alsoPersistBundlesInstalledToCatalog(); if (!isT1KeptRunningWhenT2Starts()) { launcherT1.terminate(); @@ -639,23 +646,55 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo } @Test - public void testRebindRemovedItemButLeavingJavaSucceeds() throws Exception { + public void testRebindRemovedItemAlsoRemovesLibrary() throws Exception { File initialBomFileV2 = prepForRebindRemovedItemTestReturningBomV2(false, false); createAndStartApplication(launcherLast.getManagementContext(), "services: [ { type: 'simple-entity:1' } ]"); - // should start and promote fine, even though original catalog item ID not available - - // when we switch to loading from type registry types instead of persisted java type (see RebindIteration.load) - // T2 startup may fail like testRebindRemovedItemIAlsoRemovingJavaDependencyCausesFailure does, - // or it may fall back to the java type and succeed (but note this test does NOT allow the type to be upgraded) + // failover here fails, because we depend on the java library which is removed + startupAssertions = null; + startT2(newLauncherForTests(initialBomFileV2.getAbsolutePath()), false); + } + + @Test + public void testRebindRemovedKeepsLibraryIfInstalledExplicitly() throws Exception { + File initialBomFileV2 = prepForRebindRemovedItemTestReturningBomV2(false, false); + createAndStartApplication(launcherLast.getManagementContext(), + "services: [ { type: 'simple-entity:1' } ]"); + + // as before, but if we install the java library explicitly (directly or as a dependendency), then it _is_ persisted + // (we mark it v2 so that it replaces what startT2 installs, as the bom file on its own otherwise has no version, and the tests assert 1.0 or 2.0) + launcherLast.getManagementContext().getCatalog().addItems(initialBomV1+"\n id: org.example.testRebindGetsInitialOsgiCatalog:2.0.0\n"); + startT2(newLauncherForTests(initialBomFileV2.getAbsolutePath())); promoteT2IfStandby(); - + Entity entity = Iterables.getOnlyElement( Iterables.getOnlyElement(launcherLast.getManagementContext().getApplications()).getChildren() ); Assert.assertEquals(entity.getCatalogItemId(), "simple-entity:1.0.0"); } - + + @Test + public void testRebindRemovedKeepsLibraryIfPersistFromInitialCatalogEnabled() throws Exception { + File initialBomFileV2 = prepForRebindRemovedItemTestReturningBomV2(false, false); + alsoPersistBundlesInstalledToCatalog(); + + createAndStartApplication(launcherLast.getManagementContext(), + "services: [ { type: 'simple-entity:1' } ]"); + + // here rebind/failover should start and promote fine, and it should be able to load the entity from the java type + startT2(newLauncherForTests(initialBomFileV2.getAbsolutePath())); + promoteT2IfStandby(); + + Entity entity = Iterables.getOnlyElement( Iterables.getOnlyElement(launcherLast.getManagementContext().getApplications()).getChildren() ); + Assert.assertEquals(entity.getCatalogItemId(), "simple-entity:1.0.0"); + } + + protected void alsoPersistBundlesInstalledToCatalog() { + ((ManagementContextInternal)launcherLast.getManagementContext()).getBrooklynProperties().put( + BrooklynServerConfig.PERSIST_MANAGED_BUNDLES_FROM_INITIAL_CATALOG, true); + launcherLast.getManagementContext().getRebindManager().forcePersistNow(true, null); + } + @Test public void testRebindRemovedItemAndRemovingJavaDependencyCausesFailure() throws Exception { File initialBomFileV2 = prepForRebindRemovedItemTestReturningBomV2(true, false); @@ -686,18 +725,18 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo Asserts.assertSize( Iterables.getOnlyElement(launcherLast.getManagementContext().getApplications()).getChildren(), 0 ); } } - + + private final String initialBomV1 = Joiner.on("\n").join( + "brooklyn.catalog:", + " brooklyn.libraries:", + " - " + OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_COM_EXAMPLE_URL, + " items:", + " - id: simple-entity", + " item:", + " type: com.example.brooklyn.test.osgi.entities.SimpleEntity"); private File prepForRebindRemovedItemTestReturningBomV2(boolean removeSourceJavaBundle, boolean upgradeEntity) throws Exception { TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_COM_EXAMPLE_PATH); - String initialBomV1 = Joiner.on("\n").join( - "brooklyn.catalog:", - " brooklyn.libraries:", - " - " + OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_COM_EXAMPLE_URL, - " items:", - " - id: simple-entity", - " item:", - " type: com.example.brooklyn.test.osgi.entities.SimpleEntity"); VersionedName bundleNameV1 = new VersionedName("org.example.testRebindGetsInitialOsgiCatalog", "1.0.0"); File bundleFileV1 = newTmpBundle(ImmutableMap.of(BasicBrooklynCatalog.CATALOG_BOM, initialBomV1.getBytes()), bundleNameV1); File initialBomFileV1 = newTmpFile(createCatalogYaml(ImmutableList.of(bundleFileV1.toURI()), ImmutableList.of())); @@ -740,7 +779,8 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo File initialBomFileV2 = prepForRebindRemovedItemTestReturningBomV2(CatalogUpgrades.markerForCodeThatLoadsJavaTypesButShouldLoadRegisteredType(), true); createAndStartApplication(launcherLast.getManagementContext(), "services: [ { type: 'simple-entity:1' } ]"); - + + alsoPersistBundlesInstalledToCatalog(); startT2(newLauncherForTests(initialBomFileV2.getAbsolutePath())); promoteT2IfStandby(); @@ -790,7 +830,7 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo createAndStartApplication(launcherLast.getManagementContext(), "services: [ { type: references-simple-entity } ]"); - + alsoPersistBundlesInstalledToCatalog(); startT2(newLauncherForTests(initialBomFileV2.getAbsolutePath())); promoteT2IfStandby(); @@ -836,7 +876,8 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo Entity cluster = Iterables.getOnlyElement( app.getChildren() ); ((DynamicCluster)cluster).resize(0); // at size 0 it should always persist and rebind, even with the dependent java removed (args to prep method above) - + + alsoPersistBundlesInstalledToCatalog(); startT2(newLauncherForTests(initialBomFileV2.getAbsolutePath())); promoteT2IfStandby(); @@ -953,17 +994,17 @@ public abstract class BrooklynLauncherRebindCatalogOsgiTest extends AbstractBroo return newTmpBundle(ImmutableMap.of(BasicBrooklynCatalog.CATALOG_BOM, bundleBom.getBytes(StandardCharsets.UTF_8)), bundleName); } - // convenience for testing just a single test (TestNG plugin otherwise runs lots of them) - public static void main(String[] args) throws Exception { - try { - BrooklynLauncherRebindCatalogOsgiTest fixture = new LauncherRebindSubTests(); - fixture.setUp(); - fixture.testRebindUpgradeSpecUsedInDeployedApp(); - fixture.tearDown(); - } catch (Throwable e) { - e.printStackTrace(); - System.exit(1); - } - System.exit(0); - } +// // convenience for testing just a single test (TestNG plugin otherwise runs lots of them) +// public static void main(String[] args) throws Exception { +// try { +// BrooklynLauncherRebindCatalogOsgiTest fixture = new LauncherRebindSubTests(); +// fixture.setUp(); +// fixture.testRebindUpgradeSpecUsedInDeployedApp(); +// fixture.tearDown(); +// } catch (Throwable e) { +// e.printStackTrace(); +// System.exit(1); +// } +// System.exit(0); +// } }