You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2022/07/14 10:16:32 UTC

[brooklyn-server] 01/05: add failing test for import not allowing bundles in unusual orders

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 840f6f8b840faebbd702663a162828a4601a7b78
Author: Alex Heneveld <al...@cloudsoft.io>
AuthorDate: Wed Jul 13 12:02:31 2022 +0100

    add failing test for import not allowing bundles in unusual orders
---
 .../catalog/internal/BasicBrooklynCatalog.java     |  5 +-
 .../apache/brooklyn/core/mgmt/ha/OsgiManager.java  | 11 ++-
 .../BrooklynBomYamlCatalogBundleResolver.java      |  3 +-
 .../brooklyn/rest/resources/ServerResource.java    |  1 +
 .../rest/resources/ApplicationResourceTest.java    | 10 +--
 .../rest/resources/ServerResourceTest.java         | 96 +++++++++++++++++++++-
 6 files changed, 116 insertions(+), 10 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 ce10b25a80..8e742eb6cf 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
@@ -1607,8 +1607,9 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
                     itemSpecInstantiated = internalCreateSpecLegacy(mgmt, itemToAttempt, MutableSet.<String>of(), true);
 
                     if (!candidateYaml.contains("services:")) {
-                        // 'services:' blueprints still need legacy plan-to-spec converter
-                        log.warn("Instantiation of this blueprint was only possible with legacy plan-to-spec converter, will likely not be supported in future versions:\n" + candidateYaml);
+                        // 'services:' blueprints still need legacy plan-to-spec converter, don't even debug on that.
+                        // for others
+                        log.debug("Instantiation of this blueprint was only possible with legacy plan-to-spec converter, may not be supported in future versions:\n" + candidateYaml);
                     }
                 }
 
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 65b81e5ada..edd4349396 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
@@ -440,7 +440,7 @@ public class OsgiManager {
             @Nullable ManagedBundle knownBundleMetadata, @Nullable Supplier<InputStream> zipIn, boolean validateTypes) {
         BundleInstallationOptions options = new BundleInstallationOptions();
         options.setDeferredStart(true);
-        options.setFormat(knownBundleMetadata.getFormat());
+        if (knownBundleMetadata!=null) options.setFormat(knownBundleMetadata.getFormat());
         options.setValidateTypes(validateTypes);
         options.setKnownBundleMetadata(knownBundleMetadata);
         return BrooklynCatalogBundleResolvers.install(getManagementContext(), zipIn, options);
@@ -464,11 +464,20 @@ public class OsgiManager {
     public ReferenceWithError<OsgiBundleInstallationResult> installBrooklynBomBundle(
             @Nullable ManagedBundle knownBundleMetadata, Supplier<InputStream> input,
             boolean start, boolean loadCatalogBom, boolean forceUpdateOfNonSnapshots) {
+        return installBrooklynBomBundle(knownBundleMetadata, input, start, loadCatalogBom, forceUpdateOfNonSnapshots, true, false);
+    }
+
+    @Beta
+    public ReferenceWithError<OsgiBundleInstallationResult> installBrooklynBomBundle(
+            @Nullable ManagedBundle knownBundleMetadata, Supplier<InputStream> input,
+            boolean start, boolean loadCatalogBom, boolean forceUpdateOfNonSnapshots, boolean validate, boolean deferredStart) {
         BundleInstallationOptions options = new BundleInstallationOptions();
         options.setKnownBundleMetadata(knownBundleMetadata);
         options.setStart(start);
         options.setLoadCatalogBom(loadCatalogBom);
         options.setForceUpdateOfNonSnapshots(forceUpdateOfNonSnapshots);
+        options.setValidateTypes(validate);
+        options.setDeferredStart(deferredStart);
         return BrooklynCatalogBundleResolvers.install(getManagementContext(), input, options);
     }
     
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 72ae2dc361..f4ed4b02aa 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
@@ -134,7 +134,8 @@ public class BrooklynBomYamlCatalogBundleResolver extends AbstractCatalogBundleR
                 basicManagedBundle.tags().addTags((Iterable<?>)cm.get("tags"));
             }
             result = ((ManagementContextInternal)mgmt).getOsgiManager().get().installBrooklynBomBundle(
-                    basicManagedBundle, InputStreamSource.of("ZIP generated for "+vn+": "+bf, bf), options.isStart(), options.isLoadCatalogBom(), options.isForceUpdateOfNonSnapshots()).get();
+                    basicManagedBundle, InputStreamSource.of("ZIP generated for "+vn+": "+bf, bf), options.isStart(), options.isLoadCatalogBom(), options.isForceUpdateOfNonSnapshots(),
+                    options.isValidateTypes(), options.isDeferredStart()).get();
         } finally {
             bf.delete();
         }
diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
index 0c7739a404..812ede244d 100644
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
@@ -661,6 +661,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
         } catch (Exception e){
             Exceptions.propagateIfFatal(e);
             ApiError.Builder error = ApiError.builder().errorCode(Response.Status.BAD_REQUEST);
+            log.warn("Error importing persisted state: "+e, e);
             error.message(e.getMessage());
             return error.build().asJsonResponse();
         } finally {
diff --git a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
index 701a09194b..1882fdf42e 100644
--- a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
+++ b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
@@ -213,7 +213,7 @@ public class ApplicationResourceTest extends BrooklynRestResourceTest {
                 .build();
 
         Response response = clientDeploy(spec);
-        assertTrue(response.getStatus() / 100 == 2, "response is " + response);
+        HttpAsserts.assertHealthyStatusCode(response.getStatus());
 
         // Expect app to be running
         URI appUri = response.getLocation();
@@ -227,7 +227,7 @@ public class ApplicationResourceTest extends BrooklynRestResourceTest {
 
         Response response = client().path("/applications")
                 .post(Entity.entity(yaml, "application/x-yaml"));
-        assertTrue(response.getStatus()/100 == 2, "response is "+response);
+        HttpAsserts.assertHealthyStatusCode(response.getStatus());
 
         // Expect app to be running
         URI appUri = response.getLocation();
@@ -250,7 +250,7 @@ public class ApplicationResourceTest extends BrooklynRestResourceTest {
                 "    static.value: " + SENSOR_TEXT_VALUE);
         Response response = client().path("/applications")
                 .post(Entity.entity(yaml, "application/x-yaml"));
-        assertTrue(response.getStatus()/100 == 2, "response is "+response);
+        HttpAsserts.assertHealthyStatusCode(response.getStatus());
 
         // Fetch applications, find 'simple-app-yaml-with-invalid-sensor-type' application and inspect details.
         Collection apps = client().path("/applications/fetch").get(Collection.class);
@@ -275,7 +275,7 @@ public class ApplicationResourceTest extends BrooklynRestResourceTest {
         Response response = client().path("/applications")
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.MULTIPART_FORM_DATA)
                 .post(body);
-        assertTrue(response.getStatus()/100 == 2, "response is "+response);
+        HttpAsserts.assertHealthyStatusCode(response.getStatus());
 
         // Expect app to be running
         URI appUri = response.getLocation();
@@ -297,7 +297,7 @@ public class ApplicationResourceTest extends BrooklynRestResourceTest {
 
         Response response = client().path("/applications")
                 .post(Entity.entity(yaml, "application/x-yaml"));
-        assertTrue(response.getStatus()/100 == 2, "response is "+response);
+        HttpAsserts.assertHealthyStatusCode(response.getStatus());
 
         // Expect app to be running
         URI appUri = response.getLocation();
diff --git a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceTest.java b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceTest.java
index 786f8dbfd4..d08dad477d 100644
--- a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceTest.java
+++ b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceTest.java
@@ -23,6 +23,7 @@ import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
 import java.io.ByteArrayInputStream;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
@@ -30,6 +31,8 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
@@ -37,10 +40,18 @@ import org.apache.brooklyn.api.entity.ImplementedBy;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityMode;
 import org.apache.brooklyn.api.mgmt.ha.ManagementNodeState;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
 import org.apache.brooklyn.core.BrooklynVersion;
+import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.internal.BrooklynProperties;
+import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.mgmt.rebind.RebindTestUtils;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.core.typereg.BrooklynBomYamlCatalogBundleResolver;
 import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
 import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessDriver;
 import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessImpl;
@@ -49,8 +60,15 @@ import org.apache.brooklyn.location.ssh.SshMachineLocation;
 import org.apache.brooklyn.rest.domain.HighAvailabilitySummary;
 import org.apache.brooklyn.rest.domain.VersionSummary;
 import org.apache.brooklyn.rest.testing.BrooklynRestResourceTest;
+import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Suppliers;
+import org.apache.brooklyn.util.http.HttpAsserts;
+import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.util.text.Identifiers;
 import org.apache.brooklyn.util.text.StringPredicates;
+import org.apache.brooklyn.util.text.Strings;
+import org.apache.brooklyn.util.time.Duration;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -65,7 +83,10 @@ import com.google.common.collect.Iterables;
 public class ServerResourceTest extends BrooklynRestResourceTest {
 
     private static final Logger log = LoggerFactory.getLogger(ServerResourceTest.class);
-    
+
+    @Override
+    protected boolean useOsgi() { return true; }
+
     @Test
     public void testGetVersion() throws Exception {
         VersionSummary version = client().path("/server/version").get(VersionSummary.class);
@@ -93,6 +114,79 @@ public class ServerResourceTest extends BrooklynRestResourceTest {
         List<String> entryNames = listEntryNames(zip);
         assertTrue(Iterables.tryFind(entryNames, StringPredicates.containsLiteral(app.getId())).isPresent(), "entries="+entryNames);
         assertTrue(Iterables.tryFind(entryNames, StringPredicates.containsLiteral(loc.getId())).isPresent(), "entries="+entryNames);
+
+        Entities.unmanage(app);
+    }
+
+    @Test
+    public void testExportPersistedStateWithBundlesThenReimport() throws Exception {
+        // export seems to preserve install order probably to minimise conflicts, so use deferred start to get the problematic order
+        OsgiBundleInstallationResult r2 = ((ManagementContextInternal) manager).getOsgiManager().get().installDeferredStart(null,
+                () -> new ByteArrayInputStream(Strings.lines(
+                        "brooklyn.catalog:",
+                        "  bundle: b2",
+                        "  version: 1",
+                        "  id: b2",
+                        "  itemType: entity",
+                        "  item:",
+                        "    type: b1"
+                ).getBytes()),
+                false).get();
+
+        ((ManagementContextInternal) manager).getOsgiManager().get().install(
+                () -> new ByteArrayInputStream(Strings.lines(
+                        "brooklyn.catalog:",
+                        "  bundle: b1",
+                        "  version: 1",
+                        "  id: b1",
+                        "  itemType: entity",
+                        "  item:",
+                        "    type: org.apache.brooklyn.core.test.entity.TestEntity"
+                ).getBytes()),
+                BrooklynBomYamlCatalogBundleResolver.FORMAT, false, null).get();
+
+        r2.getDeferredStart().run();
+
+        String yaml = "services: [ { type: b2 } ]";
+        Response response = client().path("/applications")
+                .post(Entity.entity(yaml, "application/x-yaml"));
+        HttpAsserts.assertHealthyStatusCode(response.getStatus());
+
+        org.apache.brooklyn.api.entity.Entity b2 = Iterables.getOnlyElement(Iterables.getOnlyElement(manager.getApplications()).getChildren());
+        Asserts.assertInstanceOf(b2, TestEntity.class);
+
+        byte[] zip = client().path("/server/ha/persist/export").get(byte[].class);
+
+        // restart the server, so it has nothing, then try importing
+        destroyClass();
+
+        File mementoDir = Os.newTempDir(getClass());
+        manager = RebindTestUtils.managementContextBuilder(mementoDir, getClass().getClassLoader())
+                .persistPeriodMillis(Duration.ONE_MINUTE.toMilliseconds())
+                .haMode(HighAvailabilityMode.MASTER)
+                .forLive(true)
+                .enablePersistenceBackups(false)
+                .emptyCatalog(true)
+//                .properties(false)
+                .setOsgiEnablementAndReuse(useOsgi(), true)
+                .buildStarted();
+        new BrooklynCampPlatformLauncherNoServer()
+                .useManagementContext(manager)
+                .launch();
+
+        initClass();
+
+        Asserts.assertNull(manager.getTypeRegistry().get("b2"));
+        Asserts.assertSize(manager.getApplications(), 0);
+
+        Response importResponse = client().path("/server/ha/persist/import").post(Entity.entity(zip, MediaType.APPLICATION_OCTET_STREAM_TYPE));
+        HttpAsserts.assertHealthyStatusCode(importResponse.getStatus());
+
+        Asserts.assertNotNull(manager.getTypeRegistry().get("b1"));
+        Asserts.assertNotNull(manager.getTypeRegistry().get("b2"));
+        org.apache.brooklyn.api.entity.Entity b2b = Iterables.getOnlyElement(Iterables.getOnlyElement(manager.getApplications()).getChildren());
+        Asserts.assertInstanceOf(b2b, TestEntity.class);
+        Asserts.assertEquals(b2b.getId(), b2.getId());
     }
 
     private List<String> listEntryNames(byte[] zip) throws Exception {