You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2014/07/09 23:47:01 UTC

[48/50] git commit: clean up how catalogs are created, being clearer about URL vs contents, and support resetting a catalog from a given XML definition, with REST API endpoint. needed for a master brooklyn to push catalog changes to a client brooklyn.

clean up how catalogs are created, being clearer about URL vs contents, and support resetting a catalog from a given XML definition, with REST API endpoint.
needed for a master brooklyn to push catalog changes to a client brooklyn.


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

Branch: refs/heads/master
Commit: df48761c5eba289c185d794e570a1446eeca5fd9
Parents: 450ce96
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 9 11:44:16 2014 -0400
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Jul 9 22:34:47 2014 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  | 14 ++--
 .../brooklyn/catalog/internal/CatalogDo.java    |  2 +-
 .../brooklyn/catalog/internal/CatalogDto.java   | 62 +++++++++------
 .../internal/AbstractManagementContext.java     |  2 +-
 .../brooklyn/camp/lite/CampYamlLiteTest.java    | 81 ++++++++++++++------
 .../main/java/brooklyn/rest/api/CatalogApi.java |  9 +++
 .../rest/resources/CatalogResource.java         |  7 ++
 7 files changed, 123 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df48761c/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index b02993c..dfa966a 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -80,14 +80,10 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
 
     private final ManagementContext mgmt;
-    private final CatalogDo catalog;
+    private CatalogDo catalog;
     private volatile CatalogDo manualAdditionsCatalog;
     private volatile LoadedClassLoader manualAdditionsClasses;
 
-    public BasicBrooklynCatalog(ManagementContext mgmt, String catalogUrl) {
-        this(mgmt, CatalogDto.newDtoFromUrl(catalogUrl));
-    }
-
     public BasicBrooklynCatalog(final ManagementContext mgmt, final CatalogDto dto) {
         this.mgmt = Preconditions.checkNotNull(mgmt, "managementContext");
         this.catalog = new CatalogDo(mgmt, dto);
@@ -101,6 +97,14 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         }
     }
     
+    public void reset(CatalogDto dto) {
+        CatalogDo catalog = new CatalogDo(mgmt, dto);
+        log.debug("Resetting "+this+" catalog to "+dto);
+        catalog.load(mgmt, null);
+        log.debug("Reloaded catalog for "+this+", now switching");
+        this.catalog = catalog;
+    }
+    
     public CatalogDo getCatalog() {
         return catalog;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df48761c/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index 125d39f..e5eba3d 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -90,7 +90,7 @@ public class CatalogDo {
             log.warn("Catalog "+this+" being initialised with different mgmt "+mgmt+" when already managed by "+this.mgmt, new Throwable("source of reparented "+this));
         this.parent = parent;
         this.mgmt = mgmt;
-        dto.populateFromUrl();
+        dto.populate();
         loadCatalogClasspath();
         loadCatalogItems();
         isLoaded = true;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df48761c/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
index 272f331..d84b2f9 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
@@ -19,7 +19,7 @@
 package brooklyn.catalog.internal;
 
 import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.io.StringReader;
 import java.util.List;
 
 import org.slf4j.Logger;
@@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
 import brooklyn.util.ResourceUtils;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.exceptions.PropagatedRuntimeException;
+import brooklyn.util.stream.Streams;
 
 import com.google.common.base.Objects;
 
@@ -36,7 +37,11 @@ public class CatalogDto {
     private static final Logger LOG = LoggerFactory.getLogger(CatalogDto.class);
 
     String id;
+    /** e.g. url */
     String url;
+    
+    String contents;
+    String contentsDescription;
     String name;
     String description;
     CatalogClasspathDto classpath;
@@ -57,15 +62,22 @@ public class CatalogDto {
         if (LOG.isDebugEnabled()) LOG.debug("Retrieving catalog from: {}", url);
         try {
             InputStream source = ResourceUtils.create().getResourceFromUrl(url);
-            CatalogDto result = (CatalogDto) new CatalogXmlSerializer().deserialize(new InputStreamReader(source));
-            if (LOG.isDebugEnabled()) LOG.debug("Retrieved catalog from: {}", url);
-            return result;
+            String contents = Streams.readFullyString(source);
+            return newDtoFromXmlContents(contents, url);
         } catch (Throwable t) {
             Exceptions.propagateIfFatal(t);
             throw new PropagatedRuntimeException("Unable to retrieve catalog from " + url + ": " + t, t);
         }
     }
 
+    public static CatalogDto newDtoFromXmlContents(String xmlContents, String originDescription) {
+        CatalogDto result = (CatalogDto) new CatalogXmlSerializer().deserialize(new StringReader(xmlContents));
+        result.contentsDescription = originDescription;
+        
+        if (LOG.isDebugEnabled()) LOG.debug("Retrieved catalog from: {}", originDescription);
+        return result;
+    }
+
     public static CatalogDto newNamedInstance(String name, String description) {
         CatalogDto result = new CatalogDto();
         result.name = name;
@@ -75,9 +87,29 @@ public class CatalogDto {
 
     public static CatalogDto newLinkedInstance(String url) {
         CatalogDto result = new CatalogDto();
-        result.url = url;
+        result.contentsDescription = url;
+        result.contents = ResourceUtils.create().getResourceAsString(url);
         return result;
     }
+    
+    void populate() {
+        if (contents==null) {
+            if (url != null) {
+                contents = ResourceUtils.create().getResourceAsString(url);
+                contentsDescription = url;
+            } else {
+                LOG.warn("Catalog DTO has no contents); ignoring call to populate it.");
+                return;
+            }
+        }
+        
+        CatalogDto remoteDto = newDtoFromXmlContents(contents, contentsDescription);
+        try {
+            copyFrom(remoteDto, true);
+        } catch (Exception e) {
+            Exceptions.propagate(e);
+        }
+    }        
 
     /**
      * @throws NullPointerException If source is null (and !skipNulls)
@@ -89,35 +121,21 @@ public class CatalogDto {
         }
         
         if (!skipNulls || source.id != null) id = source.id;
-        if (!skipNulls || source.url != null) url = source.url;
+        if (!skipNulls || source.contentsDescription != null) contentsDescription = source.contentsDescription;
+        if (!skipNulls || source.contents != null) contents = source.contents;
         if (!skipNulls || source.name != null) name = source.name;
         if (!skipNulls || source.description != null) description = source.description;
         if (!skipNulls || source.classpath != null) classpath = source.classpath;
         if (!skipNulls || source.entries != null) entries = source.entries;
     }
 
-    /**
-     * Populates this Dto by loading the catalog at its {@link #url}. Takes no action if url is null.
-     * Throws if there are any problems in retrieving or copying from url.
-     */
-    void populateFromUrl() {
-        if (url != null) {
-            CatalogDto remoteDto = newDtoFromUrl(url);
-            try {
-                copyFrom(remoteDto, true);
-            } catch (Exception e) {
-                Exceptions.propagate(e);
-            }
-        }
-    }
-
     @Override
     public String toString() {
         return Objects.toStringHelper(this)
                 .omitNullValues()
                 .add("name", name)
                 .add("id", id)
-                .add("url", url)
+                .add("contentsDescription", contentsDescription)
                 .toString();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df48761c/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
index 55399cd..860e5d4 100644
--- a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
@@ -334,7 +334,7 @@ public abstract class AbstractManagementContext implements ManagementContextInte
         
         try {
             if (!Strings.isEmpty(catalogUrl)) {
-                catalog = new BasicBrooklynCatalog(this, catalogUrl);
+                catalog = new BasicBrooklynCatalog(this, CatalogDto.newDtoFromUrl(catalogUrl));
                 if (log.isDebugEnabled())
                     log.debug("Loaded catalog from "+catalogUrl+": "+catalog);
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df48761c/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
index 3694350..0e081cf 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -40,6 +40,8 @@ import org.testng.annotations.Test;
 
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
+import brooklyn.catalog.internal.BasicBrooklynCatalog;
+import brooklyn.catalog.internal.CatalogDto;
 import brooklyn.entity.Entity;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.internal.LocalManagementContext;
@@ -132,8 +134,15 @@ public class CampYamlLiteTest {
     public void testRegisterCustomEntityWithBundleWhereEntityIsFromCoreAndIconFromBundle() throws IOException {
       String registeredTypeName = "my.catalog.app.id";
       String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
-      String yaml =
-          "brooklyn.catalog:\n"+
+      String yaml = getSampleMyCatalogAppYaml(registeredTypeName, bundleUrl);
+
+      mgmt.getCatalog().addItem(yaml);
+      
+      assertMgmtHasSampleMyCatalogApp(registeredTypeName, bundleUrl);
+    }
+
+    private String getSampleMyCatalogAppYaml(String registeredTypeName, String bundleUrl) {
+        return "brooklyn.catalog:\n"+
           "  id: " + registeredTypeName + "\n"+
           "  name: My Catalog App\n"+
           "  description: My description\n"+
@@ -144,31 +153,53 @@ public class CampYamlLiteTest {
           "\n"+
           "services:\n"+
           "- type: brooklyn.test.entity.TestEntity\n";
+    }
 
-      mgmt.getCatalog().addItem(yaml);
-      
-      CatalogItem<?, ?> item = mgmt.getCatalog().getCatalogItem(registeredTypeName);
-      assertEquals(item.getRegisteredTypeName(), registeredTypeName);
-      
-      // stored as yaml, not java
+    private void assertMgmtHasSampleMyCatalogApp(String registeredTypeName, String bundleUrl) {
+        CatalogItem<?, ?> item = mgmt.getCatalog().getCatalogItem(registeredTypeName);
+          assertEquals(item.getRegisteredTypeName(), registeredTypeName);
+          
+          // stored as yaml, not java
 //      assertEquals(entityItem.getJavaType(), "brooklyn.test.entity.TestEntity");
-      Assert.assertNotNull(item.getPlanYaml());
-      Assert.assertTrue(item.getPlanYaml().contains("brooklyn.test.entity.TestEntity"));
-      
-      assertEquals(item.getId(), registeredTypeName);
-      
-      // and let's check we have libraries
-      List<String> libs = item.getLibraries().getBundles();
-      assertEquals(libs, MutableList.of(bundleUrl));
-
-      // now let's check other things on the item
-      assertEquals(item.getName(), "My Catalog App");
-      assertEquals(item.getDescription(), "My description");
-      assertEquals(item.getIconUrl(), "classpath:/brooklyn/osgi/tests/icon.gif");
-      
-      // and confirm we can resolve ICON
-      byte[] iconData = Streams.readFully( ResourceUtils.create(item.newClassLoadingContext(mgmt)).getResourceFromUrl(item.getIconUrl()) );
-      assertEquals(iconData.length, 43);
+          Assert.assertNotNull(item.getPlanYaml());
+          Assert.assertTrue(item.getPlanYaml().contains("brooklyn.test.entity.TestEntity"));
+          
+          assertEquals(item.getId(), registeredTypeName);
+          
+          // and let's check we have libraries
+          List<String> libs = item.getLibraries().getBundles();
+          assertEquals(libs, MutableList.of(bundleUrl));
+
+          // now let's check other things on the item
+          assertEquals(item.getName(), "My Catalog App");
+          assertEquals(item.getDescription(), "My description");
+          assertEquals(item.getIconUrl(), "classpath:/brooklyn/osgi/tests/icon.gif");
+          
+          // and confirm we can resolve ICON
+          byte[] iconData = Streams.readFully( ResourceUtils.create(item.newClassLoadingContext(mgmt)).getResourceFromUrl(item.getIconUrl()) );
+          assertEquals(iconData.length, 43);
     }
+
     
+    @Test
+    public void testResetXmlWithCustomEntity() throws IOException {
+      String registeredTypeName = "my.catalog.app.id";
+      String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
+      String yaml = getSampleMyCatalogAppYaml(registeredTypeName, bundleUrl);
+
+      LocalManagementContextForTests mgmt2 = new LocalManagementContextForTests();
+      try {
+          CampPlatformWithJustBrooklynMgmt platform2 = new CampPlatformWithJustBrooklynMgmt(mgmt2);
+          MockWebPlatform.populate(platform2, TestAppAssemblyInstantiator.class);
+          
+          mgmt2.getCatalog().addItem(yaml);
+          String xml = ((BasicBrooklynCatalog)mgmt2.getCatalog()).toXmlString();
+          ((BasicBrooklynCatalog)mgmt.getCatalog()).reset(CatalogDto.newDtoFromXmlContents(xml, "copy of temporary catalog"));
+      } finally {
+          mgmt2.terminate();
+      }
+      
+      assertMgmtHasSampleMyCatalogApp(registeredTypeName, bundleUrl);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df48761c/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
index f1f07b7..769c8b9 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
@@ -58,6 +58,15 @@ public interface CatalogApi {
             @Valid String yaml
     ) ;
 
+    @POST
+    @Consumes(MediaType.APPLICATION_XML)
+    @Path("/reset")
+    @ApiOperation(value = "Resets the catalog to the given (XML) format")
+    public Response resetXml(
+            @ApiParam(name = "xml", value = "XML descriptor of the entire catalog to install", required = true)
+            @Valid String xml
+    ) ;
+
     @DELETE
     @Path("/entities/{entityId}")
     @ApiOperation(value = "Deletes an entity's definition from the catalog")

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df48761c/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
index a575d37..b6323a5 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
@@ -35,6 +35,8 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
+import brooklyn.catalog.internal.BasicBrooklynCatalog;
+import brooklyn.catalog.internal.CatalogDto;
 import brooklyn.entity.Entity;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.rest.api.CatalogApi;
@@ -98,6 +100,11 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
         }
     }
 
+    public Response resetXml(String xml) {
+        ((BasicBrooklynCatalog)mgmt().getCatalog()).reset(CatalogDto.newDtoFromXmlContents(xml, "REST reset"));
+        return Response.ok().build();
+    }
+    
     @Override
     public void deleteEntity(String entityId) throws Exception {
       CatalogItem<?,?> result = brooklyn().getCatalog().getCatalogItem(entityId);